Applied all changes from Igor and Sanja

This commit is contained in:
Michael Widenius 2013-06-15 18:32:08 +03:00
commit 5f1f2fc0e4
162 changed files with 11674 additions and 6268 deletions

7
TODO
View file

@ -32,12 +32,10 @@ Short time TODO:
- add support for host_error()
- Enable performance_schema.host_cache in scripts/mysql_system_tables.sql
- Add full support for automatic timestamp.
(remove timestamp handling from ha_write())
- Timour is working on this
- Add Sys_my_bind_addr(); Needed for perfschema
- Add support for format_section_buff in unireg.cc and table.cc
- mysql_socket_shutdown() was removed from vio/viosocket.cc.
It was replaced with inline function in include/mysql/psi/mysql_socket.h
but this doesn't call DisconnectEx(). We should check if we need to
@ -60,4 +58,3 @@ Sergei's notes:
rpl_slave.cc
XXX in mysql_client_test
net_serv.cc

View file

@ -138,6 +138,38 @@ extern MY_UNI_CTYPE my_uni_ctype[256];
#define MY_REPERTOIRE_EXTENDED 2 /* Extended characters: U+0080..U+FFFF */
#define MY_REPERTOIRE_UNICODE30 3 /* ASCII | EXTENDED: U+0000..U+FFFF */
/* Flags for strxfrm */
#define MY_STRXFRM_LEVEL1 0x00000001 /* for primary weights */
#define MY_STRXFRM_LEVEL2 0x00000002 /* for secondary weights */
#define MY_STRXFRM_LEVEL3 0x00000004 /* for tertiary weights */
#define MY_STRXFRM_LEVEL4 0x00000008 /* fourth level weights */
#define MY_STRXFRM_LEVEL5 0x00000010 /* fifth level weights */
#define MY_STRXFRM_LEVEL6 0x00000020 /* sixth level weights */
#define MY_STRXFRM_LEVEL_ALL 0x0000003F /* Bit OR for the above six */
#define MY_STRXFRM_NLEVELS 6 /* Number of possible levels*/
#define MY_STRXFRM_PAD_WITH_SPACE 0x00000040 /* if pad result with spaces */
#define MY_STRXFRM_PAD_TO_MAXLEN 0x00000080 /* if pad tail(for filesort) */
#define MY_STRXFRM_DESC_LEVEL1 0x00000100 /* if desc order for level1 */
#define MY_STRXFRM_DESC_LEVEL2 0x00000200 /* if desc order for level2 */
#define MY_STRXFRM_DESC_LEVEL3 0x00000300 /* if desc order for level3 */
#define MY_STRXFRM_DESC_LEVEL4 0x00000800 /* if desc order for level4 */
#define MY_STRXFRM_DESC_LEVEL5 0x00001000 /* if desc order for level5 */
#define MY_STRXFRM_DESC_LEVEL6 0x00002000 /* if desc order for level6 */
#define MY_STRXFRM_DESC_SHIFT 8
#define MY_STRXFRM_UNUSED_00004000 0x00004000 /* for future extensions */
#define MY_STRXFRM_UNUSED_00008000 0x00008000 /* for future extensions */
#define MY_STRXFRM_REVERSE_LEVEL1 0x00010000 /* if reverse order for level1 */
#define MY_STRXFRM_REVERSE_LEVEL2 0x00020000 /* if reverse order for level2 */
#define MY_STRXFRM_REVERSE_LEVEL3 0x00040000 /* if reverse order for level3 */
#define MY_STRXFRM_REVERSE_LEVEL4 0x00080000 /* if reverse order for level4 */
#define MY_STRXFRM_REVERSE_LEVEL5 0x00100000 /* if reverse order for level5 */
#define MY_STRXFRM_REVERSE_LEVEL6 0x00200000 /* if reverse order for level6 */
#define MY_STRXFRM_REVERSE_SHIFT 16
struct my_uni_idx_st
{
uint16 from;

View file

@ -63,6 +63,7 @@ extern uint bitmap_set_next(MY_BITMAP *map);
extern uint bitmap_get_first(const MY_BITMAP *map);
extern uint bitmap_get_first_set(const MY_BITMAP *map);
extern uint bitmap_bits_set(const MY_BITMAP *map);
extern uint bitmap_get_next_set(const MY_BITMAP *map, uint bitmap_bit);
extern void bitmap_free(MY_BITMAP *map);
extern void bitmap_set_above(MY_BITMAP *map, uint from_byte, uint use_bit);
extern void bitmap_set_prefix(MY_BITMAP *map, uint prefix_size);

View file

@ -1,34 +0,0 @@
# Install script for directory: /my/maria-10.0-merge/libevent
# Set the install prefix
IF(NOT DEFINED CMAKE_INSTALL_PREFIX)
SET(CMAKE_INSTALL_PREFIX "/usr/local/mysql")
ENDIF(NOT DEFINED CMAKE_INSTALL_PREFIX)
STRING(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}")
# Set the install configuration name.
IF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME)
IF(BUILD_TYPE)
STRING(REGEX REPLACE "^[^A-Za-z0-9_]+" ""
CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}")
ELSE(BUILD_TYPE)
SET(CMAKE_INSTALL_CONFIG_NAME "Debug")
ENDIF(BUILD_TYPE)
MESSAGE(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"")
ENDIF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME)
# Set the component getting installed.
IF(NOT CMAKE_INSTALL_COMPONENT)
IF(COMPONENT)
MESSAGE(STATUS "Install component: \"${COMPONENT}\"")
SET(CMAKE_INSTALL_COMPONENT "${COMPONENT}")
ELSE(COMPONENT)
SET(CMAKE_INSTALL_COMPONENT)
ENDIF(COMPONENT)
ENDIF(NOT CMAKE_INSTALL_COMPONENT)
# Install shared libraries without execute permission?
IF(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE)
SET(CMAKE_INSTALL_SO_NO_EXE "0")
ENDIF(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE)

View file

@ -64,7 +64,8 @@ SET(SQL_EMBEDDED_SOURCES emb_qcache.cc libmysqld.c lib_sql.cc
../sql/sql_analyse.cc ../sql/sql_base.cc ../sql/sql_cache.cc
../sql/sql_class.cc ../sql/sql_crypt.cc ../sql/sql_cursor.cc
../sql/sql_db.cc ../sql/sql_delete.cc ../sql/sql_derived.cc
../sql/sql_do.cc ../sql/sql_error.cc ../sql/sql_handler.cc
../sql/sql_do.cc ../sql/sql_error.cc ../sql/sql_handler.cc
../sql/sql_get_diagnostics.cc
../sql/sql_help.cc ../sql/sql_insert.cc ../sql/datadict.cc
../sql/sql_admin.cc ../sql/sql_truncate.cc ../sql/sql_reload.cc
../sql/sql_lex.cc ../sql/keycaches.cc
@ -118,7 +119,7 @@ ENDIF()
SET(LIBS
dbug strings regex mysys vio
dbug strings regex mysys mysys_ssl vio
${ZLIB_LIBRARY} ${SSL_LIBRARIES}
${LIBWRAP} ${LIBCRYPT} ${LIBDL}
${MYSQLD_STATIC_PLUGIN_LIBS}

View file

@ -487,7 +487,7 @@ int emb_load_querycache_result(THD *thd, Querycache_stream *src)
data->embedded_info->prev_ptr= prev_row;
return_ok:
net_send_eof(thd, thd->server_status,
thd->warning_info->statement_warn_count());
thd->get_stmt_da()->statement_warn_count());
DBUG_RETURN(0);
err:
DBUG_RETURN(1);

View file

@ -130,7 +130,7 @@ emb_advanced_command(MYSQL *mysql, enum enum_server_command command,
/* Clear result variables */
thd->clear_error();
thd->stmt_da->reset_diagnostics_area();
thd->get_stmt_da()->reset_diagnostics_area();
mysql->affected_rows= ~(my_ulonglong) 0;
mysql->field_count= 0;
net_clear_error(net);
@ -241,7 +241,7 @@ static my_bool emb_read_prepare_result(MYSQL *mysql, MYSQL_STMT *stmt)
stmt->stmt_id= thd->client_stmt_id;
stmt->param_count= thd->client_param_count;
stmt->field_count= 0;
mysql->warning_count= thd->warning_info->statement_warn_count();
mysql->warning_count= thd->get_stmt_da()->statement_warn_count();
if (thd->first_data)
{
@ -428,7 +428,7 @@ static void emb_free_embedded_thd(MYSQL *mysql)
static const char * emb_read_statistics(MYSQL *mysql)
{
THD *thd= (THD*)mysql->thd;
return thd->is_error() ? thd->stmt_da->message() : "";
return thd->is_error() ? thd->get_stmt_da()->message() : "";
}
@ -1045,7 +1045,7 @@ bool Protocol::send_result_set_metadata(List<Item> *list, uint flags)
if (flags & SEND_EOF)
write_eof_packet(thd, thd->server_status,
thd->warning_info->statement_warn_count());
thd->get_stmt_da()->statement_warn_count());
DBUG_RETURN(prepare_for_send(list->elements));
err:

View file

@ -1,4 +1,4 @@
# Copyright (c) 2007, 2010, Oracle and/or its affiliates
# Copyright (c) 2007, 2012, Oracle and/or its affiliates
# Copyright (c) 2010, 2012, Monty Program Ab
#
# This program is free software; you can redistribute it and/or modify
@ -50,18 +50,36 @@ loose-innodb_log_files_in_group= 2
slave-net-timeout=120
# MAINTAINER:
# the loose- syntax is to make sure the cnf file is also
# valid when building without the performance schema.
# Run tests with the performance schema instrumentation
loose-enable-performance-schema
# Run tests with a small number of instrumented objects
# to limit memory consumption with MTR
loose-performance-schema-accounts-size=100
loose-performance-schema-digests-size=200
loose-performance-schema-hosts-size=100
loose-performance-schema-users-size=100
loose-performance-schema-max-mutex-instances=5000
loose-performance-schema-max-rwlock-instances=5000
loose-performance-schema-max-cond-instances=1000
loose-performance-schema-max-file-instances=10000
loose-performance-schema-max-socket-instances=1000
loose-performance-schema-max-table-instances=500
loose-performance-schema-max-table-handles=1000
loose-performance-schema-events-waits-history-size=10
loose-performance-schema-events-waits-history-long-size=10000
loose-performance-schema-events-stages-history-size=10
loose-performance-schema-events-stages-history-long-size=1000
loose-performance-schema-events-statements-history-size=10
loose-performance-schema-events-statements-history-long-size=1000
loose-performance-schema-max-thread-instances=200
loose-performance-schema-session-connect-attrs-size=2048
# Enable everything, for maximun code exposure during testing
loose-performance-schema-instrument='%=ON'

View file

@ -0,0 +1,15 @@
show variables like "table_definition_cache";
show variables like "table_open_cache";
show variables like "max_connections";
# Results vary by platform:
# show variables like "open_files_limit";
show variables like "%performance_schema%";
show status like "%performance_schema%";
# Each test script should provide a different test.cnf file,
# with different settings.
# This output will show the sizes computed automatically.
# Note that this output is very dependent on the platform.
show engine performance_schema status;

View file

@ -67,7 +67,8 @@ static my_hash_value_type calc_hash(const HASH *hash,
@param[in] get_key get the key for the hash
@param[in] free_element pointer to the function that
does cleanup
@return inidicates success or failure of initialization
@param[in] flags flags set in the hash
@return indicates success or failure of initialization
@retval 0 success
@retval 1 failure
*/

View file

@ -1,329 +0,0 @@
/* Copyright (C) 2000 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/*
* This code implements the MD5 message-digest algorithm.
* The algorithm is due to Ron Rivest. This code was
* written by Colin Plumb in 1993, no copyright is claimed.
* This code is in the public domain; do with it what you wish.
*
* Equivalent code is available from RSA Data Security, Inc.
* This code has been tested against that, and is equivalent,
* except that you don't need to include two pages of legalese
* with every copy.
*
* To compute the message digest of a chunk of bytes, declare an
* MD5Context structure, pass it to MD5Init, call MD5Update as
* needed on buffers full of bytes, and then call MD5Final, which
* will fill a supplied 16-byte array with the digest.
*/
/* This code was modified in 1997 by Jim Kingdon of Cyclic Software to
not require an integer type which is exactly 32 bits. This work
draws on the changes for the same purpose by Tatu Ylonen
<ylo@cs.hut.fi> as part of SSH, but since I didn't actually use
that code, there is no copyright issue. I hereby disclaim
copyright in any changes I have made; this code remains in the
public domain. */
/*
Skip entirely if built with OpenSSL/YaSSL support.
*/
#if !defined(HAVE_OPENSSL) && !defined(HAVE_YASSL)
#include <my_global.h>
#include <m_string.h>
#include "my_md5.h"
static void
my_MD5Transform (cvs_uint32 buf[4], const unsigned char in[64]);
/* Little-endian byte-swapping routines. Note that these do not
depend on the size of datatypes such as uint32, nor do they require
us to detect the endianness of the machine we are running on. It
is possible they should be macros for speed, but I would be
surprised if they were a performance bottleneck for MD5. */
static uint32 getu32 (const unsigned char *addr)
{
return (((((unsigned long)addr[3] << 8) | addr[2]) << 8)
| addr[1]) << 8 | addr[0];
}
static void
putu32 (uint32 data, unsigned char *addr)
{
addr[0] = (unsigned char)data;
addr[1] = (unsigned char)(data >> 8);
addr[2] = (unsigned char)(data >> 16);
addr[3] = (unsigned char)(data >> 24);
}
/*
Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
initialization constants.
*/
void
my_MD5Init (my_MD5Context *ctx)
{
ctx->buf[0] = 0x67452301;
ctx->buf[1] = 0xefcdab89;
ctx->buf[2] = 0x98badcfe;
ctx->buf[3] = 0x10325476;
ctx->bits[0] = 0;
ctx->bits[1] = 0;
}
/*
Update context to reflect the concatenation of another buffer full
of bytes.
*/
void
my_MD5Update (my_MD5Context *ctx, unsigned char const *buf, unsigned len)
{
uint32 t;
/* Update bitcount */
t = ctx->bits[0];
if ((ctx->bits[0] = (t + ((uint32)len << 3)) & 0xffffffff) < t)
ctx->bits[1]++; /* Carry from low to high */
ctx->bits[1] += len >> 29;
t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
/* Handle any leading odd-sized chunks */
if ( t ) {
unsigned char *p = ctx->in + t;
t = 64-t;
if (len < t) {
memcpy(p, buf, len);
return;
}
memcpy(p, buf, t);
my_MD5Transform (ctx->buf, ctx->in);
buf += t;
len -= t;
}
/* Process data in 64-byte chunks */
while (len >= 64) {
memcpy(ctx->in, buf, 64);
my_MD5Transform (ctx->buf, ctx->in);
buf += 64;
len -= 64;
}
/* Handle any remaining bytes of data. */
memcpy(ctx->in, buf, len);
}
/*
Final wrapup - pad to 64-byte boundary with the bit pattern
1 0* (64-bit count of bits processed, MSB-first)
*/
void
my_MD5Final (unsigned char digest[16], my_MD5Context *ctx)
{
unsigned count;
unsigned char *p;
/* Compute number of bytes mod 64 */
count = (ctx->bits[0] >> 3) & 0x3F;
/* Set the first char of padding to 0x80. This is safe since there is
always at least one byte free */
p = ctx->in + count;
*p++ = 0x80;
/* Bytes of padding needed to make 64 bytes */
count = 64 - 1 - count;
/* Pad out to 56 mod 64 */
if (count < 8) {
/* Two lots of padding: Pad the first block to 64 bytes */
memset(p, 0, count);
my_MD5Transform (ctx->buf, ctx->in);
/* Now fill the next block with 56 bytes */
memset(ctx->in, 0, 56);
} else {
/* Pad block to 56 bytes */
memset(p, 0, count-8);
}
/* Append length in bits and transform */
putu32(ctx->bits[0], ctx->in + 56);
putu32(ctx->bits[1], ctx->in + 60);
my_MD5Transform (ctx->buf, ctx->in);
putu32(ctx->buf[0], digest);
putu32(ctx->buf[1], digest + 4);
putu32(ctx->buf[2], digest + 8);
putu32(ctx->buf[3], digest + 12);
memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
}
#ifndef ASM_MD5
/* The four core functions - F1 is optimized somewhat */
/* #define F1(x, y, z) (x & y | ~x & z) */
#define F1(x, y, z) (z ^ (x & (y ^ z)))
#define F2(x, y, z) F1(z, x, y)
#define F3(x, y, z) (x ^ y ^ z)
#define F4(x, y, z) (y ^ (x | ~z))
/* This is the central step in the MD5 algorithm. */
#define MD5STEP(f, w, x, y, z, data, s) \
( w += f(x, y, z) + data, w &= 0xffffffff, w = w<<s | w>>(32-s), w += x )
/*
* The core of the MD5 algorithm, this alters an existing MD5 hash to
* reflect the addition of 16 longwords of new data. MD5Update blocks
* the data and converts bytes into longwords for this routine.
*/
static void
my_MD5Transform (uint32 buf[4], const unsigned char inraw[64])
{
register uint32 a, b, c, d;
uint32 in[16];
int i;
for (i = 0; i < 16; ++i)
in[i] = getu32 (inraw + 4 * i);
a = buf[0];
b = buf[1];
c = buf[2];
d = buf[3];
MD5STEP(F1, a, b, c, d, in[ 0]+0xd76aa478, 7);
MD5STEP(F1, d, a, b, c, in[ 1]+0xe8c7b756, 12);
MD5STEP(F1, c, d, a, b, in[ 2]+0x242070db, 17);
MD5STEP(F1, b, c, d, a, in[ 3]+0xc1bdceee, 22);
MD5STEP(F1, a, b, c, d, in[ 4]+0xf57c0faf, 7);
MD5STEP(F1, d, a, b, c, in[ 5]+0x4787c62a, 12);
MD5STEP(F1, c, d, a, b, in[ 6]+0xa8304613, 17);
MD5STEP(F1, b, c, d, a, in[ 7]+0xfd469501, 22);
MD5STEP(F1, a, b, c, d, in[ 8]+0x698098d8, 7);
MD5STEP(F1, d, a, b, c, in[ 9]+0x8b44f7af, 12);
MD5STEP(F1, c, d, a, b, in[10]+0xffff5bb1, 17);
MD5STEP(F1, b, c, d, a, in[11]+0x895cd7be, 22);
MD5STEP(F1, a, b, c, d, in[12]+0x6b901122, 7);
MD5STEP(F1, d, a, b, c, in[13]+0xfd987193, 12);
MD5STEP(F1, c, d, a, b, in[14]+0xa679438e, 17);
MD5STEP(F1, b, c, d, a, in[15]+0x49b40821, 22);
MD5STEP(F2, a, b, c, d, in[ 1]+0xf61e2562, 5);
MD5STEP(F2, d, a, b, c, in[ 6]+0xc040b340, 9);
MD5STEP(F2, c, d, a, b, in[11]+0x265e5a51, 14);
MD5STEP(F2, b, c, d, a, in[ 0]+0xe9b6c7aa, 20);
MD5STEP(F2, a, b, c, d, in[ 5]+0xd62f105d, 5);
MD5STEP(F2, d, a, b, c, in[10]+0x02441453, 9);
MD5STEP(F2, c, d, a, b, in[15]+0xd8a1e681, 14);
MD5STEP(F2, b, c, d, a, in[ 4]+0xe7d3fbc8, 20);
MD5STEP(F2, a, b, c, d, in[ 9]+0x21e1cde6, 5);
MD5STEP(F2, d, a, b, c, in[14]+0xc33707d6, 9);
MD5STEP(F2, c, d, a, b, in[ 3]+0xf4d50d87, 14);
MD5STEP(F2, b, c, d, a, in[ 8]+0x455a14ed, 20);
MD5STEP(F2, a, b, c, d, in[13]+0xa9e3e905, 5);
MD5STEP(F2, d, a, b, c, in[ 2]+0xfcefa3f8, 9);
MD5STEP(F2, c, d, a, b, in[ 7]+0x676f02d9, 14);
MD5STEP(F2, b, c, d, a, in[12]+0x8d2a4c8a, 20);
MD5STEP(F3, a, b, c, d, in[ 5]+0xfffa3942, 4);
MD5STEP(F3, d, a, b, c, in[ 8]+0x8771f681, 11);
MD5STEP(F3, c, d, a, b, in[11]+0x6d9d6122, 16);
MD5STEP(F3, b, c, d, a, in[14]+0xfde5380c, 23);
MD5STEP(F3, a, b, c, d, in[ 1]+0xa4beea44, 4);
MD5STEP(F3, d, a, b, c, in[ 4]+0x4bdecfa9, 11);
MD5STEP(F3, c, d, a, b, in[ 7]+0xf6bb4b60, 16);
MD5STEP(F3, b, c, d, a, in[10]+0xbebfbc70, 23);
MD5STEP(F3, a, b, c, d, in[13]+0x289b7ec6, 4);
MD5STEP(F3, d, a, b, c, in[ 0]+0xeaa127fa, 11);
MD5STEP(F3, c, d, a, b, in[ 3]+0xd4ef3085, 16);
MD5STEP(F3, b, c, d, a, in[ 6]+0x04881d05, 23);
MD5STEP(F3, a, b, c, d, in[ 9]+0xd9d4d039, 4);
MD5STEP(F3, d, a, b, c, in[12]+0xe6db99e5, 11);
MD5STEP(F3, c, d, a, b, in[15]+0x1fa27cf8, 16);
MD5STEP(F3, b, c, d, a, in[ 2]+0xc4ac5665, 23);
MD5STEP(F4, a, b, c, d, in[ 0]+0xf4292244, 6);
MD5STEP(F4, d, a, b, c, in[ 7]+0x432aff97, 10);
MD5STEP(F4, c, d, a, b, in[14]+0xab9423a7, 15);
MD5STEP(F4, b, c, d, a, in[ 5]+0xfc93a039, 21);
MD5STEP(F4, a, b, c, d, in[12]+0x655b59c3, 6);
MD5STEP(F4, d, a, b, c, in[ 3]+0x8f0ccc92, 10);
MD5STEP(F4, c, d, a, b, in[10]+0xffeff47d, 15);
MD5STEP(F4, b, c, d, a, in[ 1]+0x85845dd1, 21);
MD5STEP(F4, a, b, c, d, in[ 8]+0x6fa87e4f, 6);
MD5STEP(F4, d, a, b, c, in[15]+0xfe2ce6e0, 10);
MD5STEP(F4, c, d, a, b, in[ 6]+0xa3014314, 15);
MD5STEP(F4, b, c, d, a, in[13]+0x4e0811a1, 21);
MD5STEP(F4, a, b, c, d, in[ 4]+0xf7537e82, 6);
MD5STEP(F4, d, a, b, c, in[11]+0xbd3af235, 10);
MD5STEP(F4, c, d, a, b, in[ 2]+0x2ad7d2bb, 15);
MD5STEP(F4, b, c, d, a, in[ 9]+0xeb86d391, 21);
buf[0] += a;
buf[1] += b;
buf[2] += c;
buf[3] += d;
}
#endif
#ifdef TEST
/*
Simple test program. Can use it to manually run the tests from
RFC1321 for example.
*/
#include <stdio.h>
int
main (int argc, char **argv)
{
my_MD5Context context;
unsigned char checksum[16];
int i;
int j;
if (argc < 2)
{
fprintf (stderr, "usage: %s string-to-hash\n", argv[0]);
exit (1);
}
for (j = 1; j < argc; ++j)
{
printf ("MD5 (\"%s\") = ", argv[j]);
my_MD5Init (&context);
my_MD5Update (&context, argv[j], strlen (argv[j]));
my_MD5Final (checksum, &context);
for (i = 0; i < 16; i++)
{
printf ("%02x", (unsigned int) checksum[i]);
}
printf ("\n");
}
return 0;
}
#endif /* TEST */
#endif /* !defined(HAVE_OPENSSL) && !defined(HAVE_YASSL) */

View file

@ -493,7 +493,7 @@ process_flags:
if (my_b_write(info, (uchar*) buff, length2))
goto err;
}
else if ((*fmt == 'l' && fmt[1] == 'd') || fmt[1] == 'u')
else if ((*fmt == 'l' && (fmt[1] == 'd' || fmt[1] == 'u')))
/* long parameter */
{
register long iarg;

View file

@ -147,6 +147,26 @@ static inline void bitmap_unlock(MY_BITMAP *map __attribute__((unused)))
}
static inline uint get_first_set(my_bitmap_map value, uint word_pos)
{
uchar *byte_ptr= (uchar*)&value;
uchar byte_value;
uint byte_pos, bit_pos;
DBUG_ASSERT(value);
for (byte_pos=0; ; byte_pos++, byte_ptr++)
{
if ((byte_value= *byte_ptr))
{
for (bit_pos=0; ; bit_pos++)
if (byte_value & (1 << bit_pos))
return (word_pos*32) + (byte_pos*8) + bit_pos;
}
}
return MY_BIT_NONE; /* Impossible */
}
my_bool bitmap_init(MY_BITMAP *map, my_bitmap_map *buf, uint n_bits,
my_bool thread_safe __attribute__((unused)))
{
@ -597,12 +617,10 @@ void bitmap_copy(MY_BITMAP *map, const MY_BITMAP *map2)
uint bitmap_get_first_set(const MY_BITMAP *map)
{
uchar *byte_ptr;
uint i,j,k;
my_bitmap_map *data_ptr, *end= map->last_word_ptr;
uint i;
my_bitmap_map *data_ptr= map->bitmap, *end= map->last_word_ptr;
DBUG_ASSERT(map->bitmap);
data_ptr= map->bitmap;
for (i=0; data_ptr < end; data_ptr++, i++)
if (*data_ptr)
@ -611,25 +629,66 @@ uint bitmap_get_first_set(const MY_BITMAP *map)
return MY_BIT_NONE;
found:
{
byte_ptr= (uchar*)data_ptr;
for (j=0; ; j++, byte_ptr++)
{
if (*byte_ptr)
{
for (k=0; ; k++)
{
if (*byte_ptr & (1 << k))
return (i*32) + (j*8) + k;
}
}
}
}
DBUG_ASSERT(0);
return MY_BIT_NONE; /* Impossible */
return get_first_set(*data_ptr, i);
}
/**
Get the next set bit.
@param map Bitmap
@param bitmap_bit Bit to start search from
@return Index to first bit set after bitmap_bit
*/
uint bitmap_get_next_set(const MY_BITMAP *map, uint bitmap_bit)
{
uint word_pos, byte_to_mask, i;
union { my_bitmap_map bitmap ; uchar bitmap_buff[sizeof(my_bitmap_map)]; }
first_word;
uchar *ptr= &first_word.bitmap_buff[0];
my_bitmap_map *data_ptr, *end= map->last_word_ptr;
DBUG_ASSERT(map->bitmap);
/* Look for the next bit */
bitmap_bit++;
if (bitmap_bit >= map->n_bits)
return MY_BIT_NONE;
word_pos= bitmap_bit / 32;
data_ptr= map->bitmap + word_pos;
first_word.bitmap= *data_ptr;
/* Mask out previous bits from first_word */
byte_to_mask= (bitmap_bit % 32) / 8;
for (i= 0; i < byte_to_mask; i++)
ptr[i]= 0;
ptr[byte_to_mask]&= 0xFFU << (bitmap_bit & 7);
if (data_ptr == end)
{
if (first_word.bitmap & ~map->last_word_mask)
return get_first_set(first_word.bitmap, word_pos);
else
return MY_BIT_NONE;
}
if (first_word.bitmap)
return get_first_set(first_word.bitmap, word_pos);
for (data_ptr++, word_pos++; data_ptr < end; data_ptr++, word_pos++)
if (*data_ptr)
return get_first_set(*data_ptr, word_pos);
if (!(*end & ~map->last_word_mask))
return MY_BIT_NONE;
return get_first_set(*end, word_pos);
}
/* Get first free bit */
uint bitmap_get_first(const MY_BITMAP *map)
{
uchar *byte_ptr;
@ -647,17 +706,15 @@ uint bitmap_get_first(const MY_BITMAP *map)
return MY_BIT_NONE;
found:
byte_ptr= (uchar*)data_ptr;
for (j=0; ; j++, byte_ptr++)
{
byte_ptr= (uchar*)data_ptr;
for (j=0; ; j++, byte_ptr++)
if (*byte_ptr != 0xFF)
{
if (*byte_ptr != 0xFF)
for (k=0; ; k++)
{
for (k=0; ; k++)
{
if (!(*byte_ptr & (1 << k)))
return (i*32) + (j*8) + k;
}
if (!(*byte_ptr & (1 << k)))
return (i*32) + (j*8) + k;
}
}
}

View file

@ -1,6 +0,0 @@
# CMake generated Testfile for
# Source directory: /my/maria-10.0-merge/mysys_ssl
# Build directory: /my/maria-10.0-merge/mysys_ssl
#
# This file includes the relevent testing commands required for
# testing this directory and lists subdirectories to be tested as well.

View file

@ -1,34 +0,0 @@
# Install script for directory: /my/maria-10.0-merge/mysys_ssl
# Set the install prefix
IF(NOT DEFINED CMAKE_INSTALL_PREFIX)
SET(CMAKE_INSTALL_PREFIX "/usr/local/mysql")
ENDIF(NOT DEFINED CMAKE_INSTALL_PREFIX)
STRING(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}")
# Set the install configuration name.
IF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME)
IF(BUILD_TYPE)
STRING(REGEX REPLACE "^[^A-Za-z0-9_]+" ""
CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}")
ELSE(BUILD_TYPE)
SET(CMAKE_INSTALL_CONFIG_NAME "Debug")
ENDIF(BUILD_TYPE)
MESSAGE(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"")
ENDIF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME)
# Set the component getting installed.
IF(NOT CMAKE_INSTALL_COMPONENT)
IF(COMPONENT)
MESSAGE(STATUS "Install component: \"${COMPONENT}\"")
SET(CMAKE_INSTALL_COMPONENT "${COMPONENT}")
ELSE(COMPONENT)
SET(CMAKE_INSTALL_COMPONENT)
ENDIF(COMPONENT)
ENDIF(NOT CMAKE_INSTALL_COMPONENT)
# Install shared libraries without execute permission?
IF(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE)
SET(CMAKE_INSTALL_SO_NO_EXE "0")
ENDIF(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE)

View file

@ -762,7 +762,7 @@ dbcontext::cmd_find_internal(dbcallback_i& cb, const prep_stmt& pst,
return cb.dbcb_resp_short(2, "idxnum");
}
KEY& kinfo = table->key_info[pst.get_idxnum()];
if (args.kvalslen > kinfo.key_parts) {
if (args.kvalslen > kinfo.user_defined_key_parts) {
return cb.dbcb_resp_short(2, "kpnum");
}
uchar *const key_buf = DENA_ALLOCA_ALLOCATE(uchar, kinfo.key_length);

View file

@ -59,7 +59,8 @@ SET (SQL_SOURCE
sp_rcontext.cc spatial.cc sql_acl.cc sql_analyse.cc sql_base.cc
sql_cache.cc sql_class.cc sql_client.cc sql_crypt.cc sql_crypt.h
sql_cursor.cc sql_db.cc sql_delete.cc sql_derived.cc sql_do.cc
sql_error.cc sql_handler.cc sql_help.cc sql_insert.cc sql_lex.cc
sql_error.cc sql_handler.cc sql_get_diagnostics.cc
sql_help.cc sql_insert.cc sql_lex.cc
sql_list.cc sql_load.cc sql_manager.cc
sql_parse.cc sql_bootstrap.cc sql_bootstrap.h
sql_partition.cc sql_plugin.cc sql_prepare.cc sql_rename.cc

View file

@ -86,7 +86,7 @@ static bool report_wrong_value(THD *thd, const char *name, const char *val,
return 1;
}
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_BAD_OPTION_VALUE,
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_BAD_OPTION_VALUE,
ER(ER_BAD_OPTION_VALUE), val, name);
return 0;
}
@ -109,7 +109,7 @@ static bool report_unknown_option(THD *thd, engine_option_value *val,
DBUG_RETURN(TRUE);
}
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_UNKNOWN_OPTION, ER(ER_UNKNOWN_OPTION), val->name.str);
DBUG_RETURN(FALSE);
}

View file

@ -734,11 +734,6 @@ static st_debug_sync_action *debug_sync_get_action(THD *thd,
static bool debug_sync_set_action(THD *thd, st_debug_sync_action *action)
{
if(!thd)
{
return;
}
st_debug_sync_control *ds_control= thd->debug_sync_control;
bool is_dsp_now= FALSE;
DBUG_ENTER("debug_sync_set_action");
@ -1455,7 +1450,7 @@ static void debug_sync_execute(THD *thd, st_debug_sync_action *action)
sig_wait, sig_glob, error));});
if (error == ETIMEDOUT || error == ETIME)
{
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning(thd, Sql_condition::WARN_LEVEL_WARN,
ER_DEBUG_SYNC_TIMEOUT, ER(ER_DEBUG_SYNC_TIMEOUT));
break;
}

View file

@ -76,7 +76,7 @@ bool init_errmessage(void)
&errmsgs, ER_ERROR_LAST - ER_ERROR_FIRST + 1) &&
!errmsgs)
{
free(errmsgs);
my_free(errmsgs);
if (org_errmsgs)
{
@ -99,7 +99,7 @@ bool init_errmessage(void)
}
}
else
free(org_errmsgs); // Free old language
my_free(org_errmsgs); // Free old language
/* Register messages for use with my_error(). */
if (my_error_register(get_server_errmsgs, ER_ERROR_FIRST, ER_ERROR_LAST))

View file

@ -608,7 +608,7 @@ Event_timed::load_from_row(THD *thd, TABLE *table)
table, &creation_ctx))
{
push_warning_printf(thd,
MYSQL_ERROR::WARN_LEVEL_WARN,
Sql_condition::WARN_LEVEL_WARN,
ER_EVENT_INVALID_CREATION_CTX,
ER(ER_EVENT_INVALID_CREATION_CTX),
(const char *) dbname.str,

View file

@ -687,7 +687,7 @@ Event_db_repository::create_event(THD *thd, Event_parse_data *parse_data,
if (create_if_not)
{
*event_already_exists= true;
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
ER_EVENT_ALREADY_EXISTS, ER(ER_EVENT_ALREADY_EXISTS),
parse_data->name.str);
ret= 0;
@ -912,7 +912,7 @@ Event_db_repository::drop_event(THD *thd, LEX_STRING db, LEX_STRING name,
goto end;
}
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
ER_SP_DOES_NOT_EXIST, ER(ER_SP_DOES_NOT_EXIST),
"Event", name.str);
ret= 0;
@ -958,7 +958,7 @@ Event_db_repository::find_named_event(LEX_STRING db, LEX_STRING name,
if (db.length > table->field[ET_FIELD_DB]->field_length ||
name.length > table->field[ET_FIELD_NAME]->field_length ||
table->s->keys == 0 ||
table->key_info[0].key_parts != 2 ||
table->key_info[0].user_defined_key_parts != 2 ||
table->key_info[0].key_part[0].fieldnr != ET_FIELD_DB+1 ||
table->key_info[0].key_part[1].fieldnr != ET_FIELD_NAME+1)
DBUG_RETURN(TRUE);

View file

@ -126,7 +126,7 @@ Event_parse_data::check_if_in_the_past(THD *thd, my_time_t ltime_utc)
{
switch (thd->lex->sql_command) {
case SQLCOM_CREATE_EVENT:
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
push_warning(thd, Sql_condition::WARN_LEVEL_NOTE,
ER_EVENT_CANNOT_CREATE_IN_THE_PAST,
ER(ER_EVENT_CANNOT_CREATE_IN_THE_PAST));
break;
@ -143,7 +143,7 @@ Event_parse_data::check_if_in_the_past(THD *thd, my_time_t ltime_utc)
{
status= Event_parse_data::DISABLED;
status_changed= true;
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
push_warning(thd, Sql_condition::WARN_LEVEL_NOTE,
ER_EVENT_EXEC_TIME_IN_THE_PAST,
ER(ER_EVENT_EXEC_TIME_IN_THE_PAST));
}

View file

@ -75,9 +75,9 @@ struct scheduler_param {
void
Event_worker_thread::print_warnings(THD *thd, Event_job_data *et)
{
MYSQL_ERROR *err;
const Sql_condition *err;
DBUG_ENTER("evex_print_warnings");
if (thd->warning_info->is_empty())
if (thd->get_stmt_da()->is_warning_info_empty())
DBUG_VOID_RETURN;
char msg_buf[10 * STRING_BUFFER_USUAL_SIZE];
@ -93,7 +93,8 @@ Event_worker_thread::print_warnings(THD *thd, Event_job_data *et)
prefix.append(et->name.str, et->name.length, system_charset_info);
prefix.append("] ", 2);
List_iterator_fast<MYSQL_ERROR> it(thd->warning_info->warn_list());
Diagnostics_area::Sql_condition_iterator it=
thd->get_stmt_da()->sql_conditions();
while ((err= it++))
{
String err_msg(msg_buf, sizeof(msg_buf), system_charset_info);

View file

@ -1076,7 +1076,7 @@ static void push_numerical_conversion_warning(THD* thd, const char* str,
String tmp(buf, sizeof(buf), cs);
tmp.copy(str, length, cs);
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
error, ER(error), typestr, tmp.c_ptr(),
field_name, row_num);
}
@ -1190,17 +1190,18 @@ int Field_num::check_int(CHARSET_INFO *cs, const char *str, int length,
if (str == int_end || error == MY_ERRNO_EDOM)
{
ErrConvString err(str, length, cs);
push_warning_printf(get_thd(), MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(get_thd(), Sql_condition::WARN_LEVEL_WARN,
ER_TRUNCATED_WRONG_VALUE_FOR_FIELD,
ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD),
"integer", err.ptr(), field_name,
(ulong) get_thd()->warning_info->current_row_for_warning());
(ulong) table->in_use->get_stmt_da()->
current_row_for_warning());
return 1;
}
/* Test if we have garbage at the end of the given string. */
if (test_if_important_data(cs, int_end, str + length))
{
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
set_warning(Sql_condition::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
return 2;
}
return 0;
@ -1269,7 +1270,7 @@ bool Field_num::get_int(CHARSET_INFO *cs, const char *from, uint len,
return 0;
out_of_range:
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
return 1;
}
@ -1289,12 +1290,12 @@ int Field::warn_if_overflow(int op_result)
{
if (op_result == E_DEC_OVERFLOW)
{
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
return 1;
}
if (op_result == E_DEC_TRUNCATED)
{
set_warning(MYSQL_ERROR::WARN_LEVEL_NOTE, WARN_DATA_TRUNCATED, 1);
set_warning(Sql_condition::WARN_LEVEL_NOTE, WARN_DATA_TRUNCATED, 1);
/* We return 0 here as this is not a critical issue */
}
return 0;
@ -1618,7 +1619,7 @@ longlong Field::convert_decimal2longlong(const my_decimal *val,
{
if (val->sign())
{
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
i= 0;
*err= 1;
}
@ -1926,7 +1927,7 @@ void Field_decimal::overflow(bool negative)
uint len=field_length;
uchar *to=ptr, filler= '9';
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
if (negative)
{
if (!unsigned_flag)
@ -2034,7 +2035,7 @@ int Field_decimal::store(const char *from_arg, uint len, CHARSET_INFO *cs)
from++;
if (from == end)
{
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
set_warning(Sql_condition::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
is_cuted_fields_incr=1;
}
else if (*from == '+' || *from == '-') // Found some sign ?
@ -2110,7 +2111,7 @@ int Field_decimal::store(const char *from_arg, uint len, CHARSET_INFO *cs)
for (;from != end && my_isspace(&my_charset_bin, *from); from++) ;
if (from != end) // If still something left, warn
{
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
set_warning(Sql_condition::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
is_cuted_fields_incr=1;
}
}
@ -2288,7 +2289,7 @@ int Field_decimal::store(const char *from_arg, uint len, CHARSET_INFO *cs)
if (tmp_char != '0') // Losing a non zero digit ?
{
if (!is_cuted_fields_incr)
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
set_warning(Sql_condition::WARN_LEVEL_WARN,
WARN_DATA_TRUNCATED, 1);
return 0;
}
@ -2311,7 +2312,7 @@ int Field_decimal::store(const char *from_arg, uint len, CHARSET_INFO *cs)
This is a note, not a warning, as we don't want to abort
when we cut decimals in strict mode
*/
set_warning(MYSQL_ERROR::WARN_LEVEL_NOTE, WARN_DATA_TRUNCATED, 1);
set_warning(Sql_condition::WARN_LEVEL_NOTE, WARN_DATA_TRUNCATED, 1);
}
return 0;
}
@ -2661,7 +2662,7 @@ bool Field_new_decimal::store_value(const my_decimal *decimal_value)
if (unsigned_flag && decimal_value->sign())
{
DBUG_PRINT("info", ("unsigned overflow"));
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
decimal_value= &decimal_zero;
}
@ -2705,32 +2706,32 @@ int Field_new_decimal::store(const char *from, uint length,
thd->abort_on_warning)
{
ErrConvString errmsg(from, length, &my_charset_bin);
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_TRUNCATED_WRONG_VALUE_FOR_FIELD,
ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD),
"decimal", errmsg.ptr(), field_name,
(ulong) thd->warning_info->current_row_for_warning());
static_cast<ulong>(thd->get_stmt_da()->
current_row_for_warning()));
DBUG_RETURN(err);
}
switch (err) {
case E_DEC_TRUNCATED:
set_warning(MYSQL_ERROR::WARN_LEVEL_NOTE, WARN_DATA_TRUNCATED, 1);
set_warning(Sql_condition::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
break;
case E_DEC_OVERFLOW:
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
set_value_on_overflow(&decimal_value, decimal_value.sign());
break;
case E_DEC_BAD_NUM:
{
ErrConvString errmsg(from, length, &my_charset_bin);
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_TRUNCATED_WRONG_VALUE_FOR_FIELD,
ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD),
"decimal", errmsg.ptr(), field_name,
(ulong) thd->warning_info->
current_row_for_warning());
static_cast<ulong>(thd->get_stmt_da()->
current_row_for_warning()));
my_decimal_set_zero(&decimal_value);
break;
}
@ -3037,13 +3038,13 @@ int Field_tiny::store(double nr)
if (nr < 0.0)
{
*ptr=0;
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else if (nr > 255.0)
{
*ptr= (uchar) 255;
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else
@ -3054,13 +3055,13 @@ int Field_tiny::store(double nr)
if (nr < -128.0)
{
*ptr= (uchar) -128;
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else if (nr > 127.0)
{
*ptr=127;
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else
@ -3080,13 +3081,13 @@ int Field_tiny::store(longlong nr, bool unsigned_val)
if (nr < 0 && !unsigned_val)
{
*ptr= 0;
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else if ((ulonglong) nr > (ulonglong) 255)
{
*ptr= (char) 255;
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else
@ -3099,13 +3100,13 @@ int Field_tiny::store(longlong nr, bool unsigned_val)
if (nr < -128)
{
*ptr= (char) -128;
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else if (nr > 127)
{
*ptr=127;
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else
@ -3216,13 +3217,13 @@ int Field_short::store(double nr)
if (nr < 0)
{
res=0;
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else if (nr > (double) UINT_MAX16)
{
res=(int16) UINT_MAX16;
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else
@ -3233,13 +3234,13 @@ int Field_short::store(double nr)
if (nr < (double) INT_MIN16)
{
res=INT_MIN16;
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else if (nr > (double) INT_MAX16)
{
res=INT_MAX16;
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else
@ -3261,13 +3262,13 @@ int Field_short::store(longlong nr, bool unsigned_val)
if (nr < 0L && !unsigned_val)
{
res=0;
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else if ((ulonglong) nr > (ulonglong) UINT_MAX16)
{
res=(int16) UINT_MAX16;
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else
@ -3281,13 +3282,13 @@ int Field_short::store(longlong nr, bool unsigned_val)
if (nr < INT_MIN16)
{
res=INT_MIN16;
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else if (nr > (longlong) INT_MAX16)
{
res=INT_MAX16;
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else
@ -3404,14 +3405,14 @@ int Field_medium::store(double nr)
if (nr < 0)
{
int3store(ptr,0);
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else if (nr >= (double) (long) (1L << 24))
{
uint32 tmp=(uint32) (1L << 24)-1L;
int3store(ptr,tmp);
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else
@ -3423,14 +3424,14 @@ int Field_medium::store(double nr)
{
long tmp=(long) INT_MIN24;
int3store(ptr,tmp);
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else if (nr > (double) INT_MAX24)
{
long tmp=(long) INT_MAX24;
int3store(ptr,tmp);
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else
@ -3450,14 +3451,14 @@ int Field_medium::store(longlong nr, bool unsigned_val)
if (nr < 0 && !unsigned_val)
{
int3store(ptr,0);
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else if ((ulonglong) nr >= (ulonglong) (long) (1L << 24))
{
long tmp= (long) (1L << 24)-1L;
int3store(ptr,tmp);
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else
@ -3472,14 +3473,14 @@ int Field_medium::store(longlong nr, bool unsigned_val)
{
long tmp= (long) INT_MIN24;
int3store(ptr,tmp);
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else if (nr > (longlong) INT_MAX24)
{
long tmp=(long) INT_MAX24;
int3store(ptr,tmp);
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else
@ -3601,7 +3602,7 @@ int Field_long::store(double nr)
else if (nr > (double) UINT_MAX32)
{
res= UINT_MAX32;
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else
@ -3623,7 +3624,7 @@ int Field_long::store(double nr)
res=(int32) (longlong) nr;
}
if (error)
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
int4store(ptr,res);
return error;
@ -3669,7 +3670,7 @@ int Field_long::store(longlong nr, bool unsigned_val)
res=(int32) nr;
}
if (error)
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
int4store(ptr,res);
return error;
@ -3768,7 +3769,7 @@ int Field_longlong::store(const char *from,uint len,CHARSET_INFO *cs)
tmp= cs->cset->strntoull10rnd(cs,from,len,unsigned_flag,&end,&error);
if (error == MY_ERRNO_ERANGE)
{
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else if (get_thd()->count_cuted_fields &&
@ -3790,7 +3791,7 @@ int Field_longlong::store(double nr)
res= double_to_longlong(nr, unsigned_flag, &error);
if (error)
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
int8store(ptr,res);
return error;
@ -3811,7 +3812,7 @@ int Field_longlong::store(longlong nr, bool unsigned_val)
if (unsigned_flag != unsigned_val)
{
nr= unsigned_flag ? (ulonglong) 0 : (ulonglong) LONGLONG_MAX;
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
}
@ -3925,7 +3926,7 @@ int Field_float::store(const char *from,uint len,CHARSET_INFO *cs)
if (error || (!len || ((uint) (end-from) != len &&
get_thd()->count_cuted_fields)))
{
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
set_warning(Sql_condition::WARN_LEVEL_WARN,
(error ? ER_WARN_DATA_OUT_OF_RANGE : WARN_DATA_TRUNCATED), 1);
error= error ? 1 : 2;
}
@ -3942,7 +3943,7 @@ int Field_float::store(double nr)
unsigned_flag, FLT_MAX);
if (error)
{
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
if (error < 0) // Wrong double value
{
error= 1;
@ -4113,7 +4114,7 @@ int Field_double::store(const char *from,uint len,CHARSET_INFO *cs)
if (error || (!len || ((uint) (end-from) != len &&
get_thd()->count_cuted_fields)))
{
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
set_warning(Sql_condition::WARN_LEVEL_WARN,
(error ? ER_WARN_DATA_OUT_OF_RANGE : WARN_DATA_TRUNCATED), 1);
error= error ? 1 : 2;
}
@ -4130,7 +4131,7 @@ int Field_double::store(double nr)
unsigned_flag, DBL_MAX);
if (error)
{
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
if (error < 0) // Wrong double value
{
error= 1;
@ -4295,7 +4296,7 @@ longlong Field_double::val_int(void)
if (error)
{
ErrConvDouble err(j);
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
ER_TRUNCATED_WRONG_VALUE,
ER(ER_TRUNCATED_WRONG_VALUE), "INTEGER",
err.ptr());
@ -4492,7 +4493,7 @@ int Field_timestamp::store_TIME_with_warning(THD *thd, MYSQL_TIME *l_time,
if (was_cut || !have_smth_to_conv)
{
error= 1;
set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED,
set_datetime_warning(Sql_condition::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED,
str, MYSQL_TIMESTAMP_DATETIME, 1);
}
/* Only convert a correct date (not a zero date) */
@ -4504,7 +4505,7 @@ int Field_timestamp::store_TIME_with_warning(THD *thd, MYSQL_TIME *l_time,
conversion_error= ER_WARN_DATA_OUT_OF_RANGE;
if (conversion_error)
{
set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN, conversion_error,
set_datetime_warning(Sql_condition::WARN_LEVEL_WARN, conversion_error,
str, MYSQL_TIMESTAMP_DATETIME, !error);
error= 1;
}
@ -4968,7 +4969,7 @@ int Field_temporal::store_TIME_with_warning(MYSQL_TIME *ltime,
const ErrConv *str,
int was_cut, int have_smth_to_conv)
{
MYSQL_ERROR::enum_warning_level trunc_level= MYSQL_ERROR::WARN_LEVEL_WARN;
Sql_condition::enum_warning_level trunc_level= Sql_condition::WARN_LEVEL_WARN;
int ret= 2;
ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
@ -4988,7 +4989,7 @@ int Field_temporal::store_TIME_with_warning(MYSQL_TIME *ltime,
mysql_type_to_time_type(type()) == MYSQL_TIMESTAMP_DATE &&
(ltime->hour || ltime->minute || ltime->second || ltime->second_part))
{
trunc_level= MYSQL_ERROR::WARN_LEVEL_NOTE;
trunc_level= Sql_condition::WARN_LEVEL_NOTE;
was_cut|= MYSQL_TIME_WARN_TRUNCATED;
ret= 3;
}
@ -4997,7 +4998,7 @@ int Field_temporal::store_TIME_with_warning(MYSQL_TIME *ltime,
(ltime->year || ltime->month))
{
ltime->year= ltime->month= ltime->day= 0;
trunc_level= MYSQL_ERROR::WARN_LEVEL_NOTE;
trunc_level= Sql_condition::WARN_LEVEL_NOTE;
was_cut|= MYSQL_TIME_WARN_TRUNCATED;
ret= 3;
}
@ -5016,7 +5017,7 @@ int Field_temporal::store_TIME_with_warning(MYSQL_TIME *ltime,
set_datetime_warning(trunc_level, WARN_DATA_TRUNCATED,
str, mysql_type_to_time_type(type()), 1);
if (was_cut & MYSQL_TIME_WARN_OUT_OF_RANGE)
set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE,
set_datetime_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE,
str, mysql_type_to_time_type(type()), 1);
store_TIME(ltime);
@ -5237,10 +5238,10 @@ bool Field_time::get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
THD *thd= get_thd();
if (!(fuzzydate & (TIME_FUZZY_DATE|TIME_TIME_ONLY)))
{
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_WARN_DATA_OUT_OF_RANGE,
ER(ER_WARN_DATA_OUT_OF_RANGE), field_name,
thd->warning_info->current_row_for_warning());
thd->get_stmt_da()->current_row_for_warning());
return 1;
}
long tmp=(long) sint3korr(ptr);
@ -5421,7 +5422,7 @@ int Field_year::store(const char *from, uint len,CHARSET_INFO *cs)
error == MY_ERRNO_ERANGE)
{
*ptr=0;
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
return 1;
}
if (get_thd()->count_cuted_fields &&
@ -5464,7 +5465,7 @@ int Field_year::store(longlong nr, bool unsigned_val)
if (nr < 0 || (nr >= 100 && nr <= 1900) || nr > 2155)
{
*ptr= 0;
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
return 1;
}
if (nr != 0 || field_length != 4) // 0000 -> 0; 00 -> 2000
@ -5485,7 +5486,7 @@ int Field_year::store_time_dec(MYSQL_TIME *ltime, uint dec)
if (Field_year::store(ltime->year, 0))
return 1;
set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED,
set_datetime_warning(Sql_condition::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED,
&str, ltime->time_type, 1);
return 0;
}
@ -6046,11 +6047,11 @@ check_string_copy_error(Field_str *field,
convert_to_printable(tmp, sizeof(tmp), pos, (end - pos), cs, 6);
push_warning_printf(thd,
MYSQL_ERROR::WARN_LEVEL_WARN,
Sql_condition::WARN_LEVEL_WARN,
ER_TRUNCATED_WRONG_VALUE_FOR_FIELD,
ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD),
"string", tmp, field->field_name,
thd->warning_info->current_row_for_warning());
thd->get_stmt_da()->current_row_for_warning());
return TRUE;
}
@ -6085,14 +6086,14 @@ Field_longstr::report_if_important_data(const char *pstr, const char *end,
if (test_if_important_data(field_charset, pstr, end))
{
if (thd->abort_on_warning)
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_DATA_TOO_LONG, 1);
set_warning(Sql_condition::WARN_LEVEL_WARN, ER_DATA_TOO_LONG, 1);
else
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
set_warning(Sql_condition::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
return 2;
}
else if (count_spaces)
{ /* If we lost only spaces then produce a NOTE, not a WARNING */
set_warning(MYSQL_ERROR::WARN_LEVEL_NOTE, WARN_DATA_TRUNCATED, 1);
set_warning(Sql_condition::WARN_LEVEL_NOTE, WARN_DATA_TRUNCATED, 1);
return 2;
}
}
@ -6158,9 +6159,9 @@ int Field_str::store(double nr)
if (error)
{
if (get_thd()->abort_on_warning)
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_DATA_TOO_LONG, 1);
set_warning(Sql_condition::WARN_LEVEL_WARN, ER_DATA_TOO_LONG, 1);
else
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
set_warning(Sql_condition::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
}
return store(buff, length, &my_charset_numeric);
}
@ -6223,7 +6224,7 @@ double Field_string::val_real(void)
(char*) ptr + field_length))))
{
ErrConvString err((char*) ptr, field_length, cs);
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
ER_TRUNCATED_WRONG_VALUE,
ER(ER_TRUNCATED_WRONG_VALUE), "DOUBLE",
err.ptr());
@ -6247,7 +6248,7 @@ longlong Field_string::val_int(void)
(char*) ptr + field_length))))
{
ErrConvString err((char*) ptr, field_length, cs);
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
ER_TRUNCATED_WRONG_VALUE,
ER(ER_TRUNCATED_WRONG_VALUE),
"INTEGER", err.ptr());
@ -6283,7 +6284,7 @@ my_decimal *Field_string::val_decimal(my_decimal *decimal_value)
if (!get_thd()->no_errors && err)
{
ErrConvString errmsg((char*) ptr, field_length, charset());
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
ER_TRUNCATED_WRONG_VALUE,
ER(ER_TRUNCATED_WRONG_VALUE),
"DECIMAL", errmsg.ptr());
@ -7695,13 +7696,13 @@ int Field_enum::store(const char *from,uint length,CHARSET_INFO *cs)
if (err || end != from+length || tmp > typelib->count)
{
tmp=0;
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
set_warning(Sql_condition::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
}
if (!get_thd()->count_cuted_fields)
err= 0;
}
else
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
set_warning(Sql_condition::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
}
store_type((ulonglong) tmp);
return err;
@ -7720,7 +7721,7 @@ int Field_enum::store(longlong nr, bool unsigned_val)
int error= 0;
if ((ulonglong) nr > typelib->count || nr == 0)
{
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
set_warning(Sql_condition::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
if (nr != 0 || get_thd()->count_cuted_fields)
{
nr= 0;
@ -7874,11 +7875,11 @@ int Field_set::store(const char *from,uint length,CHARSET_INFO *cs)
tmp > (ulonglong) (((longlong) 1 << typelib->count) - (longlong) 1))
{
tmp=0;
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
set_warning(Sql_condition::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
}
}
else if (got_warning)
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
set_warning(Sql_condition::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
store_type(tmp);
return err;
}
@ -7898,7 +7899,7 @@ int Field_set::store(longlong nr, bool unsigned_val)
if ((ulonglong) nr > max_nr)
{
nr&= max_nr;
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
set_warning(Sql_condition::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
error=1;
}
store_type((ulonglong) nr);
@ -8252,9 +8253,9 @@ int Field_bit::store(const char *from, uint length, CHARSET_INFO *cs)
set_rec_bits((1 << bit_len) - 1, bit_ptr, bit_ofs, bit_len);
memset(ptr, 0xff, bytes_in_rec);
if (get_thd()->really_abort_on_warning())
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_DATA_TOO_LONG, 1);
set_warning(Sql_condition::WARN_LEVEL_WARN, ER_DATA_TOO_LONG, 1);
else
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
return 1;
}
/* delta is >= -1 here */
@ -8689,9 +8690,9 @@ int Field_bit_as_char::store(const char *from, uint length, CHARSET_INFO *cs)
if (bits)
*ptr&= ((1 << bits) - 1); /* set first uchar */
if (get_thd()->really_abort_on_warning())
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_DATA_TOO_LONG, 1);
set_warning(Sql_condition::WARN_LEVEL_WARN, ER_DATA_TOO_LONG, 1);
else
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
return 1;
}
bzero(ptr, delta);
@ -9092,7 +9093,7 @@ bool Create_field::init(THD *thd, char *fld_name, enum_field_types fld_type,
/*
Otherwise a default of '' is just a warning.
*/
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_BLOB_CANT_HAVE_DEFAULT,
ER(ER_BLOB_CANT_HAVE_DEFAULT),
fld_name);
@ -9610,7 +9611,7 @@ Create_field::Create_field(Field *old_field,Field *orig_field)
{
char buff[sizeof("YEAR()") + MY_INT64_NUM_DECIMAL_DIGITS + 1];
my_snprintf(buff, sizeof(buff), "YEAR(%lu)", length);
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_NOTE,
ER_WARN_DEPRECATED_SYNTAX,
ER(ER_WARN_DEPRECATED_SYNTAX),
buff, "YEAR(4)");
@ -9738,11 +9739,11 @@ uint32 Field_blob::max_display_length()
*****************************************************************************/
/**
Produce warning or note about data saved into field.
* Produce warning or note about data saved into field.
@param level - level of message (Note/Warning/Error)
@param code - error code of message to be produced
@param cuted_increment - whenever we should increase cut fields count or not
@param cut_increment - whenever we should increase cut fields count
@note
This function won't produce warning and increase cut fields counter
@ -9750,11 +9751,16 @@ uint32 Field_blob::max_display_length()
if count_cuted_fields == CHECK_FIELD_IGNORE then we ignore notes.
This allows us to avoid notes in optimisation, like convert_constant_item().
@retval
1 if count_cuted_fields == CHECK_FIELD_IGNORE and error level is not NOTE
@retval
0 otherwise
*/
void
Field::set_warning(MYSQL_ERROR::enum_warning_level level, uint code,
int cuted_increment)
bool
Field::set_warning(Sql_condition::enum_warning_level level, uint code,
int cut_increment) const
{
/*
If this field was created only for type conversion purposes it
@ -9763,10 +9769,12 @@ Field::set_warning(MYSQL_ERROR::enum_warning_level level, uint code,
THD *thd= table ? table->in_use : current_thd;
if (thd->count_cuted_fields)
{
thd->cuted_fields+= cuted_increment;
thd->cuted_fields+= cut_increment;
push_warning_printf(thd, level, code, ER(code), field_name,
thd->warning_info->current_row_for_warning());
thd->get_stmt_da()->current_row_for_warning());
return 0;
}
return level >= Sql_condition::WARN_LEVEL_WARN;
}
@ -9788,12 +9796,12 @@ Field::set_warning(MYSQL_ERROR::enum_warning_level level, uint code,
*/
void Field::set_datetime_warning(MYSQL_ERROR::enum_warning_level level,
void Field::set_datetime_warning(Sql_condition::enum_warning_level level,
uint code, const ErrConv *str,
timestamp_type ts_type, int cuted_increment)
{
THD *thd= get_thd();
if (thd->really_abort_on_warning() && level >= MYSQL_ERROR::WARN_LEVEL_WARN)
if (thd->really_abort_on_warning() && level >= Sql_condition::WARN_LEVEL_WARN)
make_truncated_value_warning(thd, level, str, ts_type, field_name);
else
set_warning(level, code, cuted_increment);

View file

@ -668,9 +668,9 @@ public:
virtual uint repertoire(void) const { return MY_REPERTOIRE_UNICODE30; }
virtual void set_derivation(enum Derivation derivation_arg) { }
virtual int set_time() { return 1; }
void set_warning(MYSQL_ERROR::enum_warning_level, unsigned int code,
int cuted_increment);
void set_datetime_warning(MYSQL_ERROR::enum_warning_level, uint code,
bool set_warning(Sql_condition::enum_warning_level, unsigned int code,
int cuted_increment) const;
void set_datetime_warning(Sql_condition::enum_warning_level, uint code,
const ErrConv *str, timestamp_type ts_type,
int cuted_increment);
inline bool check_overflow(int op_result)
@ -715,6 +715,30 @@ public:
return GEOM_GEOMETRY;
}
ha_storage_media field_storage_type() const
{
return (ha_storage_media)
((flags >> FIELD_FLAGS_STORAGE_MEDIA) & 3);
}
void set_storage_type(ha_storage_media storage_type_arg)
{
DBUG_ASSERT(field_storage_type() == HA_SM_DEFAULT);
flags |= (storage_type_arg << FIELD_FLAGS_STORAGE_MEDIA);
}
column_format_type column_format() const
{
return (column_format_type)
((flags >> FIELD_FLAGS_COLUMN_FORMAT) & 3);
}
void set_column_format(column_format_type column_format_arg)
{
DBUG_ASSERT(column_format() == COLUMN_FORMAT_TYPE_DEFAULT);
flags |= (column_format_arg << FIELD_FLAGS_COLUMN_FORMAT);
}
key_map get_possible_keys();
/* Hash value */
@ -2405,6 +2429,7 @@ public:
uint8 row,col,sc_length,interval_id; // For rea_create_table
uint offset,pack_flag;
bool create_if_not_exists; // Used in ALTER TABLE IF NOT EXISTS
/*
This is additinal data provided for any computed(virtual) field.
@ -2419,7 +2444,8 @@ public:
*/
bool stored_in_db;
Create_field() :after(0), option_list(NULL), option_struct(NULL)
Create_field() :after(0), option_list(NULL), option_struct(NULL),
create_if_not_exists(FALSE)
{}
Create_field(Field *field, Field *orig_field);
/* Used to make a clone of this object for ALTER/CREATE TABLE */
@ -2443,10 +2469,24 @@ public:
{
return (flags & (BINCMP_FLAG | BINARY_FLAG)) != 0;
}
ha_storage_media field_storage_type() const
{
return (ha_storage_media)
((flags >> FIELD_FLAGS_STORAGE_MEDIA) & 3);
}
column_format_type column_format() const
{
return (column_format_type)
((flags >> FIELD_FLAGS_COLUMN_FORMAT) & 3);
}
uint virtual_col_expr_maxlen()
{
return 255 - FRM_VCOL_HEADER_SIZE(interval != NULL);
}
private:
const String empty_set_string;
};

View file

@ -133,7 +133,7 @@ set_field_to_null(Field *field)
field->reset();
switch (field->table->in_use->count_cuted_fields) {
case CHECK_FIELD_WARN:
field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
field->set_warning(Sql_condition::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
/* fall through */
case CHECK_FIELD_IGNORE:
return 0;
@ -202,7 +202,7 @@ set_field_to_null_with_conversions(Field *field, bool no_conversions)
}
switch (field->table->in_use->count_cuted_fields) {
case CHECK_FIELD_WARN:
field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_BAD_NULL_ERROR, 1);
field->set_warning(Sql_condition::WARN_LEVEL_WARN, ER_BAD_NULL_ERROR, 1);
/* fall through */
case CHECK_FIELD_IGNORE:
return 0;
@ -272,7 +272,7 @@ static void do_copy_nullable_row_to_notnull(Copy_field *copy)
if (*copy->null_row ||
(copy->from_null_ptr && (*copy->from_null_ptr & copy->from_bit)))
{
copy->to_field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
copy->to_field->set_warning(Sql_condition::WARN_LEVEL_WARN,
WARN_DATA_TRUNCATED, 1);
copy->to_field->reset();
}
@ -288,7 +288,7 @@ static void do_copy_not_null(Copy_field *copy)
{
if (*copy->from_null_ptr & copy->from_bit)
{
copy->to_field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
copy->to_field->set_warning(Sql_condition::WARN_LEVEL_WARN,
WARN_DATA_TRUNCATED, 1);
copy->to_field->reset();
}
@ -440,7 +440,7 @@ static void do_cut_string(Copy_field *copy)
(char*) copy->from_ptr + copy->from_length,
MY_SEQ_SPACES) < copy->from_length - copy->to_length)
{
copy->to_field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
copy->to_field->set_warning(Sql_condition::WARN_LEVEL_WARN,
WARN_DATA_TRUNCATED, 1);
}
}
@ -471,7 +471,7 @@ static void do_cut_string_complex(Copy_field *copy)
(char*) from_end,
MY_SEQ_SPACES) < (copy->from_length - copy_length))
{
copy->to_field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
copy->to_field->set_warning(Sql_condition::WARN_LEVEL_WARN,
WARN_DATA_TRUNCATED, 1);
}
@ -510,7 +510,7 @@ static void do_varstring1(Copy_field *copy)
length=copy->to_length - 1;
if (copy->from_field->table->in_use->count_cuted_fields &&
copy->to_field)
copy->to_field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
copy->to_field->set_warning(Sql_condition::WARN_LEVEL_WARN,
WARN_DATA_TRUNCATED, 1);
}
*(uchar*) copy->to_ptr= (uchar) length;
@ -531,7 +531,7 @@ static void do_varstring1_mb(Copy_field *copy)
if (length < from_length)
{
if (current_thd->count_cuted_fields)
copy->to_field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
copy->to_field->set_warning(Sql_condition::WARN_LEVEL_WARN,
WARN_DATA_TRUNCATED, 1);
}
*copy->to_ptr= (uchar) length;
@ -547,7 +547,7 @@ static void do_varstring2(Copy_field *copy)
length=copy->to_length-HA_KEY_BLOB_LENGTH;
if (copy->from_field->table->in_use->count_cuted_fields &&
copy->to_field)
copy->to_field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
copy->to_field->set_warning(Sql_condition::WARN_LEVEL_WARN,
WARN_DATA_TRUNCATED, 1);
}
int2store(copy->to_ptr,length);
@ -569,7 +569,7 @@ static void do_varstring2_mb(Copy_field *copy)
if (length < from_length)
{
if (current_thd->count_cuted_fields)
copy->to_field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
copy->to_field->set_warning(Sql_condition::WARN_LEVEL_WARN,
WARN_DATA_TRUNCATED, 1);
}
int2store(copy->to_ptr, length);

View file

@ -391,7 +391,8 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length,
MYF(0),
ER_THD(thd, ER_FILSORT_ABORT),
kill_errno ? ER(kill_errno) :
thd->killed == ABORT_QUERY ? "" : thd->stmt_da->message());
thd->killed == ABORT_QUERY ? "" :
thd->get_stmt_da()->message());
if (global_system_variables.log_warnings > 1)
{

View file

@ -379,11 +379,11 @@ static int ndb_to_mysql_error(const NdbError *ndberr)
- Used by replication to see if the error was temporary
*/
if (ndberr->status == NdbError::TemporaryError)
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
ER_GET_TEMPORARY_ERRMSG, ER(ER_GET_TEMPORARY_ERRMSG),
ndberr->code, ndberr->message, "NDB");
else
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
ER_GET_ERRMSG, ER(ER_GET_ERRMSG),
ndberr->code, ndberr->message, "NDB");
return error;
@ -650,7 +650,7 @@ static void set_ndb_err(THD *thd, const NdbError &err)
{
char buf[FN_REFLEN];
ndb_error_string(thd_ndb->m_error_code, buf, sizeof(buf));
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_GET_ERRMSG, ER(ER_GET_ERRMSG),
thd_ndb->m_error_code, buf, "NDB");
}
@ -3206,7 +3206,7 @@ int ha_ndbcluster::update_row(const uchar *old_data, uchar *new_data)
undo_res= write_row((uchar *)old_data);
if (undo_res)
push_warning(current_thd,
MYSQL_ERROR::WARN_LEVEL_WARN,
Sql_condition::WARN_LEVEL_WARN,
undo_res,
"NDB failed undoing delete at primary key update");
m_primary_key_update= FALSE;
@ -5416,7 +5416,7 @@ int ha_ndbcluster::create(const char *name,
{
if (create_info->storage_media == HA_SM_MEMORY)
{
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
ER(ER_ILLEGAL_HA_CREATE_OPTION),
ndbcluster_hton_name,
@ -5471,7 +5471,7 @@ int ha_ndbcluster::create(const char *name,
case ROW_TYPE_FIXED:
if (field_type_forces_var_part(field->type()))
{
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
ER(ER_ILLEGAL_HA_CREATE_OPTION),
ndbcluster_hton_name,
@ -5802,7 +5802,7 @@ int ha_ndbcluster::create_index(const char *name, KEY *key_info,
case UNIQUE_INDEX:
if (check_index_fields_not_null(key_info))
{
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
ER_NULL_COLUMN_IN_INDEX,
"Ndb does not support unique index on NULL valued attributes, index access with NULL value will become full table scan");
}
@ -5811,7 +5811,7 @@ int ha_ndbcluster::create_index(const char *name, KEY *key_info,
case ORDERED_INDEX:
if (key_info->algorithm == HA_KEY_ALG_HASH)
{
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
ER(ER_ILLEGAL_HA_CREATE_OPTION),
ndbcluster_hton_name,
@ -7284,7 +7284,7 @@ int ndbcluster_find_files(handlerton *hton, THD *thd,
file_name->str));
if (ndb_create_table_from_engine(thd, db, file_name->str))
{
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
ER_TABLE_EXISTS_ERROR,
"Discover of table %s.%s failed",
db, file_name->str);
@ -7310,7 +7310,7 @@ int ndbcluster_find_files(handlerton *hton, THD *thd,
file_name->length);
DBUG_ASSERT(record);
my_hash_delete(&ndb_tables, record);
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
ER_TABLE_EXISTS_ERROR,
"Local table %s.%s shadows ndb table",
db, file_name->str);
@ -9827,11 +9827,11 @@ char* ha_ndbcluster::get_tablespace_name(THD *thd, char* name, uint name_len)
}
err:
if (ndberr.status == NdbError::TemporaryError)
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_GET_TEMPORARY_ERRMSG, ER(ER_GET_TEMPORARY_ERRMSG),
ndberr.code, ndberr.message, "NDB");
else
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_GET_ERRMSG, ER(ER_GET_ERRMSG),
ndberr.code, ndberr.message, "NDB");
return 0;
@ -9957,7 +9957,7 @@ int ha_ndbcluster::get_default_no_partitions(HA_CREATE_INFO *create_info)
if (adjusted_frag_count(no_fragments, no_nodes, reported_frags))
{
push_warning(current_thd,
MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
Sql_condition::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
"Ndb might have problems storing the max amount of rows specified");
}
return (int)reported_frags;
@ -10146,7 +10146,7 @@ uint ha_ndbcluster::set_up_partition_info(partition_info *part_info,
{
if (!current_thd->variables.new_mode)
{
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
ER(ER_ILLEGAL_HA_CREATE_OPTION),
ndbcluster_hton_name,

View file

@ -290,13 +290,13 @@ static void run_query(THD *thd, char *buf, char *end,
Thd_ndb *thd_ndb= get_thd_ndb(thd);
for (i= 0; no_print_error[i]; i++)
if ((thd_ndb->m_error_code == no_print_error[i]) ||
(thd->stmt_da->sql_errno() == (unsigned) no_print_error[i]))
(thd->get_stmt_da()->sql_errno() == (unsigned) no_print_error[i]))
break;
if (!no_print_error[i])
sql_print_error("NDB: %s: error %s %d(ndb: %d) %d %d",
buf,
thd->stmt_da->message(),
thd->stmt_da->sql_errno(),
thd->get_stmt_da()->message(),
thd->get_stmt_da()->sql_errno(),
thd_ndb->m_error_code,
(int) thd->is_error(), thd->is_slave_error);
}
@ -310,7 +310,7 @@ static void run_query(THD *thd, char *buf, char *end,
is called from ndbcluster_reset_logs(), which is called from
mysql_flush().
*/
thd->stmt_da->reset_diagnostics_area();
thd->get_stmt_da()->reset_diagnostics_area();
thd->variables.option_bits= save_thd_options;
thd->set_query(save_thd_query, save_thd_query_length);
@ -984,8 +984,8 @@ static void print_could_not_discover_error(THD *thd,
"my_errno: %d",
schema->db, schema->name, schema->query,
schema->node_id, my_errno);
List_iterator_fast<MYSQL_ERROR> it(thd->warning_info->warn_list());
MYSQL_ERROR *err;
List_iterator_fast<Sql_condition> it(thd->warning_info->warn_list());
Sql_condition *err;
while ((err= it++))
sql_print_warning("NDB Binlog: (%d)%s", err->get_sql_errno(),
err->get_message_text());
@ -1230,7 +1230,7 @@ ndbcluster_update_slock(THD *thd,
char buf[1024];
my_snprintf(buf, sizeof(buf), "Could not release lock on '%s.%s'",
db, table_name);
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_GET_ERRMSG, ER(ER_GET_ERRMSG),
ndb_error->code, ndb_error->message, buf);
}
@ -1559,7 +1559,7 @@ err:
}
end:
if (ndb_error)
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_GET_ERRMSG, ER(ER_GET_ERRMSG),
ndb_error->code,
ndb_error->message,
@ -2349,8 +2349,8 @@ static int open_ndb_binlog_index(THD *thd, TABLE **ndb_binlog_index)
sql_print_error("NDB Binlog: Opening ndb_binlog_index: killed");
else
sql_print_error("NDB Binlog: Opening ndb_binlog_index: %d, '%s'",
thd->stmt_da->sql_errno(),
thd->stmt_da->message());
thd->get_stmt_da()->sql_errno(),
thd->get_stmt_da()->message());
thd->proc_info= save_proc_info;
return -1;
}
@ -2406,9 +2406,9 @@ int ndb_add_ndb_binlog_index(THD *thd, void *_row)
}
add_ndb_binlog_index_err:
thd->stmt_da->can_overwrite_status= TRUE;
thd->get_stmt_da()->set_overwrite_status(true);
thd->is_error() ? trans_rollback_stmt(thd) : trans_commit_stmt(thd);
thd->stmt_da->can_overwrite_status= FALSE;
thd->get_stmt_da()->set_overwrite_status(false);
close_thread_tables(thd);
thd->mdl_context.release_transactional_locks();
ndb_binlog_index= 0;
@ -2730,7 +2730,7 @@ ndbcluster_create_event(Ndb *ndb, const NDBTAB *ndbtab,
"with BLOB attribute and no PK is not supported",
share->key);
if (push_warning)
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
ER(ER_ILLEGAL_HA_CREATE_OPTION),
ndbcluster_hton_name,
@ -2774,7 +2774,7 @@ ndbcluster_create_event(Ndb *ndb, const NDBTAB *ndbtab,
failed, print a warning
*/
if (push_warning > 1)
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_GET_ERRMSG, ER(ER_GET_ERRMSG),
dict->getNdbError().code,
dict->getNdbError().message, "NDB");
@ -2802,7 +2802,7 @@ ndbcluster_create_event(Ndb *ndb, const NDBTAB *ndbtab,
dict->dropEvent(my_event.getName()))
{
if (push_warning > 1)
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_GET_ERRMSG, ER(ER_GET_ERRMSG),
dict->getNdbError().code,
dict->getNdbError().message, "NDB");
@ -2821,7 +2821,7 @@ ndbcluster_create_event(Ndb *ndb, const NDBTAB *ndbtab,
if (dict->createEvent(my_event))
{
if (push_warning > 1)
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_GET_ERRMSG, ER(ER_GET_ERRMSG),
dict->getNdbError().code,
dict->getNdbError().message, "NDB");
@ -2834,7 +2834,7 @@ ndbcluster_create_event(Ndb *ndb, const NDBTAB *ndbtab,
DBUG_RETURN(-1);
}
#ifdef NDB_BINLOG_EXTRA_WARNINGS
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_GET_ERRMSG, ER(ER_GET_ERRMSG),
0, "NDB Binlog: Removed trailing event",
"NDB");
@ -2945,7 +2945,7 @@ ndbcluster_create_event_ops(NDB_SHARE *share, const NDBTAB *ndbtab,
{
sql_print_error("NDB Binlog: Creating NdbEventOperation failed for"
" %s",event_name);
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_GET_ERRMSG, ER(ER_GET_ERRMSG),
ndb->getNdbError().code,
ndb->getNdbError().message,
@ -2994,7 +2994,7 @@ ndbcluster_create_event_ops(NDB_SHARE *share, const NDBTAB *ndbtab,
sql_print_error("NDB Binlog: Creating NdbEventOperation"
" blob field %u handles failed (code=%d) for %s",
j, op->getNdbError().code, event_name);
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_GET_ERRMSG, ER(ER_GET_ERRMSG),
op->getNdbError().code,
op->getNdbError().message,
@ -3033,7 +3033,7 @@ ndbcluster_create_event_ops(NDB_SHARE *share, const NDBTAB *ndbtab,
retries= 0;
if (retries == 0)
{
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_GET_ERRMSG, ER(ER_GET_ERRMSG),
op->getNdbError().code, op->getNdbError().message,
"NDB");
@ -3101,7 +3101,7 @@ ndbcluster_handle_drop_table(Ndb *ndb, const char *event_name,
if (dict->getNdbError().code != 4710)
{
/* drop event failed for some reason, issue a warning */
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_GET_ERRMSG, ER(ER_GET_ERRMSG),
dict->getNdbError().code,
dict->getNdbError().message, "NDB");
@ -4277,9 +4277,9 @@ err:
sql_print_information("Stopping Cluster Binlog");
DBUG_PRINT("info",("Shutting down cluster binlog thread"));
thd->proc_info= "Shutting down";
thd->stmt_da->can_overwrite_status= TRUE;
thd->get_stmt_da()->set_overwrite_status(true);
thd->is_error() ? trans_rollback_stmt(thd) : trans_commit_stmt(thd);
thd->stmt_da->can_overwrite_status= FALSE;
thd->get_stmt_da()->set_overwrite_status(false);
close_thread_tables(thd);
thd->mdl_context.release_transactional_locks();
mysql_mutex_lock(&injector_mutex);

View file

@ -1375,7 +1375,7 @@ ha_ndbcluster_cond::generate_scan_filter(NdbScanOperation *op)
{
// err.message has static storage
DBUG_PRINT("info", ("%s", err.message));
push_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning(current_thd, Sql_condition::WARN_LEVEL_WARN,
err.code, err.message);
ret=0;
}

File diff suppressed because it is too large Load diff

View file

@ -47,6 +47,92 @@ enum partition_keywords
/* offset to the engines array */
#define PAR_ENGINES_OFFSET 12
/** Struct used for partition_name_hash */
typedef struct st_part_name_def
{
uchar *partition_name;
uint length;
uint32 part_id;
my_bool is_subpart;
} PART_NAME_DEF;
/** class where to save partitions Handler_share's */
class Parts_share_refs
{
public:
uint num_parts; /**< Size of ha_share array */
Handler_share **ha_shares; /**< Storage for each part */
Parts_share_refs()
{
num_parts= 0;
ha_shares= NULL;
}
~Parts_share_refs()
{
uint i;
for (i= 0; i < num_parts; i++)
if (ha_shares[i])
delete ha_shares[i];
if (ha_shares)
delete [] ha_shares;
}
bool init(uint arg_num_parts)
{
DBUG_ASSERT(!num_parts && !ha_shares);
num_parts= arg_num_parts;
/* Allocate an array of Handler_share pointers */
ha_shares= new Handler_share *[num_parts];
if (!ha_shares)
{
num_parts= 0;
return true;
}
memset(ha_shares, 0, sizeof(Handler_share*) * num_parts);
return false;
}
};
/**
Partition specific Handler_share.
*/
class Partition_share : public Handler_share
{
public:
bool auto_inc_initialized;
mysql_mutex_t auto_inc_mutex; /**< protecting auto_inc val */
ulonglong next_auto_inc_val; /**< first non reserved value */
/**
Hash of partition names. Initialized in the first ha_partition::open()
for the table_share. After that it is read-only, i.e. no locking required.
*/
bool partition_name_hash_initialized;
HASH partition_name_hash;
/** Storage for each partitions Handler_share */
Parts_share_refs *partitions_share_refs;
Partition_share() {}
~Partition_share()
{
DBUG_ENTER("Partition_share::~Partition_share");
mysql_mutex_destroy(&auto_inc_mutex);
if (partition_name_hash_initialized)
my_hash_free(&partition_name_hash);
if (partitions_share_refs)
delete partitions_share_refs;
DBUG_VOID_RETURN;
}
bool init(uint num_parts);
void lock_auto_inc()
{
mysql_mutex_lock(&auto_inc_mutex);
}
void unlock_auto_inc()
{
mysql_mutex_unlock(&auto_inc_mutex);
}
};
class ha_partition :public handler
{
private:
@ -176,16 +262,25 @@ private:
ha_rows m_bulk_inserted_rows;
/** used for prediction of start_bulk_insert rows */
enum_monotonicity_info m_part_func_monotonicity_info;
/** keep track of locked partitions */
MY_BITMAP m_locked_partitions;
/** Stores shared auto_increment etc. */
Partition_share *part_share;
/** Temporary storage for new partitions Handler_shares during ALTER */
List<Parts_share_refs> m_new_partitions_share_refs;
/** Sorted array of partition ids in descending order of number of rows. */
uint32 *m_part_ids_sorted_by_num_of_records;
/* Compare function for my_qsort2, for reversed order. */
static int compare_number_of_records(ha_partition *me,
const uint32 *a,
const uint32 *b);
/** keep track of partitions to call ha_reset */
MY_BITMAP m_partitions_to_reset;
/** partitions that returned HA_ERR_KEY_NOT_FOUND. */
MY_BITMAP m_key_not_found_partitions;
bool m_key_not_found;
public:
Partition_share *get_part_share() { return part_share; }
handler *clone(const char *name, MEM_ROOT *mem_root);
virtual void set_part_info(partition_info *part_info)
{
@ -268,11 +363,10 @@ private:
handler *file, const char *part_name,
partition_element *p_elem);
/*
delete_table, rename_table and create uses very similar logic which
delete_table and rename_table uses very similar logic which
is packed into this routine.
*/
uint del_ren_cre_table(const char *from, const char *to,
TABLE *table_arg, HA_CREATE_INFO *create_info);
uint del_ren_table(const char *from, const char *to);
/*
One method to create the table_name.par file containing the names of the
underlying partitions, their engine and the number of partitions.
@ -289,9 +383,15 @@ private:
int set_up_table_before_create(TABLE *table_arg,
const char *partition_name_with_path,
HA_CREATE_INFO *info,
uint part_id,
partition_element *p_elem);
partition_element *find_partition_element(uint part_id);
bool insert_partition_name_in_hash(const char *name, uint part_id,
bool is_subpart);
bool populate_partition_name_hash();
Partition_share *get_share();
bool set_ha_share_ref(Handler_share **ha_share);
bool init_partition_bitmaps();
void free_partition_bitmaps();
public:
@ -397,7 +497,8 @@ public:
virtual bool is_fatal_error(int error, uint flags)
{
if (!handler::is_fatal_error(error, flags) ||
error == HA_ERR_NO_PARTITION_FOUND)
error == HA_ERR_NO_PARTITION_FOUND ||
error == HA_ERR_NOT_IN_LOCK_PARTITIONS)
return FALSE;
return TRUE;
}
@ -957,16 +1058,15 @@ private:
/* lock already taken */
if (auto_increment_safe_stmt_log_lock)
return;
DBUG_ASSERT(table_share->ha_part_data && !auto_increment_lock);
DBUG_ASSERT(!auto_increment_lock);
if(table_share->tmp_table == NO_TMP_TABLE)
{
auto_increment_lock= TRUE;
mysql_mutex_lock(&table_share->ha_part_data->LOCK_auto_inc);
part_share->lock_auto_inc();
}
}
virtual void unlock_auto_increment()
{
DBUG_ASSERT(table_share->ha_part_data);
/*
If auto_increment_safe_stmt_log_lock is true, we have to keep the lock.
It will be set to false and thus unlocked at the end of the statement by
@ -974,7 +1074,7 @@ private:
*/
if(auto_increment_lock && !auto_increment_safe_stmt_log_lock)
{
mysql_mutex_unlock(&table_share->ha_part_data->LOCK_auto_inc);
part_share->unlock_auto_inc();
auto_increment_lock= FALSE;
}
}
@ -983,10 +1083,10 @@ private:
ulonglong nr= (((Field_num*) field)->unsigned_flag ||
field->val_int() > 0) ? field->val_int() : 0;
lock_auto_increment();
DBUG_ASSERT(table_share->ha_part_data->auto_inc_initialized == TRUE);
DBUG_ASSERT(part_share->auto_inc_initialized);
/* must check when the mutex is taken */
if (nr >= table_share->ha_part_data->next_auto_inc_val)
table_share->ha_part_data->next_auto_inc_val= nr + 1;
if (nr >= part_share->next_auto_inc_val)
part_share->next_auto_inc_val= nr + 1;
unlock_auto_increment();
}
@ -1052,20 +1152,25 @@ public:
/*
-------------------------------------------------------------------------
MODULE on-line ALTER TABLE
-------------------------------------------------------------------------
MODULE in-place ALTER TABLE
-------------------------------------------------------------------------
These methods are in the handler interface. (used by innodb-plugin)
They are used for on-line/fast alter table add/drop index:
-------------------------------------------------------------------------
They are used for in-place alter table:
-------------------------------------------------------------------------
*/
virtual int add_index(TABLE *table_arg, KEY *key_info, uint num_of_keys,
handler_add_index **add);
virtual int final_add_index(handler_add_index *add, bool commit);
virtual int prepare_drop_index(TABLE *table_arg, uint *key_num,
uint num_of_keys);
virtual int final_drop_index(TABLE *table_arg);
virtual enum_alter_inplace_result
check_if_supported_inplace_alter(TABLE *altered_table,
Alter_inplace_info *ha_alter_info);
virtual bool prepare_inplace_alter_table(TABLE *altered_table,
Alter_inplace_info *ha_alter_info);
virtual bool inplace_alter_table(TABLE *altered_table,
Alter_inplace_info *ha_alter_info);
virtual bool commit_inplace_alter_table(TABLE *altered_table,
Alter_inplace_info *ha_alter_info,
bool commit);
virtual void notify_table_changed();
/*
/*
-------------------------------------------------------------------------
MODULE tablespace support
-------------------------------------------------------------------------

View file

@ -61,7 +61,7 @@ static handlerton *installed_htons[128];
#define BITMAP_STACKBUF_SIZE (128/8)
KEY_CREATE_INFO default_key_create_info=
{ HA_KEY_ALG_UNDEF, 0, {NullS, 0}, {NullS, 0}, 0 };
{ HA_KEY_ALG_UNDEF, 0, {NullS, 0}, {NullS, 0}, true };
/* number of entries in handlertons[] */
ulong total_ha= 0;
@ -98,6 +98,7 @@ uint known_extensions_id= 0;
static int commit_one_phase_2(THD *thd, bool all, THD_TRANS *trans,
bool is_real_trans);
static plugin_ref ha_default_plugin(THD *thd)
{
if (thd->variables.table_plugin)
@ -1095,7 +1096,7 @@ int ha_prepare(THD *thd)
}
else
{
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
ha_resolve_storage_engine_name(ht));
}
@ -1203,7 +1204,7 @@ int ha_commit_trans(THD *thd, bool all)
/* Just a random warning to test warnings pushed during autocommit. */
DBUG_EXECUTE_IF("warn_during_ha_commit_trans",
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning(thd, Sql_condition::WARN_LEVEL_WARN,
ER_WARNING_NOT_COMPLETE_ROLLBACK,
ER(ER_WARNING_NOT_COMPLETE_ROLLBACK)););
@ -1523,7 +1524,7 @@ int ha_rollback_trans(THD *thd, bool all)
trans->no_2pc=0;
if (is_real_trans && thd->transaction_rollback_request &&
thd->transaction.xid_state.xa_state != XA_NOTR)
thd->transaction.xid_state.rm_error= thd->stmt_da->sql_errno();
thd->transaction.xid_state.rm_error= thd->get_stmt_da()->sql_errno();
}
/* Always cleanup. Even if nht==0. There may be savepoints. */
if (is_real_trans)
@ -1546,7 +1547,7 @@ int ha_rollback_trans(THD *thd, bool all)
*/
if (is_real_trans && thd->transaction.all.modified_non_trans_table &&
!thd->slave_thread && thd->killed < KILL_CONNECTION)
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning(thd, Sql_condition::WARN_LEVEL_WARN,
ER_WARNING_NOT_COMPLETE_ROLLBACK,
ER(ER_WARNING_NOT_COMPLETE_ROLLBACK));
(void) RUN_HOOK(transaction, after_rollback, (thd, FALSE));
@ -2039,7 +2040,7 @@ int ha_start_consistent_snapshot(THD *thd)
exist:
*/
if (warn)
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
push_warning(thd, Sql_condition::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
"This MySQL server does not support any "
"consistent-read capable storage engine");
return 0;
@ -2135,9 +2136,9 @@ public:
virtual bool handle_condition(THD *thd,
uint sql_errno,
const char* sqlstate,
MYSQL_ERROR::enum_warning_level level,
Sql_condition::enum_warning_level level,
const char* msg,
MYSQL_ERROR ** cond_hdl);
Sql_condition ** cond_hdl);
char buff[MYSQL_ERRMSG_SIZE];
};
@ -2147,9 +2148,9 @@ Ha_delete_table_error_handler::
handle_condition(THD *,
uint,
const char*,
MYSQL_ERROR::enum_warning_level,
Sql_condition::enum_warning_level,
const char* msg,
MYSQL_ERROR ** cond_hdl)
Sql_condition ** cond_hdl)
{
*cond_hdl= NULL;
/* Grab the error message */
@ -2213,7 +2214,7 @@ int ha_delete_table(THD *thd, handlerton *table_type, const char *path,
XXX: should we convert *all* errors to warnings here?
What if the error is fatal?
*/
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, error,
push_warning(thd, Sql_condition::WARN_LEVEL_WARN, error,
ha_delete_table_error_handler.buff);
}
delete file;
@ -2236,8 +2237,10 @@ int ha_delete_table(THD *thd, handlerton *table_type, const char *path,
handler *handler::clone(const char *name, MEM_ROOT *mem_root)
{
handler *new_handler= get_new_handler(table->s, mem_root, ht);
if (! new_handler)
if (!new_handler)
return NULL;
if (new_handler->set_ha_share_ref(ha_share))
goto err;
/*
Allocate handler->ref here because otherwise ha_open will allocate it
@ -2247,7 +2250,7 @@ handler *handler::clone(const char *name, MEM_ROOT *mem_root)
if (!(new_handler->ref= (uchar*) alloc_root(mem_root,
ALIGN_SIZE(ref_length)*2)))
return NULL;
goto err;
/*
TODO: Implement a more efficient way to have more than one index open for
@ -2258,9 +2261,13 @@ handler *handler::clone(const char *name, MEM_ROOT *mem_root)
*/
if (new_handler->ha_open(table, name, table->db_stat,
HA_OPEN_IGNORE_IF_LOCKED))
return NULL;
goto err;
return new_handler;
err:
delete new_handler;
return NULL;
}
@ -2342,6 +2349,8 @@ int handler::ha_open(TABLE *table_arg, const char *name, int mode,
table= table_arg;
DBUG_ASSERT(table->s == table_share);
DBUG_ASSERT(m_lock_type == F_UNLCK);
DBUG_PRINT("info", ("old m_lock_type: %d F_UNLCK %d", m_lock_type, F_UNLCK));
DBUG_ASSERT(alloc_root_inited(&table->mem_root));
if ((error=open(name,mode,test_if_locked)))
@ -2363,8 +2372,16 @@ int handler::ha_open(TABLE *table_arg, const char *name, int mode,
DBUG_ASSERT(m_psi == NULL);
DBUG_ASSERT(table_share != NULL);
#ifdef HAVE_PSI_TABLE_INTERFACE
PSI_table_share *share_psi= ha_table_share_psi(table_share);
m_psi= PSI_TABLE_CALL(open_table)(share_psi, this);
/*
Do not call this for partitions handlers, since it may take too much
resources.
So only use the m_psi on table level, not for individual partitions.
*/
if (!(test_if_locked & HA_OPEN_NO_PSI_CALL))
{
PSI_table_share *share_psi= ha_table_share_psi(table_share);
m_psi= PSI_TABLE_CALL(open_table)(share_psi, this);
}
#endif
if (table->s->db_options_in_use & HA_OPTION_READ_ONLY_DATA)
@ -2400,13 +2417,20 @@ int handler::ha_close(void)
PSI_TABLE_CALL(close_table)(m_psi);
m_psi= NULL; /* instrumentation handle, invalid after close_table() */
#endif
// TODO: set table= NULL to mark the handler as closed?
DBUG_ASSERT(m_psi == NULL);
DBUG_ASSERT(m_lock_type == F_UNLCK);
DBUG_ASSERT(inited == NONE);
DBUG_RETURN(close());
}
int handler::ha_rnd_next(uchar *buf)
{
int result;
DBUG_ENTER("handler::ha_rnd_next");
DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
m_lock_type != F_UNLCK);
DBUG_ASSERT(inited == RND);
MYSQL_TABLE_IO_WAIT(m_psi, PSI_TABLE_FETCH_ROW, MAX_KEY, 0,
{ result= rnd_next(buf); })
@ -2421,12 +2445,17 @@ int handler::ha_rnd_next(uchar *buf)
increment_statistics(&SSV::ha_read_rnd_next_count);
table->status=result ? STATUS_NOT_FOUND: 0;
return result;
DBUG_RETURN(result);
}
int handler::ha_rnd_pos(uchar *buf, uchar *pos)
{
int result;
DBUG_ENTER("handler::ha_rnd_pos");
DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
m_lock_type != F_UNLCK);
/* TODO: Find out how to solve ha_rnd_pos when finding duplicate update. */
/* DBUG_ASSERT(inited == RND); */
MYSQL_TABLE_IO_WAIT(m_psi, PSI_TABLE_FETCH_ROW, MAX_KEY, 0,
{ result= rnd_pos(buf, pos); })
@ -2434,7 +2463,7 @@ int handler::ha_rnd_pos(uchar *buf, uchar *pos)
if (!result)
update_rows_read();
table->status=result ? STATUS_NOT_FOUND: 0;
return result;
DBUG_RETURN(result);
}
int handler::ha_index_read_map(uchar *buf, const uchar *key,
@ -2442,6 +2471,9 @@ int handler::ha_index_read_map(uchar *buf, const uchar *key,
enum ha_rkey_function find_flag)
{
int result;
DBUG_ENTER("handler::ha_index_read_map");
DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
m_lock_type != F_UNLCK);
DBUG_ASSERT(inited==INDEX);
MYSQL_TABLE_IO_WAIT(m_psi, PSI_TABLE_FETCH_ROW, active_index, 0,
@ -2450,7 +2482,7 @@ int handler::ha_index_read_map(uchar *buf, const uchar *key,
if (!result)
update_index_statistics();
table->status=result ? STATUS_NOT_FOUND: 0;
return result;
DBUG_RETURN(result);
}
/*
@ -2465,6 +2497,8 @@ int handler::ha_index_read_idx_map(uchar *buf, uint index, const uchar *key,
{
int result;
DBUG_ASSERT(inited==NONE);
DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
m_lock_type != F_UNLCK);
DBUG_ASSERT(end_range == NULL);
MYSQL_TABLE_IO_WAIT(m_psi, PSI_TABLE_FETCH_ROW, index, 0,
{ result= index_read_idx_map(buf, index, key, keypart_map, find_flag); })
@ -2481,6 +2515,9 @@ int handler::ha_index_read_idx_map(uchar *buf, uint index, const uchar *key,
int handler::ha_index_next(uchar * buf)
{
int result;
DBUG_ENTER("handler::ha_index_next");
DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
m_lock_type != F_UNLCK);
DBUG_ASSERT(inited==INDEX);
MYSQL_TABLE_IO_WAIT(m_psi, PSI_TABLE_FETCH_ROW, active_index, 0,
@ -2489,12 +2526,15 @@ int handler::ha_index_next(uchar * buf)
if (!result)
update_index_statistics();
table->status=result ? STATUS_NOT_FOUND: 0;
return result;
DBUG_RETURN(result);
}
int handler::ha_index_prev(uchar * buf)
{
int result;
DBUG_ENTER("handler::ha_index_prev");
DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
m_lock_type != F_UNLCK);
DBUG_ASSERT(inited==INDEX);
MYSQL_TABLE_IO_WAIT(m_psi, PSI_TABLE_FETCH_ROW, active_index, 0,
@ -2503,12 +2543,14 @@ int handler::ha_index_prev(uchar * buf)
if (!result)
update_index_statistics();
table->status=result ? STATUS_NOT_FOUND: 0;
return result;
DBUG_RETURN(result);
}
int handler::ha_index_first(uchar * buf)
{
int result;
DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
m_lock_type != F_UNLCK);
DBUG_ASSERT(inited==INDEX);
MYSQL_TABLE_IO_WAIT(m_psi, PSI_TABLE_FETCH_ROW, active_index, 0,
@ -2523,6 +2565,8 @@ int handler::ha_index_first(uchar * buf)
int handler::ha_index_last(uchar * buf)
{
int result;
DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
m_lock_type != F_UNLCK);
DBUG_ASSERT(inited==INDEX);
MYSQL_TABLE_IO_WAIT(m_psi, PSI_TABLE_FETCH_ROW, active_index, 0,
@ -2537,6 +2581,8 @@ int handler::ha_index_last(uchar * buf)
int handler::ha_index_next_same(uchar *buf, const uchar *key, uint keylen)
{
int result;
DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
m_lock_type != F_UNLCK);
DBUG_ASSERT(inited==INDEX);
MYSQL_TABLE_IO_WAIT(m_psi, PSI_TABLE_FETCH_ROW, active_index, 0,
@ -3059,6 +3105,9 @@ void handler::get_auto_increment(ulonglong offset, ulonglong increment,
void handler::ha_release_auto_increment()
{
DBUG_ENTER("ha_release_auto_increment");
DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
m_lock_type != F_UNLCK ||
(!next_insert_id && !insert_id_for_cur_row));
release_auto_increment();
insert_id_for_cur_row= 0;
auto_inc_interval_for_cur_row.replace(0, 0, 0);
@ -3190,7 +3239,9 @@ void handler::print_error(int error, myf errflag)
uint key_nr=get_dup_key(error);
if ((int) key_nr >= 0)
{
print_keydup_error(table, &table->key_info[key_nr], errflag);
print_keydup_error(table,
key_nr == MAX_KEY ? NULL : &table->key_info[key_nr],
errflag);
DBUG_VOID_RETURN;
}
}
@ -3202,9 +3253,12 @@ void handler::print_error(int error, myf errflag)
char rec_buf[MAX_KEY_LENGTH];
String rec(rec_buf, sizeof(rec_buf), system_charset_info);
/* Table is opened and defined at this point */
key_unpack(&rec, table, 0 /* just print the subset of fields that are
part of the first index, printing the whole
row from there is not easy */);
/*
Just print the subset of fields that are part of the first index,
printing the whole row from there is not easy.
*/
key_unpack(&rec, table, &table->key_info[0]);
char child_table_name[NAME_LEN + 1];
char child_key_name[NAME_LEN + 1];
@ -3339,7 +3393,7 @@ void handler::print_error(int error, myf errflag)
case HA_ERR_AUTOINC_ERANGE:
textno= error;
my_error(textno, errflag, table->next_number_field->field_name,
table->in_use->warning_info->current_row_for_warning());
table->in_use->get_stmt_da()->current_row_for_warning());
DBUG_VOID_RETURN;
break;
case HA_ERR_TOO_MANY_CONCURRENT_TRXS:
@ -3348,6 +3402,9 @@ void handler::print_error(int error, myf errflag)
case HA_ERR_INDEX_COL_TOO_LONG:
textno= ER_INDEX_COLUMN_TOO_LONG;
break;
case HA_ERR_NOT_IN_LOCK_PARTITIONS:
textno=ER_ROW_DOES_NOT_MATCH_GIVEN_PARTITION_SET;
break;
case HA_ERR_INDEX_CORRUPT:
textno= ER_INDEX_CORRUPT;
break;
@ -3567,6 +3624,8 @@ err:
*/
uint handler::get_dup_key(int error)
{
DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
m_lock_type != F_UNLCK);
DBUG_ENTER("handler::get_dup_key");
table->file->errkey = (uint) -1;
if (error == HA_ERR_FOUND_DUPP_KEY || error == HA_ERR_FOREIGN_DUPLICATE_KEY ||
@ -3672,6 +3731,8 @@ void handler::drop_table(const char *name)
int handler::ha_check(THD *thd, HA_CHECK_OPT *check_opt)
{
int error;
DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
m_lock_type != F_UNLCK);
if ((table->s->mysql_version >= MYSQL_VERSION_ID) &&
(check_opt->sql_flags & TT_FOR_UPGRADE))
@ -3758,6 +3819,8 @@ int
handler::ha_bulk_update_row(const uchar *old_data, uchar *new_data,
uint *dup_key_found)
{
DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
m_lock_type == F_WRLCK);
mark_trx_read_write();
return bulk_update_row(old_data, new_data, dup_key_found);
@ -3773,6 +3836,8 @@ handler::ha_bulk_update_row(const uchar *old_data, uchar *new_data,
int
handler::ha_delete_all_rows()
{
DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
m_lock_type == F_WRLCK);
mark_trx_read_write();
return delete_all_rows();
@ -3788,6 +3853,8 @@ handler::ha_delete_all_rows()
int
handler::ha_truncate()
{
DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
m_lock_type == F_WRLCK);
mark_trx_read_write();
return truncate();
@ -3803,6 +3870,8 @@ handler::ha_truncate()
int
handler::ha_reset_auto_increment(ulonglong value)
{
DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
m_lock_type == F_WRLCK);
mark_trx_read_write();
return reset_auto_increment(value);
@ -3818,6 +3887,8 @@ handler::ha_reset_auto_increment(ulonglong value)
int
handler::ha_optimize(THD* thd, HA_CHECK_OPT* check_opt)
{
DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
m_lock_type == F_WRLCK);
mark_trx_read_write();
return optimize(thd, check_opt);
@ -3833,6 +3904,8 @@ handler::ha_optimize(THD* thd, HA_CHECK_OPT* check_opt)
int
handler::ha_analyze(THD* thd, HA_CHECK_OPT* check_opt)
{
DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
m_lock_type != F_UNLCK);
mark_trx_read_write();
return analyze(thd, check_opt);
@ -3848,6 +3921,8 @@ handler::ha_analyze(THD* thd, HA_CHECK_OPT* check_opt)
bool
handler::ha_check_and_repair(THD *thd)
{
DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
m_lock_type == F_UNLCK);
mark_trx_read_write();
return check_and_repair(thd);
@ -3863,6 +3938,8 @@ handler::ha_check_and_repair(THD *thd)
int
handler::ha_disable_indexes(uint mode)
{
DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
m_lock_type != F_UNLCK);
mark_trx_read_write();
return disable_indexes(mode);
@ -3878,6 +3955,8 @@ handler::ha_disable_indexes(uint mode)
int
handler::ha_enable_indexes(uint mode)
{
DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
m_lock_type != F_UNLCK);
mark_trx_read_write();
return enable_indexes(mode);
@ -3893,26 +3972,116 @@ handler::ha_enable_indexes(uint mode)
int
handler::ha_discard_or_import_tablespace(my_bool discard)
{
DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
m_lock_type == F_WRLCK);
mark_trx_read_write();
return discard_or_import_tablespace(discard);
}
/**
Prepare for alter: public interface.
Called to prepare an *online* ALTER.
@sa handler::prepare_for_alter()
*/
void
handler::ha_prepare_for_alter()
bool handler::ha_prepare_inplace_alter_table(TABLE *altered_table,
Alter_inplace_info *ha_alter_info)
{
DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
m_lock_type != F_UNLCK);
mark_trx_read_write();
prepare_for_alter();
return prepare_inplace_alter_table(altered_table, ha_alter_info);
}
bool handler::ha_commit_inplace_alter_table(TABLE *altered_table,
Alter_inplace_info *ha_alter_info,
bool commit)
{
/*
At this point we should have an exclusive metadata lock on the table.
The exception is if we're about to roll back changes (commit= false).
In this case, we might be rolling back after a failed lock upgrade,
so we could be holding the same lock level as for inplace_alter_table().
*/
DBUG_ASSERT(ha_thd()->mdl_context.is_lock_owner(MDL_key::TABLE,
table->s->db.str,
table->s->table_name.str,
MDL_EXCLUSIVE) ||
!commit);
return commit_inplace_alter_table(altered_table, ha_alter_info, commit);
}
/*
Default implementation to support in-place alter table
and old online add/drop index API
*/
enum_alter_inplace_result
handler::check_if_supported_inplace_alter(TABLE *altered_table,
Alter_inplace_info *ha_alter_info)
{
DBUG_ENTER("check_if_supported_alter");
HA_CREATE_INFO *create_info= ha_alter_info->create_info;
Alter_inplace_info::HA_ALTER_FLAGS inplace_offline_operations=
Alter_inplace_info::ALTER_COLUMN_EQUAL_PACK_LENGTH |
Alter_inplace_info::ALTER_COLUMN_NAME |
Alter_inplace_info::ALTER_COLUMN_DEFAULT |
Alter_inplace_info::CHANGE_CREATE_OPTION |
Alter_inplace_info::ALTER_RENAME;
/* Is there at least one operation that requires copy algorithm? */
if (ha_alter_info->handler_flags & ~inplace_offline_operations)
DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
/*
ALTER TABLE tbl_name CONVERT TO CHARACTER SET .. and
ALTER TABLE table_name DEFAULT CHARSET = .. most likely
change column charsets and so not supported in-place through
old API.
Changing of PACK_KEYS, MAX_ROWS and ROW_FORMAT options were
not supported as in-place operations in old API either.
*/
if (create_info->used_fields & (HA_CREATE_USED_CHARSET |
HA_CREATE_USED_DEFAULT_CHARSET |
HA_CREATE_USED_PACK_KEYS |
HA_CREATE_USED_MAX_ROWS) ||
(table->s->row_type != create_info->row_type))
DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
uint table_changes= (ha_alter_info->handler_flags &
Alter_inplace_info::ALTER_COLUMN_EQUAL_PACK_LENGTH) ?
IS_EQUAL_PACK_LENGTH : IS_EQUAL_YES;
if (table->file->check_if_incompatible_data(create_info, table_changes)
== COMPATIBLE_DATA_YES)
DBUG_RETURN(HA_ALTER_INPLACE_EXCLUSIVE_LOCK);
DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
}
/*
Default implementation to support in-place alter table
and old online add/drop index API
*/
void handler::notify_table_changed()
{
ha_create_handler_files(table->s->path.str, NULL, CHF_INDEX_FLAG, NULL);
}
void Alter_inplace_info::report_unsupported_error(const char *not_supported,
const char *try_instead)
{
if (unsupported_reason == NULL)
my_error(ER_ALTER_OPERATION_NOT_SUPPORTED, MYF(0),
not_supported, try_instead);
else
my_error(ER_ALTER_OPERATION_NOT_SUPPORTED_REASON, MYF(0),
not_supported, unsupported_reason, try_instead);
}
@ -3925,6 +4094,7 @@ handler::ha_prepare_for_alter()
int
handler::ha_rename_table(const char *from, const char *to)
{
DBUG_ASSERT(m_lock_type == F_UNLCK);
mark_trx_read_write();
return rename_table(from, to);
@ -3958,6 +4128,7 @@ handler::ha_delete_table(const char *name)
void
handler::ha_drop_table(const char *name)
{
DBUG_ASSERT(m_lock_type == F_UNLCK);
mark_trx_read_write();
return drop_table(name);
@ -3973,6 +4144,7 @@ handler::ha_drop_table(const char *name)
int
handler::ha_create(const char *name, TABLE *form, HA_CREATE_INFO *info)
{
DBUG_ASSERT(m_lock_type == F_UNLCK);
mark_trx_read_write();
return create(name, form, info);
@ -3989,6 +4161,13 @@ int
handler::ha_create_handler_files(const char *name, const char *old_name,
int action_flag, HA_CREATE_INFO *info)
{
/*
Normally this is done when unlocked, but in fast_alter_partition_table,
it is done on an already locked handler when preparing to alter/rename
partitions.
*/
DBUG_ASSERT(m_lock_type == F_UNLCK ||
(!old_name && strcmp(name, table_share->path.str)));
mark_trx_read_write();
return create_handler_files(name, old_name, action_flag, info);
@ -4008,7 +4187,13 @@ handler::ha_change_partitions(HA_CREATE_INFO *create_info,
ulonglong * const deleted,
const uchar *pack_frm_data,
size_t pack_frm_len)
{
{ /*
Must have at least RDLCK or be a TMP table. Read lock is needed to read
from current partitions and write lock will be taken on new partitions.
*/
DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
m_lock_type != F_UNLCK);
mark_trx_read_write();
return change_partitions(create_info, path, copied, deleted,
@ -4025,6 +4210,8 @@ handler::ha_change_partitions(HA_CREATE_INFO *create_info,
int
handler::ha_drop_partitions(const char *path)
{
DBUG_ASSERT(!table->db_stat);
mark_trx_read_write();
return drop_partitions(path);
@ -4040,6 +4227,8 @@ handler::ha_drop_partitions(const char *path)
int
handler::ha_rename_partitions(const char *path)
{
DBUG_ASSERT(!table->db_stat);
mark_trx_read_write();
return rename_partitions(path);
@ -5345,6 +5534,12 @@ int handler::ha_external_lock(THD *thd, int lock_type)
taken a table lock), ha_release_auto_increment() was too.
*/
DBUG_ASSERT(next_insert_id == 0);
/* Consecutive calls for lock without unlocking in between is not allowed */
DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
((lock_type != F_UNLCK && m_lock_type == F_UNLCK) ||
lock_type == F_UNLCK));
/* SQL HANDLER call locks/unlock while scanning (RND/INDEX). */
DBUG_ASSERT(inited == NONE || table->open_by_handler);
if (MYSQL_HANDLER_RDLOCK_START_ENABLED() ||
MYSQL_HANDLER_WRLOCK_START_ENABLED() ||
@ -5377,7 +5572,14 @@ int handler::ha_external_lock(THD *thd, int lock_type)
{ error= external_lock(thd, lock_type); })
if (error == 0)
{
/*
The lock type is needed by MRR when creating a clone of this handler
object and for assert checking.
*/
m_lock_type= lock_type;
cached_table_flags= table_flags();
}
if (MYSQL_HANDLER_RDLOCK_DONE_ENABLED() ||
MYSQL_HANDLER_WRLOCK_DONE_ENABLED() ||
@ -5430,6 +5632,8 @@ int handler::ha_write_row(uchar *buf)
{
int error;
Log_func *log_func= Write_rows_log_event::binlog_row_logging_function;
DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
m_lock_type == F_WRLCK);
DBUG_ENTER("handler::ha_write_row");
DEBUG_SYNC_C("ha_write_row_start");
@ -5456,6 +5660,8 @@ int handler::ha_update_row(const uchar *old_data, uchar *new_data)
{
int error;
Log_func *log_func= Update_rows_log_event::binlog_row_logging_function;
DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
m_lock_type == F_WRLCK);
/*
Some storage engines require that the new record is in record[0]
@ -5483,6 +5689,8 @@ int handler::ha_delete_row(const uchar *buf)
{
int error;
Log_func *log_func= Delete_rows_log_event::binlog_row_logging_function;
DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
m_lock_type == F_WRLCK);
MYSQL_DELETE_ROW_START(table_share->db.str, table_share->table_name.str);
mark_trx_read_write();
@ -5513,6 +5721,77 @@ void handler::use_hidden_primary_key()
}
/**
Get an initialized ha_share.
@return Initialized ha_share
@retval NULL ha_share is not yet initialized.
@retval != NULL previous initialized ha_share.
@note
If not a temp table, then LOCK_ha_data must be held.
*/
Handler_share *handler::get_ha_share_ptr()
{
DBUG_ENTER("handler::get_ha_share_ptr");
DBUG_ASSERT(ha_share && table_share);
#ifndef DBUG_OFF
if (table_share->tmp_table == NO_TMP_TABLE)
mysql_mutex_assert_owner(&table_share->LOCK_ha_data);
#endif
DBUG_RETURN(*ha_share);
}
/**
Set ha_share to be used by all instances of the same table/partition.
@param ha_share Handler_share to be shared.
@note
If not a temp table, then LOCK_ha_data must be held.
*/
void handler::set_ha_share_ptr(Handler_share *arg_ha_share)
{
DBUG_ENTER("handler::set_ha_share_ptr");
DBUG_ASSERT(ha_share);
#ifndef DBUG_OFF
if (table_share->tmp_table == NO_TMP_TABLE)
mysql_mutex_assert_owner(&table_share->LOCK_ha_data);
#endif
*ha_share= arg_ha_share;
DBUG_VOID_RETURN;
}
/**
Take a lock for protecting shared handler data.
*/
void handler::lock_shared_ha_data()
{
DBUG_ASSERT(table_share);
if (table_share->tmp_table == NO_TMP_TABLE)
mysql_mutex_lock(&table_share->LOCK_ha_data);
}
/**
Release lock for protecting ha_share.
*/
void handler::unlock_shared_ha_data()
{
DBUG_ASSERT(table_share);
if (table_share->tmp_table == NO_TMP_TABLE)
mysql_mutex_unlock(&table_share->LOCK_ha_data);
}
/** @brief
Dummy function which accept information about log files which is not need
by handlers

View file

@ -404,6 +404,13 @@ enum row_type { ROW_TYPE_NOT_USED=-1, ROW_TYPE_DEFAULT, ROW_TYPE_FIXED,
/** Unused. Reserved for future versions. */
ROW_TYPE_PAGE };
/* Specifies data storage format for individual columns */
enum column_format_type {
COLUMN_FORMAT_TYPE_DEFAULT= 0, /* Not specified (use engine default) */
COLUMN_FORMAT_TYPE_FIXED= 1, /* FIXED format */
COLUMN_FORMAT_TYPE_DYNAMIC= 2 /* DYNAMIC format */
};
enum enum_binlog_func {
BFN_RESET_LOGS= 1,
BFN_RESET_SLAVE= 2,
@ -1243,6 +1250,7 @@ inline LEX_STRING *hton_name(const handlerton *hton)
#define HTON_ALTER_NOT_SUPPORTED (1 << 1) //Engine does not support alter
#define HTON_CAN_RECREATE (1 << 2) //Delete all is used for truncate
#define HTON_HIDDEN (1 << 3) //Engine does not appear in lists
#define HTON_FLUSH_AFTER_RENAME (1 << 4)
#define HTON_NOT_USER_SELECTABLE (1 << 5)
#define HTON_TEMPORARY_NOT_SUPPORTED (1 << 6) //Having temporary tables not supported
#define HTON_SUPPORT_LOG_TABLES (1 << 7) //Engine supports log tables
@ -1304,6 +1312,22 @@ struct THD_TRANS
void reset() { no_2pc= FALSE; modified_non_trans_table= FALSE; }
bool is_empty() const { return ha_list == NULL; }
THD_TRANS() {} /* Remove gcc warning */
unsigned int m_unsafe_rollback_flags;
/*
Define the type of statemens which cannot be rolled back safely.
Each type occupies one bit in m_unsafe_rollback_flags.
*/
static unsigned int const MODIFIED_NON_TRANS_TABLE= 0x01;
static unsigned int const CREATED_TEMP_TABLE= 0x02;
static unsigned int const DROPPED_TEMP_TABLE= 0x04;
void mark_created_temp_table()
{
DBUG_PRINT("debug", ("mark_created_temp_table"));
m_unsafe_rollback_flags|= CREATED_TEMP_TABLE;
}
};
@ -1427,7 +1451,6 @@ struct st_table_log_memory_entry;
class partition_info;
struct st_partition_iter;
#define NOT_A_PARTITION_ID ((uint32)-1)
enum ha_choice { HA_CHOICE_UNDEF, HA_CHOICE_NO, HA_CHOICE_YES };
@ -1438,6 +1461,7 @@ enum enum_stats_auto_recalc { HA_STATS_AUTO_RECALC_DEFAULT= 0,
typedef struct st_ha_create_information
{
CHARSET_INFO *table_charset, *default_table_charset;
LEX_CUSTRING tabledef_version;
LEX_STRING connect_string;
const char *password, *tablespace;
LEX_STRING comment;
@ -1445,7 +1469,7 @@ typedef struct st_ha_create_information
const char *alias;
ulonglong max_rows,min_rows;
ulonglong auto_increment_value;
ulong table_options;
ulong table_options; ///< HA_OPTION_ values
ulong avg_row_length;
ulong used_fields;
ulong key_block_size;
@ -1469,18 +1493,21 @@ typedef struct st_ha_create_information
uint merge_insert_method;
uint extra_size; /* length of extra data segment */
enum ha_choice transactional;
bool frm_only; ///< 1 if no ha_create_table()
bool varchar; ///< 1 if table has a VARCHAR
enum ha_storage_media storage_media; ///< DEFAULT, DISK or MEMORY
enum ha_choice page_checksum; ///< If we have page_checksums
engine_option_value *option_list; ///< list of table create options
/* the following three are only for ALTER TABLE, check_if_incompatible_data() */
ha_table_option_struct *option_struct; ///< structure with parsed table options
ha_field_option_struct **fields_option_struct; ///< array of field option structures
ha_index_option_struct **indexes_option_struct; ///< array of index option structures
bool tmp_table() { return options & HA_LEX_CREATE_TMP_TABLE; }
} HA_CREATE_INFO;
/**
In-place alter handler context.
@ -2182,34 +2209,61 @@ uint calculate_key_len(TABLE *, uint, const uchar *, key_part_map);
#define make_prev_keypart_map(N) (((key_part_map)1 << (N)) - 1)
/**
Index creation context.
Created by handler::add_index() and destroyed by handler::final_add_index().
And finally freed at the end of the statement.
(Sql_alloc does not free in delete).
*/
class handler_add_index : public Sql_alloc
/** Base class to be used by handlers different shares */
class Handler_share
{
public:
/* Table where the indexes are added */
TABLE* const table;
/* Indexes being created */
KEY* const key_info;
/* Size of key_info[] */
const uint num_of_keys;
handler_add_index(TABLE *table_arg, KEY *key_info_arg, uint num_of_keys_arg)
: table (table_arg), key_info (key_info_arg), num_of_keys (num_of_keys_arg)
{}
virtual ~handler_add_index() {}
Handler_share() {}
virtual ~Handler_share() {}
};
class Query_cache;
struct Query_cache_block_table;
/**
The handler class is the interface for dynamically loadable
storage engines. Do not add ifdefs and take care when adding or
changing virtual functions to avoid vtable confusion
Functions in this class accept and return table columns data. Two data
representation formats are used:
1. TableRecordFormat - Used to pass [partial] table records to/from
storage engine
2. KeyTupleFormat - used to pass index search tuples (aka "keys") to
storage engine. See opt_range.cc for description of this format.
TableRecordFormat
=================
[Warning: this description is work in progress and may be incomplete]
The table record is stored in a fixed-size buffer:
record: null_bytes, column1_data, column2_data, ...
The offsets of the parts of the buffer are also fixed: every column has
an offset to its column{i}_data, and if it is nullable it also has its own
bit in null_bytes.
The record buffer only includes data about columns that are marked in the
relevant column set (table->read_set and/or table->write_set, depending on
the situation).
<not-sure>It could be that it is required that null bits of non-present
columns are set to 1</not-sure>
VARIOUS EXCEPTIONS AND SPECIAL CASES
If the table has no nullable columns, then null_bytes is still
present, its length is one byte <not-sure> which must be set to 0xFF
at all times. </not-sure>
If the table has columns of type BIT, then certain bits from those columns
may be stored in null_bytes as well. Grep around for Field_bit for
details.
For blob columns (see Field_blob), the record buffer stores length of the
data, following by memory pointer to the blob data. The pointer is owned
by the storage engine and is valid until the next operation.
If a blob column has NULL value, then its length and blob data pointer
must be set to 0.
*/
class handler :public Sql_alloc
@ -2262,7 +2316,6 @@ public:
uint ref_length;
FT_INFO *ft_handler;
enum {NONE=0, INDEX, RND} inited;
bool locked;
bool implicit_emptied; /* Can be !=0 only if HEAP */
bool mark_trx_done;
const COND *pushed_cond;
@ -2323,6 +2376,21 @@ public:
virtual void unbind_psi();
virtual void rebind_psi();
private:
/**
The lock type set by when calling::ha_external_lock(). This is
propagated down to the storage engine. The reason for also storing
it here, is that when doing MRR we need to create/clone a second handler
object. This cloned handler object needs to know about the lock_type used.
*/
int m_lock_type;
/**
Pointer where to store/retrieve the Handler_share pointer.
For non partitioned handlers this is &TABLE_SHARE::ha_share.
*/
Handler_share **ha_share;
public:
handler(handlerton *ht_arg, TABLE_SHARE *share_arg)
:table_share(share_arg), table(0),
estimation_rows_to_insert(0), ht(ht_arg),
@ -2330,18 +2398,21 @@ public:
in_range_check_pushed_down(FALSE),
ref_length(sizeof(my_off_t)),
ft_handler(0), inited(NONE),
locked(FALSE), implicit_emptied(0), mark_trx_done(FALSE),
implicit_emptied(0), mark_trx_done(FALSE),
pushed_cond(0), next_insert_id(0), insert_id_for_cur_row(0),
pushed_idx_cond(NULL),
pushed_idx_cond_keyno(MAX_KEY),
auto_inc_intervals_count(0),
m_psi(NULL)
m_psi(NULL), m_lock_type(F_UNLCK), ha_share(NULL)
{
DBUG_PRINT("info",
("handler created F_UNLCK %d F_RDLCK %d F_WRLCK %d",
F_UNLCK, F_RDLCK, F_WRLCK));
reset_statistics();
}
virtual ~handler(void)
{
DBUG_ASSERT(locked == FALSE);
DBUG_ASSERT(m_lock_type == F_UNLCK);
DBUG_ASSERT(inited == NONE);
}
virtual handler *clone(const char *name, MEM_ROOT *mem_root);
@ -2456,7 +2527,6 @@ public:
int ha_disable_indexes(uint mode);
int ha_enable_indexes(uint mode);
int ha_discard_or_import_tablespace(my_bool discard);
void ha_prepare_for_alter();
int ha_rename_table(const char *from, const char *to);
int ha_delete_table(const char *name);
void ha_drop_table(const char *name);
@ -2756,6 +2826,7 @@ private:
*/
virtual int rnd_pos_by_record(uchar *record)
{
DBUG_ASSERT(table_flags() & HA_PRIMARY_KEY_REQUIRED_FOR_POSITION);
position(record);
return rnd_pos(record, ref);
}
@ -2871,10 +2942,15 @@ public:
{ return FALSE; }
virtual char* get_foreign_key_create_info()
{ return(NULL);} /* gets foreign key create string from InnoDB */
virtual char* get_tablespace_name(THD *thd, char *name, uint name_len)
{ return(NULL);} /* gets tablespace name from handler */
/** used in ALTER TABLE; 1 if changing storage engine is allowed */
virtual bool can_switch_engines() { return 1; }
/**
Used in ALTER TABLE to check if changing storage engine is allowed.
@note Called without holding thr_lock.c lock.
@retval true Changing storage engine is allowed.
@retval false Changing storage engine not allowed.
*/
virtual bool can_switch_engines() { return true; }
virtual int can_continue_handler_scan() { return 0; }
/**
Get the list of foreign keys in this table.
@ -2936,42 +3012,6 @@ public:
virtual ulong index_flags(uint idx, uint part, bool all_parts) const =0;
/**
First phase of in-place add index.
Handlers are supposed to create new indexes here but not make them
visible.
@param table_arg Table to add index to
@param key_info Information about new indexes
@param num_of_key Number of new indexes
@param add[out] Context of handler specific information needed
for final_add_index().
@note This function can be called with less than exclusive metadata
lock depending on which flags are listed in alter_table_flags.
*/
virtual int add_index(TABLE *table_arg, KEY *key_info, uint num_of_keys,
handler_add_index **add)
{ return (HA_ERR_WRONG_COMMAND); }
/**
Second and last phase of in-place add index.
Commit or rollback pending new indexes.
@param add Context of handler specific information from add_index().
@param commit If true, commit. If false, rollback index changes.
@note This function is called with exclusive metadata lock.
*/
virtual int final_add_index(handler_add_index *add, bool commit)
{ return (HA_ERR_WRONG_COMMAND); }
virtual int prepare_drop_index(TABLE *table_arg, uint *key_num,
uint num_of_keys)
{ return (HA_ERR_WRONG_COMMAND); }
virtual int final_drop_index(TABLE *table_arg)
{ return (HA_ERR_WRONG_COMMAND); }
uint max_record_length() const
{ return MY_MIN(HA_MAX_REC_LENGTH, max_supported_record_length()); }
uint max_keys() const
@ -3179,10 +3219,266 @@ public:
pushed_idx_cond_keyno= MAX_KEY;
in_range_check_pushed_down= false;
}
/**
Part of old, deprecated in-place ALTER API.
*/
virtual bool check_if_incompatible_data(HA_CREATE_INFO *create_info,
uint table_changes)
{ return COMPATIBLE_DATA_NO; }
/* On-line/in-place ALTER TABLE interface. */
/*
Here is an outline of on-line/in-place ALTER TABLE execution through
this interface.
Phase 1 : Initialization
========================
During this phase we determine which algorithm should be used
for execution of ALTER TABLE and what level concurrency it will
require.
*) This phase starts by opening the table and preparing description
of the new version of the table.
*) Then we check if it is impossible even in theory to carry out
this ALTER TABLE using the in-place algorithm. For example, because
we need to change storage engine or the user has explicitly requested
usage of the "copy" algorithm.
*) If in-place ALTER TABLE is theoretically possible, we continue
by compiling differences between old and new versions of the table
in the form of HA_ALTER_FLAGS bitmap. We also build a few
auxiliary structures describing requested changes and store
all these data in the Alter_inplace_info object.
*) Then the handler::check_if_supported_inplace_alter() method is called
in order to find if the storage engine can carry out changes requested
by this ALTER TABLE using the in-place algorithm. To determine this,
the engine can rely on data in HA_ALTER_FLAGS/Alter_inplace_info
passed to it as well as on its own checks. If the in-place algorithm
can be used for this ALTER TABLE, the level of required concurrency for
its execution is also returned.
If any errors occur during the handler call, ALTER TABLE is aborted
and no further handler functions are called.
*) Locking requirements of the in-place algorithm are compared to any
concurrency requirements specified by user. If there is a conflict
between them, we either switch to the copy algorithm or emit an error.
Phase 2 : Execution
===================
In this phase the operations are executed.
*) As the first step, we acquire a lock corresponding to the concurrency
level which was returned by handler::check_if_supported_inplace_alter()
and requested by the user. This lock is held for most of the
duration of in-place ALTER (if HA_ALTER_INPLACE_SHARED_LOCK_AFTER_PREPARE
or HA_ALTER_INPLACE_NO_LOCK_AFTER_PREPARE were returned we acquire an
exclusive lock for duration of the next step only).
*) After that we call handler::ha_prepare_inplace_alter_table() to give the
storage engine a chance to update its internal structures with a higher
lock level than the one that will be used for the main step of algorithm.
After that we downgrade the lock if it is necessary.
*) After that, the main step of this phase and algorithm is executed.
We call the handler::ha_inplace_alter_table() method, which carries out the
changes requested by ALTER TABLE but does not makes them visible to other
connections yet.
*) We ensure that no other connection uses the table by upgrading our
lock on it to exclusive.
*) a) If the previous step succeeds, handler::ha_commit_inplace_alter_table() is
called to allow the storage engine to do any final updates to its structures,
to make all earlier changes durable and visible to other connections.
b) If we have failed to upgrade lock or any errors have occured during the
handler functions calls (including commit), we call
handler::ha_commit_inplace_alter_table()
to rollback all changes which were done during previous steps.
Phase 3 : Final
===============
In this phase we:
*) Update SQL-layer data-dictionary by installing .FRM file for the new version
of the table.
*) Inform the storage engine about this change by calling the
handler::ha_notify_table_changed() method.
*) Destroy the Alter_inplace_info and handler_ctx objects.
*/
/**
Check if a storage engine supports a particular alter table in-place
@param altered_table TABLE object for new version of table.
@param ha_alter_info Structure describing changes to be done
by ALTER TABLE and holding data used
during in-place alter.
@retval HA_ALTER_ERROR Unexpected error.
@retval HA_ALTER_INPLACE_NOT_SUPPORTED Not supported, must use copy.
@retval HA_ALTER_INPLACE_EXCLUSIVE_LOCK Supported, but requires X lock.
@retval HA_ALTER_INPLACE_SHARED_LOCK_AFTER_PREPARE
Supported, but requires SNW lock
during main phase. Prepare phase
requires X lock.
@retval HA_ALTER_INPLACE_SHARED_LOCK Supported, but requires SNW lock.
@retval HA_ALTER_INPLACE_NO_LOCK_AFTER_PREPARE
Supported, concurrent reads/writes
allowed. However, prepare phase
requires X lock.
@retval HA_ALTER_INPLACE_NO_LOCK Supported, concurrent
reads/writes allowed.
@note The default implementation uses the old in-place ALTER API
to determine if the storage engine supports in-place ALTER or not.
@note Called without holding thr_lock.c lock.
*/
virtual enum_alter_inplace_result
check_if_supported_inplace_alter(TABLE *altered_table,
Alter_inplace_info *ha_alter_info);
/**
Public functions wrapping the actual handler call.
@see prepare_inplace_alter_table()
*/
bool ha_prepare_inplace_alter_table(TABLE *altered_table,
Alter_inplace_info *ha_alter_info);
/**
Public function wrapping the actual handler call.
@see inplace_alter_table()
*/
bool ha_inplace_alter_table(TABLE *altered_table,
Alter_inplace_info *ha_alter_info)
{
return inplace_alter_table(altered_table, ha_alter_info);
}
/**
Public function wrapping the actual handler call.
Allows us to enforce asserts regardless of handler implementation.
@see commit_inplace_alter_table()
*/
bool ha_commit_inplace_alter_table(TABLE *altered_table,
Alter_inplace_info *ha_alter_info,
bool commit);
/**
Public function wrapping the actual handler call.
@see notify_table_changed()
*/
void ha_notify_table_changed()
{
notify_table_changed();
}
protected:
/**
Allows the storage engine to update internal structures with concurrent
writes blocked. If check_if_supported_inplace_alter() returns
HA_ALTER_INPLACE_NO_LOCK_AFTER_PREPARE or
HA_ALTER_INPLACE_SHARED_AFTER_PREPARE, this function is called with
exclusive lock otherwise the same level of locking as for
inplace_alter_table() will be used.
@note Storage engines are responsible for reporting any errors by
calling my_error()/print_error()
@note If this function reports error, commit_inplace_alter_table()
will be called with commit= false.
@note For partitioning, failing to prepare one partition, means that
commit_inplace_alter_table() will be called to roll back changes for
all partitions. This means that commit_inplace_alter_table() might be
called without prepare_inplace_alter_table() having been called first
for a given partition.
@param altered_table TABLE object for new version of table.
@param ha_alter_info Structure describing changes to be done
by ALTER TABLE and holding data used
during in-place alter.
@retval true Error
@retval false Success
*/
virtual bool prepare_inplace_alter_table(TABLE *altered_table,
Alter_inplace_info *ha_alter_info)
{ return false; }
/**
Alter the table structure in-place with operations specified using HA_ALTER_FLAGS
and Alter_inplace_info. The level of concurrency allowed during this
operation depends on the return value from check_if_supported_inplace_alter().
@note Storage engines are responsible for reporting any errors by
calling my_error()/print_error()
@note If this function reports error, commit_inplace_alter_table()
will be called with commit= false.
@param altered_table TABLE object for new version of table.
@param ha_alter_info Structure describing changes to be done
by ALTER TABLE and holding data used
during in-place alter.
@retval true Error
@retval false Success
*/
virtual bool inplace_alter_table(TABLE *altered_table,
Alter_inplace_info *ha_alter_info)
{ return false; }
/**
Commit or rollback the changes made during prepare_inplace_alter_table()
and inplace_alter_table() inside the storage engine.
Note that in case of rollback the allowed level of concurrency during
this operation will be the same as for inplace_alter_table() and thus
might be higher than during prepare_inplace_alter_table(). (For example,
concurrent writes were blocked during prepare, but might not be during
rollback).
@note Storage engines are responsible for reporting any errors by
calling my_error()/print_error()
@note If this function with commit= true reports error, it will be called
again with commit= false.
@note In case of partitioning, this function might be called for rollback
without prepare_inplace_alter_table() having been called first.
@see prepare_inplace_alter_table().
@param altered_table TABLE object for new version of table.
@param ha_alter_info Structure describing changes to be done
by ALTER TABLE and holding data used
during in-place alter.
@param commit True => Commit, False => Rollback.
@retval true Error
@retval false Success
*/
virtual bool commit_inplace_alter_table(TABLE *altered_table,
Alter_inplace_info *ha_alter_info,
bool commit)
{ return false; }
/**
Notify the storage engine that the table structure (.FRM) has been updated.
@note No errors are allowed during notify_table_changed().
*/
virtual void notify_table_changed();
public:
/* End of On-line/in-place ALTER TABLE interface. */
/**
use_hidden_primary_key() is called in case of an update/delete when
(table_flags() and HA_PRIMARY_KEY_REQUIRED_FOR_DELETE) is defined
@ -3226,32 +3522,6 @@ protected:
*/
PSI_table_share *ha_table_share_psi(const TABLE_SHARE *share) const;
inline void psi_open()
{
DBUG_ASSERT(m_psi == NULL);
DBUG_ASSERT(table_share != NULL);
#ifdef HAVE_PSI_INTERFACE
if (PSI_server)
{
PSI_table_share *share_psi= ha_table_share_psi(table_share);
if (share_psi)
m_psi= PSI_server->open_table(share_psi, this);
}
#endif
}
inline void psi_close()
{
#ifdef HAVE_PSI_INTERFACE
if (PSI_server && m_psi)
{
PSI_server->close_table(m_psi);
m_psi= NULL; /* instrumentation handle, invalid after close_table() */
}
#endif
DBUG_ASSERT(m_psi == NULL);
}
/**
Default rename_table() and delete_table() rename/delete files with a
given name and extensions from bas_ext().
@ -3301,6 +3571,14 @@ private:
return HA_ERR_WRONG_COMMAND;
}
/**
Update a single row.
Note: If HA_ERR_FOUND_DUPP_KEY is returned, the handler must read
all columns of the row so MySQL can create an error message. If
the columns required for the error message are not read, the error
message will contain garbage.
*/
virtual int update_row(const uchar *old_data __attribute__((unused)),
uchar *new_data __attribute__((unused)))
{
@ -3364,9 +3642,12 @@ private:
}
virtual void start_bulk_insert(ha_rows rows, uint flags) {}
virtual int end_bulk_insert() { return 0; }
protected:
virtual int index_read(uchar * buf, const uchar * key, uint key_len,
enum ha_rkey_function find_flag)
{ return HA_ERR_WRONG_COMMAND; }
friend class ha_partition;
public:
/**
This method is similar to update_row, however the handler doesn't need
to execute the updates at this point in time. The handler can be certain
@ -3451,7 +3732,16 @@ private:
{ return HA_ERR_WRONG_COMMAND; }
virtual int rename_partitions(const char *path)
{ return HA_ERR_WRONG_COMMAND; }
friend class ha_partition;
virtual bool set_ha_share_ref(Handler_share **arg_ha_share)
{
DBUG_ASSERT(!ha_share);
DBUG_ASSERT(arg_ha_share);
if (ha_share || !arg_ha_share)
return true;
ha_share= arg_ha_share;
return false;
}
int get_lock_type() const { return m_lock_type; }
public:
/* XXX to be removed, see ha_partition::partition_ht() */
virtual handlerton *partition_ht() const
@ -3460,6 +3750,11 @@ public:
inline int ha_update_tmp_row(const uchar * old_data, uchar * new_data);
friend enum icp_result handler_index_cond_check(void* h_arg);
protected:
Handler_share *get_ha_share_ptr();
void set_ha_share_ptr(Handler_share *arg_ha_share);
void lock_shared_ha_data();
void unlock_shared_ha_data();
};
#include "multi_range_read.h"
@ -3541,6 +3836,8 @@ int ha_discover(THD* thd, const char* dbname, const char* name,
int ha_find_files(THD *thd,const char *db,const char *path,
const char *wild, bool dir, List<LEX_STRING>* files);
int ha_table_exists_in_engine(THD* thd, const char* db, const char* name);
bool ha_check_if_supported_system_table(handlerton *hton, const char* db,
const char* table_name);
/* key cache */
extern "C" int ha_init_key_cache(const char *name, KEY_CACHE *key_cache, void *);

View file

@ -341,7 +341,7 @@ my_decimal *Item::val_decimal_from_string(my_decimal *decimal_value)
decimal_value) & E_DEC_BAD_NUM)
{
ErrConvString err(res);
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
ER_TRUNCATED_WRONG_VALUE,
ER(ER_TRUNCATED_WRONG_VALUE), "DECIMAL",
err.ptr());
@ -980,11 +980,11 @@ void Item::set_name(const char *str, uint length, CHARSET_INFO *cs)
MY_MIN(sizeof(buff)-1, length + (int) (str-str_start)));
if (length == 0)
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
ER_NAME_BECOMES_EMPTY, ER(ER_NAME_BECOMES_EMPTY),
buff);
else
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
ER_REMOVED_SPACES, ER(ER_REMOVED_SPACES),
buff);
}
@ -1126,12 +1126,27 @@ Item *Item_static_float_func::safe_charset_converter(CHARSET_INFO *tocs)
Item *Item_string::safe_charset_converter(CHARSET_INFO *tocs)
{
return charset_converter(tocs, true);
}
/**
Convert a string item into the requested character set.
@param tocs Character set to to convert the string to.
@param lossless Whether data loss is acceptable.
@return A new item representing the converted string.
*/
Item *Item_string::charset_converter(CHARSET_INFO *tocs, bool lossless)
{
Item_string *conv;
uint conv_errors;
char *ptr;
String tmp, cstr, *ostr= val_str(&tmp);
cstr.copy(ostr->ptr(), ostr->length(), ostr->charset(), tocs, &conv_errors);
conv_errors= lossless && conv_errors;
if (conv_errors || !(conv= new Item_string(cstr.ptr(), cstr.length(),
cstr.charset(),
collation.derivation)))
@ -1152,7 +1167,6 @@ Item *Item_string::safe_charset_converter(CHARSET_INFO *tocs)
return conv;
}
Item *Item_param::safe_charset_converter(CHARSET_INFO *tocs)
{
if (const_item())
@ -2966,7 +2980,7 @@ double_from_string_with_check(CHARSET_INFO *cs, const char *cptr,
We can use err.ptr() here as ErrConvString is guranteed to put an
end \0 here.
*/
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
ER_TRUNCATED_WRONG_VALUE,
ER(ER_TRUNCATED_WRONG_VALUE), "DOUBLE",
err.ptr());
@ -3003,7 +3017,7 @@ longlong_from_string_with_check(CHARSET_INFO *cs, const char *cptr,
(end != end_of_num && !check_if_only_end_space(cs, end_of_num, end))))
{
ErrConvString err(cptr, end - cptr, cs);
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
ER_TRUNCATED_WRONG_VALUE,
ER(ER_TRUNCATED_WRONG_VALUE), "INTEGER",
err.ptr());
@ -3216,7 +3230,7 @@ void Item_param::set_time(MYSQL_TIME *tm, timestamp_type time_type,
value.time.second_part > TIME_MAX_SECOND_PART)
{
ErrConvTime str(&value.time);
make_truncated_value_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
make_truncated_value_warning(current_thd, Sql_condition::WARN_LEVEL_WARN,
&str, time_type, 0);
set_zero_time(&value.time, MYSQL_TIMESTAMP_ERROR);
}
@ -4293,7 +4307,7 @@ static bool mark_as_dependent(THD *thd, SELECT_LEX *last, SELECT_LEX *current,
return TRUE;
if (thd->lex->describe & DESCRIBE_EXTENDED)
{
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
ER_WARN_FIELD_RESOLVED, ER(ER_WARN_FIELD_RESOLVED),
db_name, (db_name[0] ? "." : ""),
table_name, (table_name [0] ? "." : ""),
@ -4541,7 +4555,7 @@ resolve_ref_in_select_and_group(THD *thd, Item_ident *ref, SELECT_LEX *select)
!((*group_by_ref)->eq(*select_ref, 0)))
{
ambiguous_fields= TRUE;
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_NON_UNIQ_ERROR,
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_NON_UNIQ_ERROR,
ER(ER_NON_UNIQ_ERROR), ref->full_name(),
current_thd->where);
@ -5523,7 +5537,7 @@ String *Item::check_well_formed_result(String *str, bool send_error)
{
str->length(wlen);
}
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_INVALID_CHARACTER_STRING,
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_INVALID_CHARACTER_STRING,
ER(ER_INVALID_CHARACTER_STRING), cs->csname, hexbuf);
}
return str;
@ -6203,7 +6217,7 @@ int Item_hex_string::save_in_field(Field *field, bool no_conversions)
warn:
if (!field->store((longlong) nr, TRUE))
field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE,
field->set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE,
1);
return 1;
}
@ -8134,7 +8148,7 @@ int Item_default_value::save_in_field(Field *field_arg, bool no_conversions)
{
TABLE_LIST *view= cached_table->top_table();
push_warning_printf(field_arg->table->in_use,
MYSQL_ERROR::WARN_LEVEL_WARN,
Sql_condition::WARN_LEVEL_WARN,
ER_NO_DEFAULT_FOR_VIEW_FIELD,
ER(ER_NO_DEFAULT_FOR_VIEW_FIELD),
view->view_db.str,
@ -8143,7 +8157,7 @@ int Item_default_value::save_in_field(Field *field_arg, bool no_conversions)
else
{
push_warning_printf(field_arg->table->in_use,
MYSQL_ERROR::WARN_LEVEL_WARN,
Sql_condition::WARN_LEVEL_WARN,
ER_NO_DEFAULT_FOR_FIELD,
ER(ER_NO_DEFAULT_FOR_FIELD),
field_arg->field_name);

View file

@ -1365,7 +1365,7 @@ public:
virtual void bring_value() {}
Field *tmp_table_field_from_field_type(TABLE *table, bool fixed_length);
virtual Item_field *filed_for_view_update() { return 0; }
virtual Item_field *field_for_view_update() { return 0; }
virtual Item *neg_transformer(THD *thd) { return NULL; }
virtual Item *update_value_transformer(uchar *select_arg) { return this; }
@ -2079,7 +2079,7 @@ public:
bool set_no_const_sub(uchar *arg);
Item *replace_equal_field(uchar *arg);
inline uint32 max_disp_length() { return field->max_display_length(); }
Item_field *filed_for_view_update() { return this; }
Item_field *field_for_view_update() { return this; }
Item *safe_charset_converter(CHARSET_INFO *tocs);
int fix_outer_field(THD *thd, Field **field, Item **reference);
virtual Item *update_value_transformer(uchar *select_arg);
@ -2570,6 +2570,7 @@ public:
str_value.length(), collation.collation);
}
Item *safe_charset_converter(CHARSET_INFO *tocs);
Item *charset_converter(CHARSET_INFO *tocs, bool lossless);
inline void append(char *str, uint length)
{
str_value.append(str, length);
@ -2914,8 +2915,8 @@ public:
}
virtual void print(String *str, enum_query_type query_type);
void cleanup();
Item_field *filed_for_view_update()
{ return (*ref)->filed_for_view_update(); }
Item_field *field_for_view_update()
{ return (*ref)->field_for_view_update(); }
virtual Ref_Type ref_type() { return REF; }
// Row emulation: forwarding of ROW-related calls to ref
@ -3121,8 +3122,8 @@ public:
}
bool enumerate_field_refs_processor(uchar *arg)
{ return orig_item->enumerate_field_refs_processor(arg); }
Item_field *filed_for_view_update()
{ return orig_item->filed_for_view_update(); }
Item_field *field_for_view_update()
{ return orig_item->field_for_view_update(); }
/* Row emulation: forwarding of ROW-related calls to orig_item */
uint cols()

View file

@ -746,7 +746,7 @@ bool get_mysql_time_from_str(THD *thd, String *str, timestamp_type warn_type,
}
if (error > 0)
make_truncated_value_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
make_truncated_value_warning(thd, Sql_condition::WARN_LEVEL_WARN,
&err, warn_type, warn_name);
return value;

View file

@ -2053,19 +2053,6 @@ protected:
};
class Create_func_row_count : public Create_func_arg0
{
public:
virtual Item *create_builder(THD *thd);
static Create_func_row_count s_singleton;
protected:
Create_func_row_count() {}
virtual ~Create_func_row_count() {}
};
class Create_func_rpad : public Create_func_arg3
{
public:
@ -4795,18 +4782,6 @@ Create_func_round::create_native(THD *thd, LEX_STRING name,
}
Create_func_row_count Create_func_row_count::s_singleton;
Item*
Create_func_row_count::create_builder(THD *thd)
{
DBUG_ENTER("Create_func_row_count::create");
thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION);
thd->lex->safe_to_cache_query= 0;
DBUG_RETURN(new (thd->mem_root) Item_func_row_count());
}
Create_func_rpad Create_func_rpad::s_singleton;
Item*
@ -5475,7 +5450,6 @@ static Native_func_registry func_array[] =
{ { C_STRING_WITH_LEN("RELEASE_LOCK") }, BUILDER(Create_func_release_lock)},
{ { C_STRING_WITH_LEN("REVERSE") }, BUILDER(Create_func_reverse)},
{ { C_STRING_WITH_LEN("ROUND") }, BUILDER(Create_func_round)},
{ { C_STRING_WITH_LEN("ROW_COUNT") }, BUILDER(Create_func_row_count)},
{ { C_STRING_WITH_LEN("RPAD") }, BUILDER(Create_func_rpad)},
{ { C_STRING_WITH_LEN("RTRIM") }, BUILDER(Create_func_rtrim)},
{ { C_STRING_WITH_LEN("SEC_TO_TIME") }, BUILDER(Create_func_sec_to_time)},

View file

@ -695,7 +695,7 @@ void Item_func::signal_divide_by_null()
{
THD *thd= current_thd;
if (thd->variables.sql_mode & MODE_ERROR_FOR_DIVISION_BY_ZERO)
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_DIVISION_BY_ZERO,
push_warning(thd, Sql_condition::WARN_LEVEL_WARN, ER_DIVISION_BY_ZERO,
ER(ER_DIVISION_BY_ZERO));
null_value= 1;
}
@ -1030,7 +1030,7 @@ longlong Item_func_signed::val_int_from_str(int *error)
char err_buff[128];
String err_tmp(err_buff,(uint32) sizeof(err_buff), system_charset_info);
err_tmp.copy(start, length, system_charset_info);
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
ER_TRUNCATED_WRONG_VALUE,
ER(ER_TRUNCATED_WRONG_VALUE), "INTEGER",
err_tmp.c_ptr());
@ -1067,7 +1067,7 @@ longlong Item_func_signed::val_int()
return value;
err:
push_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_UNKNOWN_ERROR,
push_warning(current_thd, Sql_condition::WARN_LEVEL_NOTE, ER_UNKNOWN_ERROR,
"Cast to signed converted positive out-of-range integer to "
"it's negative complement");
return value;
@ -1123,7 +1123,7 @@ longlong Item_func_unsigned::val_int()
return value;
err:
push_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_UNKNOWN_ERROR,
push_warning(current_thd, Sql_condition::WARN_LEVEL_NOTE, ER_UNKNOWN_ERROR,
"Cast to unsigned converted negative integer to it's "
"positive complement");
return value;
@ -1191,7 +1191,7 @@ my_decimal *Item_decimal_typecast::val_decimal(my_decimal *dec)
return dec;
err:
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
ER_WARN_DATA_OUT_OF_RANGE,
ER(ER_WARN_DATA_OUT_OF_RANGE),
name, 1L);
@ -1233,7 +1233,7 @@ double Item_double_typecast::val_real()
if ((error= truncate_double(&tmp, max_length, decimals, 0, DBL_MAX)))
{
push_warning_printf(current_thd,
MYSQL_ERROR::WARN_LEVEL_WARN,
Sql_condition::WARN_LEVEL_WARN,
ER_WARN_DATA_OUT_OF_RANGE,
ER(ER_WARN_DATA_OUT_OF_RANGE),
name, 1);
@ -3891,7 +3891,7 @@ longlong Item_master_pos_wait::val_int()
connection_name= thd->variables.default_master_connection;
if (!(mi= master_info_index->get_master_info(&connection_name,
MYSQL_ERROR::WARN_LEVEL_WARN)))
Sql_condition::WARN_LEVEL_WARN)))
goto err;
if ((event_count = mi->rli.wait_for_pos(thd, log_name, pos, timeout)) == -2)
{
@ -4229,7 +4229,7 @@ longlong Item_func_benchmark::val_int()
{
char buff[22];
llstr(((longlong) loop_count), buff);
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
ER_WRONG_VALUE_FOR_TYPE, ER(ER_WRONG_VALUE_FOR_TYPE),
"count", buff, "benchmark");
}

View file

@ -500,7 +500,7 @@ String *Item_func_spatial_collection::val_str(String *str)
}
if (str->length() > current_thd->variables.max_allowed_packet)
{
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
ER_WARN_ALLOWED_PACKET_OVERFLOWED,
ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED),
func_name(), current_thd->variables.max_allowed_packet);

View file

@ -282,9 +282,9 @@ String *Item_func_sha2::val_str_ascii(String *str)
default:
if (!args[1]->const_item())
push_warning_printf(current_thd,
MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WRONG_PARAMETERS_TO_NATIVE_FCT,
ER(ER_WRONG_PARAMETERS_TO_NATIVE_FCT), "sha2");
Sql_condition::WARN_LEVEL_WARN,
ER_WRONG_PARAMETERS_TO_NATIVE_FCT,
ER(ER_WRONG_PARAMETERS_TO_NATIVE_FCT), "sha2");
null_value= TRUE;
return NULL;
}
@ -306,7 +306,7 @@ String *Item_func_sha2::val_str_ascii(String *str)
#else
push_warning_printf(current_thd,
MYSQL_ERROR::WARN_LEVEL_WARN,
Sql_condition::WARN_LEVEL_WARN,
ER_FEATURE_DISABLED,
ER(ER_FEATURE_DISABLED),
"sha2", "--with-ssl");
@ -344,7 +344,7 @@ void Item_func_sha2::fix_length_and_dec()
#endif
default:
push_warning_printf(current_thd,
MYSQL_ERROR::WARN_LEVEL_WARN,
Sql_condition::WARN_LEVEL_WARN,
ER_WRONG_PARAMETERS_TO_NATIVE_FCT,
ER(ER_WRONG_PARAMETERS_TO_NATIVE_FCT), "sha2");
}
@ -363,7 +363,7 @@ void Item_func_sha2::fix_length_and_dec()
DERIVATION_COERCIBLE);
#else
push_warning_printf(current_thd,
MYSQL_ERROR::WARN_LEVEL_WARN,
Sql_condition::WARN_LEVEL_WARN,
ER_FEATURE_DISABLED,
ER(ER_FEATURE_DISABLED),
"sha2", "--with-ssl");
@ -489,7 +489,7 @@ String *Item_func_concat::val_str(String *str)
if (res->length()+res2->length() >
current_thd->variables.max_allowed_packet)
{
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
ER_WARN_ALLOWED_PACKET_OVERFLOWED,
ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED), func_name(),
current_thd->variables.max_allowed_packet);
@ -695,11 +695,11 @@ String *Item_func_des_encrypt::val_str(String *str)
return &tmp_value;
error:
push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(current_thd,Sql_condition::WARN_LEVEL_WARN,
code, ER(code),
"des_encrypt");
#else
push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(current_thd,Sql_condition::WARN_LEVEL_WARN,
ER_FEATURE_DISABLED, ER(ER_FEATURE_DISABLED),
"des_encrypt", "--with-ssl");
#endif /* defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY) */
@ -773,12 +773,12 @@ String *Item_func_des_decrypt::val_str(String *str)
return &tmp_value;
error:
push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(current_thd,Sql_condition::WARN_LEVEL_WARN,
code, ER(code),
"des_decrypt");
wrong_key:
#else
push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(current_thd,Sql_condition::WARN_LEVEL_WARN,
ER_FEATURE_DISABLED, ER(ER_FEATURE_DISABLED),
"des_decrypt", "--with-ssl");
#endif /* defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY) */
@ -829,7 +829,7 @@ String *Item_func_concat_ws::val_str(String *str)
if (res->length() + sep_str->length() + res2->length() >
current_thd->variables.max_allowed_packet)
{
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
ER_WARN_ALLOWED_PACKET_OVERFLOWED,
ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED), func_name(),
current_thd->variables.max_allowed_packet);
@ -1088,7 +1088,7 @@ redo:
if (res->length()-from_length + to_length >
current_thd->variables.max_allowed_packet)
{
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
ER_WARN_ALLOWED_PACKET_OVERFLOWED,
ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED),
func_name(),
@ -1117,7 +1117,7 @@ skip:
if (res->length()-from_length + to_length >
current_thd->variables.max_allowed_packet)
{
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
ER_WARN_ALLOWED_PACKET_OVERFLOWED,
ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED), func_name(),
current_thd->variables.max_allowed_packet);
@ -1204,7 +1204,7 @@ String *Item_func_insert::val_str(String *str)
if ((ulonglong) (res->length() - length + res2->length()) >
(ulonglong) current_thd->variables.max_allowed_packet)
{
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
ER_WARN_ALLOWED_PACKET_OVERFLOWED,
ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED),
func_name(), current_thd->variables.max_allowed_packet);
@ -2230,7 +2230,7 @@ MY_LOCALE *Item_func_format::get_locale(Item *item)
if (!locale_name ||
!(lc= my_locale_by_name(locale_name->c_ptr_safe())))
{
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
ER_UNKNOWN_LOCALE,
ER(ER_UNKNOWN_LOCALE),
locale_name ? locale_name->c_ptr_safe() : "NULL");
@ -2675,7 +2675,7 @@ String *Item_func_repeat::val_str(String *str)
// Safe length check
if (length > current_thd->variables.max_allowed_packet / (uint) count)
{
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
ER_WARN_ALLOWED_PACKET_OVERFLOWED,
ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED),
func_name(), current_thd->variables.max_allowed_packet);
@ -2768,7 +2768,7 @@ String *Item_func_rpad::val_str(String *str)
byte_count= count * collation.collation->mbmaxlen;
if ((ulonglong) byte_count > current_thd->variables.max_allowed_packet)
{
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
ER_WARN_ALLOWED_PACKET_OVERFLOWED,
ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED),
func_name(), current_thd->variables.max_allowed_packet);
@ -2876,7 +2876,7 @@ String *Item_func_lpad::val_str(String *str)
if ((ulonglong) byte_count > current_thd->variables.max_allowed_packet)
{
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
ER_WARN_ALLOWED_PACKET_OVERFLOWED,
ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED),
func_name(), current_thd->variables.max_allowed_packet);
@ -3254,7 +3254,7 @@ String *Item_load_file::val_str(String *str)
}
if (stat_info.st_size > (long) current_thd->variables.max_allowed_packet)
{
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
ER_WARN_ALLOWED_PACKET_OVERFLOWED,
ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED),
func_name(), current_thd->variables.max_allowed_packet);
@ -3345,7 +3345,7 @@ String* Item_func_export_set::val_str(String* str)
if (unlikely(max_total_length > max_allowed_packet))
{
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
ER_WARN_ALLOWED_PACKET_OVERFLOWED,
ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED),
func_name(), max_allowed_packet);
@ -3593,7 +3593,7 @@ longlong Item_func_uncompressed_length::val_int()
*/
if (res->length() <= 4)
{
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
ER_ZLIB_Z_DATA_ERROR,
ER(ER_ZLIB_Z_DATA_ERROR));
null_value= 1;
@ -3670,7 +3670,7 @@ String *Item_func_compress::val_str(String *str)
res->length())) != Z_OK)
{
code= err==Z_MEM_ERROR ? ER_ZLIB_Z_MEM_ERROR : ER_ZLIB_Z_BUF_ERROR;
push_warning(current_thd,MYSQL_ERROR::WARN_LEVEL_WARN,code,ER(code));
push_warning(current_thd,Sql_condition::WARN_LEVEL_WARN,code,ER(code));
null_value= 1;
return 0;
}
@ -3708,7 +3708,7 @@ String *Item_func_uncompress::val_str(String *str)
/* If length is less than 4 bytes, data is corrupt */
if (res->length() <= 4)
{
push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(current_thd,Sql_condition::WARN_LEVEL_WARN,
ER_ZLIB_Z_DATA_ERROR,
ER(ER_ZLIB_Z_DATA_ERROR));
goto err;
@ -3718,7 +3718,7 @@ String *Item_func_uncompress::val_str(String *str)
new_size= uint4korr(res->ptr()) & 0x3FFFFFFF;
if (new_size > current_thd->variables.max_allowed_packet)
{
push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(current_thd,Sql_condition::WARN_LEVEL_WARN,
ER_TOO_BIG_FOR_UNCOMPRESS,
ER(ER_TOO_BIG_FOR_UNCOMPRESS),
static_cast<int>(current_thd->variables.
@ -3737,7 +3737,7 @@ String *Item_func_uncompress::val_str(String *str)
code= ((err == Z_BUF_ERROR) ? ER_ZLIB_Z_BUF_ERROR :
((err == Z_MEM_ERROR) ? ER_ZLIB_Z_MEM_ERROR : ER_ZLIB_Z_DATA_ERROR));
push_warning(current_thd,MYSQL_ERROR::WARN_LEVEL_WARN,code,ER(code));
push_warning(current_thd,Sql_condition::WARN_LEVEL_WARN,code,ER(code));
err:
null_value= 1;
@ -4423,7 +4423,7 @@ longlong Item_dyncol_get::val_int()
{
char buff[30];
sprintf(buff, "%lg", val.x.double_value);
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
ER_DATA_OVERFLOW,
ER(ER_DATA_OVERFLOW),
buff,
@ -4443,7 +4443,7 @@ longlong Item_dyncol_get::val_int()
char buff[80];
strmake(buff, val.x.string.value.str, MY_MIN(sizeof(buff)-1,
val.x.string.value.length));
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
ER_BAD_DATA,
ER(ER_BAD_DATA),
buff,
@ -4507,7 +4507,7 @@ double Item_dyncol_get::val_real()
char buff[80];
strmake(buff, val.x.string.value.str, MY_MIN(sizeof(buff)-1,
val.x.string.value.length));
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
ER_BAD_DATA,
ER(ER_BAD_DATA),
buff, "DOUBLE");
@ -4565,7 +4565,7 @@ my_decimal *Item_dyncol_get::val_decimal(my_decimal *decimal_value)
val.x.string.value.length));
if (rc != E_DEC_OK)
{
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
ER_BAD_DATA,
ER(ER_BAD_DATA),
buff, "DECIMAL");

View file

@ -897,7 +897,7 @@ public:
Item_field *filed_for_view_update()
{
/* this function is transparent for view updating */
return args[0]->filed_for_view_update();
return args[0]->field_for_view_update();
}
};

View file

@ -1063,7 +1063,7 @@ Item_singlerow_subselect::select_transformer(JOIN *join)
{
char warn_buff[MYSQL_ERRMSG_SIZE];
sprintf(warn_buff, ER(ER_SELECT_REDUCED), select_lex->select_number);
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
push_warning(thd, Sql_condition::WARN_LEVEL_NOTE,
ER_SELECT_REDUCED, warn_buff);
}
substitution= select_lex->item_list.head();
@ -1727,7 +1727,7 @@ Item_in_subselect::single_value_transformer(JOIN *join)
{
char warn_buff[MYSQL_ERRMSG_SIZE];
sprintf(warn_buff, ER(ER_SELECT_REDUCED), select_lex->select_number);
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
push_warning(thd, Sql_condition::WARN_LEVEL_NOTE,
ER_SELECT_REDUCED, warn_buff);
}
DBUG_RETURN(false);

View file

@ -3067,7 +3067,7 @@ int dump_leaf_key(void* key_arg, element_count count __attribute__((unused)),
&well_formed_error);
result->length(old_length + add_length);
item->warning_for_row= TRUE;
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
ER_CUT_VALUE_GROUP_CONCAT, ER(ER_CUT_VALUE_GROUP_CONCAT),
item->row_count);

View file

@ -425,7 +425,7 @@ static bool extract_date_time(DATE_TIME_FORMAT *format,
{
if (!my_isspace(&my_charset_latin1,*val))
{
make_truncated_value_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
make_truncated_value_warning(current_thd, Sql_condition::WARN_LEVEL_WARN,
val_begin, length,
cached_timestamp_type, NullS);
break;
@ -438,7 +438,7 @@ err:
{
char buff[128];
strmake(buff, val_begin, MY_MIN(length, sizeof(buff)-1));
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
ER_WRONG_VALUE_FOR_TYPE, ER(ER_WRONG_VALUE_FOR_TYPE),
date_time_type, buff, "str_to_date");
}
@ -1721,7 +1721,7 @@ overflow:
ltime->hour= TIME_MAX_HOUR+1;
check_time_range(ltime, decimals, &unused);
make_truncated_value_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
make_truncated_value_warning(current_thd, Sql_condition::WARN_LEVEL_WARN,
err->ptr(), err->length(),
MYSQL_TIMESTAMP_TIME, NullS);
return 0;
@ -2270,7 +2270,7 @@ String *Item_char_typecast::val_str(String *str)
if (cast_length != ~0U &&
cast_length > current_thd->variables.max_allowed_packet)
{
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
ER_WARN_ALLOWED_PACKET_OVERFLOWED,
ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED),
cast_cs == &my_charset_bin ?
@ -2328,7 +2328,7 @@ String *Item_char_typecast::val_str(String *str)
res= &str_value;
}
ErrConvString err(res);
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
ER_TRUNCATED_WRONG_VALUE,
ER(ER_TRUNCATED_WRONG_VALUE), char_type,
err.ptr());
@ -2350,7 +2350,7 @@ String *Item_char_typecast::val_str(String *str)
if (res->length() > current_thd->variables.max_allowed_packet)
{
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
ER_WARN_ALLOWED_PACKET_OVERFLOWED,
ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED),
cast_cs == &my_charset_bin ?
@ -2442,7 +2442,7 @@ bool Item_date_typecast::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date)
fuzzy_date, &unused))
{
ErrConvTime str(ltime);
make_truncated_value_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
make_truncated_value_warning(current_thd, Sql_condition::WARN_LEVEL_WARN,
&str, MYSQL_TIMESTAMP_DATE, 0);
return (null_value= 1);
}
@ -2468,7 +2468,7 @@ bool Item_datetime_typecast::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date)
if (ltime->neg)
{
ErrConvTime str(ltime);
make_truncated_value_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
make_truncated_value_warning(current_thd, Sql_condition::WARN_LEVEL_WARN,
&str, MYSQL_TIMESTAMP_DATETIME, 0);
return (null_value= 1);
}
@ -2622,7 +2622,7 @@ bool Item_func_add_time::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date)
check_time_range(ltime, decimals, &was_cut);
if (was_cut)
make_truncated_value_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
make_truncated_value_warning(current_thd, Sql_condition::WARN_LEVEL_WARN,
&str, MYSQL_TIMESTAMP_TIME, NullS);
return (null_value= 0);
@ -2710,7 +2710,7 @@ bool Item_func_timediff::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date)
check_time_range(ltime, decimals, &was_cut);
if (was_cut)
make_truncated_value_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
make_truncated_value_warning(current_thd, Sql_condition::WARN_LEVEL_WARN,
&str, MYSQL_TIMESTAMP_TIME, NullS);
return (null_value= 0);
}
@ -2762,7 +2762,7 @@ bool Item_func_maketime::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date)
char buf[28];
char *ptr= longlong10_to_str(hour, buf, args[0]->unsigned_flag ? 10 : -10);
int len = (int)(ptr - buf) + sprintf(ptr, ":%02u:%02u", (uint)minute, (uint)second);
make_truncated_value_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
make_truncated_value_warning(current_thd, Sql_condition::WARN_LEVEL_WARN,
buf, len, MYSQL_TIMESTAMP_TIME,
NullS);
}

View file

@ -1037,7 +1037,7 @@ static char simpletok[128]=
/*
! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
@ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _
` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~
` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~ \200
*/
0,1,0,0,1,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,1,0,1,1,1,0,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,
@ -2811,7 +2811,7 @@ String *Item_xml_str_func::parse_xml(String *raw_xml, String *parsed_xml_buf)
my_xml_error_lineno(&p) + 1,
(ulong) my_xml_error_pos(&p) + 1,
my_xml_error_string(&p));
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
ER_WRONG_VALUE,
ER(ER_WRONG_VALUE), "XML", buf);
}

View file

@ -150,6 +150,7 @@ static SYMBOL symbols[] = {
{ "CREATE", SYM(CREATE)},
{ "CROSS", SYM(CROSS)},
{ "CUBE", SYM(CUBE_SYM)},
{ "CURRENT", SYM(CURRENT_SYM)},
{ "CURRENT_DATE", SYM(CURDATE)},
{ "CURRENT_TIME", SYM(CURTIME)},
{ "CURRENT_TIMESTAMP", SYM(NOW_SYM)},
@ -180,6 +181,7 @@ static SYMBOL symbols[] = {
{ "DESCRIBE", SYM(DESCRIBE)},
{ "DES_KEY_FILE", SYM(DES_KEY_FILE)},
{ "DETERMINISTIC", SYM(DETERMINISTIC_SYM)},
{ "DIAGNOSTICS", SYM(DIAGNOSTICS_SYM)},
{ "DIRECTORY", SYM(DIRECTORY_SYM)},
{ "DISABLE", SYM(DISABLE_SYM)},
{ "DISCARD", SYM(DISCARD)},
@ -212,6 +214,7 @@ static SYMBOL symbols[] = {
{ "EVENTS", SYM(EVENTS_SYM)},
{ "EVERY", SYM(EVERY_SYM)},
{ "EXAMINED", SYM(EXAMINED_SYM)},
{ "EXCHANGE", SYM(EXCHANGE_SYM)},
{ "EXECUTE", SYM(EXECUTE_SYM)},
{ "EXISTS", SYM(EXISTS)},
{ "EXIT", SYM(EXIT_SYM)},
@ -244,6 +247,7 @@ static SYMBOL symbols[] = {
{ "GEOMETRY", SYM(GEOMETRY_SYM)},
{ "GEOMETRYCOLLECTION",SYM(GEOMETRYCOLLECTION)},
{ "GET_FORMAT", SYM(GET_FORMAT)},
{ "GET", SYM(GET_SYM)},
{ "GLOBAL", SYM(GLOBAL_SYM)},
{ "GRANT", SYM(GRANT)},
{ "GRANTS", SYM(GRANTS)},
@ -394,6 +398,7 @@ static SYMBOL symbols[] = {
{ "NOT", SYM(NOT_SYM)},
{ "NO_WRITE_TO_BINLOG", SYM(NO_WRITE_TO_BINLOG)},
{ "NULL", SYM(NULL_SYM)},
{ "NUMBER", SYM(NUMBER_SYM)},
{ "NUMERIC", SYM(NUMERIC_SYM)},
{ "NVARCHAR", SYM(NVARCHAR_SYM)},
{ "OFFSET", SYM(OFFSET_SYM)},
@ -480,6 +485,7 @@ static SYMBOL symbols[] = {
{ "RESTORE", SYM(RESTORE_SYM)},
{ "RESTRICT", SYM(RESTRICT)},
{ "RESUME", SYM(RESUME_SYM)},
{ "RETURNED_SQLSTATE",SYM(RETURNED_SQLSTATE_SYM)},
{ "RETURN", SYM(RETURN_SYM)},
{ "RETURNS", SYM(RETURNS_SYM)},
{ "REVOKE", SYM(REVOKE)},
@ -489,6 +495,7 @@ static SYMBOL symbols[] = {
{ "ROLLUP", SYM(ROLLUP_SYM)},
{ "ROUTINE", SYM(ROUTINE_SYM)},
{ "ROW", SYM(ROW_SYM)},
{ "ROW_COUNT", SYM(ROW_COUNT_SYM)},
{ "ROWS", SYM(ROWS_SYM)},
{ "ROW_FORMAT", SYM(ROW_FORMAT_SYM)},
{ "RTREE", SYM(RTREE_SYM)},

View file

@ -170,9 +170,9 @@ public:
virtual bool handle_condition(THD *thd,
uint sql_errno,
const char* sql_state,
MYSQL_ERROR::enum_warning_level level,
Sql_condition::enum_warning_level level,
const char* msg,
MYSQL_ERROR ** cond_hdl);
Sql_condition ** cond_hdl);
const char *message() const { return m_message; }
};
@ -180,9 +180,9 @@ bool
Silence_log_table_errors::handle_condition(THD *,
uint,
const char*,
MYSQL_ERROR::enum_warning_level,
Sql_condition::enum_warning_level,
const char* msg,
MYSQL_ERROR ** cond_hdl)
Sql_condition ** cond_hdl)
{
*cond_hdl= NULL;
strmake(m_message, msg, sizeof(m_message)-1);
@ -2057,7 +2057,7 @@ bool MYSQL_BIN_LOG::check_write_error(THD *thd)
if (!thd->is_error())
DBUG_RETURN(checked);
switch (thd->stmt_da->sql_errno())
switch (thd->get_stmt_da()->sql_errno())
{
case ER_TRANS_CACHE_FULL:
case ER_STMT_CACHE_FULL:
@ -3778,7 +3778,7 @@ bool MYSQL_BIN_LOG::reset_logs(THD* thd, bool create_new_log)
{
if (my_errno == ENOENT)
{
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
ER_LOG_PURGE_NO_FILE, ER(ER_LOG_PURGE_NO_FILE),
linfo.log_file_name);
sql_print_information("Failed to delete file '%s'",
@ -3788,7 +3788,7 @@ bool MYSQL_BIN_LOG::reset_logs(THD* thd, bool create_new_log)
}
else
{
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
ER_BINLOG_PURGE_FATAL_ERR,
"a problem with deleting %s; "
"consider examining correspondence "
@ -3809,7 +3809,7 @@ bool MYSQL_BIN_LOG::reset_logs(THD* thd, bool create_new_log)
{
if (my_errno == ENOENT)
{
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
ER_LOG_PURGE_NO_FILE, ER(ER_LOG_PURGE_NO_FILE),
index_file_name);
sql_print_information("Failed to delete file '%s'",
@ -3819,7 +3819,7 @@ bool MYSQL_BIN_LOG::reset_logs(THD* thd, bool create_new_log)
}
else
{
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
ER_BINLOG_PURGE_FATAL_ERR,
"a problem with deleting %s; "
"consider examining correspondence "
@ -4261,7 +4261,7 @@ int MYSQL_BIN_LOG::purge_index_entry(THD *thd, ulonglong *decrease_log_space,
*/
if (thd)
{
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_LOG_PURGE_NO_FILE, ER(ER_LOG_PURGE_NO_FILE),
log_info.log_file_name);
}
@ -4276,7 +4276,7 @@ int MYSQL_BIN_LOG::purge_index_entry(THD *thd, ulonglong *decrease_log_space,
*/
if (thd)
{
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_BINLOG_PURGE_FATAL_ERR,
"a problem with getting info on being purged %s; "
"consider examining correspondence "
@ -4304,7 +4304,7 @@ int MYSQL_BIN_LOG::purge_index_entry(THD *thd, ulonglong *decrease_log_space,
{
if (thd)
{
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_BINLOG_PURGE_FATAL_ERR,
"a problem with deleting %s and "
"reading the binlog index file",
@ -4340,7 +4340,7 @@ int MYSQL_BIN_LOG::purge_index_entry(THD *thd, ulonglong *decrease_log_space,
{
if (thd)
{
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_LOG_PURGE_NO_FILE, ER(ER_LOG_PURGE_NO_FILE),
log_info.log_file_name);
}
@ -4352,7 +4352,7 @@ int MYSQL_BIN_LOG::purge_index_entry(THD *thd, ulonglong *decrease_log_space,
{
if (thd)
{
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_BINLOG_PURGE_FATAL_ERR,
"a problem with deleting %s; "
"consider examining correspondence "
@ -4442,7 +4442,7 @@ int MYSQL_BIN_LOG::purge_logs_before_date(time_t purge_time)
*/
if (thd)
{
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_BINLOG_PURGE_FATAL_ERR,
"a problem with getting info on being purged %s; "
"consider examining correspondence "
@ -6066,9 +6066,9 @@ int query_error_code(THD *thd, bool not_killed)
if (not_killed || (killed_mask_hard(thd->killed) == KILL_BAD_DATA))
{
error= thd->is_error() ? thd->stmt_da->sql_errno() : 0;
error= thd->is_error() ? thd->get_stmt_da()->sql_errno() : 0;
/* thd->stmt_da->sql_errno() might be ER_SERVER_SHUTDOWN or
/* thd->get_get_stmt_da()->sql_errno() might be ER_SERVER_SHUTDOWN or
ER_QUERY_INTERRUPTED, So here we need to make sure that error
is not set to these errors when specified not_killed by the
caller.

View file

@ -215,8 +215,9 @@ static void inline slave_rows_error_report(enum loglevel level, int ha_error,
char buff[MAX_SLAVE_ERRMSG], *slider;
const char *buff_end= buff + sizeof(buff);
uint len;
List_iterator_fast<MYSQL_ERROR> it(thd->warning_info->warn_list());
MYSQL_ERROR *err;
Diagnostics_area::Sql_condition_iterator it=
thd->get_stmt_da()->sql_conditions();
const Sql_condition *err;
buff[0]= 0;
for (err= it++, slider= buff; err && slider < buff_end - 1;
@ -228,7 +229,7 @@ static void inline slave_rows_error_report(enum loglevel level, int ha_error,
}
if (ha_error != 0)
rli->report(level, thd->is_error() ? thd->stmt_da->sql_errno() : 0,
rli->report(level, thd->is_error() ? thd->get_stmt_da()->sql_errno() : 0,
"Could not execute %s event on table %s.%s;"
"%s handler error %s; "
"the event's master log %s, end_log_pos %lu",
@ -236,7 +237,7 @@ static void inline slave_rows_error_report(enum loglevel level, int ha_error,
buff, handler_error == NULL ? "<unknown>" : handler_error,
log_name, pos);
else
rli->report(level, thd->is_error() ? thd->stmt_da->sql_errno() : 0,
rli->report(level, thd->is_error() ? thd->get_stmt_da()->sql_errno() : 0,
"Could not execute %s event on table %s.%s;"
"%s the event's master log %s, end_log_pos %lu",
type, table->s->db.str, table->s->table_name.str,
@ -440,13 +441,13 @@ inline int ignored_error_code(int err_code)
*/
int convert_handler_error(int error, THD* thd, TABLE *table)
{
uint actual_error= (thd->is_error() ? thd->stmt_da->sql_errno() :
uint actual_error= (thd->is_error() ? thd->get_stmt_da()->sql_errno() :
0);
if (actual_error == 0)
{
table->file->print_error(error, MYF(0));
actual_error= (thd->is_error() ? thd->stmt_da->sql_errno() :
actual_error= (thd->is_error() ? thd->get_stmt_da()->sql_errno() :
ER_UNKNOWN_ERROR);
if (actual_error == ER_UNKNOWN_ERROR)
if (global_system_variables.log_warnings)
@ -2108,7 +2109,8 @@ log_event_print_value(IO_CACHE *file, const uchar *ptr,
{
uint i32= uint3korr(ptr);
my_b_printf(file , "'%04d:%02d:%02d'",
(i32 / (16L * 32L)), (i32 / 32L % 16L), (i32 % 32L));
(int)(i32 / (16L * 32L)), (int)(i32 / 32L % 16L),
(int)(i32 % 32L));
my_snprintf(typestr, typestr_length, "DATE");
return 3;
}
@ -2236,11 +2238,11 @@ Rows_log_event::print_verbose_one_row(IO_CACHE *file, table_def *td,
if (is_null)
{
my_b_printf(file, "### @%d=NULL", i + 1);
my_b_printf(file, "### @%lu=NULL", (ulong)i + 1);
}
else
{
my_b_printf(file, "### @%d=", i + 1);
my_b_printf(file, "### @%lu=", (ulong)i + 1);
size_t size= log_event_print_value(file, value,
td->type(i), td->field_metadata(i),
typestr, sizeof(typestr));
@ -2311,14 +2313,23 @@ void Rows_log_event::print_verbose(IO_CACHE *file,
if (!(map= print_event_info->m_table_map.get_table(m_table_id)) ||
!(td= map->create_table_def()))
{
my_b_printf(file, "### Row event for unknown table #%d", m_table_id);
my_b_printf(file, "### Row event for unknown table #%lu",
(ulong) m_table_id);
return;
}
/* If the write rows event contained no values for the AI */
if (((type_code == WRITE_ROWS_EVENT) && (m_rows_buf==m_rows_end)))
{
my_b_printf(file, "### INSERT INTO `%s`.`%s` VALUES ()\n",
map->get_db_name(), map->get_table_name());
goto end;
}
for (const uchar *value= m_rows_buf; value < m_rows_end; )
{
size_t length;
my_b_printf(file, "### %s %`s.%`s\n",
my_b_printf(file, "### %s '%s'.'%s'\n",
sql_command,
map->get_db_name(), map->get_table_name());
/* Print the first image */
@ -3467,7 +3478,7 @@ void Query_log_event::print_query_header(IO_CACHE* file,
if (different_db)
memcpy(print_event_info->db, db, db_len + 1);
if (db[0] && different_db)
my_b_printf(file, "use %`s%s\n", db, print_event_info->delimiter);
my_b_printf(file, "use %s%s\n", db, print_event_info->delimiter);
}
end=int10_to_str((long) when, strmov(buff,"SET TIMESTAMP="),10);
@ -3943,7 +3954,8 @@ START SLAVE; . Query: '%s'", expected_error, thd->query());
}
/* If the query was not ignored, it is printed to the general log */
if (!thd->is_error() || thd->stmt_da->sql_errno() != ER_SLAVE_IGNORED_TABLE)
if (!thd->is_error() ||
thd->get_stmt_da()->sql_errno() != ER_SLAVE_IGNORED_TABLE)
general_log_write(thd, COM_QUERY, thd->query(), thd->query_length());
else
{
@ -3968,14 +3980,14 @@ compare_errors:
not exist errors", we silently clear the error if TEMPORARY was used.
*/
if (thd->lex->sql_command == SQLCOM_DROP_TABLE && thd->lex->drop_temporary &&
thd->is_error() && thd->stmt_da->sql_errno() == ER_BAD_TABLE_ERROR &&
thd->is_error() && thd->get_stmt_da()->sql_errno() == ER_BAD_TABLE_ERROR &&
!expected_error)
thd->stmt_da->reset_diagnostics_area();
thd->get_stmt_da()->reset_diagnostics_area();
/*
If we expected a non-zero error code, and we don't get the same error
code, and it should be ignored or is related to a concurrency issue.
*/
actual_error= thd->is_error() ? thd->stmt_da->sql_errno() : 0;
actual_error= thd->is_error() ? thd->get_stmt_da()->sql_errno() : 0;
DBUG_PRINT("info",("expected_error: %d sql_errno: %d",
expected_error, actual_error));
@ -3993,7 +4005,7 @@ Error on slave: actual message='%s', error code=%d. \
Default database: '%s'. Query: '%s'",
ER_SAFE(expected_error),
expected_error,
actual_error ? thd->stmt_da->message() : "no error",
actual_error ? thd->get_stmt_da()->message() : "no error",
actual_error,
print_slave_db_safe(db), query_arg);
thd->is_slave_error= 1;
@ -4017,7 +4029,7 @@ Default database: '%s'. Query: '%s'",
{
rli->report(ERROR_LEVEL, actual_error,
"Error '%s' on query. Default database: '%s'. Query: '%s'",
(actual_error ? thd->stmt_da->message() :
(actual_error ? thd->get_stmt_da()->message() :
"unexpected success or fatal error"),
print_slave_db_safe(thd->db), query_arg);
thd->is_slave_error= 1;
@ -5301,7 +5313,7 @@ void Load_log_event::print(FILE* file_arg, PRINT_EVENT_INFO* print_event_info,
}
if (db && db[0] && different_db)
my_b_printf(&cache, "%suse %`s%s\n",
my_b_printf(&cache, "%suse %s%s\n",
commented ? "# " : "",
db, print_event_info->delimiter);
@ -5353,7 +5365,7 @@ void Load_log_event::print(FILE* file_arg, PRINT_EVENT_INFO* print_event_info,
{
if (i)
my_b_printf(&cache, ",");
my_b_printf(&cache, "%`s", field);
my_b_printf(&cache, "%s", field);
field += field_lens[i] + 1;
}
@ -5484,7 +5496,7 @@ int Load_log_event::do_apply_event(NET* net, Relay_log_info const *rli,
{
thd->set_time(when, when_sec_part);
thd->set_query_id(next_query_id());
thd->warning_info->opt_clear_warning_info(thd->query_id);
thd->get_stmt_da()->opt_clear_warning_info(thd->query_id);
TABLE_LIST tables;
tables.init_one_table(thd->strmake(thd->db, thd->db_length),
@ -5630,9 +5642,9 @@ error:
thd->catalog= 0;
thd->set_db(NULL, 0); /* will free the current database */
thd->reset_query();
thd->stmt_da->can_overwrite_status= TRUE;
thd->get_stmt_da()->set_overwrite_status(true);
thd->is_error() ? trans_rollback_stmt(thd) : trans_commit_stmt(thd);
thd->stmt_da->can_overwrite_status= FALSE;
thd->get_stmt_da()->set_overwrite_status(false);
close_thread_tables(thd);
/*
- If inside a multi-statement transaction,
@ -5659,8 +5671,8 @@ error:
int sql_errno;
if (thd->is_error())
{
err= thd->stmt_da->message();
sql_errno= thd->stmt_da->sql_errno();
err= thd->get_stmt_da()->message();
sql_errno= thd->get_stmt_da()->sql_errno();
}
else
{
@ -8496,7 +8508,7 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli)
if (open_and_lock_tables(thd, rli->tables_to_lock, FALSE, 0))
{
uint actual_error= thd->stmt_da->sql_errno();
uint actual_error= thd->get_stmt_da()->sql_errno();
if (thd->is_slave_error || thd->is_fatal_error)
{
/*
@ -8507,7 +8519,7 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli)
*/
rli->report(ERROR_LEVEL, actual_error,
"Error executing row event: '%s'",
(actual_error ? thd->stmt_da->message() :
(actual_error ? thd->get_stmt_da()->message() :
"unexpected success or fatal error"));
thd->is_slave_error= 1;
}
@ -9835,8 +9847,8 @@ void Table_map_log_event::print(FILE *, PRINT_EVENT_INFO *print_event_info)
{
print_header(&print_event_info->head_cache, print_event_info, TRUE);
my_b_printf(&print_event_info->head_cache,
"\tTable_map: %`s.%`s mapped to number %lu\n",
m_dbnam, m_tblnam, m_table_id);
"\tTable_map: '%s'.'%s' mapped to number %lu\n",
m_dbnam, m_tblnam, (ulong) m_table_id);
print_base64(&print_event_info->body_cache, print_event_info, TRUE);
}
}

View file

@ -99,7 +99,7 @@ Old_rows_log_event::do_apply_event(Old_rows_log_event *ev, const Relay_log_info
if (open_and_lock_tables(ev_thd, rli->tables_to_lock, FALSE, 0))
{
uint actual_error= ev_thd->stmt_da->sql_errno();
uint actual_error= ev_thd->get_stmt_da()->sql_errno();
if (ev_thd->is_slave_error || ev_thd->is_fatal_error)
{
/*
@ -108,7 +108,7 @@ Old_rows_log_event::do_apply_event(Old_rows_log_event *ev, const Relay_log_info
*/
rli->report(ERROR_LEVEL, actual_error,
"Error '%s' on opening tables",
(actual_error ? ev_thd->stmt_da->message() :
(actual_error ? ev_thd->get_stmt_da()->message() :
"unexpected success or fatal error"));
ev_thd->is_slave_error= 1;
}
@ -243,10 +243,10 @@ Old_rows_log_event::do_apply_event(Old_rows_log_event *ev, const Relay_log_info
break;
default:
rli->report(ERROR_LEVEL, ev_thd->stmt_da->sql_errno(),
rli->report(ERROR_LEVEL, ev_thd->get_stmt_da()->sql_errno(),
"Error in %s event: row application failed. %s",
ev->get_type_str(),
ev_thd->is_error() ? ev_thd->stmt_da->message() : "");
ev_thd->is_error() ? ev_thd->get_stmt_da()->message() : "");
thd->is_slave_error= 1;
break;
}
@ -260,12 +260,12 @@ Old_rows_log_event::do_apply_event(Old_rows_log_event *ev, const Relay_log_info
if (error)
{ /* error has occured during the transaction */
rli->report(ERROR_LEVEL, ev_thd->stmt_da->sql_errno(),
rli->report(ERROR_LEVEL, ev_thd->get_stmt_da()->sql_errno(),
"Error in %s event: error during transaction execution "
"on table %s.%s. %s",
ev->get_type_str(), table->s->db.str,
table->s->table_name.str,
ev_thd->is_error() ? ev_thd->stmt_da->message() : "");
ev_thd->is_error() ? ev_thd->get_stmt_da()->message() : "");
/*
If one day we honour --skip-slave-errors in row-based replication, and

View file

@ -317,7 +317,7 @@ Deadlock_detection_visitor::opt_change_victim_to(MDL_context *new_victim)
class MDL_lock
{
public:
typedef uchar bitmap_t;
typedef unsigned short bitmap_t;
class Ticket_list
{
@ -1108,7 +1108,7 @@ void MDL_ticket::destroy(MDL_ticket *ticket)
uint MDL_ticket::get_deadlock_weight() const
{
return (m_lock->key.mdl_namespace() == MDL_key::GLOBAL ||
m_type >= MDL_SHARED_NO_WRITE ?
m_type >= MDL_SHARED_UPGRADABLE ?
DEADLOCK_WEIGHT_DDL : DEADLOCK_WEIGHT_DML);
}
@ -1440,16 +1440,6 @@ void MDL_lock::reschedule_waiters()
lock. Arrays of bitmaps which elements specify which granted/waiting locks
are incompatible with type of lock being requested.
Here is how types of individual locks are translated to type of scoped lock:
----------------+-------------+
Type of request | Correspond. |
for indiv. lock | scoped lock |
----------------+-------------+
S, SH, SR, SW | IS |
SNW, SNRW, X | IX |
SNW, SNRW -> X | IX (*) |
The first array specifies if particular type of request can be satisfied
if there is granted scoped lock of certain type.
@ -1478,24 +1468,33 @@ void MDL_lock::reschedule_waiters()
Here: "+" -- means that request can be satisfied
"-" -- means that request can't be satisfied and should wait
(*) Since for upgradable locks we always take intention exclusive scoped
lock at the same time when obtaining the shared lock, there is no
need to obtain such lock during the upgrade itself.
(**) Since intention shared scoped locks are compatible with all other
type of locks we don't even have any accounting for them.
(*) Since intention shared scoped locks are compatible with all other
type of locks we don't even have any accounting for them.
Note that relation between scoped locks and objects locks requested
by statement is not straightforward and is therefore fully defined
by SQL-layer.
For example, in order to support global read lock implementation
SQL-layer acquires IX lock in GLOBAL namespace for each statement
that can modify metadata or data (i.e. for each statement that
needs SW, SU, SNW, SNRW or X object locks). OTOH, to ensure that
DROP DATABASE works correctly with concurrent DDL, IX metadata locks
in SCHEMA namespace are acquired for DDL statements which can update
metadata in the schema (i.e. which acquire SU, SNW, SNRW and X locks
on schema objects) and aren't acquired for DML.
*/
const MDL_lock::bitmap_t MDL_scoped_lock::m_granted_incompatible[MDL_TYPE_END] =
{
MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED),
MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_INTENTION_EXCLUSIVE), 0, 0, 0, 0, 0,
MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_INTENTION_EXCLUSIVE), 0, 0, 0, 0, 0, 0,
MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED) | MDL_BIT(MDL_INTENTION_EXCLUSIVE)
};
const MDL_lock::bitmap_t MDL_scoped_lock::m_waiting_incompatible[MDL_TYPE_END] =
{
MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED),
MDL_BIT(MDL_EXCLUSIVE), 0, 0, 0, 0, 0, 0
MDL_BIT(MDL_EXCLUSIVE), 0, 0, 0, 0, 0, 0, 0
};
@ -1507,35 +1506,39 @@ const MDL_lock::bitmap_t MDL_scoped_lock::m_waiting_incompatible[MDL_TYPE_END] =
The first array specifies if particular type of request can be satisfied
if there is granted lock of certain type.
Request | Granted requests for lock |
type | S SH SR SW SNW SNRW X |
----------+------------------------------+
S | + + + + + + - |
SH | + + + + + + - |
SR | + + + + + - - |
SW | + + + + - - - |
SNW | + + + - - - - |
SNRW | + + - - - - - |
X | - - - - - - - |
SNW -> X | - - - 0 0 0 0 |
SNRW -> X | - - 0 0 0 0 0 |
Request | Granted requests for lock |
type | S SH SR SW SU SNW SNRW X |
----------+----------------------------------+
S | + + + + + + + - |
SH | + + + + + + + - |
SR | + + + + + + - - |
SW | + + + + + - - - |
SU | + + + + - - - - |
SNW | + + + - - - - - |
SNRW | + + - - - - - - |
X | - - - - - - - - |
SU -> X | - - - - 0 0 0 0 |
SNW -> X | - - - 0 0 0 0 0 |
SNRW -> X | - - 0 0 0 0 0 0 |
The second array specifies if particular type of request can be satisfied
if there is waiting request for the same lock of certain type. In other
words it specifies what is the priority of different lock types.
Request | Pending requests for lock |
type | S SH SR SW SNW SNRW X |
----------+-----------------------------+
S | + + + + + + - |
SH | + + + + + + + |
SR | + + + + + - - |
SW | + + + + - - - |
SNW | + + + + + + - |
SNRW | + + + + + + - |
X | + + + + + + + |
SNW -> X | + + + + + + + |
SNRW -> X | + + + + + + + |
Request | Pending requests for lock |
type | S SH SR SW SU SNW SNRW X |
----------+---------------------------------+
S | + + + + + + + - |
SH | + + + + + + + + |
SR | + + + + + + - - |
SW | + + + + + - - - |
SU | + + + + + + + - |
SNW | + + + + + + + - |
SNRW | + + + + + + + - |
X | + + + + + + + + |
SU -> X | + + + + + + + + |
SNW -> X | + + + + + + + + |
SNRW -> X | + + + + + + + + |
Here: "+" -- means that request can be satisfied
"-" -- means that request can't be satisfied and should wait
@ -1544,6 +1547,9 @@ const MDL_lock::bitmap_t MDL_scoped_lock::m_waiting_incompatible[MDL_TYPE_END] =
@note In cases then current context already has "stronger" type
of lock on the object it will be automatically granted
thanks to usage of the MDL_context::find_ticket() method.
@note IX locks are excluded since they are not used for per-object
metadata locks.
*/
const MDL_lock::bitmap_t
@ -1556,14 +1562,17 @@ MDL_object_lock::m_granted_incompatible[MDL_TYPE_END] =
MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED_NO_READ_WRITE) |
MDL_BIT(MDL_SHARED_NO_WRITE),
MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED_NO_READ_WRITE) |
MDL_BIT(MDL_SHARED_NO_WRITE) | MDL_BIT(MDL_SHARED_WRITE),
MDL_BIT(MDL_SHARED_NO_WRITE) | MDL_BIT(MDL_SHARED_UPGRADABLE),
MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED_NO_READ_WRITE) |
MDL_BIT(MDL_SHARED_NO_WRITE) | MDL_BIT(MDL_SHARED_WRITE) |
MDL_BIT(MDL_SHARED_READ),
MDL_BIT(MDL_SHARED_NO_WRITE) | MDL_BIT(MDL_SHARED_UPGRADABLE) |
MDL_BIT(MDL_SHARED_WRITE),
MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED_NO_READ_WRITE) |
MDL_BIT(MDL_SHARED_NO_WRITE) | MDL_BIT(MDL_SHARED_WRITE) |
MDL_BIT(MDL_SHARED_READ) | MDL_BIT(MDL_SHARED_HIGH_PRIO) |
MDL_BIT(MDL_SHARED)
MDL_BIT(MDL_SHARED_NO_WRITE) | MDL_BIT(MDL_SHARED_UPGRADABLE) |
MDL_BIT(MDL_SHARED_WRITE) | MDL_BIT(MDL_SHARED_READ),
MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED_NO_READ_WRITE) |
MDL_BIT(MDL_SHARED_NO_WRITE) | MDL_BIT(MDL_SHARED_UPGRADABLE) |
MDL_BIT(MDL_SHARED_WRITE) | MDL_BIT(MDL_SHARED_READ) |
MDL_BIT(MDL_SHARED_HIGH_PRIO) | MDL_BIT(MDL_SHARED)
};
@ -1578,6 +1587,7 @@ MDL_object_lock::m_waiting_incompatible[MDL_TYPE_END] =
MDL_BIT(MDL_SHARED_NO_WRITE),
MDL_BIT(MDL_EXCLUSIVE),
MDL_BIT(MDL_EXCLUSIVE),
MDL_BIT(MDL_EXCLUSIVE),
0
};
@ -1990,7 +2000,7 @@ void MDL_object_lock::notify_conflicting_locks(MDL_context *ctx)
{
/* Only try to abort locks on which we back off. */
if (conflicting_ticket->get_ctx() != ctx &&
conflicting_ticket->get_type() < MDL_SHARED_NO_WRITE)
conflicting_ticket->get_type() < MDL_SHARED_UPGRADABLE)
{
MDL_context *conflicting_ctx= conflicting_ticket->get_ctx();
@ -2258,11 +2268,12 @@ err:
/**
Upgrade a shared metadata lock to exclusive.
Upgrade a shared metadata lock.
Used in ALTER TABLE, when a copy of the table with the
new definition has been constructed.
Used in ALTER TABLE.
@param mdl_ticket Lock to upgrade.
@param new_type Lock type to upgrade to.
@param lock_wait_timeout Seconds to wait before timeout.
@note In case of failure to upgrade lock (e.g. because upgrader
@ -2270,7 +2281,7 @@ err:
shared mode).
@note There can be only one upgrader for a lock or we will have deadlock.
This invariant is ensured by the fact that upgradeable locks SNW
This invariant is ensured by the fact that upgradeable locks SU, SNW
and SNRW are not compatible with each other and themselves.
@retval FALSE Success
@ -2278,28 +2289,30 @@ err:
*/
bool
MDL_context::upgrade_shared_lock_to_exclusive(MDL_ticket *mdl_ticket,
ulong lock_wait_timeout)
MDL_context::upgrade_shared_lock(MDL_ticket *mdl_ticket,
enum_mdl_type new_type,
ulong lock_wait_timeout)
{
MDL_request mdl_xlock_request;
MDL_savepoint mdl_svp= mdl_savepoint();
bool is_new_ticket;
DBUG_ENTER("MDL_ticket::upgrade_shared_lock_to_exclusive");
DEBUG_SYNC(get_thd(), "mdl_upgrade_shared_lock_to_exclusive");
DBUG_ENTER("MDL_context::upgrade_shared_lock");
DEBUG_SYNC(get_thd(), "mdl_upgrade_lock");
/*
Do nothing if already upgraded. Used when we FLUSH TABLE under
LOCK TABLES and a table is listed twice in LOCK TABLES list.
*/
if (mdl_ticket->m_type == MDL_EXCLUSIVE)
if (mdl_ticket->has_stronger_or_equal_type(new_type))
DBUG_RETURN(FALSE);
/* Only allow upgrades from MDL_SHARED_NO_WRITE/NO_READ_WRITE */
DBUG_ASSERT(mdl_ticket->m_type == MDL_SHARED_NO_WRITE ||
/* Only allow upgrades from SHARED_UPGRADABLE/NO_WRITE/NO_READ_WRITE */
DBUG_ASSERT(mdl_ticket->m_type == MDL_SHARED_UPGRADABLE ||
mdl_ticket->m_type == MDL_SHARED_NO_WRITE ||
mdl_ticket->m_type == MDL_SHARED_NO_READ_WRITE);
mdl_xlock_request.init(&mdl_ticket->m_lock->key, MDL_EXCLUSIVE,
mdl_xlock_request.init(&mdl_ticket->m_lock->key, new_type,
MDL_TRANSACTION);
if (acquire_lock(&mdl_xlock_request, lock_wait_timeout))
@ -2317,7 +2330,7 @@ MDL_context::upgrade_shared_lock_to_exclusive(MDL_ticket *mdl_ticket,
ticket from the granted queue and then include it back.
*/
mdl_ticket->m_lock->m_granted.remove_ticket(mdl_ticket);
mdl_ticket->m_type= MDL_EXCLUSIVE;
mdl_ticket->m_type= new_type;
mdl_ticket->m_lock->m_granted.add_ticket(mdl_ticket);
mysql_prlock_unlock(&mdl_ticket->m_lock->m_rwlock);
@ -2681,22 +2694,29 @@ void MDL_context::release_all_locks_for_name(MDL_ticket *name)
/**
Downgrade an exclusive lock to shared metadata lock.
Downgrade an EXCLUSIVE or SHARED_NO_WRITE lock to shared metadata lock.
@param type Type of lock to which exclusive lock should be downgraded.
*/
void MDL_ticket::downgrade_exclusive_lock(enum_mdl_type type)
void MDL_ticket::downgrade_lock(enum_mdl_type type)
{
mysql_mutex_assert_not_owner(&LOCK_open);
/*
Do nothing if already downgraded. Used when we FLUSH TABLE under
LOCK TABLES and a table is listed twice in LOCK TABLES list.
Note that this code might even try to "downgrade" a weak lock
(e.g. SW) to a stronger one (e.g SNRW). So we can't even assert
here that target lock is weaker than existing lock.
*/
if (m_type != MDL_EXCLUSIVE)
if (m_type == type || !has_stronger_or_equal_type(type))
return;
/* Only allow downgrade from EXCLUSIVE and SHARED_NO_WRITE. */
DBUG_ASSERT(m_type == MDL_EXCLUSIVE ||
m_type == MDL_SHARED_NO_WRITE);
mysql_prlock_wrlock(&m_lock->m_rwlock);
/*
To update state of MDL_lock object correctly we need to temporarily

View file

@ -131,6 +131,15 @@ enum enum_mdl_type {
SELECT ... FOR UPDATE.
*/
MDL_SHARED_WRITE,
/*
An upgradable shared metadata lock for cases when there is an intention
to modify (and not just read) data in the table.
Can be upgraded to MDL_SHARED_NO_WRITE and MDL_EXCLUSIVE.
A connection holding SU lock can read table metadata and modify or read
table data (after acquiring appropriate table and row-level locks).
To be used for the first phase of ALTER TABLE.
*/
MDL_SHARED_UPGRADABLE,
/*
An upgradable shared metadata lock which blocks all attempts to update
table data, allowing reads.
@ -502,13 +511,14 @@ public:
MDL_context *get_ctx() const { return m_ctx; }
bool is_upgradable_or_exclusive() const
{
return m_type == MDL_SHARED_NO_WRITE ||
return m_type == MDL_SHARED_UPGRADABLE ||
m_type == MDL_SHARED_NO_WRITE ||
m_type == MDL_SHARED_NO_READ_WRITE ||
m_type == MDL_EXCLUSIVE;
}
enum_mdl_type get_type() const { return m_type; }
MDL_lock *get_lock() const { return m_lock; }
void downgrade_exclusive_lock(enum_mdl_type type);
void downgrade_lock(enum_mdl_type type);
bool has_stronger_or_equal_type(enum_mdl_type type) const;
@ -660,8 +670,9 @@ public:
bool try_acquire_lock(MDL_request *mdl_request);
bool acquire_lock(MDL_request *mdl_request, ulong lock_wait_timeout);
bool acquire_locks(MDL_request_list *requests, ulong lock_wait_timeout);
bool upgrade_shared_lock_to_exclusive(MDL_ticket *mdl_ticket,
ulong lock_wait_timeout);
bool upgrade_shared_lock(MDL_ticket *mdl_ticket,
enum_mdl_type new_type,
ulong lock_wait_timeout);
bool clone_ticket(MDL_request *mdl_request);

View file

@ -1496,7 +1496,7 @@ ha_rows DsMrr_impl::dsmrr_info_const(uint keyno, RANGE_SEQ_IF *seq,
bool key_uses_partial_cols(TABLE *table, uint keyno)
{
KEY_PART_INFO *kp= table->key_info[keyno].key_part;
KEY_PART_INFO *kp_end= kp + table->key_info[keyno].key_parts;
KEY_PART_INFO *kp_end= kp + table->key_info[keyno].user_defined_key_parts;
for (; kp != kp_end; kp++)
{
if (!kp->field->part_of_key.is_set(keyno))

View file

@ -45,21 +45,21 @@ int decimal_operation_results(int result, const char *value, const char *type)
case E_DEC_OK:
break;
case E_DEC_TRUNCATED:
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
ER_DATA_TRUNCATED, ER(ER_DATA_TRUNCATED),
value, type);
break;
case E_DEC_OVERFLOW:
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
ER_DATA_OVERFLOW, ER(ER_DATA_OVERFLOW),
value, type);
break;
case E_DEC_DIV_ZERO:
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
ER_DIVISION_BY_ZERO, ER(ER_DIVISION_BY_ZERO));
break;
case E_DEC_BAD_NUM:
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
ER_BAD_DATA, ER(ER_BAD_DATA),
value, type);
break;

View file

@ -738,6 +738,7 @@ static char **remaining_argv;
int orig_argc;
char **orig_argv;
#ifndef EMBEDDED_LIBRARY
static struct my_option pfs_early_options[]=
{
{"performance_schema_instrument", OPT_PFS_INSTRUMENT,
@ -805,8 +806,7 @@ static struct my_option pfs_early_options[]=
&pfs_param.m_consumer_statement_digest_enabled, 0,
GET_BOOL, OPT_ARG, TRUE, 0, 0, 0, 0, 0}
};
#endif
#ifdef HAVE_PSI_INTERFACE
#ifdef HAVE_MMAP
@ -1086,7 +1086,8 @@ void net_after_header_psi(struct st_net *net, void *user_data, size_t /* unused:
{
thd->m_statement_psi= MYSQL_START_STATEMENT(&thd->m_statement_state,
stmt_info_new_packet.m_key,
thd->db, thd->db_length);
thd->db, thd->db_length,
thd->charset());
THD_STAGE_INFO(thd, stage_init);
}
@ -1118,12 +1119,6 @@ void init_net_server_extension(THD *thd)
}
#endif /* EMBEDDED_LIBRARY */
/*
Since buffered_option_error_reporter is only used currently
for parsing performance schema options, this code is not needed
when the performance schema is not compiled in.
*/
#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
/**
A log message for the error log, buffered in memory.
Log messages are temporarily buffered when generated before the error log
@ -1259,13 +1254,16 @@ void Buffered_logs::print()
/** Logs reported before a logger is available. */
static Buffered_logs buffered_logs;
static MYSQL_SOCKET unix_sock, base_ip_sock, extra_ip_sock;
struct my_rnd_struct sql_rand; ///< used by sql_class.cc:THD::THD()
#ifndef EMBEDDED_LIBRARY
/**
Error reporter that buffer log messages.
@param level log message level
@param format log message format string
*/
C_MODE_START
static void buffered_option_error_reporter(enum loglevel level,
const char *format, ...)
{
@ -1277,14 +1275,7 @@ static void buffered_option_error_reporter(enum loglevel level,
va_end(args);
buffered_logs.buffer(level, buffer);
}
C_MODE_END
#endif /* !EMBEDDED_LIBRARY */
#endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */
static MYSQL_SOCKET unix_sock, base_ip_sock, extra_ip_sock;
struct my_rnd_struct sql_rand; ///< used by sql_class.cc:THD::THD()
#ifndef EMBEDDED_LIBRARY
struct passwd *user_info;
static pthread_t select_thread;
#endif
@ -3246,7 +3237,7 @@ extern "C" void my_message_sql(uint error, const char *str, myf MyFlags);
void my_message_sql(uint error, const char *str, myf MyFlags)
{
THD *thd= current_thd;
MYSQL_ERROR::enum_warning_level level;
Sql_condition::enum_warning_level level;
sql_print_message_func func;
DBUG_ENTER("my_message_sql");
DBUG_PRINT("error", ("error: %u message: '%s' Flag: %lu", error, str,
@ -3258,17 +3249,17 @@ void my_message_sql(uint error, const char *str, myf MyFlags)
mysql_audit_general(thd, MYSQL_AUDIT_GENERAL_ERROR, error, str);
if (MyFlags & ME_JUST_INFO)
{
level= MYSQL_ERROR::WARN_LEVEL_NOTE;
level= Sql_condition::WARN_LEVEL_NOTE;
func= sql_print_information;
}
else if (MyFlags & ME_JUST_WARNING)
{
level= MYSQL_ERROR::WARN_LEVEL_WARN;
level= Sql_condition::WARN_LEVEL_WARN;
func= sql_print_warning;
}
else
{
level= MYSQL_ERROR::WARN_LEVEL_ERROR;
level= Sql_condition::WARN_LEVEL_ERROR;
func= sql_print_error;
}
@ -3428,6 +3419,7 @@ SHOW_VAR com_status_vars[]= {
{"empty_query", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_EMPTY_QUERY]), SHOW_LONG_STATUS},
{"execute_sql", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_EXECUTE]), SHOW_LONG_STATUS},
{"flush", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_FLUSH]), SHOW_LONG_STATUS},
{"get_diagnostics", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_GET_DIAGNOSTICS]), SHOW_LONG_STATUS},
{"grant", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_GRANT]), SHOW_LONG_STATUS},
{"ha_close", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_HA_CLOSE]), SHOW_LONG_STATUS},
{"ha_open", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_HA_OPEN]), SHOW_LONG_STATUS},
@ -4916,7 +4908,6 @@ int mysqld_main(int argc, char **argv)
sys_var_init();
#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
/*
The performance schema needs to be initialized as early as possible,
before to-be-instrumented objects of the server are initialized.
@ -4944,22 +4935,30 @@ int mysqld_main(int argc, char **argv)
my_charset_error_reporter= buffered_option_error_reporter;
pfs_param.m_pfs_instrument= const_cast<char*>("");
#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
/*
Initialize the array of performance schema instrument configurations.
*/
init_pfs_instrument_array();
#endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */
ho_error= handle_options(&remaining_argc, &remaining_argv,
(my_option*)(all_early_options.buffer),
mysqld_get_one_option);
delete_dynamic(&all_early_options);
#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
if (ho_error == 0)
{
/* Add back the program name handle_options removes */
remaining_argc++;
remaining_argv--;
if (pfs_param.m_enabled)
if (pfs_param.m_enabled && !opt_help && !opt_bootstrap)
{
/* Add sizing hints from the server sizing parameters. */
pfs_param.m_hints.m_table_definition_cache= table_def_size;
pfs_param.m_hints.m_table_open_cache= table_cache_size;
pfs_param.m_hints.m_max_connections= max_connections;
pfs_param.m_hints.m_open_files_limit= open_files_limit;
PSI_hook= initialize_performance_schema(&pfs_param);
if (PSI_hook == NULL)
{
@ -6853,7 +6852,7 @@ static int show_slave_running(THD *thd, SHOW_VAR *var, char *buff)
mysql_mutex_lock(&LOCK_active_mi);
mi= master_info_index->
get_master_info(&thd->variables.default_master_connection,
MYSQL_ERROR::WARN_LEVEL_NOTE);
Sql_condition::WARN_LEVEL_NOTE);
if (mi)
*((my_bool *)buff)= (my_bool) (mi->slave_running ==
MYSQL_SLAVE_RUN_CONNECT &&
@ -6873,7 +6872,7 @@ static int show_slave_received_heartbeats(THD *thd, SHOW_VAR *var, char *buff)
mysql_mutex_lock(&LOCK_active_mi);
mi= master_info_index->
get_master_info(&thd->variables.default_master_connection,
MYSQL_ERROR::WARN_LEVEL_NOTE);
Sql_condition::WARN_LEVEL_NOTE);
if (mi)
*((longlong *)buff)= mi->received_heartbeats;
else
@ -6891,7 +6890,7 @@ static int show_heartbeat_period(THD *thd, SHOW_VAR *var, char *buff)
mysql_mutex_lock(&LOCK_active_mi);
mi= master_info_index->
get_master_info(&thd->variables.default_master_connection,
MYSQL_ERROR::WARN_LEVEL_NOTE);
Sql_condition::WARN_LEVEL_NOTE);
if (mi)
sprintf(buff, "%.3f", mi->heartbeat_period);
else
@ -8892,6 +8891,9 @@ static PSI_file_info all_server_files[]=
PSI_stage_info stage_after_create= { 0, "After create", 0};
PSI_stage_info stage_allocating_local_table= { 0, "allocating local table", 0};
PSI_stage_info stage_alter_inplace_prepare= { 0, "preparing for alter table", 0};
PSI_stage_info stage_alter_inplace= { 0, "altering table", 0};
PSI_stage_info stage_alter_inplace_commit= { 0, "committing alter table to storage engine", 0};
PSI_stage_info stage_changing_master= { 0, "Changing master", 0};
PSI_stage_info stage_checking_master_version= { 0, "Checking master version", 0};
PSI_stage_info stage_checking_permissions= { 0, "checking permissions", 0};

View file

@ -306,6 +306,9 @@ void init_server_psi_keys();
*/
extern PSI_stage_info stage_after_create;
extern PSI_stage_info stage_allocating_local_table;
extern PSI_stage_info stage_alter_inplace_prepare;
extern PSI_stage_info stage_alter_inplace;
extern PSI_stage_info stage_alter_inplace_commit;
extern PSI_stage_info stage_changing_master;
extern PSI_stage_info stage_checking_master_version;
extern PSI_stage_info stage_checking_permissions;

View file

@ -112,7 +112,7 @@
#include "key.h" // is_key_used, key_copy, key_cmp, key_restore
#include "sql_parse.h" // check_stack_overrun
#include "sql_partition.h" // get_part_id_func, PARTITION_ITERATOR,
// struct partition_info
// struct partition_info, NOT_A_PARTITION_ID
#include "sql_base.h" // free_io_cache
#include "records.h" // init_read_record, end_read_record
#include <m_ctype.h>
@ -3386,29 +3386,26 @@ static void dbug_print_singlepoint_range(SEL_ARG **start, uint num);
#endif
/*
/**
Perform partition pruning for a given table and condition.
SYNOPSIS
prune_partitions()
thd Thread handle
table Table to perform partition pruning for
pprune_cond Condition to use for partition pruning
@param thd Thread handle
@param table Table to perform partition pruning for
@param pprune_cond Condition to use for partition pruning
DESCRIPTION
This function assumes that all partitions are marked as unused when it
is invoked. The function analyzes the condition, finds partitions that
need to be used to retrieve the records that match the condition, and
marks them as used by setting appropriate bit in part_info->used_partitions
In the worst case all partitions are marked as used.
@note This function assumes that lock_partitions are setup when it
is invoked. The function analyzes the condition, finds partitions that
need to be used to retrieve the records that match the condition, and
marks them as used by setting appropriate bit in part_info->read_partitions
In the worst case all partitions are marked as used. If the table is not
yet locked, it will also unset bits in part_info->lock_partitions that is
not set in read_partitions.
NOTE
This function returns promptly if called for non-partitioned table.
This function returns promptly if called for non-partitioned table.
RETURN
TRUE We've inferred that no partitions need to be used (i.e. no table
records will satisfy pprune_cond)
FALSE Otherwise
@return Operation status
@retval true Failure
@retval false Success
*/
bool prune_partitions(THD *thd, TABLE *table, Item *pprune_cond)
@ -3461,7 +3458,7 @@ bool prune_partitions(THD *thd, TABLE *table, Item *pprune_cond)
thd->no_errors=1; // Don't warn about NULL
thd->mem_root=&alloc;
bitmap_clear_all(&part_info->used_partitions);
bitmap_clear_all(&part_info->read_partitions);
prune_param.key= prune_param.range_param.key_parts;
SEL_TREE *tree;
@ -3545,6 +3542,30 @@ end:
thd->mem_root= range_par->old_root;
free_root(&alloc,MYF(0)); // Return memory & allocator
DBUG_RETURN(retval);
/*
Must be a subset of the locked partitions.
lock_partitions contains the partitions marked by explicit partition
selection (... t PARTITION (pX) ...) and we must only use partitions
within that set.
*/
bitmap_intersect(&prune_param.part_info->read_partitions,
&prune_param.part_info->lock_partitions);
/*
If not yet locked, also prune partitions to lock if not UPDATEing
partition key fields. This will also prune lock_partitions if we are under
LOCK TABLES, so prune away calls to start_stmt().
TODO: enhance this prune locking to also allow pruning of
'UPDATE t SET part_key = const WHERE cond_is_prunable' so it adds
a lock for part_key partition.
*/
if (!thd->lex->is_query_tables_locked() &&
!partition_key_modified(table, table->write_set))
{
bitmap_copy(&prune_param.part_info->lock_partitions,
&prune_param.part_info->read_partitions);
}
if (bitmap_is_clear_all(&(prune_param.part_info->read_partitions)))
table->all_partitions_pruned_away= true;
}
@ -3619,7 +3640,7 @@ static void mark_full_partition_used_no_parts(partition_info* part_info,
{
DBUG_ENTER("mark_full_partition_used_no_parts");
DBUG_PRINT("enter", ("Mark partition %u as used", part_id));
bitmap_set_bit(&part_info->used_partitions, part_id);
bitmap_set_bit(&part_info->read_partitions, part_id);
DBUG_VOID_RETURN;
}
@ -3635,7 +3656,7 @@ static void mark_full_partition_used_with_parts(partition_info *part_info,
for (; start != end; start++)
{
DBUG_PRINT("info", ("1:Mark subpartition %u as used", start));
bitmap_set_bit(&part_info->used_partitions, start);
bitmap_set_bit(&part_info->read_partitions, start);
}
DBUG_VOID_RETURN;
}
@ -3663,7 +3684,7 @@ static int find_used_partitions_imerge_list(PART_PRUNE_PARAM *ppar,
MY_BITMAP all_merges;
uint bitmap_bytes;
my_bitmap_map *bitmap_buf;
uint n_bits= ppar->part_info->used_partitions.n_bits;
uint n_bits= ppar->part_info->read_partitions.n_bits;
bitmap_bytes= bitmap_buffer_size(n_bits);
if (!(bitmap_buf= (my_bitmap_map*) alloc_root(ppar->range_param.mem_root,
bitmap_bytes)))
@ -3689,14 +3710,15 @@ static int find_used_partitions_imerge_list(PART_PRUNE_PARAM *ppar,
}
if (res != -1)
bitmap_intersect(&all_merges, &ppar->part_info->used_partitions);
bitmap_intersect(&all_merges, &ppar->part_info->read_partitions);
if (bitmap_is_clear_all(&all_merges))
return 0;
bitmap_clear_all(&ppar->part_info->used_partitions);
bitmap_clear_all(&ppar->part_info->read_partitions);
}
memcpy(ppar->part_info->used_partitions.bitmap, all_merges.bitmap,
memcpy(ppar->part_info->read_partitions.bitmap, all_merges.bitmap,
bitmap_bytes);
return 1;
}
@ -4056,7 +4078,7 @@ int find_used_partitions(PART_PRUNE_PARAM *ppar, SEL_ARG *key_tree)
{
for (uint i= 0; i < ppar->part_info->num_subparts; i++)
if (bitmap_is_set(&ppar->subparts_bitmap, i))
bitmap_set_bit(&ppar->part_info->used_partitions,
bitmap_set_bit(&ppar->part_info->read_partitions,
part_id * ppar->part_info->num_subparts + i);
}
goto pop_and_go_right;
@ -4118,7 +4140,7 @@ int find_used_partitions(PART_PRUNE_PARAM *ppar, SEL_ARG *key_tree)
while ((part_id= ppar->part_iter.get_next(&ppar->part_iter)) !=
NOT_A_PARTITION_ID)
{
bitmap_set_bit(&part_info->used_partitions,
bitmap_set_bit(&part_info->read_partitions,
part_id * part_info->num_subparts + subpart_id);
}
res= 1; /* Some partitions were marked as used */
@ -4204,7 +4226,8 @@ pop_and_go_right:
static void mark_all_partitions_as_used(partition_info *part_info)
{
bitmap_set_all(&part_info->used_partitions);
bitmap_copy(&(part_info->read_partitions),
&(part_info->lock_partitions));
}

View file

@ -2370,7 +2370,7 @@ bool find_eq_ref_candidate(TABLE *table, table_map sj_inner_tables)
keyuse++;
} while (keyuse->key == key && keyuse->table == table);
if (bound_parts == PREV_BITS(uint, keyinfo->key_parts))
if (bound_parts == PREV_BITS(uint, keyinfo->user_defined_key_parts))
return TRUE;
}
else
@ -3521,7 +3521,7 @@ bool setup_sj_materialization_part2(JOIN_TAB *sjm_tab)
KEY *tmp_key; /* The only index on the temporary table. */
uint tmp_key_parts; /* Number of keyparts in tmp_key. */
tmp_key= sjm->table->key_info;
tmp_key_parts= tmp_key->key_parts;
tmp_key_parts= tmp_key->user_defined_key_parts;
/*
Create/initialize everything we will need to index lookups into the
@ -4057,7 +4057,7 @@ SJ_TMP_TABLE::create_sj_weedout_tmp_table(THD *thd)
table->key_info=keyinfo;
keyinfo->key_part=key_part_info;
keyinfo->flags=HA_NOSAME;
keyinfo->usable_key_parts= keyinfo->key_parts= 1;
keyinfo->usable_key_parts= keyinfo->user_defined_key_parts= 1;
keyinfo->key_length=0;
keyinfo->rec_per_key=0;
keyinfo->algorithm= HA_KEY_ALG_UNDEF;

View file

@ -464,7 +464,7 @@ int opt_sum_query(THD *thd,
}
if (thd->is_error())
DBUG_RETURN(thd->stmt_da->sql_errno());
DBUG_RETURN(thd->get_stmt_da()->sql_errno());
/*
If we have a where clause, we can only ignore searching in the

View file

@ -1563,7 +1563,7 @@ Dep_value_table *Dep_analysis_context::create_table_value(TABLE *table)
if (key->flags & HA_NOSAME)
{
Dep_module_key *key_dep;
if (!(key_dep= new Dep_module_key(tbl_dep, i, key->key_parts)))
if (!(key_dep= new Dep_module_key(tbl_dep, i, key->user_defined_key_parts)))
return NULL;
*key_list= key_dep;
key_list= &(key_dep->next_table_key);

View file

@ -23,10 +23,12 @@
#include "sql_priv.h"
// Required to get server definitions for mysql/plugin.h right
#include "sql_plugin.h"
#include "sql_partition.h" /* partition_info.h: LIST_PART_ENTRY */
#include "sql_partition.h" // partition_info.h: LIST_PART_ENTRY
// NOT_A_PARTITION_ID
#include "partition_info.h"
#include "sql_parse.h" // test_if_data_home_dir
#include "sql_acl.h" // *_ACL
#include "sql_base.h" // fill_record
#ifdef WITH_PARTITION_STORAGE_ENGINE
#include "ha_partition.h"
@ -34,17 +36,21 @@
partition_info *partition_info::get_clone()
{
DBUG_ENTER("partition_info::get_clone");
if (!this)
return 0;
DBUG_RETURN(NULL);
List_iterator<partition_element> part_it(partitions);
partition_element *part;
partition_info *clone= new partition_info();
if (!clone)
{
mem_alloc_error(sizeof(partition_info));
return NULL;
DBUG_RETURN(NULL);
}
memcpy(clone, this, sizeof(partition_info));
memset(&(clone->read_partitions), 0, sizeof(clone->read_partitions));
memset(&(clone->lock_partitions), 0, sizeof(clone->lock_partitions));
clone->bitmaps_are_initialized= FALSE;
clone->partitions.empty();
while ((part= (part_it++)))
@ -55,7 +61,7 @@ partition_info *partition_info::get_clone()
if (!part_clone)
{
mem_alloc_error(sizeof(partition_element));
return NULL;
DBUG_RETURN(NULL);
}
memcpy(part_clone, part, sizeof(partition_element));
part_clone->subpartitions.empty();
@ -65,16 +71,427 @@ partition_info *partition_info::get_clone()
if (!subpart_clone)
{
mem_alloc_error(sizeof(partition_element));
return NULL;
DBUG_RETURN(NULL);
}
memcpy(subpart_clone, subpart, sizeof(partition_element));
part_clone->subpartitions.push_back(subpart_clone);
}
clone->partitions.push_back(part_clone);
}
return clone;
DBUG_RETURN(clone);
}
/**
Mark named [sub]partition to be used/locked.
@param part_name Partition name to match.
@param length Partition name length.
@return Success if partition found
@retval true Partition found
@retval false Partition not found
*/
bool partition_info::add_named_partition(const char *part_name,
uint length)
{
HASH *part_name_hash;
PART_NAME_DEF *part_def;
Partition_share *part_share;
DBUG_ENTER("partition_info::add_named_partition");
DBUG_ASSERT(table && table->s && table->s->ha_share);
part_share= static_cast<Partition_share*>((table->s->ha_share));
DBUG_ASSERT(part_share->partition_name_hash_initialized);
part_name_hash= &part_share->partition_name_hash;
DBUG_ASSERT(part_name_hash->records);
part_def= (PART_NAME_DEF*) my_hash_search(part_name_hash,
(const uchar*) part_name,
length);
if (!part_def)
{
// my_error(ER_UNKNOWN_PARTITION, MYF(0), part_name, table->alias);
DBUG_RETURN(true);
}
if (part_def->is_subpart)
{
bitmap_set_bit(&read_partitions, part_def->part_id);
}
else
{
if (is_sub_partitioned())
{
/* Mark all subpartitions in the partition */
uint j, start= part_def->part_id;
uint end= start + num_subparts;
for (j= start; j < end; j++)
bitmap_set_bit(&read_partitions, j);
}
else
bitmap_set_bit(&read_partitions, part_def->part_id);
}
DBUG_PRINT("info", ("Found partition %u is_subpart %d for name %s",
part_def->part_id, part_def->is_subpart,
part_name));
DBUG_RETURN(false);
}
/**
Mark named [sub]partition to be used/locked.
@param part_elem Partition element that matched.
*/
bool partition_info::set_named_partition_bitmap(const char *part_name,
uint length)
{
DBUG_ENTER("partition_info::set_named_partition_bitmap");
bitmap_clear_all(&read_partitions);
if (add_named_partition(part_name, length))
DBUG_RETURN(true);
bitmap_copy(&lock_partitions, &read_partitions);
DBUG_RETURN(false);
}
/**
Prune away partitions not mentioned in the PARTITION () clause,
if used.
@param table_list Table list pointing to table to prune.
@return Operation status
@retval true Failure
@retval false Success
*/
bool partition_info::prune_partition_bitmaps(TABLE_LIST *table_list)
{
List_iterator<String> partition_names_it(*(table_list->partition_names));
uint num_names= table_list->partition_names->elements;
uint i= 0;
DBUG_ENTER("partition_info::prune_partition_bitmaps");
if (num_names < 1)
DBUG_RETURN(true);
/*
TODO: When adding support for FK in partitioned tables, the referenced
table must probably lock all partitions for read, and also write depending
of ON DELETE/UPDATE.
*/
bitmap_clear_all(&read_partitions);
/* No check for duplicate names or overlapping partitions/subpartitions. */
DBUG_PRINT("info", ("Searching through partition_name_hash"));
do
{
String *part_name_str= partition_names_it++;
if (add_named_partition(part_name_str->c_ptr(), part_name_str->length()))
DBUG_RETURN(true);
} while (++i < num_names);
DBUG_RETURN(false);
}
/**
Set read/lock_partitions bitmap over non pruned partitions
@param table_list Possible TABLE_LIST which can contain
list of partition names to query
@return Operation status
@retval FALSE OK
@retval TRUE Failed to allocate memory for bitmap or list of partitions
did not match
@note OK to call multiple times without the need for free_bitmaps.
*/
bool partition_info::set_partition_bitmaps(TABLE_LIST *table_list)
{
DBUG_ENTER("partition_info::set_partition_bitmaps");
DBUG_ASSERT(bitmaps_are_initialized);
DBUG_ASSERT(table);
is_pruning_completed= false;
if (!bitmaps_are_initialized)
DBUG_RETURN(TRUE);
if (table_list &&
table_list->partition_names &&
table_list->partition_names->elements)
{
if (table->s->db_type()->partition_flags() & HA_USE_AUTO_PARTITION)
{
/*
Don't allow PARTITION () clause on a NDB tables yet.
TODO: Add partition name handling to NDB/partition_info.
which is currently ha_partition specific.
*/
my_error(ER_PARTITION_CLAUSE_ON_NONPARTITIONED, MYF(0));
DBUG_RETURN(true);
}
if (prune_partition_bitmaps(table_list))
DBUG_RETURN(TRUE);
}
else
{
bitmap_set_all(&read_partitions);
DBUG_PRINT("info", ("Set all partitions"));
}
bitmap_copy(&lock_partitions, &read_partitions);
DBUG_ASSERT(bitmap_get_first_set(&lock_partitions) != MY_BIT_NONE);
DBUG_RETURN(FALSE);
}
/**
Checks if possible to do prune partitions on insert.
@param thd Thread context
@param duplic How to handle duplicates
@param update In case of ON DUPLICATE UPDATE, default function fields
@param update_fields In case of ON DUPLICATE UPDATE, which fields to update
@param fields Listed fields
@param empty_values True if values is empty (only defaults)
@param[out] prune_needs_default_values Set on return if copying of default
values is needed
@param[out] can_prune_partitions Enum showing if possible to prune
@param[inout] used_partitions If possible to prune the bitmap
is initialized and cleared
@return Operation status
@retval false Success
@retval true Failure
*/
bool partition_info::can_prune_insert(THD* thd,
enum_duplicates duplic,
COPY_INFO &update,
List<Item> &update_fields,
List<Item> &fields,
bool empty_values,
enum_can_prune *can_prune_partitions,
bool *prune_needs_default_values,
MY_BITMAP *used_partitions)
{
uint32 *bitmap_buf;
uint bitmap_bytes;
uint num_partitions= 0;
*can_prune_partitions= PRUNE_NO;
DBUG_ASSERT(bitmaps_are_initialized);
DBUG_ENTER("partition_info::can_prune_insert");
if (table->s->db_type()->partition_flags() & HA_USE_AUTO_PARTITION)
DBUG_RETURN(false); /* Should not insert prune NDB tables */
/*
If under LOCK TABLES pruning will skip start_stmt instead of external_lock
for unused partitions.
Cannot prune if there are BEFORE INSERT triggers that changes any
partitioning column, since they may change the row to be in another
partition.
*/
if (table->triggers &&
table->triggers->has_triggers(TRG_EVENT_INSERT, TRG_ACTION_BEFORE) &&
table->triggers->is_fields_updated_in_trigger(&full_part_field_set,
TRG_EVENT_INSERT,
TRG_ACTION_BEFORE))
DBUG_RETURN(false);
if (table->found_next_number_field)
{
/*
If the field is used in the partitioning expression, we cannot prune.
TODO: If all rows have not null values and
is not 0 (with NO_AUTO_VALUE_ON_ZERO sql_mode), then pruning is possible!
*/
if (bitmap_is_set(&full_part_field_set,
table->found_next_number_field->field_index))
DBUG_RETURN(false);
}
/*
If updating a field in the partitioning expression, we cannot prune.
Note: TIMESTAMP_AUTO_SET_ON_INSERT is handled by converting Item_null
to the start time of the statement. Which will be the same as in
write_row(). So pruning of TIMESTAMP DEFAULT CURRENT_TIME will work.
But TIMESTAMP_AUTO_SET_ON_UPDATE cannot be pruned if the timestamp
column is a part of any part/subpart expression.
*/
if (duplic == DUP_UPDATE)
{
/*
TODO: add check for static update values, which can be pruned.
*/
if (is_field_in_part_expr(update_fields))
DBUG_RETURN(false);
/*
Cannot prune if there are BEFORE UPDATE triggers that changes any
partitioning column, since they may change the row to be in another
partition.
*/
if (table->triggers &&
table->triggers->has_triggers(TRG_EVENT_UPDATE,
TRG_ACTION_BEFORE) &&
table->triggers->is_fields_updated_in_trigger(&full_part_field_set,
TRG_EVENT_UPDATE,
TRG_ACTION_BEFORE))
{
DBUG_RETURN(false);
}
}
/*
If not all partitioning fields are given,
we also must set all non given partitioning fields
to get correct defaults.
TODO: If any gain, we could enhance this by only copy the needed default
fields by
1) check which fields needs to be set.
2) only copy those fields from the default record.
*/
*prune_needs_default_values= false;
if (fields.elements)
{
if (!is_full_part_expr_in_fields(fields))
*prune_needs_default_values= true;
}
else if (empty_values)
{
*prune_needs_default_values= true; // like 'INSERT INTO t () VALUES ()'
}
else
{
/*
In case of INSERT INTO t VALUES (...) we must get values for
all fields in table from VALUES (...) part, so no defaults
are needed.
*/
}
/* Pruning possible, have to initialize the used_partitions bitmap. */
num_partitions= lock_partitions.n_bits;
bitmap_bytes= bitmap_buffer_size(num_partitions);
if (!(bitmap_buf= (uint32*) thd->alloc(bitmap_bytes)))
{
mem_alloc_error(bitmap_bytes);
DBUG_RETURN(true);
}
/* Also clears all bits. */
if (bitmap_init(used_partitions, bitmap_buf, num_partitions, false))
{
/* purecov: begin deadcode */
/* Cannot happen, due to pre-alloc. */
mem_alloc_error(bitmap_bytes);
DBUG_RETURN(true);
/* purecov: end */
}
/*
If no partitioning field in set (e.g. defaults) check pruning only once.
*/
if (fields.elements &&
!is_field_in_part_expr(fields))
*can_prune_partitions= PRUNE_DEFAULTS;
else
*can_prune_partitions= PRUNE_YES;
DBUG_RETURN(false);
}
/**
Mark the partition, the record belongs to, as used.
@param fields Fields to set
@param values Values to use
@param info COPY_INFO used for default values handling
@param copy_default_values True if we should copy default values
@param used_partitions Bitmap to set
@returns Operational status
@retval false Success
@retval true Failure
*/
bool partition_info::set_used_partition(List<Item> &fields,
List<Item> &values,
COPY_INFO &info,
bool copy_default_values,
MY_BITMAP *used_partitions)
{
THD *thd= table->in_use;
uint32 part_id;
longlong func_value;
Dummy_error_handler error_handler;
bool ret= true;
DBUG_ENTER("set_partition");
DBUG_ASSERT(thd);
/* Only allow checking of constant values */
List_iterator_fast<Item> v(values);
Item *item;
thd->push_internal_handler(&error_handler);
while ((item= v++))
{
if (!item->const_item())
goto err;
}
if (copy_default_values)
restore_record(table,s->default_values);
if (fields.elements || !values.elements)
{
if (fill_record(thd, table, fields, values, false))
goto err;
}
else
{
if (fill_record(thd, table, table->field, values, false, false))
goto err;
}
DBUG_ASSERT(!table->auto_increment_field_not_null);
/*
Evaluate DEFAULT functions like CURRENT_TIMESTAMP.
TODO: avoid setting non partitioning fields default value, to avoid
overhead. Not yet done, since mostly only one DEFAULT function per
table, or at least very few such columns.
*/
// if (info.function_defaults_apply_on_columns(&full_part_field_set))
// info.set_function_defaults(table);
{
/*
This function is used in INSERT; 'values' are supplied by user,
or are default values, not values read from a table, so read_set is
irrelevant.
*/
my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, table->read_set);
const int rc= get_partition_id(this, &part_id, &func_value);
dbug_tmp_restore_column_map(table->read_set, old_map);
if (rc)
goto err;
}
DBUG_PRINT("info", ("Insert into partition %u", part_id));
bitmap_set_bit(used_partitions, part_id);
ret= false;
err:
thd->pop_internal_handler();
DBUG_RETURN(ret);
}
/*
Create a memory area where default partition names are stored and fill it
up with the names.
@ -160,8 +577,9 @@ void partition_info::set_show_version_string(String *packet)
/*
Create a unique name for the subpartition as part_name'sp''subpart_no'
SYNOPSIS
create_subpartition_name()
create_default_subpartition_name()
subpart_no Number of subpartition
part_name Name of partition
RETURN VALUES
@ -169,12 +587,12 @@ void partition_info::set_show_version_string(String *packet)
0 Memory allocation error
*/
char *partition_info::create_subpartition_name(uint subpart_no,
char *partition_info::create_default_subpartition_name(uint subpart_no,
const char *part_name)
{
uint size_alloc= strlen(part_name) + MAX_PART_NAME_SIZE;
char *ptr= (char*) sql_calloc(size_alloc);
DBUG_ENTER("create_subpartition_name");
DBUG_ENTER("create_default_subpartition_name");
if (likely(ptr != NULL))
{
@ -320,7 +738,8 @@ bool partition_info::set_up_default_subpartitions(handler *file,
if (likely(subpart_elem != 0 &&
(!part_elem->subpartitions.push_back(subpart_elem))))
{
char *ptr= create_subpartition_name(j, part_elem->partition_name);
char *ptr= create_default_subpartition_name(j,
part_elem->partition_name);
if (!ptr)
goto end;
subpart_elem->engine_type= default_engine_type;
@ -380,7 +799,7 @@ bool partition_info::set_up_defaults_for_partitioning(handler *file,
Support routine for check_partition_info
SYNOPSIS
has_unique_fields
find_duplicate_field
no parameters
RETURN VALUE
@ -391,13 +810,13 @@ bool partition_info::set_up_defaults_for_partitioning(handler *file,
Check that the user haven't defined the same field twice in
key or column list partitioning.
*/
char* partition_info::has_unique_fields()
char* partition_info::find_duplicate_field()
{
char *field_name_outer, *field_name_inner;
List_iterator<char> it_outer(part_field_list);
uint num_fields= part_field_list.elements;
uint i,j;
DBUG_ENTER("partition_info::has_unique_fields");
DBUG_ENTER("partition_info::find_duplicate_field");
for (i= 0; i < num_fields; i++)
{
@ -419,88 +838,149 @@ char* partition_info::has_unique_fields()
DBUG_RETURN(NULL);
}
/*
A support function to check if a partition element's name is unique
SYNOPSIS
has_unique_name()
partition_element element to check
RETURN VALUES
TRUE Has unique name
FALSE Doesn't
/**
@brief Get part_elem and part_id from partition name
@param partition_name Name of partition to search for.
@param file_name[out] Partition file name (part after table name,
#P#<part>[#SP#<subpart>]), skipped if NULL.
@param part_id[out] Id of found partition or NOT_A_PARTITION_ID.
@retval Pointer to part_elem of [sub]partition, if not found NULL
@note Since names of partitions AND subpartitions must be unique,
this function searches both partitions and subpartitions and if name of
a partition is given for a subpartitioned table, part_elem will be
the partition, but part_id will be NOT_A_PARTITION_ID and file_name not set.
*/
bool partition_info::has_unique_name(partition_element *element)
partition_element *partition_info::get_part_elem(const char *partition_name,
char *file_name,
uint32 *part_id)
{
DBUG_ENTER("partition_info::has_unique_name");
const char *name_to_check= element->partition_name;
List_iterator<partition_element> parts_it(partitions);
partition_element *el;
while ((el= (parts_it++)))
List_iterator<partition_element> part_it(partitions);
uint i= 0;
DBUG_ENTER("partition_info::get_part_elem");
DBUG_ASSERT(part_id);
*part_id= NOT_A_PARTITION_ID;
do
{
if (!(my_strcasecmp(system_charset_info, el->partition_name,
name_to_check)) && el != element)
DBUG_RETURN(FALSE);
if (!el->subpartitions.is_empty())
partition_element *part_elem= part_it++;
if (is_sub_partitioned())
{
partition_element *sub_el;
List_iterator<partition_element> subparts_it(el->subpartitions);
while ((sub_el= (subparts_it++)))
List_iterator<partition_element> sub_part_it(part_elem->subpartitions);
uint j= 0;
do
{
if (!(my_strcasecmp(system_charset_info, sub_el->partition_name,
name_to_check)) && sub_el != element)
DBUG_RETURN(FALSE);
}
partition_element *sub_part_elem= sub_part_it++;
if (!my_strcasecmp(system_charset_info,
sub_part_elem->partition_name, partition_name))
{
if (file_name)
create_subpartition_name(file_name, "",
part_elem->partition_name,
partition_name,
NORMAL_PART_NAME);
*part_id= j + (i * num_subparts);
DBUG_RETURN(sub_part_elem);
}
} while (++j < num_subparts);
/* Naming a partition (first level) on a subpartitioned table. */
if (!my_strcasecmp(system_charset_info,
part_elem->partition_name, partition_name))
DBUG_RETURN(part_elem);
}
}
DBUG_RETURN(TRUE);
else if (!my_strcasecmp(system_charset_info,
part_elem->partition_name, partition_name))
{
if (file_name)
create_partition_name(file_name, "", partition_name,
NORMAL_PART_NAME, TRUE);
*part_id= i;
DBUG_RETURN(part_elem);
}
} while (++i < num_parts);
DBUG_RETURN(NULL);
}
/**
Helper function to find_duplicate_name.
*/
static const char *get_part_name_from_elem(const char *name, size_t *length,
my_bool not_used __attribute__((unused)))
{
*length= strlen(name);
return name;
}
/*
A support function to check partition names for duplication in a
partitioned table
SYNOPSIS
has_unique_names()
find_duplicate_name()
RETURN VALUES
TRUE Has unique part and subpart names
FALSE Doesn't
NULL Has unique part and subpart names
!NULL Pointer to duplicated name
DESCRIPTION
Checks that the list of names in the partitions doesn't contain any
duplicated names.
*/
char *partition_info::has_unique_names()
char *partition_info::find_duplicate_name()
{
DBUG_ENTER("partition_info::has_unique_names");
HASH partition_names;
uint max_names;
const uchar *curr_name= NULL;
List_iterator<partition_element> parts_it(partitions);
partition_element *p_elem;
partition_element *el;
while ((el= (parts_it++)))
DBUG_ENTER("partition_info::find_duplicate_name");
/*
TODO: If table->s->ha_part_data->partition_name_hash.elements is > 0,
then we could just return NULL, but that has not been verified.
And this only happens when in ALTER TABLE with full table copy.
*/
max_names= num_parts;
if (is_sub_partitioned())
max_names+= num_parts * num_subparts;
if (my_hash_init(&partition_names, system_charset_info, max_names, 0, 0,
(my_hash_get_key) get_part_name_from_elem, 0, HASH_UNIQUE))
{
if (! has_unique_name(el))
DBUG_RETURN(el->partition_name);
if (!el->subpartitions.is_empty())
DBUG_ASSERT(0);
curr_name= (const uchar*) "Internal failure";
goto error;
}
while ((p_elem= (parts_it++)))
{
curr_name= (const uchar*) p_elem->partition_name;
if (my_hash_insert(&partition_names, curr_name))
goto error;
if (!p_elem->subpartitions.is_empty())
{
List_iterator<partition_element> subparts_it(el->subpartitions);
partition_element *subel;
while ((subel= (subparts_it++)))
List_iterator<partition_element> subparts_it(p_elem->subpartitions);
partition_element *subp_elem;
while ((subp_elem= (subparts_it++)))
{
if (! has_unique_name(subel))
DBUG_RETURN(subel->partition_name);
curr_name= (const uchar*) subp_elem->partition_name;
if (my_hash_insert(&partition_names, curr_name))
goto error;
}
}
}
}
my_hash_free(&partition_names);
DBUG_RETURN(NULL);
error:
my_hash_free(&partition_names);
DBUG_RETURN((char*) curr_name);
}
@ -1058,11 +1538,11 @@ static void warn_if_dir_in_part_elem(THD *thd, partition_element *part_elem)
#endif
{
if (part_elem->data_file_name)
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
WARN_OPTION_IGNORED, ER(WARN_OPTION_IGNORED),
"DATA DIRECTORY");
if (part_elem->index_file_name)
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
WARN_OPTION_IGNORED, ER(WARN_OPTION_IGNORED),
"INDEX DIRECTORY");
part_elem->data_file_name= part_elem->index_file_name= NULL;
@ -1188,12 +1668,12 @@ bool partition_info::check_partition_info(THD *thd, handlerton **eng_type,
}
if (part_field_list.elements > 0 &&
(same_name= has_unique_fields()))
(same_name= find_duplicate_field()))
{
my_error(ER_SAME_NAME_PARTITION_FIELD, MYF(0), same_name);
goto end;
}
if ((same_name= has_unique_names()))
if ((same_name= find_duplicate_name()))
{
my_error(ER_SAME_NAME_PARTITION, MYF(0), same_name);
goto end;
@ -1653,6 +2133,71 @@ void partition_info::report_part_expr_error(bool use_subpart_expr)
}
/**
Check if fields are in the partitioning expression.
@param fields List of Items (fields)
@return True if any field in the fields list is used by a partitioning expr.
@retval true At least one field in the field list is found.
@retval false No field is within any partitioning expression.
*/
bool partition_info::is_field_in_part_expr(List<Item> &fields)
{
List_iterator<Item> it(fields);
Item *item;
Item_field *field;
DBUG_ENTER("is_fields_in_part_expr");
while ((item= it++))
{
field= item->field_for_view_update();
DBUG_ASSERT(field->field->table == table);
if (bitmap_is_set(&full_part_field_set, field->field->field_index))
DBUG_RETURN(true);
}
DBUG_RETURN(false);
}
/**
Check if all partitioning fields are included.
*/
bool partition_info::is_full_part_expr_in_fields(List<Item> &fields)
{
Field **part_field= full_part_field_array;
DBUG_ASSERT(*part_field);
DBUG_ENTER("is_full_part_expr_in_fields");
/*
It is very seldom many fields in full_part_field_array, so it is OK
to loop over all of them instead of creating a bitmap fields argument
to compare with.
*/
do
{
List_iterator<Item> it(fields);
Item *item;
Item_field *field;
bool found= false;
while ((item= it++))
{
field= item->field_for_view_update();
DBUG_ASSERT(field->field->table == table);
if (*part_field == field->field)
{
found= true;
break;
}
}
if (!found)
DBUG_RETURN(false);
} while (*(++part_field));
DBUG_RETURN(true);
}
/*
Create a new column value in current list with maxvalue
Called from parser

View file

@ -20,10 +20,11 @@
#pragma interface /* gcc class implementation */
#endif
#include "sql_class.h"
#include "partition_element.h"
class partition_info;
struct TABLE_LIST;
/* Some function typedefs */
typedef int (*get_part_id_func)(partition_info *part_info,
uint32 *part_id,
@ -111,14 +112,30 @@ public:
struct st_ddl_log_memory_entry *frm_log_entry;
/*
A bitmap of partitions used by the current query.
Bitmaps of partitions used by the current query.
* read_partitions - partitions to be used for reading.
* lock_partitions - partitions that must be locked (read or write).
Usually read_partitions is the same set as lock_partitions, but
in case of UPDATE the WHERE clause can limit the read_partitions set,
but not neccesarily the lock_partitions set.
Usage pattern:
* The handler->extra(HA_EXTRA_RESET) call at query start/end sets all
partitions to be unused.
* Before index/rnd_init(), partition pruning code sets the bits for used
partitions.
* Initialized in ha_partition::open().
* read+lock_partitions is set according to explicit PARTITION,
WL#5217, in open_and_lock_tables().
* Bits in read_partitions can be cleared in prune_partitions()
in the optimizing step.
(WL#4443 is about allowing prune_partitions() to affect lock_partitions
and be done before locking too).
* When the partition enabled handler get an external_lock call it locks
all partitions in lock_partitions (and remembers which partitions it
locked, so that it can unlock them later). In case of LOCK TABLES it will
lock all partitions, and keep them locked while lock_partitions can
change for each statement under LOCK TABLES.
* Freed at the same time item_free_list is freed.
*/
MY_BITMAP used_partitions;
MY_BITMAP read_partitions;
MY_BITMAP lock_partitions;
bool bitmaps_are_initialized;
union {
longlong *range_int_array;
@ -157,6 +174,7 @@ public:
uint curr_list_object;
uint num_columns;
TABLE *table;
/*
These key_map's are used for Partitioning to enable quick decisions
on whether we can derive more information about which partition to
@ -207,6 +225,15 @@ public:
bool from_openfrm;
bool has_null_value;
bool column_list;
/**
True if pruning has been completed and can not be pruned any further,
even if there are subqueries or stored programs in the condition.
Some times it is needed to run prune_partitions() a second time to prune
read partitions after tables are locked, when subquery and
stored functions might have been evaluated.
*/
bool is_pruning_completed;
partition_info()
: get_partition_id(NULL), get_part_partition_id(NULL),
@ -219,6 +246,7 @@ public:
restore_part_field_ptrs(NULL), restore_subpart_field_ptrs(NULL),
part_expr(NULL), subpart_expr(NULL), item_free_list(NULL),
first_log_entry(NULL), exec_log_entry(NULL), frm_log_entry(NULL),
bitmaps_are_initialized(FALSE),
list_array(NULL), err_value(0),
part_info_string(NULL),
part_func_string(NULL), subpart_func_string(NULL),
@ -238,7 +266,7 @@ public:
list_of_part_fields(FALSE), list_of_subpart_fields(FALSE),
linear_hash_ind(FALSE), fixed(FALSE),
is_auto_partitioned(FALSE), from_openfrm(FALSE),
has_null_value(FALSE), column_list(FALSE)
has_null_value(FALSE), column_list(FALSE), is_pruning_completed(false)
{
all_fields_in_PF.clear_all();
all_fields_in_PPF.clear_all();
@ -252,6 +280,8 @@ public:
~partition_info() {}
partition_info *get_clone();
bool set_named_partition_bitmap(const char *part_name, uint length);
bool set_partition_bitmaps(TABLE_LIST *table_list);
/* Answers the question if subpartitioning is used for a certain table */
bool is_sub_partitioned()
{
@ -266,8 +296,8 @@ public:
bool set_up_defaults_for_partitioning(handler *file, HA_CREATE_INFO *info,
uint start_no);
char *has_unique_fields();
char *has_unique_names();
char *find_duplicate_field();
char *find_duplicate_name();
bool check_engine_mix(handlerton *engine_type, bool default_engine);
bool check_range_constants(THD *thd);
bool check_list_constants(THD *thd);
@ -297,7 +327,34 @@ public:
bool init_column_part();
bool add_column_list_value(THD *thd, Item *item);
void set_show_version_string(String *packet);
partition_element *get_part_elem(const char *partition_name,
char *file_name,
uint32 *part_id);
void report_part_expr_error(bool use_subpart_expr);
bool set_used_partition(List<Item> &fields,
List<Item> &values,
COPY_INFO &info,
bool copy_default_values,
MY_BITMAP *used_partitions);
/**
PRUNE_NO - Unable to prune.
PRUNE_DEFAULTS - Partitioning field is only set to
DEFAULT values, only need to check
pruning for one row where the DEFAULTS
values are set.
PRUNE_YES - Pruning is possible, calculate the used partition set
by evaluate the partition_id on row by row basis.
*/
enum enum_can_prune {PRUNE_NO=0, PRUNE_DEFAULTS, PRUNE_YES};
bool can_prune_insert(THD *thd,
enum_duplicates duplic,
COPY_INFO &update,
List<Item> &update_fields,
List<Item> &fields,
bool empty_values,
enum_can_prune *can_prune_partitions,
bool *prune_needs_default_values,
MY_BITMAP *used_partitions);
private:
static int list_part_cmp(const void* a, const void* b);
bool set_up_default_partitions(handler *file, HA_CREATE_INFO *info,
@ -305,7 +362,13 @@ private:
bool set_up_default_subpartitions(handler *file, HA_CREATE_INFO *info);
char *create_default_partition_names(uint part_no, uint num_parts,
uint start_no);
char *create_subpartition_name(uint subpart_no, const char *part_name);
char *create_default_subpartition_name(uint subpart_no,
const char *part_name);
bool prune_partition_bitmaps(TABLE_LIST *table_list);
bool add_named_partition(const char *part_name, uint length);
bool is_field_in_part_expr(List<Item> &fields);
bool is_full_part_expr_in_fields(List<Item> &fields);
public:
bool has_unique_name(partition_element *element);
};

View file

@ -161,14 +161,14 @@ bool net_send_error(THD *thd, uint sql_errno, const char *err,
It's one case when we can push an error even though there
is an OK or EOF already.
*/
thd->stmt_da->can_overwrite_status= TRUE;
thd->get_stmt_da()->set_overwrite_status(true);
/* Abort multi-result sets */
thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
error= net_send_error_packet(thd, sql_errno, err, sqlstate);
thd->stmt_da->can_overwrite_status= FALSE;
thd->get_stmt_da()->set_overwrite_status(false);
DBUG_RETURN(error);
}
@ -242,7 +242,7 @@ net_send_ok(THD *thd,
int2store(pos, server_status);
pos+=2;
}
thd->stmt_da->can_overwrite_status= TRUE;
thd->get_stmt_da()->set_overwrite_status(true);
if (message && message[0])
pos= net_store_data(pos, (uchar*) message, strlen(message));
@ -251,7 +251,7 @@ net_send_ok(THD *thd,
error= net_flush(net);
thd->stmt_da->can_overwrite_status= FALSE;
thd->get_stmt_da()->set_overwrite_status(false);
DBUG_PRINT("info", ("OK sent, so no more error sending allowed"));
DBUG_RETURN(error);
@ -291,11 +291,11 @@ net_send_eof(THD *thd, uint server_status, uint statement_warn_count)
/* Set to TRUE if no active vio, to work well in case of --init-file */
if (net->vio != 0)
{
thd->stmt_da->can_overwrite_status= TRUE;
thd->get_stmt_da()->set_overwrite_status(true);
error= write_eof_packet(thd, net, server_status, statement_warn_count);
if (!error)
error= net_flush(net);
thd->stmt_da->can_overwrite_status= FALSE;
thd->get_stmt_da()->set_overwrite_status(false);
DBUG_PRINT("info", ("EOF sent, so no more error sending allowed"));
}
DBUG_RETURN(error);
@ -486,30 +486,30 @@ static uchar *net_store_length_fast(uchar *packet, uint length)
void Protocol::end_statement()
{
DBUG_ENTER("Protocol::end_statement");
DBUG_ASSERT(! thd->stmt_da->is_sent);
DBUG_ASSERT(! thd->get_stmt_da()->is_sent());
bool error= FALSE;
/* Can not be true, but do not take chances in production. */
if (thd->stmt_da->is_sent)
if (thd->get_stmt_da()->is_sent())
DBUG_VOID_RETURN;
switch (thd->stmt_da->status()) {
switch (thd->get_stmt_da()->status()) {
case Diagnostics_area::DA_ERROR:
/* The query failed, send error to log and abort bootstrap. */
error= send_error(thd->stmt_da->sql_errno(),
thd->stmt_da->message(),
thd->stmt_da->get_sqlstate());
error= send_error(thd->get_stmt_da()->sql_errno(),
thd->get_stmt_da()->message(),
thd->get_stmt_da()->get_sqlstate());
break;
case Diagnostics_area::DA_EOF:
error= send_eof(thd->server_status,
thd->stmt_da->statement_warn_count());
thd->get_stmt_da()->statement_warn_count());
break;
case Diagnostics_area::DA_OK:
error= send_ok(thd->server_status,
thd->stmt_da->statement_warn_count(),
thd->stmt_da->affected_rows(),
thd->stmt_da->last_insert_id(),
thd->stmt_da->message());
thd->get_stmt_da()->statement_warn_count(),
thd->get_stmt_da()->affected_rows(),
thd->get_stmt_da()->last_insert_id(),
thd->get_stmt_da()->message());
break;
case Diagnostics_area::DA_DISABLED:
break;
@ -520,7 +520,7 @@ void Protocol::end_statement()
break;
}
if (!error)
thd->stmt_da->is_sent= TRUE;
thd->get_stmt_da()->set_is_sent(true);
DBUG_VOID_RETURN;
}
@ -688,9 +688,9 @@ bool Protocol::flush()
{
#ifndef EMBEDDED_LIBRARY
bool error;
thd->stmt_da->can_overwrite_status= TRUE;
thd->get_stmt_da()->set_overwrite_status(true);
error= net_flush(&thd->net);
thd->stmt_da->can_overwrite_status= FALSE;
thd->get_stmt_da()->set_overwrite_status(false);
return error;
#else
return 0;
@ -856,7 +856,7 @@ bool Protocol::send_result_set_metadata(List<Item> *list, uint flags)
Send no warning information, as it will be sent at statement end.
*/
if (write_eof_packet(thd, &thd->net, thd->server_status,
thd->warning_info->statement_warn_count()))
thd->get_stmt_da()->current_statement_warn_count()))
DBUG_RETURN(1);
}
DBUG_RETURN(prepare_for_send(list->elements));

View file

@ -818,7 +818,7 @@ bool Master_info_index::init_all_master_info()
sql_print_error("Initialized Master_info from '%s' failed",
buf_master_info_file);
if (!master_info_index->get_master_info(&connection_name,
MYSQL_ERROR::WARN_LEVEL_NOTE))
Sql_condition::WARN_LEVEL_NOTE))
{
/* Master_info is not in HASH; Add it */
if (master_info_index->add_master_info(mi, FALSE))
@ -843,7 +843,7 @@ bool Master_info_index::init_all_master_info()
sql_print_information("Initialized Master_info from '%s'",
buf_master_info_file);
if (master_info_index->get_master_info(&connection_name,
MYSQL_ERROR::WARN_LEVEL_NOTE))
Sql_condition::WARN_LEVEL_NOTE))
{
/* Master_info was already registered */
sql_print_error(ER(ER_CONNECTION_ALREADY_EXISTS),
@ -940,7 +940,7 @@ bool Master_info_index::write_master_name_to_index_file(LEX_STRING *name,
Master_info *
Master_info_index::get_master_info(LEX_STRING *connection_name,
MYSQL_ERROR::enum_warning_level warning)
Sql_condition::enum_warning_level warning)
{
Master_info *mi;
char buff[MAX_CONNECTION_NAME+1], *res;
@ -957,10 +957,10 @@ Master_info_index::get_master_info(LEX_STRING *connection_name,
mi= (Master_info*) my_hash_search(&master_info_hash,
(uchar*) buff, buff_length);
if (!mi && warning != MYSQL_ERROR::WARN_LEVEL_NOTE)
if (!mi && warning != Sql_condition::WARN_LEVEL_NOTE)
{
my_error(WARN_NO_MASTER_INFO,
MYF(warning == MYSQL_ERROR::WARN_LEVEL_WARN ? ME_JUST_WARNING :
MYF(warning == Sql_condition::WARN_LEVEL_WARN ? ME_JUST_WARNING :
0),
(int) connection_name->length,
connection_name->str);
@ -979,7 +979,7 @@ bool Master_info_index::check_duplicate_master_info(LEX_STRING *name_arg,
/* Get full host and port name */
if ((mi= master_info_index->get_master_info(name_arg,
MYSQL_ERROR::WARN_LEVEL_NOTE)))
Sql_condition::WARN_LEVEL_NOTE)))
{
if (!host)
host= mi->host;
@ -1043,7 +1043,7 @@ bool Master_info_index::remove_master_info(LEX_STRING *name)
Master_info* mi;
DBUG_ENTER("remove_master_info");
if ((mi= get_master_info(name, MYSQL_ERROR::WARN_LEVEL_WARN)))
if ((mi= get_master_info(name, Sql_condition::WARN_LEVEL_WARN)))
{
// Delete Master_info and rewrite others to file
if (!my_hash_delete(&master_info_hash, (uchar*) mi))
@ -1155,7 +1155,7 @@ bool Master_info_index::start_all_slaves(THD *thd)
break;
}
else
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
ER_SLAVE_STARTED, ER(ER_SLAVE_STARTED),
(int) mi->connection_name.length,
mi->connection_name.str);
@ -1200,7 +1200,7 @@ bool Master_info_index::stop_all_slaves(THD *thd)
break;
}
else
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
ER_SLAVE_STOPPED, ER(ER_SLAVE_STOPPED),
(int) mi->connection_name.length,
mi->connection_name.str);

View file

@ -164,7 +164,7 @@ public:
bool add_master_info(Master_info *mi, bool write_to_file);
bool remove_master_info(LEX_STRING *connection_name);
Master_info *get_master_info(LEX_STRING *connection_name,
MYSQL_ERROR::enum_warning_level warning);
Sql_condition::enum_warning_level warning);
bool give_error_if_slave_running();
bool start_all_slaves(THD *thd);
bool stop_all_slaves(THD *thd);

View file

@ -287,7 +287,7 @@ unpack_row(Relay_log_info const *rli,
else
{
f->set_default();
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
ER_BAD_NULL_ERROR, ER(ER_BAD_NULL_ERROR),
f->field_name);
}
@ -447,7 +447,7 @@ int prepare_record(TABLE *const table, const uint skip, const bool check)
{
f->set_default();
push_warning_printf(current_thd,
MYSQL_ERROR::WARN_LEVEL_WARN,
Sql_condition::WARN_LEVEL_WARN,
ER_NO_DEFAULT_FOR_FIELD,
ER(ER_NO_DEFAULT_FOR_FIELD),
f->field_name);

View file

@ -247,7 +247,7 @@ a file name for --relay-log-index option", opt_relaylog_index_name);
{
sql_print_error("Failed to create a new relay log info file (\
file '%s', errno %d)", fname, my_errno);
msg= current_thd->stmt_da->message();
msg= current_thd->get_stmt_da()->message();
goto err;
}
if (init_io_cache(&rli->info_file, info_fd, IO_SIZE*2, READ_CACHE, 0L,0,
@ -255,7 +255,7 @@ file '%s', errno %d)", fname, my_errno);
{
sql_print_error("Failed to create a cache on relay log info file '%s'",
fname);
msg= current_thd->stmt_da->message();
msg= current_thd->get_stmt_da()->message();
goto err;
}
@ -1334,9 +1334,9 @@ void Relay_log_info::clear_tables_to_lock()
void Relay_log_info::slave_close_thread_tables(THD *thd)
{
DBUG_ENTER("Relay_log_info::slave_close_thread_tables(THD *thd)");
thd->stmt_da->can_overwrite_status= TRUE;
thd->get_stmt_da()->set_overwrite_status(true);
thd->is_error() ? trans_rollback_stmt(thd) : trans_commit_stmt(thd);
thd->stmt_da->can_overwrite_status= FALSE;
thd->get_stmt_da()->set_overwrite_status(false);
close_thread_tables(thd);
/*

View file

@ -279,7 +279,7 @@ void sys_var::do_deprecated_warning(THD *thd)
? ER_WARN_DEPRECATED_SYNTAX_NO_REPLACEMENT
: ER_WARN_DEPRECATED_SYNTAX;
if (thd)
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_WARN_DEPRECATED_SYNTAX, ER(errmsg),
buf1, deprecation_substitute);
else
@ -316,7 +316,7 @@ bool throw_bounds_warning(THD *thd, const char *name,
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, buf);
return true;
}
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_TRUNCATED_WRONG_VALUE,
ER(ER_TRUNCATED_WRONG_VALUE), name, buf);
}
@ -336,7 +336,7 @@ bool throw_bounds_warning(THD *thd, const char *name, bool fixed, double v)
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, buf);
return true;
}
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_TRUNCATED_WRONG_VALUE,
ER(ER_TRUNCATED_WRONG_VALUE), name, buf);
}

View file

@ -2650,7 +2650,7 @@ static int has_temporary_error(THD *thd)
DBUG_ENTER("has_temporary_error");
DBUG_EXECUTE_IF("all_errors_are_temporary_errors",
if (thd->stmt_da->is_error())
if (thd->get_stmt_da()->is_error())
{
thd->clear_error();
my_error(ER_LOCK_DEADLOCK, MYF(0));
@ -2669,16 +2669,16 @@ static int has_temporary_error(THD *thd)
currently, InnoDB deadlock detected by InnoDB or lock
wait timeout (innodb_lock_wait_timeout exceeded
*/
if (thd->stmt_da->sql_errno() == ER_LOCK_DEADLOCK ||
thd->stmt_da->sql_errno() == ER_LOCK_WAIT_TIMEOUT)
if (thd->get_stmt_da()->sql_errno() == ER_LOCK_DEADLOCK ||
thd->get_stmt_da()->sql_errno() == ER_LOCK_WAIT_TIMEOUT)
DBUG_RETURN(1);
#ifdef HAVE_NDB_BINLOG
/*
currently temporary error set in ndbcluster
*/
List_iterator_fast<MYSQL_ERROR> it(thd->warning_info->warn_list());
MYSQL_ERROR *err;
List_iterator_fast<Sql_condition> it(thd->warning_info->warn_list());
Sql_condition *err;
while ((err= it++))
{
DBUG_PRINT("info", ("has condition %d %s", err->get_sql_errno(),
@ -3738,9 +3738,9 @@ log '%s' at position %s, relay log '%s' position: %s", RPL_LOG_NAME,
if (check_temp_dir(rli->slave_patternload_file))
{
rli->report(ERROR_LEVEL, thd->stmt_da->sql_errno(),
rli->report(ERROR_LEVEL, thd->get_stmt_da()->sql_errno(),
"Unable to use slave's temporary directory %s - %s",
slave_load_tmpdir, thd->stmt_da->message());
slave_load_tmpdir, thd->get_stmt_da()->message());
goto err;
}
@ -3750,7 +3750,7 @@ log '%s' at position %s, relay log '%s' position: %s", RPL_LOG_NAME,
execute_init_command(thd, &opt_init_slave, &LOCK_sys_init_slave);
if (thd->is_slave_error)
{
rli->report(ERROR_LEVEL, thd->stmt_da->sql_errno(),
rli->report(ERROR_LEVEL, thd->get_stmt_da()->sql_errno(),
"Slave SQL thread aborted. Can't execute init_slave query");
goto err;
}
@ -3817,20 +3817,20 @@ log '%s' at position %s, relay log '%s' position: %s", RPL_LOG_NAME,
if (thd->is_error())
{
char const *const errmsg= thd->stmt_da->message();
char const *const errmsg= thd->get_stmt_da()->message();
DBUG_PRINT("info",
("thd->stmt_da->sql_errno()=%d; rli->last_error.number=%d",
thd->stmt_da->sql_errno(), last_errno));
("thd->get_stmt_da()->sql_errno()=%d; rli->last_error.number=%d",
thd->get_stmt_da()->sql_errno(), last_errno));
if (last_errno == 0)
{
/*
This function is reporting an error which was not reported
while executing exec_relay_log_event().
*/
rli->report(ERROR_LEVEL, thd->stmt_da->sql_errno(), "%s", errmsg);
rli->report(ERROR_LEVEL, thd->get_stmt_da()->sql_errno(), "%s", errmsg);
}
else if (last_errno != thd->stmt_da->sql_errno())
else if (last_errno != thd->get_stmt_da()->sql_errno())
{
/*
* An error was reported while executing exec_relay_log_event()
@ -3839,13 +3839,14 @@ log '%s' at position %s, relay log '%s' position: %s", RPL_LOG_NAME,
* what caused the problem.
*/
sql_print_error("Slave (additional info): %s Error_code: %d",
errmsg, thd->stmt_da->sql_errno());
errmsg, thd->get_stmt_da()->sql_errno());
}
}
/* Print any warnings issued */
List_iterator_fast<MYSQL_ERROR> it(thd->warning_info->warn_list());
MYSQL_ERROR *err;
Diagnostics_area::Sql_condition_iterator it=
thd->get_stmt_da()->sql_conditions();
const Sql_condition *err;
/*
Added controlled slave thread cancel for replication
of user-defined variables.

View file

@ -325,7 +325,7 @@ Stored_routine_creation_ctx::load_from_db(THD *thd,
if (invalid_creation_ctx)
{
push_warning_printf(thd,
MYSQL_ERROR::WARN_LEVEL_WARN,
Sql_condition::WARN_LEVEL_WARN,
ER_SR_INVALID_CREATION_CTX,
ER(ER_SR_INVALID_CREATION_CTX),
(const char *) db_name,
@ -683,9 +683,9 @@ public:
virtual bool handle_condition(THD *thd,
uint sql_errno,
const char* sqlstate,
MYSQL_ERROR::enum_warning_level level,
Sql_condition::enum_warning_level level,
const char* msg,
MYSQL_ERROR ** cond_hdl);
Sql_condition ** cond_hdl);
};
bool
@ -693,13 +693,13 @@ Silence_deprecated_warning::handle_condition(
THD *,
uint sql_errno,
const char*,
MYSQL_ERROR::enum_warning_level level,
Sql_condition::enum_warning_level level,
const char*,
MYSQL_ERROR ** cond_hdl)
Sql_condition ** cond_hdl)
{
*cond_hdl= NULL;
if (sql_errno == ER_WARN_DEPRECATED_SYNTAX &&
level == MYSQL_ERROR::WARN_LEVEL_WARN)
level == Sql_condition::WARN_LEVEL_WARN)
return TRUE;
return FALSE;
@ -772,9 +772,9 @@ public:
virtual bool handle_condition(THD *thd,
uint sql_errno,
const char* sqlstate,
MYSQL_ERROR::enum_warning_level level,
Sql_condition::enum_warning_level level,
const char* message,
MYSQL_ERROR ** cond_hdl);
Sql_condition ** cond_hdl);
bool error_caught() const { return m_error_caught; }
@ -786,9 +786,9 @@ bool
Bad_db_error_handler::handle_condition(THD *thd,
uint sql_errno,
const char* sqlstate,
MYSQL_ERROR::enum_warning_level level,
Sql_condition::enum_warning_level level,
const char* message,
MYSQL_ERROR ** cond_hdl)
Sql_condition ** cond_hdl)
{
if (sql_errno == ER_BAD_DB_ERROR)
{
@ -1390,9 +1390,9 @@ public:
bool handle_condition(THD *thd,
uint sql_errno,
const char* sqlstate,
MYSQL_ERROR::enum_warning_level level,
Sql_condition::enum_warning_level level,
const char* msg,
MYSQL_ERROR ** cond_hdl)
Sql_condition ** cond_hdl)
{
if (sql_errno == ER_NO_SUCH_TABLE ||
sql_errno == ER_NO_SUCH_TABLE_IN_ENGINE ||
@ -1757,7 +1757,7 @@ sp_exist_routines(THD *thd, TABLE_LIST *routines, bool any)
&thd->sp_proc_cache, FALSE) != NULL ||
sp_find_routine(thd, TYPE_ENUM_FUNCTION, name,
&thd->sp_func_cache, FALSE) != NULL;
thd->warning_info->clear_warning_info(thd->query_id);
thd->get_stmt_da()->clear_warning_info(thd->query_id);
if (sp_object_found)
{
if (any)

View file

@ -1148,19 +1148,20 @@ find_handler_after_execution(THD *thd, sp_rcontext *ctx)
if (thd->is_error())
{
ctx->find_handler(thd,
thd->stmt_da->sql_errno(),
thd->stmt_da->get_sqlstate(),
MYSQL_ERROR::WARN_LEVEL_ERROR,
thd->stmt_da->message());
thd->get_stmt_da()->sql_errno(),
thd->get_stmt_da()->get_sqlstate(),
Sql_condition::WARN_LEVEL_ERROR,
thd->get_stmt_da()->message());
}
else if (thd->warning_info->statement_warn_count())
else if (thd->get_stmt_da()->statement_warn_count())
{
List_iterator<MYSQL_ERROR> it(thd->warning_info->warn_list());
MYSQL_ERROR *err;
Diagnostics_area::Sql_condition_iterator it=
thd->get_stmt_da()->sql_conditions();
const Sql_condition *err;
while ((err= it++))
{
if (err->get_level() != MYSQL_ERROR::WARN_LEVEL_WARN &&
err->get_level() != MYSQL_ERROR::WARN_LEVEL_NOTE)
if (err->get_level() != Sql_condition::WARN_LEVEL_WARN &&
err->get_level() != Sql_condition::WARN_LEVEL_NOTE)
continue;
if (ctx->find_handler(thd,
@ -1221,8 +1222,8 @@ sp_head::execute(THD *thd, bool merge_da_on_success)
String old_packet;
Reprepare_observer *save_reprepare_observer= thd->m_reprepare_observer;
Object_creation_ctx *saved_creation_ctx;
Warning_info *saved_warning_info;
Warning_info warning_info(thd->warning_info->warn_id(), false);
Diagnostics_area *da= thd->get_stmt_da();
Warning_info sp_wi(da->warning_info_id(), false, true);
/*
Just reporting a stack overrun error
@ -1293,9 +1294,8 @@ sp_head::execute(THD *thd, bool merge_da_on_success)
old_arena= thd->stmt_arena;
/* Push a new warning information area. */
warning_info.append_warning_info(thd, thd->warning_info);
saved_warning_info= thd->warning_info;
thd->warning_info= &warning_info;
da->copy_sql_conditions_to_wi(thd, &sp_wi);
da->push_warning_info(&sp_wi);
/*
Switch query context. This has to be done early as this is sometimes
@ -1395,7 +1395,7 @@ sp_head::execute(THD *thd, bool merge_da_on_success)
}
/* Reset number of warnings for this query. */
thd->warning_info->reset_for_next_command();
thd->get_stmt_da()->reset_for_next_command();
DBUG_PRINT("execute", ("Instruction %u", ip));
@ -1502,9 +1502,40 @@ sp_head::execute(THD *thd, bool merge_da_on_success)
- if there was an exception during execution, warning info should be
propagated to the caller in any case.
*/
da->pop_warning_info();
if (err_status || merge_da_on_success)
saved_warning_info->merge_with_routine_info(thd, thd->warning_info);
thd->warning_info= saved_warning_info;
{
/*
If a routine body is empty or if a routine did not generate any warnings,
do not duplicate our own contents by appending the contents of the called
routine. We know that the called routine did not change its warning info.
On the other hand, if the routine body is not empty and some statement in
the routine generates a warning or uses tables, warning info is guaranteed
to have changed. In this case we know that the routine warning info
contains only new warnings, and thus we perform a copy.
*/
if (da->warning_info_changed(&sp_wi))
{
/*
If the invocation of the routine was a standalone statement,
rather than a sub-statement, in other words, if it's a CALL
of a procedure, rather than invocation of a function or a
trigger, we need to clear the current contents of the caller's
warning info.
This is per MySQL rules: if a statement generates a warning,
warnings from the previous statement are flushed. Normally
it's done in push_warning(). However, here we don't use
push_warning() to avoid invocation of condition handlers or
escalation of warnings to errors.
*/
da->opt_clear_warning_info(thd->query_id);
da->copy_sql_conditions_from_wi(thd, &sp_wi);
da->remove_marked_sql_conditions();
}
}
done:
DBUG_PRINT("info", ("err_status: %d killed: %d is_slave_error: %d report_error: %d",
@ -1958,7 +1989,7 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount,
if (mysql_bin_log.write(&qinfo) &&
thd->binlog_evt_union.unioned_events_trans)
{
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
push_warning(thd, Sql_condition::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
"Invoked ROUTINE modified a transactional table but MySQL "
"failed to reflect this change in the binary log");
err_status= TRUE;
@ -2137,9 +2168,9 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
if (!thd->in_sub_stmt)
{
thd->stmt_da->can_overwrite_status= TRUE;
thd->get_stmt_da()->set_overwrite_status(true);
thd->is_error() ? trans_rollback_stmt(thd) : trans_commit_stmt(thd);
thd->stmt_da->can_overwrite_status= FALSE;
thd->get_stmt_da()->set_overwrite_status(false);
}
thd_proc_info(thd, "closing tables");
@ -2884,7 +2915,7 @@ sp_head::show_routine_code(THD *thd)
Since this is for debugging purposes only, we don't bother to
introduce a special error code for it.
*/
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR, tmp);
push_warning(thd, Sql_condition::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR, tmp);
}
protocol->prepare_for_resend();
protocol->store((longlong)ip);
@ -2991,9 +3022,9 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp,
/* Here we also commit or rollback the current statement. */
if (! thd->in_sub_stmt)
{
thd->stmt_da->can_overwrite_status= TRUE;
thd->get_stmt_da()->set_overwrite_status(true);
thd->is_error() ? trans_rollback_stmt(thd) : trans_commit_stmt(thd);
thd->stmt_da->can_overwrite_status= FALSE;
thd->get_stmt_da()->set_overwrite_status(false);
}
thd_proc_info(thd, "closing tables");
close_thread_tables(thd);
@ -3027,10 +3058,10 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp,
open_tables stage.
*/
if (!res || !thd->is_error() ||
(thd->stmt_da->sql_errno() != ER_CANT_REOPEN_TABLE &&
thd->stmt_da->sql_errno() != ER_NO_SUCH_TABLE &&
thd->stmt_da->sql_errno() != ER_NO_SUCH_TABLE_IN_ENGINE &&
thd->stmt_da->sql_errno() != ER_UPDATE_TABLE_USED))
(thd->get_stmt_da()->sql_errno() != ER_CANT_REOPEN_TABLE &&
thd->get_stmt_da()->sql_errno() != ER_NO_SUCH_TABLE &&
thd->get_stmt_da()->sql_errno() != ER_NO_SUCH_TABLE_IN_ENGINE &&
thd->get_stmt_da()->sql_errno() != ER_UPDATE_TABLE_USED))
thd->stmt_arena->state= Query_arena::STMT_EXECUTED;
/*
@ -3117,7 +3148,7 @@ sp_instr_stmt::execute(THD *thd, uint *nextp)
{
res= m_lex_keeper.reset_lex_and_exec_core(thd, nextp, FALSE, this);
if (thd->stmt_da->is_eof())
if (thd->get_stmt_da()->is_eof())
{
/* Finalize server status flags after executing a statement. */
thd->update_server_status();
@ -3136,7 +3167,7 @@ sp_instr_stmt::execute(THD *thd, uint *nextp)
thd->query_name_consts= 0;
if (!thd->is_error())
thd->stmt_da->reset_diagnostics_area();
thd->get_stmt_da()->reset_diagnostics_area();
}
DBUG_RETURN(res || thd->is_error());
}

View file

@ -274,6 +274,15 @@ public:
*/
Security_context m_security_ctx;
/**
List of all items (Item_trigger_field objects) representing fields in
old/new version of row in trigger. We use this list for checking whenever
all such fields are valid at trigger creation time and for binding these
fields to TABLE object at table open (although for latter pointer to table
being opened is probably enough).
*/
SQL_I_List<Item_trigger_field> m_trg_table_fields;
static void *
operator new(size_t size) throw ();

View file

@ -204,7 +204,7 @@ bool
sp_rcontext::find_handler(THD *thd,
uint sql_errno,
const char *sqlstate,
MYSQL_ERROR::enum_warning_level level,
Sql_condition::enum_warning_level level,
const char *msg)
{
int i= m_hcount;
@ -248,7 +248,7 @@ sp_rcontext::find_handler(THD *thd,
break;
case sp_cond_type_t::warning:
if ((IS_WARNING_CONDITION(sqlstate) ||
level == MYSQL_ERROR::WARN_LEVEL_WARN) &&
level == Sql_condition::WARN_LEVEL_WARN) &&
m_hfound < 0)
m_hfound= i;
break;
@ -258,7 +258,7 @@ sp_rcontext::find_handler(THD *thd,
break;
case sp_cond_type_t::exception:
if (IS_EXCEPTION_CONDITION(sqlstate) &&
level == MYSQL_ERROR::WARN_LEVEL_ERROR &&
level == Sql_condition::WARN_LEVEL_ERROR &&
m_hfound < 0)
m_hfound= i;
break;
@ -281,7 +281,7 @@ sp_rcontext::find_handler(THD *thd,
(warning or "not found") we will simply resume execution.
*/
if (m_prev_runtime_ctx && IS_EXCEPTION_CONDITION(sqlstate) &&
level == MYSQL_ERROR::WARN_LEVEL_ERROR)
level == Sql_condition::WARN_LEVEL_ERROR)
{
return m_prev_runtime_ctx->find_handler(thd, sql_errno, sqlstate,
level, msg);
@ -575,7 +575,7 @@ sp_cursor::fetch(THD *thd, List<struct sp_variable> *vars)
}
DBUG_EXECUTE_IF("bug23032_emit_warning",
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning(thd, Sql_condition::WARN_LEVEL_WARN,
ER_UNKNOWN_ERROR,
ER(ER_UNKNOWN_ERROR)););

View file

@ -66,7 +66,7 @@ public:
uint m_sql_errno;
/** Error level. */
MYSQL_ERROR::enum_warning_level m_level;
Sql_condition::enum_warning_level m_level;
/** SQLSTATE. */
char m_sql_state[SQLSTATE_LENGTH + 1];
@ -75,7 +75,7 @@ public:
char m_message[MYSQL_ERRMSG_SIZE];
void set(uint sql_errno, const char* sqlstate,
MYSQL_ERROR::enum_warning_level level,
Sql_condition::enum_warning_level level,
const char* msg)
{
m_sql_errno= sql_errno;
@ -90,7 +90,7 @@ public:
void clear()
{
m_sql_errno= 0;
m_level= MYSQL_ERROR::WARN_LEVEL_ERROR;
m_level= Sql_condition::WARN_LEVEL_ERROR;
m_sql_state[0]= '\0';
m_message[0]= '\0';
@ -183,7 +183,7 @@ class sp_rcontext : public Sql_alloc
find_handler(THD *thd,
uint sql_errno,
const char *sqlstate,
MYSQL_ERROR::enum_warning_level level,
Sql_condition::enum_warning_level level,
const char *msg);
Sql_condition_info *raised_condition() const;

View file

@ -1207,9 +1207,9 @@ my_bool acl_reload(THD *thd)
Execution might have been interrupted; only print the error message
if an error condition has been raised.
*/
if (thd->stmt_da->is_error())
if (thd->get_stmt_da()->is_error())
sql_print_error("Fatal error: Can't open and lock privilege tables: %s",
thd->stmt_da->message());
thd->get_stmt_da()->message());
goto end;
}
@ -1968,7 +1968,7 @@ bool change_password(THD *thd, const char *host, const char *user,
set_user_plugin(acl_user, new_password_len);
}
else
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
push_warning(thd, Sql_condition::WARN_LEVEL_NOTE,
ER_SET_PASSWORD_AUTH_PLUGIN, ER(ER_SET_PASSWORD_AUTH_PLUGIN));
if (update_user_table(thd, table,
@ -6857,9 +6857,9 @@ public:
virtual bool handle_condition(THD *thd,
uint sql_errno,
const char* sqlstate,
MYSQL_ERROR::enum_warning_level level,
Sql_condition::enum_warning_level level,
const char* msg,
MYSQL_ERROR ** cond_hdl);
Sql_condition ** cond_hdl);
bool has_errors() { return is_grave; }
@ -6872,18 +6872,18 @@ Silence_routine_definer_errors::handle_condition(
THD *thd,
uint sql_errno,
const char*,
MYSQL_ERROR::enum_warning_level level,
Sql_condition::enum_warning_level level,
const char* msg,
MYSQL_ERROR ** cond_hdl)
Sql_condition ** cond_hdl)
{
*cond_hdl= NULL;
if (level == MYSQL_ERROR::WARN_LEVEL_ERROR)
if (level == Sql_condition::WARN_LEVEL_ERROR)
{
switch (sql_errno)
{
case ER_NONEXISTING_PROC_GRANT:
/* Convert the error into a warning. */
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning(thd, Sql_condition::WARN_LEVEL_WARN,
sql_errno, msg);
return TRUE;
default:
@ -7050,7 +7050,7 @@ bool sp_grant_privileges(THD *thd, const char *sp_db, const char *sp_name,
}
else
{
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_PASSWD_LENGTH,
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_PASSWD_LENGTH,
ER(ER_PASSWD_LENGTH), SCRAMBLED_PASSWORD_CHAR_LENGTH);
return TRUE;
}
@ -9156,15 +9156,14 @@ bool acl_authenticate(THD *thd, uint connect_errors,
sctx->external_user= my_strdup(mpvio.auth_info.external_user, MYF(0));
if (res == CR_OK_HANDSHAKE_COMPLETE)
thd->stmt_da->disable_status();
thd->get_stmt_da()->disable_status();
else
my_ok(thd);
#ifdef HAVE_PSI_THREAD_INTERFACE
PSI_CALL(set_thread_user_host)(thd->main_security_ctx.user,
strlen(thd->main_security_ctx.user),
thd->main_security_ctx.host_or_ip,
strlen(thd->main_security_ctx.host_or_ip));
PSI_THREAD_CALL(set_thread_user_host)
(thd->main_security_ctx.user, strlen(thd->main_security_ctx.user),
thd->main_security_ctx.host_or_ip, strlen(thd->main_security_ctx.host_or_ip));
#endif
/* Ready to handle queries */

View file

@ -52,8 +52,8 @@ static bool admin_recreate_table(THD *thd, TABLE_LIST *table_list)
we will store the error message in a result set row
and then clear.
*/
if (thd->stmt_da->is_ok())
thd->stmt_da->reset_diagnostics_area();
if (thd->get_stmt_da()->is_ok())
thd->get_stmt_da()->reset_diagnostics_area();
table_list->table= NULL;
result_code= result_code ? HA_ADMIN_FAILED : HA_ADMIN_OK;
DBUG_RETURN(result_code);
@ -98,7 +98,7 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list,
if (!(table= table_list->table))
{
char key[MAX_DBKEY_LENGTH];
const char *key;
uint key_length;
/*
If the table didn't exist, we have a shared metadata lock
@ -114,7 +114,8 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list,
*/
my_hash_value_type hash_value;
key_length= create_table_def_key(thd, key, table_list, 0);
key_length= get_table_def_key(table_list, &key);
table_list->mdl_request.init(MDL_key::TABLE,
table_list->db, table_list->table_name,
MDL_EXCLUSIVE, MDL_TRANSACTION);
@ -203,7 +204,7 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list,
goto end;
/* Close table but don't remove from locked list */
close_all_tables_for_name(thd, table_list->table->s,
HA_EXTRA_NOT_USED);
HA_EXTRA_NOT_USED, NULL);
table_list->table= 0;
}
/*
@ -398,14 +399,14 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
because it's already known that the table is badly damaged.
*/
Warning_info wi(thd->query_id, false);
Warning_info *wi_saved= thd->warning_info;
Diagnostics_area *da= thd->get_stmt_da();
Warning_info tmp_wi(thd->query_id, false, true);
thd->warning_info= &wi;
da->push_warning_info(&tmp_wi);
open_error= open_and_lock_tables(thd, table, TRUE, 0);
thd->warning_info= wi_saved;
da->pop_warning_info(&tmp_wi);
}
else
{
@ -452,7 +453,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
*/
Alter_info *alter_info= &lex->alter_info;
if (alter_info->flags & ALTER_ADMIN_PARTITION)
if (alter_info->flags & Alter_info::ALTER_ADMIN_PARTITION)
{
if (!table->table->part_info)
{
@ -516,16 +517,16 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
if (!table->table)
{
DBUG_PRINT("admin", ("open table failed"));
if (thd->warning_info->is_empty())
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
if (thd->get_stmt_da()->is_warning_info_empty())
push_warning(thd, Sql_condition::WARN_LEVEL_WARN,
ER_CHECK_NO_SUCH_TABLE, ER(ER_CHECK_NO_SUCH_TABLE));
/* if it was a view will check md5 sum */
if (table->view &&
view_checksum(thd, table) == HA_ADMIN_WRONG_CHECKSUM)
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning(thd, Sql_condition::WARN_LEVEL_WARN,
ER_VIEW_CHECKSUM, ER(ER_VIEW_CHECKSUM));
if (thd->stmt_da->is_error() &&
table_not_corrupt_error(thd->stmt_da->sql_errno()))
if (thd->get_stmt_da()->is_error() &&
table_not_corrupt_error(thd->get_stmt_da()->sql_errno()))
result_code= HA_ADMIN_FAILED;
else
/* Default failure code is corrupt table */
@ -573,7 +574,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
table->table=0; // For query cache
if (protocol->write())
goto err;
thd->stmt_da->reset_diagnostics_area();
thd->get_stmt_da()->reset_diagnostics_area();
continue;
/* purecov: end */
}
@ -744,8 +745,9 @@ send_result:
lex->cleanup_after_one_table_open();
thd->clear_error(); // these errors shouldn't get client
{
List_iterator_fast<MYSQL_ERROR> it(thd->warning_info->warn_list());
MYSQL_ERROR *err;
Diagnostics_area::Sql_condition_iterator it=
thd->get_stmt_da()->sql_conditions();
const Sql_condition *err;
while ((err= it++))
{
protocol->prepare_for_resend();
@ -758,7 +760,7 @@ send_result:
if (protocol->write())
goto err;
}
thd->warning_info->clear_warning_info(thd->query_id);
thd->get_stmt_da()->clear_warning_info(thd->query_id);
}
protocol->prepare_for_resend();
protocol->store(table_name, system_charset_info);
@ -875,7 +877,7 @@ send_result_message:
DBUG_ASSERT(thd->is_error() || thd->killed);
if (thd->is_error())
{
const char *err_msg= thd->stmt_da->message();
const char *err_msg= thd->get_stmt_da()->message();
if (!thd->vio_ok())
{
sql_print_error("%s", err_msg);
@ -1072,12 +1074,13 @@ bool mysql_preload_keys(THD* thd, TABLE_LIST* tables)
}
bool Analyze_table_statement::execute(THD *thd)
bool Sql_cmd_analyze_table::execute(THD *thd)
{
LEX *m_lex= thd->lex;
TABLE_LIST *first_table= m_lex->select_lex.table_list.first;
bool res= TRUE;
thr_lock_type lock_type = TL_READ_NO_INSERT;
DBUG_ENTER("Analyze_table_statement::execute");
DBUG_ENTER("Sql_cmd_analyze_table::execute");
if (check_table_access(thd, SELECT_ACL | INSERT_ACL, first_table,
FALSE, UINT_MAX, FALSE))
@ -1102,12 +1105,13 @@ error:
}
bool Check_table_statement::execute(THD *thd)
bool Sql_cmd_check_table::execute(THD *thd)
{
LEX *m_lex= thd->lex;
TABLE_LIST *first_table= m_lex->select_lex.table_list.first;
thr_lock_type lock_type = TL_READ_NO_INSERT;
bool res= TRUE;
DBUG_ENTER("Check_table_statement::execute");
DBUG_ENTER("Sql_cmd_check_table::execute");
if (check_table_access(thd, SELECT_ACL, first_table,
TRUE, UINT_MAX, FALSE))
@ -1126,17 +1130,18 @@ error:
}
bool Optimize_table_statement::execute(THD *thd)
bool Sql_cmd_optimize_table::execute(THD *thd)
{
LEX *m_lex= thd->lex;
TABLE_LIST *first_table= m_lex->select_lex.table_list.first;
bool res= TRUE;
DBUG_ENTER("Optimize_table_statement::execute");
DBUG_ENTER("Sql_cmd_optimize_table::execute");
if (check_table_access(thd, SELECT_ACL | INSERT_ACL, first_table,
FALSE, UINT_MAX, FALSE))
goto error; /* purecov: inspected */
thd->enable_slow_log= opt_log_slow_admin_statements;
res= (specialflag & (SPECIAL_SAFE_MODE | SPECIAL_NO_NEW_FUNC)) ?
res= (specialflag & SPECIAL_NO_NEW_FUNC) ?
mysql_recreate_table(thd, first_table) :
mysql_admin_table(thd, first_table, &m_lex->check_opt,
"optimize", TL_WRITE, 1, 0, 0, 0,
@ -1157,11 +1162,12 @@ error:
}
bool Repair_table_statement::execute(THD *thd)
bool Sql_cmd_repair_table::execute(THD *thd)
{
LEX *m_lex= thd->lex;
TABLE_LIST *first_table= m_lex->select_lex.table_list.first;
bool res= TRUE;
DBUG_ENTER("Repair_table_statement::execute");
DBUG_ENTER("Sql_cmd_repair_table::execute");
if (check_table_access(thd, SELECT_ACL | INSERT_ACL, first_table,
FALSE, UINT_MAX, FALSE))

View file

@ -24,109 +24,100 @@ int reassign_keycache_tables(THD* thd, KEY_CACHE *src_cache,
KEY_CACHE *dst_cache);
/**
Analyze_statement represents the ANALYZE TABLE statement.
Sql_cmd_analyze_table represents the ANALYZE TABLE statement.
*/
class Analyze_table_statement : public Sql_statement
class Sql_cmd_analyze_table : public Sql_cmd
{
public:
/**
Constructor, used to represent a ANALYZE TABLE statement.
@param lex the LEX structure for this statement.
*/
Analyze_table_statement(LEX *lex)
: Sql_statement(lex)
Sql_cmd_analyze_table()
{}
~Analyze_table_statement()
~Sql_cmd_analyze_table()
{}
/**
Execute a ANALYZE TABLE statement at runtime.
@param thd the current thread.
@return false on success.
*/
bool execute(THD *thd);
virtual enum_sql_command sql_command_code() const
{
return SQLCOM_ANALYZE;
}
};
/**
Check_table_statement represents the CHECK TABLE statement.
Sql_cmd_check_table represents the CHECK TABLE statement.
*/
class Check_table_statement : public Sql_statement
class Sql_cmd_check_table : public Sql_cmd
{
public:
/**
Constructor, used to represent a CHECK TABLE statement.
@param lex the LEX structure for this statement.
*/
Check_table_statement(LEX *lex)
: Sql_statement(lex)
Sql_cmd_check_table()
{}
~Check_table_statement()
~Sql_cmd_check_table()
{}
/**
Execute a CHECK TABLE statement at runtime.
@param thd the current thread.
@return false on success.
*/
bool execute(THD *thd);
virtual enum_sql_command sql_command_code() const
{
return SQLCOM_CHECK;
}
};
/**
Optimize_table_statement represents the OPTIMIZE TABLE statement.
Sql_cmd_optimize_table represents the OPTIMIZE TABLE statement.
*/
class Optimize_table_statement : public Sql_statement
class Sql_cmd_optimize_table : public Sql_cmd
{
public:
/**
Constructor, used to represent a OPTIMIZE TABLE statement.
@param lex the LEX structure for this statement.
*/
Optimize_table_statement(LEX *lex)
: Sql_statement(lex)
Sql_cmd_optimize_table()
{}
~Optimize_table_statement()
~Sql_cmd_optimize_table()
{}
/**
Execute a OPTIMIZE TABLE statement at runtime.
@param thd the current thread.
@return false on success.
*/
bool execute(THD *thd);
virtual enum_sql_command sql_command_code() const
{
return SQLCOM_OPTIMIZE;
}
};
/**
Repair_table_statement represents the REPAIR TABLE statement.
Sql_cmd_repair_table represents the REPAIR TABLE statement.
*/
class Repair_table_statement : public Sql_statement
class Sql_cmd_repair_table : public Sql_cmd
{
public:
/**
Constructor, used to represent a REPAIR TABLE statement.
@param lex the LEX structure for this statement.
*/
Repair_table_statement(LEX *lex)
: Sql_statement(lex)
Sql_cmd_repair_table()
{}
~Repair_table_statement()
~Sql_cmd_repair_table()
{}
/**
Execute a REPAIR TABLE statement at runtime.
@param thd the current thread.
@return false on success.
*/
bool execute(THD *thd);
virtual enum_sql_command sql_command_code() const
{
return SQLCOM_REPAIR;
}
};
#endif

View file

@ -16,9 +16,176 @@
#include "sql_parse.h" // check_access
#include "sql_table.h" // mysql_alter_table,
// mysql_exchange_partition
#include "sql_base.h" // open_temporary_tables
#include "sql_alter.h"
bool Alter_table_statement::execute(THD *thd)
Alter_info::Alter_info(const Alter_info &rhs, MEM_ROOT *mem_root)
:drop_list(rhs.drop_list, mem_root),
alter_list(rhs.alter_list, mem_root),
key_list(rhs.key_list, mem_root),
create_list(rhs.create_list, mem_root),
flags(rhs.flags),
keys_onoff(rhs.keys_onoff),
partition_names(rhs.partition_names, mem_root),
num_parts(rhs.num_parts),
requested_algorithm(rhs.requested_algorithm),
requested_lock(rhs.requested_lock)
{
/*
Make deep copies of used objects.
This is not a fully deep copy - clone() implementations
of Alter_drop, Alter_column, Key, foreign_key, Key_part_spec
do not copy string constants. At the same length the only
reason we make a copy currently is that ALTER/CREATE TABLE
code changes input Alter_info definitions, but string
constants never change.
*/
list_copy_and_replace_each_value(drop_list, mem_root);
list_copy_and_replace_each_value(alter_list, mem_root);
list_copy_and_replace_each_value(key_list, mem_root);
list_copy_and_replace_each_value(create_list, mem_root);
/* partition_names are not deeply copied currently */
}
bool Alter_info::set_requested_algorithm(const LEX_STRING *str)
{
// To avoid adding new keywords to the grammar, we match strings here.
if (!my_strcasecmp(system_charset_info, str->str, "INPLACE"))
requested_algorithm= ALTER_TABLE_ALGORITHM_INPLACE;
else if (!my_strcasecmp(system_charset_info, str->str, "COPY"))
requested_algorithm= ALTER_TABLE_ALGORITHM_COPY;
else if (!my_strcasecmp(system_charset_info, str->str, "DEFAULT"))
requested_algorithm= ALTER_TABLE_ALGORITHM_DEFAULT;
else
return true;
return false;
}
bool Alter_info::set_requested_lock(const LEX_STRING *str)
{
// To avoid adding new keywords to the grammar, we match strings here.
if (!my_strcasecmp(system_charset_info, str->str, "NONE"))
requested_lock= ALTER_TABLE_LOCK_NONE;
else if (!my_strcasecmp(system_charset_info, str->str, "SHARED"))
requested_lock= ALTER_TABLE_LOCK_SHARED;
else if (!my_strcasecmp(system_charset_info, str->str, "EXCLUSIVE"))
requested_lock= ALTER_TABLE_LOCK_EXCLUSIVE;
else if (!my_strcasecmp(system_charset_info, str->str, "DEFAULT"))
requested_lock= ALTER_TABLE_LOCK_DEFAULT;
else
return true;
return false;
}
Alter_table_ctx::Alter_table_ctx()
: datetime_field(NULL), error_if_not_empty(false),
tables_opened(0),
db(NULL), table_name(NULL), alias(NULL),
new_db(NULL), new_name(NULL), new_alias(NULL),
fk_error_if_delete_row(false), fk_error_id(NULL),
fk_error_table(NULL)
#ifndef DBUG_OFF
, tmp_table(false)
#endif
{
}
Alter_table_ctx::Alter_table_ctx(THD *thd, TABLE_LIST *table_list,
uint tables_opened_arg,
char *new_db_arg, char *new_name_arg)
: datetime_field(NULL), error_if_not_empty(false),
tables_opened(tables_opened_arg),
new_db(new_db_arg), new_name(new_name_arg),
fk_error_if_delete_row(false), fk_error_id(NULL),
fk_error_table(NULL)
#ifndef DBUG_OFF
, tmp_table(false)
#endif
{
/*
Assign members db, table_name, new_db and new_name
to simplify further comparisions: we want to see if it's a RENAME
later just by comparing the pointers, avoiding the need for strcmp.
*/
db= table_list->db;
table_name= table_list->table_name;
alias= (lower_case_table_names == 2) ? table_list->alias : table_name;
if (!new_db || !my_strcasecmp(table_alias_charset, new_db, db))
new_db= db;
if (new_name)
{
DBUG_PRINT("info", ("new_db.new_name: '%s'.'%s'", new_db, new_name));
if (lower_case_table_names == 1) // Convert new_name/new_alias to lower case
{
my_casedn_str(files_charset_info, new_name);
new_alias= new_name;
}
else if (lower_case_table_names == 2) // Convert new_name to lower case
{
strmov(new_alias= new_alias_buff, new_name);
my_casedn_str(files_charset_info, new_name);
}
else
new_alias= new_name; // LCTN=0 => case sensitive + case preserving
if (!is_database_changed() &&
!my_strcasecmp(table_alias_charset, new_name, table_name))
{
/*
Source and destination table names are equal:
make is_table_renamed() more efficient.
*/
new_alias= table_name;
new_name= table_name;
}
}
else
{
new_alias= alias;
new_name= table_name;
}
my_snprintf(tmp_name, sizeof(tmp_name), "%s-%lx_%lx", tmp_file_prefix,
current_pid, thd->thread_id);
/* Safety fix for InnoDB */
if (lower_case_table_names)
my_casedn_str(files_charset_info, tmp_name);
if (table_list->table->s->tmp_table == NO_TMP_TABLE)
{
build_table_filename(path, sizeof(path) - 1, db, table_name, "", 0);
build_table_filename(new_path, sizeof(new_path) - 1, new_db, new_name, "", 0);
build_table_filename(new_filename, sizeof(new_filename) - 1,
new_db, new_name, reg_ext, 0);
build_table_filename(tmp_path, sizeof(tmp_path) - 1, new_db, tmp_name, "",
FN_IS_TMP);
}
else
{
/*
We are not filling path, new_path and new_filename members if
we are altering temporary table as these members are not used in
this case. This fact is enforced with assert.
*/
build_tmptable_filename(thd, tmp_path, sizeof(tmp_path));
#ifndef DBUG_OFF
tmp_table= true;
#endif
}
}
bool Sql_cmd_alter_table::execute(THD *thd)
{
LEX *lex= thd->lex;
/* first SELECT_LEX (have special meaning for many of non-SELECTcommands) */
@ -38,7 +205,7 @@ bool Alter_table_statement::execute(THD *thd)
ulong priv_needed= ALTER_ACL;
bool result;
DBUG_ENTER("Alter_table_statement::execute");
DBUG_ENTER("Sql_cmd_alter_table::execute");
if (thd->is_fatal_error) /* out of memory creating a copy of alter_info */
DBUG_RETURN(TRUE);
@ -46,12 +213,14 @@ bool Alter_table_statement::execute(THD *thd)
We also require DROP priv for ALTER TABLE ... DROP PARTITION, as well
as for RENAME TO, as being done by SQLCOM_RENAME_TABLE
*/
if (alter_info.flags & (ALTER_DROP_PARTITION | ALTER_RENAME))
if (alter_info.flags & (Alter_info::ALTER_DROP_PARTITION |
Alter_info::ALTER_RENAME))
priv_needed|= DROP_ACL;
/* Must be set in the parser */
DBUG_ASSERT(select_lex->db);
DBUG_ASSERT(!(alter_info.flags & ALTER_ADMIN_PARTITION));
DBUG_ASSERT(!(alter_info.flags & Alter_info::ALTER_EXCHANGE_PARTITION));
DBUG_ASSERT(!(alter_info.flags & Alter_info::ALTER_ADMIN_PARTITION));
if (check_access(thd, priv_needed, first_table->db,
&first_table->grant.privilege,
&first_table->grant.m_internal,
@ -63,10 +232,47 @@ bool Alter_table_statement::execute(THD *thd)
DBUG_RETURN(TRUE); /* purecov: inspected */
/* If it is a merge table, check privileges for merge children. */
if (create_info.merge_list.first &&
check_table_access(thd, SELECT_ACL | UPDATE_ACL | DELETE_ACL,
create_info.merge_list.first, FALSE, UINT_MAX, FALSE))
DBUG_RETURN(TRUE);
if (create_info.merge_list.first)
{
/*
The user must have (SELECT_ACL | UPDATE_ACL | DELETE_ACL) on the
underlying base tables, even if there are temporary tables with the same
names.
From user's point of view, it might look as if the user must have these
privileges on temporary tables to create a merge table over them. This is
one of two cases when a set of privileges is required for operations on
temporary tables (see also CREATE TABLE).
The reason for this behavior stems from the following facts:
- For merge tables, the underlying table privileges are checked only
at CREATE TABLE / ALTER TABLE time.
In other words, once a merge table is created, the privileges of
the underlying tables can be revoked, but the user will still have
access to the merge table (provided that the user has privileges on
the merge table itself).
- Temporary tables shadow base tables.
I.e. there might be temporary and base tables with the same name, and
the temporary table takes the precedence in all operations.
- For temporary MERGE tables we do not track if their child tables are
base or temporary. As result we can't guarantee that privilege check
which was done in presence of temporary child will stay relevant later
as this temporary table might be removed.
If SELECT_ACL | UPDATE_ACL | DELETE_ACL privileges were not checked for
the underlying *base* tables, it would create a security breach as in
Bug#12771903.
*/
if (check_table_access(thd, SELECT_ACL | UPDATE_ACL | DELETE_ACL,
create_info.merge_list.first, FALSE, UINT_MAX, FALSE))
DBUG_RETURN(TRUE);
}
if (check_grant(thd, priv_needed, first_table, FALSE, UINT_MAX, FALSE))
DBUG_RETURN(TRUE); /* purecov: inspected */
@ -75,7 +281,7 @@ bool Alter_table_statement::execute(THD *thd)
{
// Rename of table
TABLE_LIST tmp_table;
bzero((char*) &tmp_table,sizeof(tmp_table));
memset(&tmp_table, 0, sizeof(tmp_table));
tmp_table.table_name= lex->name.str;
tmp_table.db= select_lex->db;
tmp_table.grant.privilege= priv;
@ -86,11 +292,11 @@ bool Alter_table_statement::execute(THD *thd)
/* Don't yet allow changing of symlinks with ALTER TABLE */
if (create_info.data_file_name)
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
WARN_OPTION_IGNORED, ER(WARN_OPTION_IGNORED),
"DATA DIRECTORY");
if (create_info.index_file_name)
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
WARN_OPTION_IGNORED, ER(WARN_OPTION_IGNORED),
"INDEX DIRECTORY");
create_info.data_file_name= create_info.index_file_name= NULL;
@ -103,7 +309,50 @@ bool Alter_table_statement::execute(THD *thd)
&alter_info,
select_lex->order_list.elements,
select_lex->order_list.first,
lex->ignore, lex->online);
lex->ignore);
DBUG_RETURN(result);
}
bool Sql_cmd_discard_import_tablespace::execute(THD *thd)
{
/* first SELECT_LEX (have special meaning for many of non-SELECTcommands) */
SELECT_LEX *select_lex= &thd->lex->select_lex;
/* first table of first SELECT_LEX */
TABLE_LIST *table_list= (TABLE_LIST*) select_lex->table_list.first;
if (check_access(thd, ALTER_ACL, table_list->db,
&table_list->grant.privilege,
&table_list->grant.m_internal,
0, 0))
return true;
if (check_grant(thd, ALTER_ACL, table_list, false, UINT_MAX, false))
return true;
thd->enable_slow_log= opt_log_slow_admin_statements;
/*
Check if we attempt to alter mysql.slow_log or
mysql.general_log table and return an error if
it is the case.
TODO: this design is obsolete and will be removed.
*/
int table_kind= check_if_log_table(table_list->db_length, table_list->db,
table_list->table_name_length,
table_list->table_name, false);
if (table_kind)
{
/* Disable alter of enabled log tables */
if (logger.is_log_table_enabled(table_kind))
{
my_error(ER_BAD_LOG_STATEMENT, MYF(0), "ALTER");
return true;
}
}
return
mysql_discard_or_import_tablespace(thd, table_list,
m_tablespace_op == DISCARD_TABLESPACE);
}

View file

@ -122,7 +122,7 @@ void mysql_audit_general(THD *thd, uint event_subtype,
query= thd->query_string;
user= user_buff;
userlen= make_user_name(thd, user_buff);
rows= thd->warning_info->current_row_for_warning();
rows= thd->get_stmt_da()->current_row_for_warning();
}
else
{
@ -139,7 +139,7 @@ void mysql_audit_general(THD *thd, uint event_subtype,
#define MYSQL_AUDIT_NOTIFY_CONNECTION_CONNECT(thd) mysql_audit_notify(\
(thd), MYSQL_AUDIT_CONNECTION_CLASS, MYSQL_AUDIT_CONNECTION_CONNECT,\
(thd)->stmt_da->is_error() ? (thd)->stmt_da->sql_errno() : 0,\
(thd)->get_stmt_da()->is_error() ? (thd)->get_stmt_da()->sql_errno() : 0,\
(thd)->thread_id, (thd)->security_ctx->user,\
(thd)->security_ctx->user ? strlen((thd)->security_ctx->user) : 0,\
(thd)->security_ctx->priv_user, strlen((thd)->security_ctx->priv_user),\
@ -160,7 +160,7 @@ void mysql_audit_general(THD *thd, uint event_subtype,
#define MYSQL_AUDIT_NOTIFY_CONNECTION_CHANGE_USER(thd) mysql_audit_notify(\
(thd), MYSQL_AUDIT_CONNECTION_CLASS, MYSQL_AUDIT_CONNECTION_CHANGE_USER,\
(thd)->stmt_da->is_error() ? (thd)->stmt_da->sql_errno() : 0,\
(thd)->get_stmt_da()->is_error() ? (thd)->get_stmt_da()->sql_errno() : 0,\
(thd)->thread_id, (thd)->security_ctx->user,\
(thd)->security_ctx->user ? strlen((thd)->security_ctx->user) : 0,\
(thd)->security_ctx->priv_user, strlen((thd)->security_ctx->priv_user),\

File diff suppressed because it is too large Load diff

View file

@ -60,7 +60,8 @@ enum find_item_error_report_type {REPORT_ALL_ERRORS, REPORT_EXCEPT_NOT_FOUND,
IGNORE_EXCEPT_NON_UNIQUE};
enum enum_tdc_remove_table_type {TDC_RT_REMOVE_ALL, TDC_RT_REMOVE_NOT_OWN,
TDC_RT_REMOVE_UNUSED};
TDC_RT_REMOVE_UNUSED,
TDC_RT_REMOVE_NOT_OWN_KEEP_SHARE};
/* bits for last argument to remove_table_from_cache() */
#define RTFC_NO_FLAG 0x0000
@ -76,13 +77,12 @@ bool table_def_init(void);
void table_def_free(void);
void table_def_start_shutdown(void);
void assign_new_table_id(TABLE_SHARE *share);
uint cached_open_tables(void);
uint cached_table_definitions(void);
uint create_table_def_key(THD *thd, char *key,
const TABLE_LIST *table_list,
bool tmp_table);
TABLE_SHARE *get_table_share(THD *thd, TABLE_LIST *table_list, char *key,
uint key_length, uint db_flags, int *error,
uint cached_open_tables(void);
uint get_table_def_key(const TABLE_LIST *table_list, const char **key);
TABLE_SHARE *get_table_share(THD *thd, TABLE_LIST *table_list,
const char *key, uint key_length,
uint db_flags, int *error,
my_hash_value_type hash_value);
void release_table_share(TABLE_SHARE *share);
TABLE_SHARE *get_cached_table_share(const char *db, const char *table_name);
@ -128,6 +128,11 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type update,
*/
#define MYSQL_OPEN_SKIP_SCOPED_MDL_LOCK 0x1000
#define MYSQL_LOCK_NOT_TEMPORARY 0x2000
/**
Only check THD::killed if waits happen (e.g. wait on MDL, wait on
table flush, wait on thr_lock.c locks) while opening and locking table.
*/
#define MYSQL_OPEN_IGNORE_KILLED 0x4000
/** Please refer to the internals manual. */
#define MYSQL_OPEN_REOPEN (MYSQL_OPEN_IGNORE_FLUSH |\
@ -140,6 +145,7 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type update,
bool open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
Open_table_context *ot_ctx);
bool open_new_frm(THD *thd, TABLE_SHARE *share, const char *alias,
uint db_stat, uint prgflag,
uint ha_open_flags, TABLE *outparam, TABLE_LIST *table_desc,
@ -149,7 +155,8 @@ bool get_key_map_from_key_list(key_map *map, TABLE *table,
List<String> *index_list);
TABLE *open_table_uncached(THD *thd, const char *path, const char *db,
const char *table_name,
bool add_to_temporary_tables_list);
bool add_to_temporary_tables_list,
bool open_in_engine);
TABLE *find_locked_table(TABLE *list, const char *db, const char *table_name);
TABLE *find_write_locked_table(TABLE *list, const char *db,
const char *table_name);
@ -158,7 +165,7 @@ thr_lock_type read_lock_type_for_table(THD *thd,
TABLE_LIST *table_list);
my_bool mysql_rm_tmp_tables(void);
bool rm_temporary_table(handlerton *base, char *path);
bool rm_temporary_table(handlerton *base, const char *path);
void close_tables_for_reopen(THD *thd, TABLE_LIST **tables,
const MDL_savepoint &start_of_statement_svp);
TABLE_LIST *find_table_in_list(TABLE_LIST *table,
@ -191,6 +198,8 @@ bool setup_fields(THD *thd, Item** ref_pointer_array,
List<Item> &item, enum_mark_columns mark_used_columns,
List<Item> *sum_func_list, bool allow_sum_func);
void unfix_fields(List<Item> &items);
bool fill_record(THD * thd, TABLE *table_arg, List<Item> &fields,
List<Item> &values, bool ignore_errors);
bool fill_record(THD *thd, TABLE *table, Field **field, List<Item> &values,
bool ignore_errors, bool use_value);
@ -260,7 +269,7 @@ bool lock_tables(THD *thd, TABLE_LIST *tables, uint counter, uint flags);
int decide_logging_format(THD *thd, TABLE_LIST *tables);
void free_io_cache(TABLE *entry);
void intern_close_table(TABLE *entry);
bool close_thread_table(THD *thd, TABLE **table_ptr);
void close_thread_table(THD *thd, TABLE **table_ptr);
bool close_temporary_tables(THD *thd);
TABLE_LIST *unique_table(THD *thd, TABLE_LIST *table, TABLE_LIST *table_list,
bool check_alias);
@ -270,6 +279,8 @@ void close_temporary_table(THD *thd, TABLE *table, bool free_share,
void close_temporary(TABLE *table, bool free_share, bool delete_table);
bool rename_temporary_table(THD* thd, TABLE *table, const char *new_db,
const char *table_name);
bool open_temporary_tables(THD *thd, TABLE_LIST *tl_list);
bool open_temporary_table(THD *thd, TABLE_LIST *tl);
bool is_equal(const LEX_STRING *a, const LEX_STRING *b);
class Open_tables_backup;
@ -290,13 +301,14 @@ bool close_cached_tables(THD *thd, TABLE_LIST *tables,
bool wait_for_refresh, ulong timeout);
bool close_cached_connection_tables(THD *thd, LEX_STRING *connect_string);
void close_all_tables_for_name(THD *thd, TABLE_SHARE *share,
ha_extra_function extra);
ha_extra_function extra,
TABLE *skip_table);
OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *db, const char *wild);
void tdc_remove_table(THD *thd, enum_tdc_remove_table_type remove_type,
const char *db, const char *table_name,
bool has_lock);
bool tdc_open_view(THD *thd, TABLE_LIST *table_list, const char *alias,
char *cache_key, uint cache_key_length,
const char *cache_key, uint cache_key_length,
MEM_ROOT *mem_root, uint flags);
void tdc_flush_unused_tables();
TABLE *find_table_for_mdl_upgrade(THD *thd, const char *db,
@ -457,11 +469,6 @@ class Lock_tables_prelocking_strategy : public DML_prelocking_strategy
class Alter_table_prelocking_strategy : public Prelocking_strategy
{
public:
Alter_table_prelocking_strategy(Alter_info *alter_info)
: m_alter_info(alter_info)
{}
virtual bool handle_routine(THD *thd, Query_tables_list *prelocking_ctx,
Sroutine_hash_entry *rt, sp_head *sp,
bool *need_prelocking);
@ -469,9 +476,6 @@ public:
TABLE_LIST *table_list, bool *need_prelocking);
virtual bool handle_view(THD *thd, Query_tables_list *prelocking_ctx,
TABLE_LIST *table_list, bool *need_prelocking);
private:
Alter_info *m_alter_info;
};
@ -592,6 +596,30 @@ private:
};
/**
Check if a TABLE_LIST instance represents a pre-opened temporary table.
*/
inline bool is_temporary_table(TABLE_LIST *tl)
{
if (tl->view || tl->schema_table)
return FALSE;
if (!tl->table)
return FALSE;
/*
NOTE: 'table->s' might be NULL for specially constructed TABLE
instances. See SHOW TRIGGERS for example.
*/
if (!tl->table->s)
return FALSE;
return tl->table->s->tmp_table != NO_TMP_TABLE;
}
/**
This internal handler is used to trap ER_NO_SUCH_TABLE.
*/
@ -606,9 +634,9 @@ public:
bool handle_condition(THD *thd,
uint sql_errno,
const char* sqlstate,
MYSQL_ERROR::enum_warning_level level,
Sql_condition::enum_warning_level level,
const char* msg,
MYSQL_ERROR ** cond_hdl);
Sql_condition ** cond_hdl);
/**
Returns TRUE if one or more ER_NO_SUCH_TABLE errors have been

View file

@ -1173,7 +1173,7 @@ void Query_cache::end_of_result(THD *thd)
DBUG_VOID_RETURN;
/* Ensure that only complete results are cached. */
DBUG_ASSERT(thd->stmt_da->is_eof());
DBUG_ASSERT(thd->get_stmt_da()->is_eof());
if (thd->killed)
{
@ -2089,8 +2089,8 @@ def_week_frmt: %lu, in_trans: %d, autocommit: %d",
response, we can't handle it anyway.
*/
(void) trans_commit_stmt(thd);
if (!thd->stmt_da->is_set())
thd->stmt_da->disable_status();
if (!thd->get_stmt_da()->is_set())
thd->get_stmt_da()->disable_status();
BLOCK_UNLOCK_RD(query_block);
MYSQL_QUERY_CACHE_HIT(thd->query(), (ulong) thd->limit_found_rows);

View file

@ -691,7 +691,7 @@ int thd_tx_is_read_only(const THD *thd)
extern "C"
void thd_inc_row_count(THD *thd)
{
thd->warning_info->inc_current_row_for_warning();
thd->get_stmt_da()->inc_current_row_for_warning();
}
@ -810,9 +810,9 @@ char *thd_security_context(THD *thd, char *buffer, unsigned int length,
bool Drop_table_error_handler::handle_condition(THD *thd,
uint sql_errno,
const char* sqlstate,
MYSQL_ERROR::enum_warning_level level,
Sql_condition::enum_warning_level level,
const char* msg,
MYSQL_ERROR ** cond_hdl)
Sql_condition ** cond_hdl)
{
*cond_hdl= NULL;
return ((sql_errno == EE_DELETE && my_errno == ENOENT) ||
@ -835,8 +835,6 @@ THD::THD()
stmt_depends_on_first_successful_insert_id_in_prev_stmt(FALSE),
m_examined_row_count(0),
accessed_rows_and_keys(0),
warning_info(&main_warning_info),
stmt_da(&main_da),
m_statement_psi(NULL),
m_idle_psi(NULL),
m_server_idle(false),
@ -856,7 +854,8 @@ THD::THD()
#if defined(ENABLED_DEBUG_SYNC)
debug_sync_control(0),
#endif /* defined(ENABLED_DEBUG_SYNC) */
main_warning_info(0, false, false)
main_da(0, false),
m_stmt_da(&main_da)
{
ulong tmp;
@ -868,8 +867,8 @@ THD::THD()
THD *old_THR_THD= current_thd;
set_current_thd(this);
status_var.memory_used= 0;
main_da.init();
main_warning_info.init();
/*
Pass nominal parameters to init_alloc_root only to ensure that
the destructor works OK in case of an error. The main_mem_root
@ -1029,9 +1028,9 @@ void THD::push_internal_handler(Internal_error_handler *handler)
bool THD::handle_condition(uint sql_errno,
const char* sqlstate,
MYSQL_ERROR::enum_warning_level level,
Sql_condition::enum_warning_level level,
const char* msg,
MYSQL_ERROR ** cond_hdl)
Sql_condition ** cond_hdl)
{
if (!m_internal_handler)
{
@ -1068,7 +1067,7 @@ void THD::raise_error(uint sql_errno)
const char* msg= ER(sql_errno);
(void) raise_condition(sql_errno,
NULL,
MYSQL_ERROR::WARN_LEVEL_ERROR,
Sql_condition::WARN_LEVEL_ERROR,
msg);
}
@ -1084,7 +1083,7 @@ void THD::raise_error_printf(uint sql_errno, ...)
va_end(args);
(void) raise_condition(sql_errno,
NULL,
MYSQL_ERROR::WARN_LEVEL_ERROR,
Sql_condition::WARN_LEVEL_ERROR,
ebuff);
DBUG_VOID_RETURN;
}
@ -1094,7 +1093,7 @@ void THD::raise_warning(uint sql_errno)
const char* msg= ER(sql_errno);
(void) raise_condition(sql_errno,
NULL,
MYSQL_ERROR::WARN_LEVEL_WARN,
Sql_condition::WARN_LEVEL_WARN,
msg);
}
@ -1110,7 +1109,7 @@ void THD::raise_warning_printf(uint sql_errno, ...)
va_end(args);
(void) raise_condition(sql_errno,
NULL,
MYSQL_ERROR::WARN_LEVEL_WARN,
Sql_condition::WARN_LEVEL_WARN,
ebuff);
DBUG_VOID_RETURN;
}
@ -1124,7 +1123,7 @@ void THD::raise_note(uint sql_errno)
const char* msg= ER(sql_errno);
(void) raise_condition(sql_errno,
NULL,
MYSQL_ERROR::WARN_LEVEL_NOTE,
Sql_condition::WARN_LEVEL_NOTE,
msg);
DBUG_VOID_RETURN;
}
@ -1143,24 +1142,25 @@ void THD::raise_note_printf(uint sql_errno, ...)
va_end(args);
(void) raise_condition(sql_errno,
NULL,
MYSQL_ERROR::WARN_LEVEL_NOTE,
Sql_condition::WARN_LEVEL_NOTE,
ebuff);
DBUG_VOID_RETURN;
}
MYSQL_ERROR* THD::raise_condition(uint sql_errno,
Sql_condition* THD::raise_condition(uint sql_errno,
const char* sqlstate,
MYSQL_ERROR::enum_warning_level level,
Sql_condition::enum_warning_level level,
const char* msg)
{
MYSQL_ERROR *cond= NULL;
Diagnostics_area *da= get_stmt_da();
Sql_condition *cond= NULL;
DBUG_ENTER("THD::raise_condition");
if (!(variables.option_bits & OPTION_SQL_NOTES) &&
(level == MYSQL_ERROR::WARN_LEVEL_NOTE))
(level == Sql_condition::WARN_LEVEL_NOTE))
DBUG_RETURN(NULL);
warning_info->opt_clear_warning_info(query_id);
da->opt_clear_warning_info(query_id);
/*
TODO: replace by DBUG_ASSERT(sql_errno != 0) once all bugs similar to
@ -1174,24 +1174,24 @@ MYSQL_ERROR* THD::raise_condition(uint sql_errno,
if (sqlstate == NULL)
sqlstate= mysql_errno_to_sqlstate(sql_errno);
if ((level == MYSQL_ERROR::WARN_LEVEL_WARN) &&
if ((level == Sql_condition::WARN_LEVEL_WARN) &&
really_abort_on_warning())
{
/*
FIXME:
push_warning and strict SQL_MODE case.
*/
level= MYSQL_ERROR::WARN_LEVEL_ERROR;
level= Sql_condition::WARN_LEVEL_ERROR;
killed= KILL_BAD_DATA;
}
switch (level)
{
case MYSQL_ERROR::WARN_LEVEL_NOTE:
case MYSQL_ERROR::WARN_LEVEL_WARN:
case Sql_condition::WARN_LEVEL_NOTE:
case Sql_condition::WARN_LEVEL_WARN:
got_warning= 1;
break;
case MYSQL_ERROR::WARN_LEVEL_ERROR:
case Sql_condition::WARN_LEVEL_ERROR:
break;
default:
DBUG_ASSERT(FALSE);
@ -1200,14 +1200,14 @@ MYSQL_ERROR* THD::raise_condition(uint sql_errno,
if (handle_condition(sql_errno, sqlstate, level, msg, &cond))
DBUG_RETURN(cond);
if (level == MYSQL_ERROR::WARN_LEVEL_ERROR)
if (level == Sql_condition::WARN_LEVEL_ERROR)
{
is_slave_error= 1; // needed to catch query errors during replication
if (! stmt_da->is_error())
if (!da->is_error())
{
set_row_count_func(-1);
stmt_da->set_error_status(this, sql_errno, msg, sqlstate);
da->set_error_status(sql_errno, msg, sqlstate, cond);
}
}
@ -1216,7 +1216,7 @@ MYSQL_ERROR* THD::raise_condition(uint sql_errno,
/* When simulating OOM, skip writing to error log to avoid mtr errors */
DBUG_EXECUTE_IF("simulate_out_of_memory", DBUG_RETURN(NULL););
cond= warning_info->push_warning(this, sql_errno, sqlstate, level, msg);
da->push_warning(this, sql_errno, sqlstate, level, msg);
DBUG_RETURN(cond);
}
@ -1553,7 +1553,7 @@ THD::~THD()
#endif
free_root(&main_mem_root, MYF(0));
main_warning_info.free_memory();
main_da.free_memory();
if (status_var.memory_used != 0)
{
DBUG_PRINT("error", ("memory_used: %lld", status_var.memory_used));
@ -1942,42 +1942,6 @@ void THD::cleanup_after_query()
table_map_for_update= 0;
m_binlog_invoker= FALSE;
extern "C" enum durability_properties thd_get_durability_property(const MYSQL_THD thd)
{
enum durability_properties ret= HA_REGULAR_DURABILITY;
if (thd != NULL)
ret= thd->durability_property;
return ret;
}
/** Get the auto_increment_offset auto_increment_increment.
Needed by InnoDB.
@param thd Thread object
@param off auto_increment_offset
@param inc auto_increment_increment */
extern "C" void thd_get_autoinc(const MYSQL_THD thd, ulong* off, ulong* inc)
{
*off = thd->variables.auto_increment_offset;
*inc = thd->variables.auto_increment_increment;
}
/**
Is strict sql_mode set.
Needed by InnoDB.
@param thd Thread object
@return True if sql_mode has strict mode (all or trans).
@retval true sql_mode has strict mode (all or trans).
@retval false sql_mode has not strict mode (all or trans).
*/
extern "C" bool thd_is_strict_mode(const MYSQL_THD thd)
{
return thd->is_strict_mode();
}
#ifndef EMBEDDED_LIBRARY
if (rli_slave)
rli_slave->cleanup_after_query();
@ -2691,7 +2655,7 @@ select_export::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
Non-ASCII separator arguments are not fully supported
*/
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning(thd, Sql_condition::WARN_LEVEL_WARN,
WARN_NON_ASCII_SEPARATOR_NOT_IMPLEMENTED,
ER(WARN_NON_ASCII_SEPARATOR_NOT_IMPLEMENTED));
}
@ -2722,7 +2686,7 @@ select_export::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
(exchange->opt_enclosed && non_string_results &&
field_term_length && strchr(NUMERIC_CHARS, field_term_char)))
{
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning(thd, Sql_condition::WARN_LEVEL_WARN,
ER_AMBIGUOUS_FIELD_TERM, ER(ER_AMBIGUOUS_FIELD_TERM));
is_ambiguous_field_term= TRUE;
}
@ -2805,7 +2769,7 @@ int select_export::send_data(List<Item> &items)
convert_to_printable(printable_buff, sizeof(printable_buff),
error_pos, res->ptr() + res->length() - error_pos,
res->charset(), 6);
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_TRUNCATED_WRONG_VALUE_FOR_FIELD,
ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD),
"string", printable_buff,
@ -2816,7 +2780,7 @@ int select_export::send_data(List<Item> &items)
/*
result is longer than UINT_MAX32 and doesn't fit into String
*/
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
WARN_DATA_TRUNCATED, ER(WARN_DATA_TRUNCATED),
item->full_name(), static_cast<long>(row_count));
}
@ -3621,7 +3585,7 @@ int select_dumpvar::send_data(List<Item> &items)
bool select_dumpvar::send_eof()
{
if (! row_count)
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning(thd, Sql_condition::WARN_LEVEL_WARN,
ER_SP_FETCH_NO_DATA, ER(ER_SP_FETCH_NO_DATA));
/*
Don't send EOF if we're in error condition (which implies we've already
@ -4202,6 +4166,41 @@ extern "C" bool thd_sqlcom_can_generate_row_events(const MYSQL_THD thd)
}
extern "C" enum durability_properties thd_get_durability_property(const MYSQL_THD thd)
{
enum durability_properties ret= HA_REGULAR_DURABILITY;
if (thd != NULL)
ret= thd->durability_property;
return ret;
}
/** Get the auto_increment_offset auto_increment_increment.
Needed by InnoDB.
@param thd Thread object
@param off auto_increment_offset
@param inc auto_increment_increment */
extern "C" void thd_get_autoinc(const MYSQL_THD thd, ulong* off, ulong* inc)
{
*off = thd->variables.auto_increment_offset;
*inc = thd->variables.auto_increment_increment;
}
/**
Is strict sql_mode set.
Needed by InnoDB.
@param thd Thread object
@return True if sql_mode has strict mode (all or trans).
@retval true sql_mode has strict mode (all or trans).
@retval false sql_mode has not strict mode (all or trans).
*/
extern "C" bool thd_is_strict_mode(const MYSQL_THD thd)
{
return thd->is_strict_mode();
}
/*
Interface for MySQL Server, plugins and storage engines to report
@ -5691,7 +5690,7 @@ void THD::issue_unsafe_warnings()
{
if ((unsafe_type_flags & (1 << unsafe_type)) != 0)
{
push_warning_printf(this, MYSQL_ERROR::WARN_LEVEL_NOTE,
push_warning_printf(this, Sql_condition::WARN_LEVEL_NOTE,
ER_BINLOG_UNSAFE_STATEMENT,
ER(ER_BINLOG_UNSAFE_STATEMENT),
ER(LEX::binlog_stmt_unsafe_errcode[unsafe_type]));

View file

@ -72,7 +72,6 @@ class Sroutine_hash_entry;
class User_level_lock;
class user_var_entry;
enum enum_enable_or_disable { LEAVE_AS_IS, ENABLE, DISABLE };
enum enum_ha_read_modes { RFIRST, RNEXT, RPREV, RLAST, RKEY, RNEXT_SAME };
enum enum_duplicates { DUP_ERROR, DUP_REPLACE, DUP_UPDATE };
enum enum_delay_key_write { DELAY_KEY_WRITE_NONE, DELAY_KEY_WRITE_ON,
@ -235,6 +234,7 @@ public:
enum drop_type {KEY, COLUMN, FOREIGN_KEY };
const char *name;
enum drop_type type;
bool drop_if_exists;
Alter_drop(enum drop_type par_type,const char *par_name)
:name(par_name), type(par_type)
{
@ -303,7 +303,6 @@ public:
{ return new (mem_root) Key(*this, mem_root); }
};
class Table_ident;
class Foreign_key: public Key {
public:
@ -318,23 +317,25 @@ public:
uint delete_opt, update_opt, match_opt;
Foreign_key(const LEX_STRING &name_arg, List<Key_part_spec> &cols,
const LEX_STRING &ref_db_arg, const LEX_STRING &ref_table_arg,
List<Key_part_spec> &ref_cols,
List<Key_part_spec> &ref_cols,
uint delete_opt_arg, uint update_opt_arg, uint match_opt_arg)
:Key(FOREIGN_KEY, name_arg, &default_key_create_info, 0, cols, NULL),
ref_db(ref_db_arg), ref_table(ref_table_arg), ref_columns(ref_cols),
delete_opt(delete_opt_arg), update_opt(update_opt_arg),
match_opt(match_opt_arg)
{
{
// We don't check for duplicate FKs.
key_create_info.check_for_duplicate_indexes= false;
}
Foreign_key(const Foreign_key &rhs, MEM_ROOT *mem_root);
Foreign_key(const Foreign_key &rhs, MEM_ROOT *mem_root);
/**
Used to make a clone of this object for ALTER/CREATE TABLE
@sa comment for Key_part_spec::clone
*/
virtual Key *clone(MEM_ROOT *mem_root) const
{ return new (mem_root) Foreign_key(*this, mem_root); }
/* Used to validate foreign key options */
bool validate(List<Create_field> &table_fields);
};
typedef struct st_mysql_lock
@ -1348,9 +1349,9 @@ public:
virtual bool handle_condition(THD *thd,
uint sql_errno,
const char* sqlstate,
MYSQL_ERROR::enum_warning_level level,
Sql_condition::enum_warning_level level,
const char* msg,
MYSQL_ERROR ** cond_hdl) = 0;
Sql_condition ** cond_hdl) = 0;
private:
Internal_error_handler *m_prev_internal_handler;
@ -1369,9 +1370,9 @@ public:
bool handle_condition(THD *thd,
uint sql_errno,
const char* sqlstate,
MYSQL_ERROR::enum_warning_level level,
Sql_condition::enum_warning_level level,
const char* msg,
MYSQL_ERROR ** cond_hdl)
Sql_condition ** cond_hdl)
{
/* Ignore error */
return TRUE;
@ -1396,9 +1397,9 @@ public:
bool handle_condition(THD *thd,
uint sql_errno,
const char* sqlstate,
MYSQL_ERROR::enum_warning_level level,
Sql_condition::enum_warning_level level,
const char* msg,
MYSQL_ERROR ** cond_hdl);
Sql_condition ** cond_hdl);
private:
};
@ -2216,8 +2217,6 @@ public:
USER_CONN *user_connect;
CHARSET_INFO *db_charset;
Warning_info *warning_info;
Diagnostics_area *stmt_da;
#if defined(ENABLED_PROFILING)
PROFILING profiling;
#endif
@ -2756,8 +2755,8 @@ public:
inline void clear_error()
{
DBUG_ENTER("clear_error");
if (stmt_da->is_error())
stmt_da->reset_diagnostics_area();
if (get_stmt_da()->is_error())
get_stmt_da()->reset_diagnostics_area();
is_slave_error= 0;
DBUG_VOID_RETURN;
}
@ -2784,7 +2783,7 @@ public:
*/
inline void fatal_error()
{
DBUG_ASSERT(stmt_da->is_error() || killed);
DBUG_ASSERT(get_stmt_da()->is_error() || killed);
is_fatal_error= 1;
DBUG_PRINT("error",("Fatal error set"));
}
@ -2801,11 +2800,19 @@ public:
To raise this flag, use my_error().
*/
inline bool is_error() const { return stmt_da->is_error(); }
inline bool is_error() const { return m_stmt_da->is_error(); }
/// Returns Diagnostics-area for the current statement.
Diagnostics_area *get_stmt_da()
{ return stmt_da; }
{ return m_stmt_da; }
/// Returns Diagnostics-area for the current statement.
const Diagnostics_area *get_stmt_da() const
{ return m_stmt_da; }
/// Sets Diagnostics-area for the current statement.
void set_stmt_da(Diagnostics_area *da)
{ m_stmt_da= da; }
inline CHARSET_INFO *charset() { return variables.character_set_client; }
void update_charset();
@ -3096,6 +3103,7 @@ public:
*/
void push_internal_handler(Internal_error_handler *handler);
private:
/**
Handle a sql condition.
@param sql_errno the condition error number
@ -3105,12 +3113,13 @@ public:
@param[out] cond_hdl the sql condition raised, if any
@return true if the condition is handled
*/
virtual bool handle_condition(uint sql_errno,
const char* sqlstate,
MYSQL_ERROR::enum_warning_level level,
const char* msg,
MYSQL_ERROR ** cond_hdl);
bool handle_condition(uint sql_errno,
const char* sqlstate,
Sql_condition::enum_warning_level level,
const char* msg,
Sql_condition ** cond_hdl);
public:
/**
Remove the error handler last pushed.
*/
@ -3160,10 +3169,10 @@ private:
To raise a SQL condition, the code should use the public
raise_error() or raise_warning() methods provided by class THD.
*/
friend class Signal_common;
friend class Signal_statement;
friend class Resignal_statement;
friend void push_warning(THD*, MYSQL_ERROR::enum_warning_level, uint, const char*);
friend class Sql_cmd_common_signal;
friend class Sql_cmd_signal;
friend class Sql_cmd_resignal;
friend void push_warning(THD*, Sql_condition::enum_warning_level, uint, const char*);
friend void my_message_sql(uint, const char *, myf);
/**
@ -3174,10 +3183,10 @@ private:
@param msg the condition message text
@return The condition raised, or NULL
*/
MYSQL_ERROR*
Sql_condition*
raise_condition(uint sql_errno,
const char* sqlstate,
MYSQL_ERROR::enum_warning_level level,
Sql_condition::enum_warning_level level,
const char* msg);
public:
@ -3307,8 +3316,8 @@ private:
tree itself is reused between executions and thus is stored elsewhere.
*/
MEM_ROOT main_mem_root;
Warning_info main_warning_info;
Diagnostics_area main_da;
Diagnostics_area *m_stmt_da;
/**
It will be set TURE if CURRENT_USER() is called in account management
@ -3341,24 +3350,24 @@ private:
};
/** A short cut for thd->stmt_da->set_ok_status(). */
/** A short cut for thd->get_stmt_da()->set_ok_status(). */
inline void
my_ok(THD *thd, ulonglong affected_rows= 0, ulonglong id= 0,
const char *message= NULL)
{
thd->set_row_count_func(affected_rows);
thd->stmt_da->set_ok_status(thd, affected_rows, id, message);
thd->get_stmt_da()->set_ok_status(affected_rows, id, message);
}
/** A short cut for thd->stmt_da->set_eof_status(). */
/** A short cut for thd->get_stmt_da()->set_eof_status(). */
inline void
my_eof(THD *thd)
{
thd->set_row_count_func(-1);
thd->stmt_da->set_eof_status(thd);
thd->get_stmt_da()->set_eof_status(thd);
}
#define tmp_disable_binlog(A) \

View file

@ -88,6 +88,7 @@ enum enum_sql_command {
SQLCOM_SHOW_PROFILE, SQLCOM_SHOW_PROFILES,
SQLCOM_SIGNAL, SQLCOM_RESIGNAL,
SQLCOM_SHOW_RELAYLOG_EVENTS,
SQLCOM_GET_DIAGNOSTICS,
SQLCOM_SHOW_USER_STATS, SQLCOM_SHOW_TABLE_STATS, SQLCOM_SHOW_INDEX_STATS,
SQLCOM_SHOW_CLIENT_STATS,
SQLCOM_SLAVE_ALL_START, SQLCOM_SLAVE_ALL_STOP,

View file

@ -1120,7 +1120,7 @@ void prepare_new_connection_state(THD* thd)
{
thd->killed= KILL_CONNECTION;
thd->print_aborted_warning(0, "init_connect command failed");
sql_print_warning("%s", thd->stmt_da->message());
sql_print_warning("%s", thd->get_stmt_da()->message());
/*
now let client to send its first command,

View file

@ -22,7 +22,7 @@
#endif
#include "sql_list.h" /* Sql_alloc */
#include "mysql_com.h" /* rand_struct */
#include "my_rnd.h" /* rand_struct */
class SQL_CRYPT :public Sql_alloc
{

View file

@ -32,6 +32,7 @@
#include "log_event.h" // Query_log_event
#include "sql_base.h" // lock_table_names, tdc_remove_table
#include "sql_handler.h" // mysql_ha_rm_tables
#include "sql_class.h"
#include <mysys_err.h>
#include "sp_head.h"
#include "sp.h"
@ -575,7 +576,7 @@ int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info,
error= -1;
goto exit;
}
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
ER_DB_CREATE_EXISTS, ER(ER_DB_CREATE_EXISTS), db);
error= 0;
goto not_silent;
@ -784,7 +785,7 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
}
else
{
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
ER_DB_DROP_EXISTS, ER(ER_DB_DROP_EXISTS), db);
error= false;
goto update_binlog;
@ -1537,7 +1538,7 @@ bool mysql_change_db(THD *thd, const LEX_STRING *new_db_name, bool force_switch)
{
/* Throw a warning and free new_db_file_name. */
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
ER_BAD_DB_ERROR, ER(ER_BAD_DB_ERROR),
new_db_file_name.str);

View file

@ -666,9 +666,9 @@ exit:
if (derived->view)
{
if (thd->is_error() &&
(thd->stmt_da->sql_errno() == ER_BAD_FIELD_ERROR ||
thd->stmt_da->sql_errno() == ER_FUNC_INEXISTENT_NAME_COLLISION ||
thd->stmt_da->sql_errno() == ER_SP_DOES_NOT_EXIST))
(thd->get_stmt_da()->sql_errno() == ER_BAD_FIELD_ERROR ||
thd->get_stmt_da()->sql_errno() == ER_FUNC_INEXISTENT_NAME_COLLISION ||
thd->get_stmt_da()->sql_errno() == ER_SP_DOES_NOT_EXIST))
{
thd->clear_error();
my_error(ER_VIEW_INVALID, MYF(0), derived->db,

View file

@ -47,12 +47,12 @@ This file contains the implementation of error and warnings related
#include "sp_rcontext.h"
/*
Design notes about MYSQL_ERROR::m_message_text.
Design notes about Sql_condition::m_message_text.
The member MYSQL_ERROR::m_message_text contains the text associated with
The member Sql_condition::m_message_text contains the text associated with
an error, warning or note (which are all SQL 'conditions')
Producer of MYSQL_ERROR::m_message_text:
Producer of Sql_condition::m_message_text:
----------------------------------------
(#1) the server implementation itself, when invoking functions like
@ -78,16 +78,16 @@ This file contains the implementation of error and warnings related
- a RESIGNAL statement,
the message text is provided by the user logic, and is expressed in UTF8.
Storage of MYSQL_ERROR::m_message_text:
Storage of Sql_condition::m_message_text:
---------------------------------------
(#4) The class MYSQL_ERROR is used to hold the message text member.
(#4) The class Sql_condition is used to hold the message text member.
This class represents a single SQL condition.
(#5) The class Warning_info represents a SQL condition area, and contains
a collection of SQL conditions in the Warning_info::m_warn_list
Consumer of MYSQL_ERROR::m_message_text:
Consumer of Sql_condition::m_message_text:
----------------------------------------
(#6) The statements SHOW WARNINGS and SHOW ERRORS display the content of
@ -97,9 +97,9 @@ This file contains the implementation of error and warnings related
also read the content of:
- the top level statement condition area (when executed in a query),
- a sub statement (when executed in a stored program)
and return the data stored in a MYSQL_ERROR.
and return the data stored in a Sql_condition.
(#8) The RESIGNAL statement reads the MYSQL_ERROR caught by an exception
(#8) The RESIGNAL statement reads the Sql_condition caught by an exception
handler, to raise a new or modified condition (in #3).
The big picture
@ -113,7 +113,7 @@ This file contains the implementation of error and warnings related
----------------------------|---------------------------- |
| |
V |
MYSQL_ERROR(#4) |
Sql_condition(#4) |
| |
| |
V |
@ -151,10 +151,10 @@ This file contains the implementation of error and warnings related
As a result, the design choice for (#4) and (#5) is to store data in
the 'error_message_charset_info' CHARSET, to minimize impact on the code base.
This is implemented by using 'String MYSQL_ERROR::m_message_text'.
This is implemented by using 'String Sql_condition::m_message_text'.
The UTF8 -> error_message_charset_info conversion is implemented in
Signal_common::eval_signal_informations() (for path #B and #C).
Sql_cmd_common_signal::eval_signal_informations() (for path #B and #C).
Future work
-----------
@ -164,14 +164,14 @@ This file contains the implementation of error and warnings related
- Change (#4 and #5) to store message text in UTF8 natively.
In practice, this means changing the type of the message text to
'<UTF8 String 128 class> MYSQL_ERROR::m_message_text', and is a direct
'<UTF8 String 128 class> Sql_condition::m_message_text', and is a direct
consequence of WL#751.
- Implement (#9) (GET DIAGNOSTICS).
See WL#2111 (Stored Procedures: Implement GET DIAGNOSTICS)
*/
MYSQL_ERROR::MYSQL_ERROR()
Sql_condition::Sql_condition()
: Sql_alloc(),
m_class_origin((const char*) NULL, 0, & my_charset_utf8_bin),
m_subclass_origin((const char*) NULL, 0, & my_charset_utf8_bin),
@ -185,20 +185,20 @@ MYSQL_ERROR::MYSQL_ERROR()
m_cursor_name((const char*) NULL, 0, & my_charset_utf8_bin),
m_message_text(),
m_sql_errno(0),
m_level(MYSQL_ERROR::WARN_LEVEL_ERROR),
m_level(Sql_condition::WARN_LEVEL_ERROR),
m_mem_root(NULL)
{
memset(m_returned_sqlstate, 0, sizeof(m_returned_sqlstate));
}
void MYSQL_ERROR::init(MEM_ROOT *mem_root)
void Sql_condition::init(MEM_ROOT *mem_root)
{
DBUG_ASSERT(mem_root != NULL);
DBUG_ASSERT(m_mem_root == NULL);
m_mem_root= mem_root;
}
void MYSQL_ERROR::clear()
void Sql_condition::clear()
{
m_class_origin.length(0);
m_subclass_origin.length(0);
@ -212,10 +212,10 @@ void MYSQL_ERROR::clear()
m_cursor_name.length(0);
m_message_text.length(0);
m_sql_errno= 0;
m_level= MYSQL_ERROR::WARN_LEVEL_ERROR;
m_level= Sql_condition::WARN_LEVEL_ERROR;
}
MYSQL_ERROR::MYSQL_ERROR(MEM_ROOT *mem_root)
Sql_condition::Sql_condition(MEM_ROOT *mem_root)
: Sql_alloc(),
m_class_origin((const char*) NULL, 0, & my_charset_utf8_bin),
m_subclass_origin((const char*) NULL, 0, & my_charset_utf8_bin),
@ -229,7 +229,7 @@ MYSQL_ERROR::MYSQL_ERROR(MEM_ROOT *mem_root)
m_cursor_name((const char*) NULL, 0, & my_charset_utf8_bin),
m_message_text(),
m_sql_errno(0),
m_level(MYSQL_ERROR::WARN_LEVEL_ERROR),
m_level(Sql_condition::WARN_LEVEL_ERROR),
m_mem_root(mem_root)
{
DBUG_ASSERT(mem_root != NULL);
@ -254,7 +254,7 @@ static void copy_string(MEM_ROOT *mem_root, String* dst, const String* src)
}
void
MYSQL_ERROR::copy_opt_attributes(const MYSQL_ERROR *cond)
Sql_condition::copy_opt_attributes(const Sql_condition *cond)
{
DBUG_ASSERT(this != cond);
copy_string(m_mem_root, & m_class_origin, & cond->m_class_origin);
@ -270,8 +270,8 @@ MYSQL_ERROR::copy_opt_attributes(const MYSQL_ERROR *cond)
}
void
MYSQL_ERROR::set(uint sql_errno, const char* sqlstate,
MYSQL_ERROR::enum_warning_level level, const char* msg)
Sql_condition::set(uint sql_errno, const char* sqlstate,
Sql_condition::enum_warning_level level, const char* msg)
{
DBUG_ASSERT(sql_errno != 0);
DBUG_ASSERT(sqlstate != NULL);
@ -286,11 +286,11 @@ MYSQL_ERROR::set(uint sql_errno, const char* sqlstate,
}
void
MYSQL_ERROR::set_builtin_message_text(const char* str)
Sql_condition::set_builtin_message_text(const char* str)
{
/*
See the comments
"Design notes about MYSQL_ERROR::m_message_text."
"Design notes about Sql_condition::m_message_text."
*/
const char* copy;
@ -300,24 +300,41 @@ MYSQL_ERROR::set_builtin_message_text(const char* str)
}
const char*
MYSQL_ERROR::get_message_text() const
Sql_condition::get_message_text() const
{
return m_message_text.ptr();
}
int
MYSQL_ERROR::get_message_octet_length() const
Sql_condition::get_message_octet_length() const
{
return m_message_text.length();
}
void
MYSQL_ERROR::set_sqlstate(const char* sqlstate)
Sql_condition::set_sqlstate(const char* sqlstate)
{
memcpy(m_returned_sqlstate, sqlstate, SQLSTATE_LENGTH);
m_returned_sqlstate[SQLSTATE_LENGTH]= '\0';
}
Diagnostics_area::Diagnostics_area(bool initialize)
: m_main_wi(0, false, initialize)
{
push_warning_info(&m_main_wi);
reset_diagnostics_area();
}
Diagnostics_area::Diagnostics_area(ulonglong warning_info_id,
bool allow_unlimited_warnings)
: m_main_wi(warning_info_id, allow_unlimited_warnings, true)
{
push_warning_info(&m_main_wi);
reset_diagnostics_area();
}
/**
Clear this diagnostics area.
@ -337,7 +354,8 @@ Diagnostics_area::reset_diagnostics_area()
m_last_insert_id= 0;
m_statement_warn_count= 0;
#endif
is_sent= FALSE;
get_warning_info()->clear_error_condition();
set_is_sent(false);
/** Tiny reset in debug mode to see garbage right away */
m_status= DA_EMPTY;
DBUG_VOID_RETURN;
@ -350,9 +368,9 @@ Diagnostics_area::reset_diagnostics_area()
*/
void
Diagnostics_area::set_ok_status(THD *thd, ulonglong affected_rows_arg,
ulonglong last_insert_id_arg,
const char *message_arg)
Diagnostics_area::set_ok_status(ulonglong affected_rows,
ulonglong last_insert_id,
const char *message)
{
DBUG_ENTER("set_ok_status");
DBUG_ASSERT(! is_set());
@ -363,11 +381,11 @@ Diagnostics_area::set_ok_status(THD *thd, ulonglong affected_rows_arg,
if (is_error() || is_disabled())
return;
m_statement_warn_count= thd->warning_info->statement_warn_count();
m_affected_rows= affected_rows_arg;
m_last_insert_id= last_insert_id_arg;
if (message_arg)
strmake(m_message, message_arg, sizeof(m_message) - 1);
m_statement_warn_count= current_statement_warn_count();
m_affected_rows= affected_rows;
m_last_insert_id= last_insert_id;
if (message)
strmake(m_message, message, sizeof(m_message) - 1);
else
m_message[0]= '\0';
m_status= DA_OK;
@ -398,20 +416,48 @@ Diagnostics_area::set_eof_status(THD *thd)
anyway.
*/
m_statement_warn_count= (thd->spcont ?
0 : thd->warning_info->statement_warn_count());
0 :
current_statement_warn_count());
m_status= DA_EOF;
DBUG_VOID_RETURN;
}
/**
Set ERROR status.
Set ERROR status in the Diagnostics Area. This function should be used to
report fatal errors (such as out-of-memory errors) when no further
processing is possible.
@param sql_errno SQL-condition error number
*/
void
Diagnostics_area::set_error_status(THD *thd, uint sql_errno_arg,
const char *message_arg,
const char *sqlstate)
Diagnostics_area::set_error_status(uint sql_errno)
{
set_error_status(sql_errno,
ER(sql_errno),
mysql_errno_to_sqlstate(sql_errno),
NULL);
}
/**
Set ERROR status in the Diagnostics Area.
@note error_condition may be NULL. It happens if a) OOM error is being
reported; or b) when Warning_info is full.
@param sql_errno SQL-condition error number
@param message SQL-condition message
@param sqlstate SQL-condition state
@param error_condition SQL-condition object representing the error state
*/
void
Diagnostics_area::set_error_status(uint sql_errno,
const char *message,
const char *sqlstate,
const Sql_condition *error_condition)
{
DBUG_ENTER("set_error_status");
/*
@ -419,7 +465,14 @@ Diagnostics_area::set_error_status(THD *thd, uint sql_errno_arg,
The only exception is when we flush the message to the client,
an error can happen during the flush.
*/
DBUG_ASSERT(! is_set() || can_overwrite_status);
DBUG_ASSERT(! is_set() || m_can_overwrite_status);
// message must be set properly by the caller.
DBUG_ASSERT(message);
// sqlstate must be set properly by the caller.
DBUG_ASSERT(sqlstate);
#ifdef DBUG_OFF
/*
In production, refuse to overwrite a custom response with an
@ -429,19 +482,17 @@ Diagnostics_area::set_error_status(THD *thd, uint sql_errno_arg,
return;
#endif
if (sqlstate == NULL)
sqlstate= mysql_errno_to_sqlstate(sql_errno_arg);
m_sql_errno= sql_errno_arg;
m_sql_errno= sql_errno;
memcpy(m_sqlstate, sqlstate, SQLSTATE_LENGTH);
m_sqlstate[SQLSTATE_LENGTH]= '\0';
strmake(m_message, message_arg, sizeof(m_message)-1);
strmake(m_message, message, sizeof(m_message)-1);
get_warning_info()->set_error_condition(error_condition);
m_status= DA_ERROR;
DBUG_VOID_RETURN;
}
/**
Mark the diagnostics area as 'DISABLED'.
@ -459,15 +510,16 @@ Diagnostics_area::disable_status()
Warning_info::Warning_info(ulonglong warn_id_arg,
bool allow_unlimited_warnings, bool initialize)
:m_statement_warn_count(0),
:m_current_statement_warn_count(0),
m_current_row_for_warning(1),
m_warn_id(warn_id_arg),
m_error_condition(NULL),
m_allow_unlimited_warnings(allow_unlimited_warnings),
initialized(0),
m_read_only(FALSE)
{
m_warn_list.empty();
bzero((char*) m_warn_count, sizeof(m_warn_count));
memset(m_warn_count, 0, sizeof(m_warn_count));
if (initialize)
init();
}
@ -492,92 +544,164 @@ Warning_info::~Warning_info()
}
/**
Reset the warning information of this connection.
*/
void Warning_info::clear_warning_info(ulonglong warn_id_arg)
bool Warning_info::has_sql_condition(const char *message_str,
ulong message_length) const
{
m_warn_id= warn_id_arg;
free_memory();
bzero((char*) m_warn_count, sizeof(m_warn_count));
m_warn_list.empty();
m_statement_warn_count= 0;
m_current_row_for_warning= 1; /* Start counting from the first row */
Diagnostics_area::Sql_condition_iterator it(m_warn_list);
const Sql_condition *err;
while ((err= it++))
{
if (strncmp(message_str, err->get_message_text(), message_length) == 0)
return true;
}
return false;
}
/**
Append warnings only if the original contents of the routine
warning info was replaced.
*/
void Warning_info::merge_with_routine_info(THD *thd, Warning_info *source)
void Warning_info::clear(ulonglong new_id)
{
/*
If a routine body is empty or if a routine did not
generate any warnings (thus m_warn_id didn't change),
do not duplicate our own contents by appending the
contents of the called routine. We know that the called
routine did not change its warning info.
id(new_id);
m_warn_list.empty();
m_marked_sql_conditions.empty();
free_memory();
memset(m_warn_count, 0, sizeof(m_warn_count));
m_current_statement_warn_count= 0;
m_current_row_for_warning= 1; /* Start counting from the first row */
clear_error_condition();
}
On the other hand, if the routine body is not empty and
some statement in the routine generates a warning or
uses tables, m_warn_id is guaranteed to have changed.
In this case we know that the routine warning info
contains only new warnings, and thus we perform a copy.
*/
if (m_warn_id != source->m_warn_id)
void Warning_info::append_warning_info(THD *thd, const Warning_info *source)
{
const Sql_condition *err;
Diagnostics_area::Sql_condition_iterator it(source->m_warn_list);
const Sql_condition *src_error_condition = source->get_error_condition();
while ((err= it++))
{
/*
If the invocation of the routine was a standalone statement,
rather than a sub-statement, in other words, if it's a CALL
of a procedure, rather than invocation of a function or a
trigger, we need to clear the current contents of the caller's
warning info.
// Do not use ::push_warning() to avoid invocation of THD-internal-handlers.
Sql_condition *new_error= Warning_info::push_warning(thd, err);
This is per MySQL rules: if a statement generates a warning,
warnings from the previous statement are flushed. Normally
it's done in push_warning(). However, here we don't use
push_warning() to avoid invocation of condition handlers or
escalation of warnings to errors.
*/
opt_clear_warning_info(thd->query_id);
append_warning_info(thd, source);
if (src_error_condition && src_error_condition == err)
set_error_condition(new_error);
if (source->is_marked_for_removal(err))
mark_condition_for_removal(new_error);
}
}
/**
Add a warning to the list of warnings. Increment the respective
counters.
Copy Sql_conditions that are not WARN_LEVEL_ERROR from the source
Warning_info to the current Warning_info.
@param thd Thread context.
@param sp_wi Stored-program Warning_info
@param thd Thread context.
@param src_wi Warning_info to copy from.
*/
MYSQL_ERROR *Warning_info::push_warning(THD *thd,
uint sql_errno, const char* sqlstate,
MYSQL_ERROR::enum_warning_level level,
const char *msg)
void Diagnostics_area::copy_non_errors_from_wi(THD *thd,
const Warning_info *src_wi)
{
MYSQL_ERROR *cond= NULL;
Sql_condition_iterator it(src_wi->m_warn_list);
const Sql_condition *cond;
Warning_info *wi= get_warning_info();
while ((cond= it++))
{
if (cond->get_level() == Sql_condition::WARN_LEVEL_ERROR)
continue;
Sql_condition *new_condition= wi->push_warning(thd, cond);
if (src_wi->is_marked_for_removal(cond))
wi->mark_condition_for_removal(new_condition);
}
}
void Warning_info::mark_sql_conditions_for_removal()
{
Sql_condition_list::Iterator it(m_warn_list);
Sql_condition *cond;
while ((cond= it++))
mark_condition_for_removal(cond);
}
void Warning_info::remove_marked_sql_conditions()
{
List_iterator_fast<Sql_condition> it(m_marked_sql_conditions);
Sql_condition *cond;
while ((cond= it++))
{
m_warn_list.remove(cond);
m_warn_count[cond->get_level()]--;
m_current_statement_warn_count--;
if (cond == m_error_condition)
m_error_condition= NULL;
}
m_marked_sql_conditions.empty();
}
bool Warning_info::is_marked_for_removal(const Sql_condition *cond) const
{
List_iterator_fast<Sql_condition> it(
const_cast<List<Sql_condition>&> (m_marked_sql_conditions));
Sql_condition *c;
while ((c= it++))
{
if (c == cond)
return true;
}
return false;
}
void Warning_info::reserve_space(THD *thd, uint count)
{
while (m_warn_list.elements() &&
(m_warn_list.elements() + count) > thd->variables.max_error_count)
m_warn_list.remove(m_warn_list.front());
}
Sql_condition *Warning_info::push_warning(THD *thd,
uint sql_errno, const char* sqlstate,
Sql_condition::enum_warning_level level,
const char *msg)
{
Sql_condition *cond= NULL;
if (! m_read_only)
{
if (m_allow_unlimited_warnings ||
m_warn_list.elements < thd->variables.max_error_count)
m_warn_list.elements() < thd->variables.max_error_count)
{
cond= new (& m_warn_root) MYSQL_ERROR(& m_warn_root);
cond= new (& m_warn_root) Sql_condition(& m_warn_root);
if (cond)
{
cond->set(sql_errno, sqlstate, level, msg);
m_warn_list.push_back(cond, &m_warn_root);
m_warn_list.push_back(cond);
}
}
m_warn_count[(uint) level]++;
}
m_statement_warn_count++;
m_current_statement_warn_count++;
return cond;
}
MYSQL_ERROR *Warning_info::push_warning(THD *thd, const MYSQL_ERROR *sql_condition)
Sql_condition *Warning_info::push_warning(THD *thd, const Sql_condition *sql_condition)
{
MYSQL_ERROR *new_condition= push_warning(thd,
Sql_condition *new_condition= push_warning(thd,
sql_condition->get_sql_errno(),
sql_condition->get_sqlstate(),
sql_condition->get_level(),
@ -600,7 +724,7 @@ MYSQL_ERROR *Warning_info::push_warning(THD *thd, const MYSQL_ERROR *sql_conditi
msg Clear error message
*/
void push_warning(THD *thd, MYSQL_ERROR::enum_warning_level level,
void push_warning(THD *thd, Sql_condition::enum_warning_level level,
uint code, const char *msg)
{
DBUG_ENTER("push_warning");
@ -611,15 +735,15 @@ void push_warning(THD *thd, MYSQL_ERROR::enum_warning_level level,
WARN_LEVEL_ERROR *is* a bug. Either use my_printf_error(),
my_error(), or WARN_LEVEL_WARN.
*/
DBUG_ASSERT(level != MYSQL_ERROR::WARN_LEVEL_ERROR);
DBUG_ASSERT(level != Sql_condition::WARN_LEVEL_ERROR);
if (level == MYSQL_ERROR::WARN_LEVEL_ERROR)
level= MYSQL_ERROR::WARN_LEVEL_WARN;
if (level == Sql_condition::WARN_LEVEL_ERROR)
level= Sql_condition::WARN_LEVEL_WARN;
(void) thd->raise_condition(code, NULL, level, msg);
/* Make sure we also count warnings pushed after calling set_ok_status(). */
thd->stmt_da->increment_warning();
thd->get_stmt_da()->increment_warning();
DBUG_VOID_RETURN;
}
@ -636,7 +760,7 @@ void push_warning(THD *thd, MYSQL_ERROR::enum_warning_level level,
msg Clear error message
*/
void push_warning_printf(THD *thd, MYSQL_ERROR::enum_warning_level level,
void push_warning_printf(THD *thd, Sql_condition::enum_warning_level level,
uint code, const char *format, ...)
{
va_list args;
@ -685,7 +809,7 @@ bool mysqld_show_warnings(THD *thd, ulong levels_to_show)
List<Item> field_list;
DBUG_ENTER("mysqld_show_warnings");
DBUG_ASSERT(thd->warning_info->is_read_only());
DBUG_ASSERT(thd->get_stmt_da()->is_warning_info_read_only());
field_list.push_back(new Item_empty_string("Level", 7));
field_list.push_back(new Item_return_int("Code",4, MYSQL_TYPE_LONG));
@ -695,7 +819,7 @@ bool mysqld_show_warnings(THD *thd, ulong levels_to_show)
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
DBUG_RETURN(TRUE);
MYSQL_ERROR *err;
const Sql_condition *err;
SELECT_LEX *sel= &thd->lex->select_lex;
SELECT_LEX_UNIT *unit= &thd->lex->unit;
ulonglong idx= 0;
@ -703,7 +827,8 @@ bool mysqld_show_warnings(THD *thd, ulong levels_to_show)
unit->set_limit(sel);
List_iterator_fast<MYSQL_ERROR> it(thd->warning_info->warn_list());
Diagnostics_area::Sql_condition_iterator it=
thd->get_stmt_da()->sql_conditions();
while ((err= it++))
{
/* Skip levels that the user is not interested in */
@ -726,7 +851,7 @@ bool mysqld_show_warnings(THD *thd, ulong levels_to_show)
}
my_eof(thd);
thd->warning_info->set_read_only(FALSE);
thd->get_stmt_da()->set_warning_info_read_only(FALSE);
DBUG_RETURN(FALSE);
}

View file

@ -19,126 +19,13 @@
#include "sql_list.h" /* Sql_alloc, MEM_ROOT */
#include "m_string.h" /* LEX_STRING */
#include "sql_string.h" /* String */
#include "sql_plist.h" /* I_P_List */
#include "mysql_com.h" /* MYSQL_ERRMSG_SIZE */
#include "my_time.h" /* MYSQL_TIME */
#include "decimal.h"
class THD;
/**
Stores status of the currently executed statement.
Cleared at the beginning of the statement, and then
can hold either OK, ERROR, or EOF status.
Can not be assigned twice per statement.
*/
class Diagnostics_area
{
public:
enum enum_diagnostics_status
{
/** The area is cleared at start of a statement. */
DA_EMPTY= 0,
/** Set whenever one calls my_ok(). */
DA_OK,
/** Set whenever one calls my_eof(). */
DA_EOF,
/** Set whenever one calls my_error() or my_message(). */
DA_ERROR,
/** Set in case of a custom response, such as one from COM_STMT_PREPARE. */
DA_DISABLED
};
/** True if status information is sent to the client. */
bool is_sent;
/** Set to make set_error_status after set_{ok,eof}_status possible. */
bool can_overwrite_status;
void set_ok_status(THD *thd, ulonglong affected_rows_arg,
ulonglong last_insert_id_arg,
const char *message);
void set_eof_status(THD *thd);
void set_error_status(THD *thd, uint sql_errno_arg, const char *message_arg,
const char *sqlstate);
void disable_status();
void reset_diagnostics_area();
bool is_set() const { return m_status != DA_EMPTY; }
bool is_error() const { return m_status == DA_ERROR; }
bool is_eof() const { return m_status == DA_EOF; }
bool is_ok() const { return m_status == DA_OK; }
bool is_disabled() const { return m_status == DA_DISABLED; }
enum_diagnostics_status status() const { return m_status; }
const char *message() const
{ DBUG_ASSERT(m_status == DA_ERROR || m_status == DA_OK); return m_message; }
uint sql_errno() const
{ DBUG_ASSERT(m_status == DA_ERROR); return m_sql_errno; }
const char* get_sqlstate() const
{ DBUG_ASSERT(m_status == DA_ERROR); return m_sqlstate; }
ulonglong affected_rows() const
{ DBUG_ASSERT(m_status == DA_OK); return m_affected_rows; }
ulonglong last_insert_id() const
{ DBUG_ASSERT(m_status == DA_OK); return m_last_insert_id; }
uint statement_warn_count() const
{
DBUG_ASSERT(m_status == DA_OK || m_status == DA_EOF);
return m_statement_warn_count;
}
/* Used to count any warnings pushed after calling set_ok_status(). */
void increment_warning()
{
if (m_status != DA_EMPTY)
m_statement_warn_count++;
}
Diagnostics_area() { reset_diagnostics_area(); }
private:
/** Message buffer. Can be used by OK or ERROR status. */
char m_message[MYSQL_ERRMSG_SIZE];
/**
SQL error number. One of ER_ codes from share/errmsg.txt.
Set by set_error_status.
*/
uint m_sql_errno;
char m_sqlstate[SQLSTATE_LENGTH+1];
/**
The number of rows affected by the last statement. This is
semantically close to thd->row_count_func, but has a different
life cycle. thd->row_count_func stores the value returned by
function ROW_COUNT() and is cleared only by statements that
update its value, such as INSERT, UPDATE, DELETE and few others.
This member is cleared at the beginning of the next statement.
We could possibly merge the two, but life cycle of thd->row_count_func
can not be changed.
*/
ulonglong m_affected_rows;
/**
Similarly to the previous member, this is a replacement of
thd->first_successful_insert_id_in_prev_stmt, which is used
to implement LAST_INSERT_ID().
*/
ulonglong m_last_insert_id;
/**
Number of warnings of this last statement. May differ from
the number of warnings returned by SHOW WARNINGS e.g. in case
the statement doesn't clear the warnings, and doesn't generate
them.
*/
uint m_statement_warn_count;
enum_diagnostics_status m_status;
};
class my_decimal;
///////////////////////////////////////////////////////////////////////////
@ -146,10 +33,8 @@ private:
Representation of a SQL condition.
A SQL condition can be a completion condition (note, warning),
or an exception condition (error, not found).
@note This class is named MYSQL_ERROR instead of SQL_condition for
historical reasons, to facilitate merging code with previous releases.
*/
class MYSQL_ERROR : public Sql_alloc
class Sql_condition : public Sql_alloc
{
public:
/*
@ -160,6 +45,7 @@ public:
*/
enum enum_warning_level
{ WARN_LEVEL_NOTE, WARN_LEVEL_WARN, WARN_LEVEL_ERROR, WARN_LEVEL_END};
/**
Get the MESSAGE_TEXT of this condition.
@return the message text.
@ -190,19 +76,15 @@ public:
Get the error level of this condition.
@return the error level condition item.
*/
MYSQL_ERROR::enum_warning_level get_level() const
Sql_condition::enum_warning_level get_level() const
{ return m_level; }
/** Destructor. */
~MYSQL_ERROR()
{}
private:
/*
The interface of MYSQL_ERROR is mostly private, by design,
The interface of Sql_condition is mostly private, by design,
so that only the following code:
- various raise_error() or raise_warning() methods in class THD,
- the implementation of SIGNAL / RESIGNAL
- the implementation of SIGNAL / RESIGNAL / GET DIAGNOSTICS
- catch / re-throw of SQL conditions in stored procedures (sp_rcontext)
is allowed to create / modify a SQL condition.
Enforcing this policy prevents confusion, since the only public
@ -212,20 +94,21 @@ private:
*/
friend class THD;
friend class Warning_info;
friend class Signal_common;
friend class Signal_statement;
friend class Resignal_statement;
friend class Sql_cmd_common_signal;
friend class Sql_cmd_signal;
friend class Sql_cmd_resignal;
friend class sp_rcontext;
friend class Condition_information_item;
/**
Default constructor.
This constructor is usefull when allocating arrays.
Note that the init() method should be called to complete the MYSQL_ERROR.
Note that the init() method should be called to complete the Sql_condition.
*/
MYSQL_ERROR();
Sql_condition();
/**
Complete the MYSQL_ERROR initialisation.
Complete the Sql_condition initialisation.
@param mem_root The memory root to use for the condition items
of this condition
*/
@ -236,15 +119,17 @@ private:
@param mem_root The memory root to use for the condition items
of this condition
*/
MYSQL_ERROR(MEM_ROOT *mem_root);
Sql_condition(MEM_ROOT *mem_root);
/** Destructor. */
~Sql_condition()
{}
/**
Copy optional condition items attributes.
@param cond the condition to copy.
*/
void copy_opt_attributes(const MYSQL_ERROR *cond);
void copy_opt_attributes(const Sql_condition *cond);
/**
Set this condition area with a fixed message text.
@ -255,7 +140,7 @@ private:
@param MyFlags additional flags.
*/
void set(uint sql_errno, const char* sqlstate,
MYSQL_ERROR::enum_warning_level level,
Sql_condition::enum_warning_level level,
const char* msg);
/**
@ -268,6 +153,12 @@ private:
/** Set the SQLSTATE of this condition. */
void set_sqlstate(const char* sqlstate);
/** Set the CLASS_ORIGIN of this condition. */
void set_class_origin();
/** Set the SUBCLASS_ORIGIN of this condition. */
void set_subclass_origin();
/**
Clear this SQL condition.
*/
@ -317,44 +208,48 @@ private:
char m_returned_sqlstate[SQLSTATE_LENGTH+1];
/** Severity (error, warning, note) of this condition. */
MYSQL_ERROR::enum_warning_level m_level;
Sql_condition::enum_warning_level m_level;
/** Pointers for participating in the list of conditions. */
Sql_condition *next_in_wi;
Sql_condition **prev_in_wi;
/** Memory root to use to hold condition item values. */
MEM_ROOT *m_mem_root;
};
class Sql_condition : public MYSQL_ERROR
{
/*
Wrapper class to allow one to use Sql_condition in handlers instead of
MYSQL_ERROR
*/
};
///////////////////////////////////////////////////////////////////////////
/**
Information about warnings of the current connection.
*/
class Warning_info
{
/** The type of the counted and doubly linked list of conditions. */
typedef I_P_List<Sql_condition,
I_P_List_adapter<Sql_condition,
&Sql_condition::next_in_wi,
&Sql_condition::prev_in_wi>,
I_P_List_counter,
I_P_List_fast_push_back<Sql_condition> >
Sql_condition_list;
/** A memory root to allocate warnings and errors */
MEM_ROOT m_warn_root;
/** List of warnings of all severities (levels). */
List <MYSQL_ERROR> m_warn_list;
Sql_condition_list m_warn_list;
/** A break down of the number of warnings per severity (level). */
uint m_warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_END];
uint m_warn_count[(uint) Sql_condition::WARN_LEVEL_END];
/**
The number of warnings of the current statement. Warning_info
life cycle differs from statement life cycle -- it may span
multiple statements. In that case we get
m_statement_warn_count 0, whereas m_warn_list is not empty.
m_current_statement_warn_count 0, whereas m_warn_list is not empty.
*/
uint m_statement_warn_count;
uint m_current_statement_warn_count;
/*
Row counter, to print in errors and warnings. Not increased in
@ -365,29 +260,67 @@ class Warning_info
/** Used to optionally clear warnings only once per statement. */
ulonglong m_warn_id;
/**
A pointer to an element of m_warn_list. It determines SQL-condition
instance which corresponds to the error state in Diagnostics_area.
This is needed for properly processing SQL-conditions in SQL-handlers.
When an SQL-handler is found for the current error state in Diagnostics_area,
this pointer is needed to remove the corresponding SQL-condition from the
Warning_info list.
@note m_error_condition might be NULL in the following cases:
- Diagnostics_area set to fatal error state (like OOM);
- Max number of Warning_info elements has been reached (thus, there is
no corresponding SQL-condition object in Warning_info).
*/
const Sql_condition *m_error_condition;
/** Indicates if push_warning() allows unlimited number of warnings. */
bool m_allow_unlimited_warnings;
bool initialized; /* Set to 1 if init() has been called */
private:
Warning_info(const Warning_info &rhs); /* Not implemented */
Warning_info& operator=(const Warning_info &rhs); /* Not implemented */
/** Read only status. */
bool m_read_only;
/** Pointers for participating in the stack of Warning_info objects. */
Warning_info *m_next_in_da;
Warning_info **m_prev_in_da;
List<Sql_condition> m_marked_sql_conditions;
public:
Warning_info(ulonglong warn_id_arg, bool allow_unlimited_warnings,
bool initialize=true);
bool initialized);
~Warning_info();
/* Allocate memory for structures */
void init();
void free_memory();
private:
Warning_info(const Warning_info &rhs); /* Not implemented */
Warning_info& operator=(const Warning_info &rhs); /* Not implemented */
/**
Checks if Warning_info contains SQL-condition with the given message.
@param message_str Message string.
@param message_length Length of message string.
@return true if the Warning_info contains an SQL-condition with the given
message.
*/
bool has_sql_condition(const char *message_str, ulong message_length) const;
/**
Reset the warning information. Clear all warnings,
the number of warnings, reset current row counter
to point to the first row.
@param new_id new Warning_info id.
*/
void clear_warning_info(ulonglong warn_id_arg);
void clear(ulonglong new_id);
/**
Only clear warning info if haven't yet done that already
for the current query. Allows to be issued at any time
@ -396,46 +329,72 @@ public:
@todo: This is a sign of sloppy coding. Instead we need to
designate one place in a statement life cycle where we call
clear_warning_info().
Warning_info::clear().
@param query_id Current query id.
*/
void opt_clear_warning_info(ulonglong query_id)
void opt_clear(ulonglong query_id)
{
if (query_id != m_warn_id)
clear_warning_info(query_id);
}
void append_warning_info(THD *thd, Warning_info *source)
{
append_warnings(thd, & source->warn_list());
clear(query_id);
}
/**
Concatenate the list of warnings.
It's considered tolerable to lose a warning.
*/
void append_warnings(THD *thd, List<MYSQL_ERROR> *src)
{
MYSQL_ERROR *err;
List_iterator_fast<MYSQL_ERROR> it(*src);
/*
Don't use ::push_warning() to avoid invocation of condition
handlers or escalation of warnings to errors.
*/
while ((err= it++))
Warning_info::push_warning(thd, err);
}
/**
Conditional merge of related warning information areas.
It's considered tolerable to lose an SQL-condition in case of OOM-error,
or if the number of SQL-conditions in the Warning_info reached top limit.
@param thd Thread context.
@param source Warning_info object to copy SQL-conditions from.
*/
void merge_with_routine_info(THD *thd, Warning_info *source);
void append_warning_info(THD *thd, const Warning_info *source);
/**
Reset between two COM_ commands. Warnings are preserved
between commands, but statement_warn_count indicates
the number of warnings of this particular statement only.
*/
void reset_for_next_command() { m_statement_warn_count= 0; }
void reset_for_next_command()
{ m_current_statement_warn_count= 0; }
/**
Mark active SQL-conditions for later removal.
This is done to simulate stacked DAs for HANDLER statements.
*/
void mark_sql_conditions_for_removal();
/**
Unmark SQL-conditions, which were marked for later removal.
This is done to simulate stacked DAs for HANDLER statements.
*/
void unmark_sql_conditions_from_removal()
{ m_marked_sql_conditions.empty(); }
/**
Remove SQL-conditions that are marked for deletion.
This is done to simulate stacked DAs for HANDLER statements.
*/
void remove_marked_sql_conditions();
/**
Check if the given SQL-condition is marked for removal in this Warning_info
instance.
@param cond the SQL-condition.
@retval true if the given SQL-condition is marked for removal in this
Warning_info instance.
@retval false otherwise.
*/
bool is_marked_for_removal(const Sql_condition *cond) const;
/**
Mark a single SQL-condition for removal (add the given SQL-condition to the
removal list of this Warning_info instance).
*/
void mark_condition_for_removal(Sql_condition *cond)
{ m_marked_sql_conditions.push_back(cond, &m_warn_root); }
/**
Used for @@warning_count system variable, which prints
@ -444,52 +403,82 @@ public:
ulong warn_count() const
{
/*
This may be higher than warn_list.elements if we have
This may be higher than warn_list.elements() if we have
had more warnings than thd->variables.max_error_count.
*/
return (m_warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_NOTE] +
m_warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_ERROR] +
m_warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_WARN]);
return (m_warn_count[(uint) Sql_condition::WARN_LEVEL_NOTE] +
m_warn_count[(uint) Sql_condition::WARN_LEVEL_ERROR] +
m_warn_count[(uint) Sql_condition::WARN_LEVEL_WARN]);
}
/**
This is for iteration purposes. We return a non-constant reference
since List doesn't have constant iterators.
*/
List<MYSQL_ERROR> &warn_list() { return m_warn_list; }
/**
The number of errors, or number of rows returned by SHOW ERRORS,
also the value of session variable @@error_count.
*/
ulong error_count() const
{ return m_warn_count[(uint) Sql_condition::WARN_LEVEL_ERROR]; }
/**
The number of conditions (errors, warnings and notes) in the list.
*/
uint cond_count() const
{
return m_warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_ERROR];
return m_warn_list.elements();
}
/** Id of the warning information area. */
ulonglong warn_id() const { return m_warn_id; }
ulonglong id() const { return m_warn_id; }
/** Set id of the warning information area. */
void id(ulonglong id) { m_warn_id= id; }
/** Do we have any errors and warnings that we can *show*? */
bool is_empty() const { return m_warn_list.elements == 0; }
bool is_empty() const { return m_warn_list.is_empty(); }
/** Increment the current row counter to point at the next row. */
void inc_current_row_for_warning() { m_current_row_for_warning++; }
/** Reset the current row counter. Start counting from the first row. */
void reset_current_row_for_warning() { m_current_row_for_warning= 1; }
/** Return the current counter value. */
ulong current_row_for_warning() const { return m_current_row_for_warning; }
ulong statement_warn_count() const { return m_statement_warn_count; }
/** Return the number of warnings thrown by the current statement. */
ulong current_statement_warn_count() const
{ return m_current_statement_warn_count; }
/** Add a new condition to the current list. */
MYSQL_ERROR *push_warning(THD *thd,
uint sql_errno, const char* sqlstate,
MYSQL_ERROR::enum_warning_level level,
const char* msg);
/** Make sure there is room for the given number of conditions. */
void reserve_space(THD *thd, uint count);
/** Add a new condition to the current list. */
MYSQL_ERROR *push_warning(THD *thd, const MYSQL_ERROR *sql_condition);
/**
Add a new SQL-condition to the current list and increment the respective
counters.
@param thd Thread context.
@param sql_errno SQL-condition error number.
@param sqlstate SQL-condition state.
@param level SQL-condition level.
@param msg SQL-condition message.
@return a pointer to the added SQL-condition.
*/
Sql_condition *push_warning(THD *thd,
uint sql_errno,
const char* sqlstate,
Sql_condition::enum_warning_level level,
const char* msg);
/**
Add a new SQL-condition to the current list and increment the respective
counters.
@param thd Thread context.
@param sql_condition SQL-condition to copy values from.
@return a pointer to the added SQL-condition.
*/
Sql_condition *push_warning(THD *thd, const Sql_condition *sql_condition);
/**
Set the read only status for this statement area.
@ -500,25 +489,51 @@ public:
- SHOW WARNINGS
- SHOW ERRORS
- GET DIAGNOSTICS
@param read_only the read only property to set
@param read_only the read only property to set.
*/
void set_read_only(bool read_only)
{ m_read_only= read_only; }
/**
Read only status.
@return the read only property
@return the read only property.
*/
bool is_read_only() const
{ return m_read_only; }
private:
/** Read only status. */
bool m_read_only;
/**
@return SQL-condition, which corresponds to the error state in
Diagnostics_area.
friend class Resignal_statement;
@see m_error_condition.
*/
const Sql_condition *get_error_condition() const
{ return m_error_condition; }
/**
Set SQL-condition, which corresponds to the error state in Diagnostics_area.
@see m_error_condition.
*/
void set_error_condition(const Sql_condition *error_condition)
{ m_error_condition= error_condition; }
/**
Reset SQL-condition, which corresponds to the error state in
Diagnostics_area.
@see m_error_condition.
*/
void clear_error_condition()
{ m_error_condition= NULL; }
// for:
// - m_next_in_da / m_prev_in_da
// - is_marked_for_removal()
friend class Diagnostics_area;
};
extern char *err_conv(char *buff, uint to_length, const char *from,
uint from_length, CHARSET_INFO *from_cs);
@ -592,15 +607,352 @@ public:
}
};
void push_warning(THD *thd, MYSQL_ERROR::enum_warning_level level,
///////////////////////////////////////////////////////////////////////////
/**
Stores status of the currently executed statement.
Cleared at the beginning of the statement, and then
can hold either OK, ERROR, or EOF status.
Can not be assigned twice per statement.
*/
class Diagnostics_area
{
private:
/** The type of the counted and doubly linked list of conditions. */
typedef I_P_List<Warning_info,
I_P_List_adapter<Warning_info,
&Warning_info::m_next_in_da,
&Warning_info::m_prev_in_da>,
I_P_List_counter,
I_P_List_fast_push_back<Warning_info> >
Warning_info_list;
public:
/** Const iterator used to iterate through the warning list. */
typedef Warning_info::Sql_condition_list::Const_Iterator
Sql_condition_iterator;
enum enum_diagnostics_status
{
/** The area is cleared at start of a statement. */
DA_EMPTY= 0,
/** Set whenever one calls my_ok(). */
DA_OK,
/** Set whenever one calls my_eof(). */
DA_EOF,
/** Set whenever one calls my_error() or my_message(). */
DA_ERROR,
/** Set in case of a custom response, such as one from COM_STMT_PREPARE. */
DA_DISABLED
};
void set_overwrite_status(bool can_overwrite_status)
{ m_can_overwrite_status= can_overwrite_status; }
/** True if status information is sent to the client. */
bool is_sent() const { return m_is_sent; }
void set_is_sent(bool is_sent) { m_is_sent= is_sent; }
void set_ok_status(ulonglong affected_rows,
ulonglong last_insert_id,
const char *message);
void set_eof_status(THD *thd);
void set_error_status(uint sql_errno);
void set_error_status(uint sql_errno,
const char *message,
const char *sqlstate,
const Sql_condition *error_condition);
void disable_status();
void reset_diagnostics_area();
bool is_set() const { return m_status != DA_EMPTY; }
bool is_error() const { return m_status == DA_ERROR; }
bool is_eof() const { return m_status == DA_EOF; }
bool is_ok() const { return m_status == DA_OK; }
bool is_disabled() const { return m_status == DA_DISABLED; }
enum_diagnostics_status status() const { return m_status; }
const char *message() const
{ DBUG_ASSERT(m_status == DA_ERROR || m_status == DA_OK); return m_message; }
uint sql_errno() const
{ DBUG_ASSERT(m_status == DA_ERROR); return m_sql_errno; }
const char* get_sqlstate() const
{ DBUG_ASSERT(m_status == DA_ERROR); return m_sqlstate; }
ulonglong affected_rows() const
{ DBUG_ASSERT(m_status == DA_OK); return m_affected_rows; }
ulonglong last_insert_id() const
{ DBUG_ASSERT(m_status == DA_OK); return m_last_insert_id; }
uint statement_warn_count() const
{
DBUG_ASSERT(m_status == DA_OK || m_status == DA_EOF);
return m_statement_warn_count;
}
/* Used to count any warnings pushed after calling set_ok_status(). */
void increment_warning()
{
if (m_status != DA_EMPTY)
m_statement_warn_count++;
}
Diagnostics_area(bool initialize);
Diagnostics_area(ulonglong warning_info_id, bool allow_unlimited_warnings);
void init() { m_main_wi.init() ; }
void free_memory() { m_main_wi.free_memory() ; }
void push_warning_info(Warning_info *wi)
{ m_wi_stack.push_front(wi); }
void pop_warning_info()
{
DBUG_ASSERT(m_wi_stack.elements() > 0);
m_wi_stack.remove(m_wi_stack.front());
}
void set_warning_info_id(ulonglong id)
{ get_warning_info()->id(id); }
ulonglong warning_info_id() const
{ return get_warning_info()->id(); }
/**
Compare given current warning info and current warning info
and see if they are different. They will be different if
warnings have been generated or statements that use tables
have been executed. This is checked by comparing m_warn_id.
@param wi Warning info to compare with current Warning info.
@return false if they are equal, true if they are not.
*/
bool warning_info_changed(const Warning_info *wi) const
{ return get_warning_info()->id() != wi->id(); }
bool is_warning_info_empty() const
{ return get_warning_info()->is_empty(); }
ulong current_statement_warn_count() const
{ return get_warning_info()->current_statement_warn_count(); }
bool has_sql_condition(const char *message_str, ulong message_length) const
{ return get_warning_info()->has_sql_condition(message_str, message_length); }
void reset_for_next_command()
{ get_warning_info()->reset_for_next_command(); }
void clear_warning_info(ulonglong id)
{ get_warning_info()->clear(id); }
void opt_clear_warning_info(ulonglong query_id)
{ get_warning_info()->opt_clear(query_id); }
ulong current_row_for_warning() const
{ return get_warning_info()->current_row_for_warning(); }
void inc_current_row_for_warning()
{ get_warning_info()->inc_current_row_for_warning(); }
void reset_current_row_for_warning()
{ get_warning_info()->reset_current_row_for_warning(); }
bool is_warning_info_read_only() const
{ return get_warning_info()->is_read_only(); }
void set_warning_info_read_only(bool read_only)
{ get_warning_info()->set_read_only(read_only); }
ulong error_count() const
{ return get_warning_info()->error_count(); }
ulong warn_count() const
{ return get_warning_info()->warn_count(); }
uint cond_count() const
{ return get_warning_info()->cond_count(); }
Sql_condition_iterator sql_conditions() const
{ return get_warning_info()->m_warn_list; }
void reserve_space(THD *thd, uint count)
{ get_warning_info()->reserve_space(thd, count); }
Sql_condition *push_warning(THD *thd, const Sql_condition *sql_condition)
{ return get_warning_info()->push_warning(thd, sql_condition); }
Sql_condition *push_warning(THD *thd,
uint sql_errno,
const char* sqlstate,
Sql_condition::enum_warning_level level,
const char* msg)
{
return get_warning_info()->push_warning(thd,
sql_errno, sqlstate, level, msg);
}
void mark_sql_conditions_for_removal()
{ get_warning_info()->mark_sql_conditions_for_removal(); }
void unmark_sql_conditions_from_removal()
{ get_warning_info()->unmark_sql_conditions_from_removal(); }
void remove_marked_sql_conditions()
{ get_warning_info()->remove_marked_sql_conditions(); }
const Sql_condition *get_error_condition() const
{ return get_warning_info()->get_error_condition(); }
void copy_sql_conditions_to_wi(THD *thd, Warning_info *dst_wi) const
{ dst_wi->append_warning_info(thd, get_warning_info()); }
void copy_sql_conditions_from_wi(THD *thd, const Warning_info *src_wi)
{ get_warning_info()->append_warning_info(thd, src_wi); }
void copy_non_errors_from_wi(THD *thd, const Warning_info *src_wi);
private:
Warning_info *get_warning_info() { return m_wi_stack.front(); }
const Warning_info *get_warning_info() const { return m_wi_stack.front(); }
private:
/** True if status information is sent to the client. */
bool m_is_sent;
/** Set to make set_error_status after set_{ok,eof}_status possible. */
bool m_can_overwrite_status;
/** Message buffer. Can be used by OK or ERROR status. */
char m_message[MYSQL_ERRMSG_SIZE];
/**
SQL error number. One of ER_ codes from share/errmsg.txt.
Set by set_error_status.
*/
uint m_sql_errno;
char m_sqlstate[SQLSTATE_LENGTH+1];
/**
The number of rows affected by the last statement. This is
semantically close to thd->row_count_func, but has a different
life cycle. thd->row_count_func stores the value returned by
function ROW_COUNT() and is cleared only by statements that
update its value, such as INSERT, UPDATE, DELETE and few others.
This member is cleared at the beginning of the next statement.
We could possibly merge the two, but life cycle of thd->row_count_func
can not be changed.
*/
ulonglong m_affected_rows;
/**
Similarly to the previous member, this is a replacement of
thd->first_successful_insert_id_in_prev_stmt, which is used
to implement LAST_INSERT_ID().
*/
ulonglong m_last_insert_id;
/**
Number of warnings of this last statement. May differ from
the number of warnings returned by SHOW WARNINGS e.g. in case
the statement doesn't clear the warnings, and doesn't generate
them.
*/
uint m_statement_warn_count;
enum_diagnostics_status m_status;
Warning_info m_main_wi;
Warning_info_list m_wi_stack;
};
///////////////////////////////////////////////////////////////////////////
void push_warning(THD *thd, Sql_condition::enum_warning_level level,
uint code, const char *msg);
void push_warning_printf(THD *thd, MYSQL_ERROR::enum_warning_level level,
uint code, const char *format, ...);
void push_warning_printf(THD *thd, Sql_condition::enum_warning_level level,
uint code, const char *format, ...);
bool mysqld_show_warnings(THD *thd, ulong levels_to_show);
uint32 convert_error_message(char *to, uint32 to_length, CHARSET_INFO *to_cs,
uint32 convert_error_message(char *to, uint32 to_length,
CHARSET_INFO *to_cs,
const char *from, uint32 from_length,
CHARSET_INFO *from_cs, uint *errors);
extern const LEX_STRING warning_level_names[];
bool is_sqlstate_valid(const LEX_STRING *sqlstate);
/**
Checks if the specified SQL-state-string defines COMPLETION condition.
This function assumes that the given string contains a valid SQL-state.
@param s the condition SQLSTATE.
@retval true if the given string defines COMPLETION condition.
@retval false otherwise.
*/
inline bool is_sqlstate_completion(const char *s)
{ return s[0] == '0' && s[1] == '0'; }
/**
Checks if the specified SQL-state-string defines WARNING condition.
This function assumes that the given string contains a valid SQL-state.
@param s the condition SQLSTATE.
@retval true if the given string defines WARNING condition.
@retval false otherwise.
*/
inline bool is_sqlstate_warning(const char *s)
{ return s[0] == '0' && s[1] == '1'; }
/**
Checks if the specified SQL-state-string defines NOT FOUND condition.
This function assumes that the given string contains a valid SQL-state.
@param s the condition SQLSTATE.
@retval true if the given string defines NOT FOUND condition.
@retval false otherwise.
*/
inline bool is_sqlstate_not_found(const char *s)
{ return s[0] == '0' && s[1] == '2'; }
/**
Checks if the specified SQL-state-string defines EXCEPTION condition.
This function assumes that the given string contains a valid SQL-state.
@param s the condition SQLSTATE.
@retval true if the given string defines EXCEPTION condition.
@retval false otherwise.
*/
inline bool is_sqlstate_exception(const char *s)
{ return s[0] != '0' || s[1] > '2'; }
#endif // SQL_ERROR_H

340
sql/sql_get_diagnostics.cc Normal file
View file

@ -0,0 +1,340 @@
/* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02111-1307 USA */
#include "sql_list.h" // Sql_alloc, List, List_iterator
#include "sql_cmd.h" // Sql_cmd
#include "sql_class.h" // Diagnostics_area
#include "sql_get_diagnostics.h" // Sql_cmd_get_diagnostics
/**
Execute this GET DIAGNOSTICS statement.
@param thd The current thread.
@remark Errors or warnings occurring during the execution of the GET
DIAGNOSTICS statement should not affect the diagnostics area
of a previous statement as the diagnostics information there
would be wiped out. Thus, in order to preserve the contents
of the diagnostics area from which information is being
retrieved, the GET DIAGNOSTICS statement is executed under
a separate diagnostics area. If any errors or warnings occur
during the execution of the GET DIAGNOSTICS statement, these
error or warnings (conditions) are appended to the list of
the original diagnostics area. The only exception to this is
fatal errors, which must always cause the statement to fail.
@retval false on success.
@retval true on error
*/
bool
Sql_cmd_get_diagnostics::execute(THD *thd)
{
bool rv;
Diagnostics_area new_stmt_da(thd->query_id, false);
Diagnostics_area *save_stmt_da= thd->get_stmt_da();
DBUG_ENTER("Sql_cmd_get_diagnostics::execute");
/* Disable the unneeded read-only mode of the original DA. */
save_stmt_da->set_warning_info_read_only(false);
/* Set new diagnostics area, execute statement and restore. */
thd->set_stmt_da(&new_stmt_da);
rv= m_info->aggregate(thd, save_stmt_da);
thd->set_stmt_da(save_stmt_da);
/* Bail out early if statement succeeded. */
if (! rv)
{
thd->get_stmt_da()->set_ok_status(0, 0, NULL);
DBUG_RETURN(false);
}
/* Statement failed, retrieve the error information for propagation. */
uint sql_errno= new_stmt_da.sql_errno();
const char *message= new_stmt_da.message();
const char *sqlstate= new_stmt_da.get_sqlstate();
/* In case of a fatal error, set it into the original DA.*/
if (thd->is_fatal_error)
{
save_stmt_da->set_error_status(sql_errno, message, sqlstate, NULL);
DBUG_RETURN(true);
}
/* Otherwise, just append the new error as a exception condition. */
save_stmt_da->push_warning(thd, sql_errno, sqlstate,
Sql_condition::WARN_LEVEL_ERROR,
message);
/* Appending might have failed. */
if (! (rv= thd->is_error()))
thd->get_stmt_da()->set_ok_status(0, 0, NULL);
DBUG_RETURN(rv);
}
/**
Set a value for this item.
@param thd The current thread.
@param value The obtained value.
@retval false on success.
@retval true on error.
*/
bool
Diagnostics_information_item::set_value(THD *thd, Item **value)
{
bool rv;
Settable_routine_parameter *srp;
DBUG_ENTER("Diagnostics_information_item::set_value");
/* Get a settable reference to the target. */
srp= m_target->get_settable_routine_parameter();
DBUG_ASSERT(srp);
/* Set variable/parameter value. */
rv= srp->set_value(thd, thd->spcont, value);
DBUG_RETURN(rv);
}
/**
Obtain statement information in the context of a given diagnostics area.
@param thd The current thread.
@param da The diagnostics area.
@retval false on success.
@retval true on error
*/
bool
Statement_information::aggregate(THD *thd, const Diagnostics_area *da)
{
bool rv= false;
Statement_information_item *stmt_info_item;
List_iterator<Statement_information_item> it(*m_items);
DBUG_ENTER("Statement_information::aggregate");
/*
Each specified target gets the value of each given
information item obtained from the diagnostics area.
*/
while ((stmt_info_item= it++))
{
if ((rv= evaluate(thd, stmt_info_item, da)))
break;
}
DBUG_RETURN(rv);
}
/**
Obtain the value of this statement information item in the context of
a given diagnostics area.
@param thd The current thread.
@param da The diagnostics area.
@retval Item representing the value.
@retval NULL on error.
*/
Item *
Statement_information_item::get_value(THD *thd, const Diagnostics_area *da)
{
Item *value= NULL;
DBUG_ENTER("Statement_information_item::get_value");
switch (m_name)
{
/*
The number of condition areas that have information. That is,
the number of errors and warnings within the diagnostics area.
*/
case NUMBER:
{
ulong count= da->cond_count();
value= new (thd->mem_root) Item_uint(count);
break;
}
/*
Number that shows how many rows were directly affected by
a data-change statement (INSERT, UPDATE, DELETE, MERGE,
REPLACE, LOAD).
*/
case ROW_COUNT:
value= new (thd->mem_root) Item_int(thd->get_row_count_func());
break;
}
DBUG_RETURN(value);
}
/**
Obtain condition information in the context of a given diagnostics area.
@param thd The current thread.
@param da The diagnostics area.
@retval false on success.
@retval true on error
*/
bool
Condition_information::aggregate(THD *thd, const Diagnostics_area *da)
{
bool rv= false;
longlong cond_number;
const Sql_condition *cond= NULL;
Condition_information_item *cond_info_item;
Diagnostics_area::Sql_condition_iterator it_conds= da->sql_conditions();
List_iterator_fast<Condition_information_item> it_items(*m_items);
DBUG_ENTER("Condition_information::aggregate");
/* Prepare the expression for evaluation. */
if (!m_cond_number_expr->fixed &&
m_cond_number_expr->fix_fields(thd, &m_cond_number_expr))
DBUG_RETURN(true);
cond_number= m_cond_number_expr->val_int();
/*
Limit to the number of available conditions. Warning_info::warn_count()
is not used because it indicates the number of condition regardless of
@@max_error_count, which prevents conditions from being pushed, but not
counted.
*/
if (cond_number < 1 || (ulonglong) cond_number > da->cond_count())
{
my_error(ER_DA_INVALID_CONDITION_NUMBER, MYF(0));
DBUG_RETURN(true);
}
/* Advance to the requested condition. */
while (cond_number--)
cond= it_conds++;
DBUG_ASSERT(cond);
/* Evaluate the requested information in the context of the condition. */
while ((cond_info_item= it_items++))
{
if ((rv= evaluate(thd, cond_info_item, cond)))
break;
}
DBUG_RETURN(rv);
}
/**
Create an UTF-8 string item to represent a condition item string.
@remark The string might not have a associated charset. For example,
this can be the case if the server does not or fails to process
the error message file.
@remark See "Design notes about Sql_condition::m_message_text." in sql_error.cc
@return Pointer to an string item, NULL on failure.
*/
Item *
Condition_information_item::make_utf8_string_item(THD *thd, const String *str)
{
/* Default is utf8 character set and utf8_general_ci collation. */
CHARSET_INFO *to_cs= &my_charset_utf8_general_ci;
/* If a charset was not set, assume that no conversion is needed. */
CHARSET_INFO *from_cs= str->charset() ? str->charset() : to_cs;
Item_string *item= new Item_string(str->ptr(), str->length(), from_cs);
/* If necessary, convert the string (ignoring errors), then copy it over. */
return item ? item->charset_converter(to_cs, false) : NULL;
}
/**
Obtain the value of this condition information item in the context of
a given condition.
@param thd The current thread.
@param da The diagnostics area.
@retval Item representing the value.
@retval NULL on error.
*/
Item *
Condition_information_item::get_value(THD *thd, const Sql_condition *cond)
{
String str;
Item *value= NULL;
DBUG_ENTER("Condition_information_item::get_value");
switch (m_name)
{
case CLASS_ORIGIN:
value= make_utf8_string_item(thd, &(cond->m_class_origin));
break;
case SUBCLASS_ORIGIN:
value= make_utf8_string_item(thd, &(cond->m_subclass_origin));
break;
case CONSTRAINT_CATALOG:
value= make_utf8_string_item(thd, &(cond->m_constraint_catalog));
break;
case CONSTRAINT_SCHEMA:
value= make_utf8_string_item(thd, &(cond->m_constraint_schema));
break;
case CONSTRAINT_NAME:
value= make_utf8_string_item(thd, &(cond->m_constraint_name));
break;
case CATALOG_NAME:
value= make_utf8_string_item(thd, &(cond->m_catalog_name));
break;
case SCHEMA_NAME:
value= make_utf8_string_item(thd, &(cond->m_schema_name));
break;
case TABLE_NAME:
value= make_utf8_string_item(thd, &(cond->m_table_name));
break;
case COLUMN_NAME:
value= make_utf8_string_item(thd, &(cond->m_column_name));
break;
case CURSOR_NAME:
value= make_utf8_string_item(thd, &(cond->m_cursor_name));
break;
case MESSAGE_TEXT:
value= make_utf8_string_item(thd, &(cond->m_message_text));
break;
case MYSQL_ERRNO:
value= new (thd->mem_root) Item_uint(cond->m_sql_errno);
break;
case RETURNED_SQLSTATE:
str.set_ascii(cond->get_sqlstate(), strlen(cond->get_sqlstate()));
value= make_utf8_string_item(thd, &str);
break;
}
DBUG_RETURN(value);
}

318
sql/sql_get_diagnostics.h Normal file
View file

@ -0,0 +1,318 @@
/* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02111-1307 USA */
#ifndef SQL_GET_DIAGNOSTICS_H
#define SQL_GET_DIAGNOSTICS_H
/** Diagnostics information forward reference. */
class Diagnostics_information;
/**
Sql_cmd_get_diagnostics represents a GET DIAGNOSTICS statement.
The GET DIAGNOSTICS statement retrieves exception or completion
condition information from a diagnostics area, usually pertaining
to the last non-diagnostic SQL statement that was executed.
*/
class Sql_cmd_get_diagnostics : public Sql_cmd
{
public:
/**
Constructor, used to represent a GET DIAGNOSTICS statement.
@param info Diagnostics information to be obtained.
*/
Sql_cmd_get_diagnostics(Diagnostics_information *info)
: m_info(info)
{}
virtual enum_sql_command sql_command_code() const
{
return SQLCOM_GET_DIAGNOSTICS;
}
virtual bool execute(THD *thd);
private:
/** The information to be obtained. */
Diagnostics_information *m_info;
};
/**
Represents the diagnostics information to be obtained.
Diagnostic information is made available through statement
information and condition information items.
*/
class Diagnostics_information : public Sql_alloc
{
public:
/**
Which diagnostics area to access.
Only CURRENT is supported for now.
*/
enum Which_area
{
/** Access the first diagnostics area. */
CURRENT_AREA
};
/** Set which diagnostics area to access. */
void set_which_da(Which_area area)
{ m_area= area; }
/** Get which diagnostics area to access. */
Which_area get_which_da(void) const
{ return m_area; }
/**
Aggregate diagnostics information.
@param thd The current thread.
@param da The diagnostics area.
@retval false on success.
@retval true on error
*/
virtual bool aggregate(THD *thd, const Diagnostics_area *da) = 0;
protected:
/**
Diagnostics_information objects are allocated in thd->mem_root.
Do not rely on the destructor for any cleanup.
*/
virtual ~Diagnostics_information()
{
DBUG_ASSERT(false);
}
/**
Evaluate a diagnostics information item in a specific context.
@param thd The current thread.
@param diag_item The diagnostics information item.
@param ctx The context to evaluate the item.
@retval false on success.
@retval true on error.
*/
template <typename Diag_item, typename Context>
bool evaluate(THD *thd, Diag_item *diag_item, Context ctx)
{
Item *value;
/* Get this item's value. */
if (! (value= diag_item->get_value(thd, ctx)))
return true;
/* Set variable/parameter value. */
return diag_item->set_value(thd, &value);
}
private:
/** Which diagnostics area to access. */
Which_area m_area;
};
/**
A diagnostics information item. Used to associate a specific
diagnostics information item to a target variable.
*/
class Diagnostics_information_item : public Sql_alloc
{
public:
/**
Set a value for this item.
@param thd The current thread.
@param value The obtained value.
@retval false on success.
@retval true on error.
*/
bool set_value(THD *thd, Item **value);
protected:
/**
Constructor, used to represent a diagnostics information item.
@param target A target that gets the value of this item.
*/
Diagnostics_information_item(Item *target)
: m_target(target)
{}
/**
Diagnostics_information_item objects are allocated in thd->mem_root.
Do not rely on the destructor for any cleanup.
*/
virtual ~Diagnostics_information_item()
{
DBUG_ASSERT(false);
}
private:
/** The target variable that will receive the value of this item. */
Item *m_target;
};
/**
A statement information item.
*/
class Statement_information_item : public Diagnostics_information_item
{
public:
/** The name of a statement information item. */
enum Name
{
NUMBER,
ROW_COUNT
};
/**
Constructor, used to represent a statement information item.
@param name The name of this item.
@param target A target that gets the value of this item.
*/
Statement_information_item(Name name, Item *target)
: Diagnostics_information_item(target), m_name(name)
{}
/** Obtain value of this statement information item. */
Item *get_value(THD *thd, const Diagnostics_area *da);
private:
/** The name of this statement information item. */
Name m_name;
};
/**
Statement information.
@remark Provides information about the execution of a statement.
*/
class Statement_information : public Diagnostics_information
{
public:
/**
Constructor, used to represent the statement information of a
GET DIAGNOSTICS statement.
@param items List of requested statement information items.
*/
Statement_information(List<Statement_information_item> *items)
: m_items(items)
{}
/** Obtain statement information in the context of a diagnostics area. */
bool aggregate(THD *thd, const Diagnostics_area *da);
private:
/* List of statement information items. */
List<Statement_information_item> *m_items;
};
/**
A condition information item.
*/
class Condition_information_item : public Diagnostics_information_item
{
public:
/**
The name of a condition information item.
*/
enum Name
{
CLASS_ORIGIN,
SUBCLASS_ORIGIN,
CONSTRAINT_CATALOG,
CONSTRAINT_SCHEMA,
CONSTRAINT_NAME,
CATALOG_NAME,
SCHEMA_NAME,
TABLE_NAME,
COLUMN_NAME,
CURSOR_NAME,
MESSAGE_TEXT,
MYSQL_ERRNO,
RETURNED_SQLSTATE
};
/**
Constructor, used to represent a condition information item.
@param name The name of this item.
@param target A target that gets the value of this item.
*/
Condition_information_item(Name name, Item *target)
: Diagnostics_information_item(target), m_name(name)
{}
/** Obtain value of this condition information item. */
Item *get_value(THD *thd, const Sql_condition *cond);
private:
/** The name of this condition information item. */
Name m_name;
/** Create an string item to represent a condition item string. */
Item *make_utf8_string_item(THD *thd, const String *str);
};
/**
Condition information.
@remark Provides information about conditions raised during the
execution of a statement.
*/
class Condition_information : public Diagnostics_information
{
public:
/**
Constructor, used to represent the condition information of a
GET DIAGNOSTICS statement.
@param cond_number_expr Number that identifies the diagnostic condition.
@param items List of requested condition information items.
*/
Condition_information(Item *cond_number_expr,
List<Condition_information_item> *items)
: m_cond_number_expr(cond_number_expr), m_items(items)
{}
/** Obtain condition information in the context of a diagnostics area. */
bool aggregate(THD *thd, const Diagnostics_area *da);
private:
/**
Number that identifies the diagnostic condition for which
information is to be obtained.
*/
Item *m_cond_number_expr;
/** List of condition information items. */
List<Condition_information_item> *m_items;
};
#endif

View file

@ -171,7 +171,7 @@ static void mysql_ha_close_table(SQL_HANDLER *handler)
table->file->ha_index_or_rnd_end();
table->open_by_handler= 0;
(void) close_thread_table(thd, &table);
close_thread_table(thd, &table);
thd->mdl_context.release_lock(handler->mdl_request.ticket);
}
else
@ -501,9 +501,9 @@ public:
bool handle_condition(THD *thd,
uint sql_errno,
const char *sqlstate,
MYSQL_ERROR::enum_warning_level level,
Sql_condition::enum_warning_level level,
const char* msg,
MYSQL_ERROR **cond_hdl);
Sql_condition **cond_hdl);
bool need_reopen() const { return m_need_reopen; };
void init() { m_need_reopen= FALSE; };
@ -522,9 +522,9 @@ Sql_handler_lock_error_handler::
handle_condition(THD *thd,
uint sql_errno,
const char *sqlstate,
MYSQL_ERROR::enum_warning_level level,
Sql_condition::enum_warning_level level,
const char* msg,
MYSQL_ERROR **cond_hdl)
Sql_condition **cond_hdl)
{
*cond_hdl= NULL;
if (sql_errno == ER_LOCK_ABORTED)
@ -639,9 +639,10 @@ mysql_ha_fix_cond_and_key(SQL_HANDLER *handler,
key_part_map keypart_map;
uint key_len;
if (key_expr->elements > keyinfo->key_parts)
if (key_expr->elements > keyinfo->user_defined_key_parts)
{
my_error(ER_TOO_MANY_KEY_PARTS, MYF(0), keyinfo->key_parts);
my_error(ER_TOO_MANY_KEY_PARTS, MYF(0),
keyinfo->user_defined_key_parts);
return 1;
}
for (keypart_map= key_len=0 ; (item=it_ke++) ; key_part++)

View file

@ -963,7 +963,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
error=write_record(thd, table ,&info);
if (error)
break;
thd->warning_info->inc_current_row_for_warning();
thd->get_stmt_da()->inc_current_row_for_warning();
}
free_underlaid_joins(thd, &thd->lex->select_lex);
@ -1120,11 +1120,11 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
sprintf(buff, ER(ER_INSERT_INFO), (ulong) info.records,
(lock_type == TL_WRITE_DELAYED) ? (ulong) 0 :
(ulong) (info.records - info.copied),
(ulong) thd->warning_info->statement_warn_count());
(long) thd->get_stmt_da()->current_statement_warn_count());
else
sprintf(buff, ER(ER_INSERT_INFO), (ulong) info.records,
(ulong) (info.deleted + updated),
(ulong) thd->warning_info->statement_warn_count());
(long) thd->get_stmt_da()->current_statement_warn_count());
::my_ok(thd, info.copied + info.deleted + updated, id, buff);
}
thd->abort_on_warning= 0;
@ -1209,7 +1209,7 @@ static bool check_view_insertability(THD * thd, TABLE_LIST *view)
}
Item_field *field;
/* simple SELECT list entry (field without expression) */
if (!(field= trans->item->filed_for_view_update()))
if (!(field= trans->item->field_for_view_update()))
{
thd->mark_used_columns= save_mark_used_columns;
DBUG_RETURN(TRUE);
@ -1645,7 +1645,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
}
}
key_copy((uchar*) key,table->record[0],table->key_info+key_nr,0);
key_part_map keypart_map= (1 << table->key_info[key_nr].key_parts) - 1;
key_part_map keypart_map= (1 << table->key_info[key_nr].user_defined_key_parts) - 1;
if ((error= (table->file->ha_index_read_idx_map(table->record[1],
key_nr, (uchar*) key,
keypart_map,
@ -1894,7 +1894,7 @@ int check_that_all_fields_are_given_values(THD *thd, TABLE *entry,
}
if (view)
{
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_NO_DEFAULT_FOR_VIEW_FIELD,
ER(ER_NO_DEFAULT_FOR_VIEW_FIELD),
table_list->view_db.str,
@ -1902,7 +1902,7 @@ int check_that_all_fields_are_given_values(THD *thd, TABLE *entry,
}
else
{
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_NO_DEFAULT_FOR_FIELD,
ER(ER_NO_DEFAULT_FOR_FIELD),
(*field)->field_name);
@ -2253,7 +2253,8 @@ bool delayed_get_table(THD *thd, MDL_request *grl_protection_request,
want to send "Server shutdown in progress" in the
INSERT THREAD.
*/
my_message(di->thd.stmt_da->sql_errno(), di->thd.stmt_da->message(),
my_message(di->thd.get_stmt_da()->sql_errno(),
di->thd.get_stmt_da()->message(),
MYF(0));
}
di->unlock();
@ -2343,7 +2344,8 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd)
if (!thd.is_error())
my_message(ER_QUERY_INTERRUPTED, ER(ER_QUERY_INTERRUPTED), MYF(0));
else
my_message(thd.stmt_da->sql_errno(), thd.stmt_da->message(), MYF(0));
my_message(thd.get_stmt_da()->sql_errno(),
thd.get_stmt_da()->message(), MYF(0));
goto error;
}
}
@ -2765,8 +2767,7 @@ pthread_handler_t handle_delayed_insert(void *arg)
if (my_thread_init())
{
/* Can't use my_error since store_globals has not yet been called */
thd->stmt_da->set_error_status(thd, ER_OUT_OF_RESOURCES,
ER(ER_OUT_OF_RESOURCES), NULL);
thd->get_stmt_da()->set_error_status(ER_OUT_OF_RESOURCES);
di->handler_thread_initialized= TRUE;
}
else
@ -2776,8 +2777,7 @@ pthread_handler_t handle_delayed_insert(void *arg)
if (init_thr_lock() || thd->store_globals())
{
/* Can't use my_error since store_globals has perhaps failed */
thd->stmt_da->set_error_status(thd, ER_OUT_OF_RESOURCES,
ER(ER_OUT_OF_RESOURCES), NULL);
thd->get_stmt_da()->set_error_status(ER_OUT_OF_RESOURCES);
di->handler_thread_initialized= TRUE;
thd->fatal_error();
goto err;
@ -3167,7 +3167,7 @@ bool Delayed_insert::handle_inserts(void)
{
/* This should never happen */
table->file->print_error(error,MYF(0));
sql_print_error("%s", thd.stmt_da->message());
sql_print_error("%s", thd.get_stmt_da()->message());
DBUG_PRINT("error", ("HA_EXTRA_NO_CACHE failed in loop"));
goto err;
}
@ -3213,7 +3213,7 @@ bool Delayed_insert::handle_inserts(void)
if ((error=table->file->extra(HA_EXTRA_NO_CACHE)))
{ // This shouldn't happen
table->file->print_error(error,MYF(0));
sql_print_error("%s", thd.stmt_da->message());
sql_print_error("%s", thd.get_stmt_da()->message());
DBUG_PRINT("error", ("HA_EXTRA_NO_CACHE failed after loop"));
goto err;
}
@ -3644,7 +3644,7 @@ bool select_insert::send_eof()
error= (thd->locked_tables_mode <= LTM_LOCK_TABLES ?
table->file->ha_end_bulk_insert() : 0);
if (!error && thd->is_error())
error= thd->stmt_da->sql_errno();
error= thd->get_stmt_da()->sql_errno();
table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
@ -3697,11 +3697,11 @@ bool select_insert::send_eof()
if (info.ignore)
sprintf(buff, ER(ER_INSERT_INFO), (ulong) info.records,
(ulong) (info.records - info.copied),
(ulong) thd->warning_info->statement_warn_count());
(long) thd->get_stmt_da()->current_statement_warn_count());
else
sprintf(buff, ER(ER_INSERT_INFO), (ulong) info.records,
(ulong) (info.deleted+info.updated),
(ulong) thd->warning_info->statement_warn_count());
(long) thd->get_stmt_da()->current_statement_warn_count());
row_count= info.copied + info.deleted +
((thd->client_capabilities & CLIENT_FOUND_ROWS) ?
info.touched : info.updated);
@ -3891,8 +3891,8 @@ static TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
{
if (!mysql_create_table_no_lock(thd, create_table->db,
create_table->table_name,
create_info, alter_info, 0,
select_field_count, NULL))
create_info, alter_info, NULL,
select_field_count))
{
DEBUG_SYNC(thd,"create_table_select_before_open");
@ -3905,7 +3905,7 @@ static TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
*/
if (open_table(thd, create_table, thd->mem_root, &ot_ctx))
{
quick_rm_table(create_info->db_type, create_table->db,
quick_rm_table(thd, create_info->db_type, create_table->db,
table_case_name(create_info, create_table->table_name),
0);
}

View file

@ -494,12 +494,13 @@ void lex_start(THD *thd)
lex->select_lex.ftfunc_list= &lex->select_lex.ftfunc_list_alloc;
lex->select_lex.group_list.empty();
lex->select_lex.order_list.empty();
lex->m_sql_cmd= NULL;
lex->duplicates= DUP_ERROR;
lex->ignore= 0;
lex->spname= NULL;
lex->sphead= NULL;
lex->spcont= NULL;
lex->m_stmt= NULL;
lex->m_sql_cmd= NULL;
lex->proc_list.first= 0;
lex->escape_used= FALSE;
lex->query_tables= 0;
@ -1746,50 +1747,6 @@ int lex_one_token(void *arg, void *yythd)
}
/**
Construct a copy of this object to be used for mysql_alter_table
and mysql_create_table.
Historically, these two functions modify their Alter_info
arguments. This behaviour breaks re-execution of prepared
statements and stored procedures and is compensated by always
supplying a copy of Alter_info to these functions.
@return You need to use check the error in THD for out
of memory condition after calling this function.
*/
Alter_info::Alter_info(const Alter_info &rhs, MEM_ROOT *mem_root)
:drop_list(rhs.drop_list, mem_root),
alter_list(rhs.alter_list, mem_root),
key_list(rhs.key_list, mem_root),
create_list(rhs.create_list, mem_root),
flags(rhs.flags),
keys_onoff(rhs.keys_onoff),
tablespace_op(rhs.tablespace_op),
partition_names(rhs.partition_names, mem_root),
num_parts(rhs.num_parts),
change_level(rhs.change_level),
datetime_field(rhs.datetime_field),
error_if_not_empty(rhs.error_if_not_empty)
{
/*
Make deep copies of used objects.
This is not a fully deep copy - clone() implementations
of Alter_drop, Alter_column, Key, foreign_key, Key_part_spec
do not copy string constants. At the same length the only
reason we make a copy currently is that ALTER/CREATE TABLE
code changes input Alter_info definitions, but string
constants never change.
*/
list_copy_and_replace_each_value(drop_list, mem_root);
list_copy_and_replace_each_value(alter_list, mem_root);
list_copy_and_replace_each_value(key_list, mem_root);
list_copy_and_replace_each_value(create_list, mem_root);
/* partition_names are not deeply copied currently */
}
void trim_whitespace(CHARSET_INFO *cs, LEX_STRING *str)
{
/*
@ -2195,12 +2152,13 @@ bool st_select_lex_node::inc_in_sum_expr() { return 1; }
uint st_select_lex_node::get_in_sum_expr() { return 0; }
TABLE_LIST* st_select_lex_node::get_table_list() { return 0; }
List<Item>* st_select_lex_node::get_item_list() { return 0; }
TABLE_LIST *st_select_lex_node::add_table_to_list (THD *thd, Table_ident *table,
TABLE_LIST *st_select_lex_node::add_table_to_list(THD *thd, Table_ident *table,
LEX_STRING *alias,
ulong table_join_options,
thr_lock_type flags,
enum_mdl_type mdl_type,
List<Index_hint> *hints,
List<String> *partition_names,
LEX_STRING *option)
{
return 0;
@ -4299,8 +4257,8 @@ int st_select_lex_unit::print_explain(select_result_sink *output,
bool LEX::is_partition_management() const
{
return (sql_command == SQLCOM_ALTER_TABLE &&
(alter_info.flags == ALTER_ADD_PARTITION ||
alter_info.flags == ALTER_REORGANIZE_PARTITION));
(alter_info.flags == Alter_info::ALTER_ADD_PARTITION ||
alter_info.flags == Alter_info::ALTER_REORGANIZE_PARTITION));
}
#ifdef MYSQL_SERVER

View file

@ -44,9 +44,6 @@ class Event_parse_data;
class set_var_base;
class sys_var;
class Item_func_match;
class Alter_drop;
class Alter_column;
class Key;
class File_parser;
class Key_part_spec;
@ -117,6 +114,7 @@ struct sys_var_with_base
#include "lex_symbol.h"
#if MYSQL_LEX
#include "item_func.h" /* Cast_target used in sql_yacc.h */
#include "sql_get_diagnostics.h" /* Types used in sql_yacc.h */
#include "sql_yacc.h"
#define LEX_YYSTYPE YYSTYPE *
#else
@ -257,11 +255,6 @@ enum olap_type
UNSPECIFIED_OLAP_TYPE, CUBE_TYPE, ROLLUP_TYPE
};
enum tablespace_op_type
{
NO_TABLESPACE_OP, DISCARD_TABLESPACE, IMPORT_TABLESPACE
};
/*
String names used to print a statement with index hints.
Keep in sync with index_hint_type.
@ -505,6 +498,7 @@ public:
thr_lock_type flags= TL_UNLOCK,
enum_mdl_type mdl_type= MDL_SHARED_READ,
List<Index_hint> *hints= 0,
List<String> *partition_names= 0,
LEX_STRING *option= 0);
virtual void set_lock_for_tables(thr_lock_type lock_type) {}
@ -861,6 +855,7 @@ public:
thr_lock_type flags= TL_UNLOCK,
enum_mdl_type mdl_type= MDL_SHARED_READ,
List<Index_hint> *hints= 0,
List<String> *partition_names= 0,
LEX_STRING *option= 0);
TABLE_LIST* get_table_list();
bool init_nested_join(THD *thd);
@ -1074,7 +1069,38 @@ public:
Sroutine_hash_entry **sroutines_list_own_last;
uint sroutines_list_own_elements;
/*
/**
Locking state of tables in this particular statement.
If we under LOCK TABLES or in prelocked mode we consider tables
for the statement to be "locked" if there was a call to lock_tables()
(which called handler::start_stmt()) for tables of this statement
and there was no matching close_thread_tables() call.
As result this state may differ significantly from one represented
by Open_tables_state::lock/locked_tables_mode more, which are always
"on" under LOCK TABLES or in prelocked mode.
*/
enum enum_lock_tables_state {
LTS_NOT_LOCKED = 0,
LTS_LOCKED
};
enum_lock_tables_state lock_tables_state;
bool is_query_tables_locked()
{
return (lock_tables_state == LTS_LOCKED);
}
/**
Number of tables which were open by open_tables() and to be locked
by lock_tables().
Note that we set this member only in some cases, when this value
needs to be passed from open_tables() to lock_tables() which are
separated by some amount of code.
*/
uint table_count;
/*
These constructor and destructor serve for creation/destruction
of Query_tables_list instances which are used as backup storage.
*/
@ -2274,7 +2300,7 @@ struct LEX: public Query_tables_list
*/
nesting_map allow_sum_func;
Sql_statement *m_stmt;
Sql_cmd *m_sql_cmd;
/*
Usually `expr` rule of yacc is quite reused but some commands better
@ -2331,6 +2357,7 @@ struct LEX: public Query_tables_list
uint8 create_view_check;
uint8 context_analysis_only;
bool drop_if_exists, drop_temporary, local_file, one_shot_set;
bool check_exists;
bool autocommit;
bool verbose, no_write_to_binlog;

View file

@ -218,7 +218,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
!field_term->is_ascii() ||
!ex->line_term->is_ascii() || !ex->line_start->is_ascii())
{
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning(thd, Sql_condition::WARN_LEVEL_WARN,
WARN_NON_ASCII_SEPARATOR_NOT_IMPLEMENTED,
ER(WARN_NON_ASCII_SEPARATOR_NOT_IMPLEMENTED));
}
@ -588,7 +588,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
}
sprintf(name, ER(ER_LOAD_INFO), (ulong) info.records, (ulong) info.deleted,
(ulong) (info.records - info.copied),
(ulong) thd->warning_info->statement_warn_count());
(long) thd->get_stmt_da()->current_statement_warn_count());
if (thd->transaction.stmt.modified_non_trans_table)
thd->transaction.all.modified_non_trans_table= TRUE;
@ -829,10 +829,10 @@ read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
if (pos == read_info.row_end)
{
thd->cuted_fields++; /* Not enough fields */
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_WARN_TOO_FEW_RECORDS,
ER(ER_WARN_TOO_FEW_RECORDS),
thd->warning_info->current_row_for_warning());
thd->get_stmt_da()->current_row_for_warning());
/*
Timestamp fields that are NOT NULL are autoupdated if there is no
corresponding value in the data file.
@ -859,10 +859,10 @@ read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
if (pos != read_info.row_end)
{
thd->cuted_fields++; /* To long row */
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_WARN_TOO_MANY_RECORDS,
ER(ER_WARN_TOO_MANY_RECORDS),
thd->warning_info->current_row_for_warning());
thd->get_stmt_da()->current_row_for_warning());
}
if (thd->killed ||
@ -895,12 +895,12 @@ read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
if (read_info.line_cuted)
{
thd->cuted_fields++; /* To long row */
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_WARN_TOO_MANY_RECORDS,
ER(ER_WARN_TOO_MANY_RECORDS),
thd->warning_info->current_row_for_warning());
thd->get_stmt_da()->current_row_for_warning());
}
thd->warning_info->inc_current_row_for_warning();
thd->get_stmt_da()->inc_current_row_for_warning();
continue_loop:;
}
DBUG_RETURN(test(read_info.error));
@ -980,7 +980,7 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
if (field->reset())
{
my_error(ER_WARN_NULL_TO_NOTNULL, MYF(0), field->field_name,
thd->warning_info->current_row_for_warning());
thd->get_stmt_da()->current_row_for_warning());
DBUG_RETURN(1);
}
field->set_null();
@ -993,7 +993,7 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
if (field->type() == MYSQL_TYPE_TIMESTAMP)
field->set_time();
else if (field != table->next_number_field)
field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
field->set_warning(Sql_condition::WARN_LEVEL_WARN,
ER_WARN_NULL_TO_NOTNULL, 1);
}
/* Do not auto-update this field. */
@ -1059,7 +1059,7 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
if (field->reset())
{
my_error(ER_WARN_NULL_TO_NOTNULL, MYF(0),field->field_name,
thd->warning_info->current_row_for_warning());
thd->get_stmt_da()->current_row_for_warning());
DBUG_RETURN(1);
}
if (!field->maybe_null() && field->type() == FIELD_TYPE_TIMESTAMP)
@ -1072,10 +1072,10 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
in the end ?)
*/
thd->cuted_fields++;
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_WARN_TOO_FEW_RECORDS,
ER(ER_WARN_TOO_FEW_RECORDS),
thd->warning_info->current_row_for_warning());
thd->get_stmt_da()->current_row_for_warning());
}
else if (item->type() == Item::STRING_ITEM)
{
@ -1119,13 +1119,13 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
if (read_info.line_cuted)
{
thd->cuted_fields++; /* To long row */
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_WARN_TOO_MANY_RECORDS, ER(ER_WARN_TOO_MANY_RECORDS),
thd->warning_info->current_row_for_warning());
thd->get_stmt_da()->current_row_for_warning());
if (thd->killed)
DBUG_RETURN(1);
}
thd->warning_info->inc_current_row_for_warning();
thd->get_stmt_da()->inc_current_row_for_warning();
continue_loop:;
}
DBUG_RETURN(test(read_info.error));
@ -1206,7 +1206,7 @@ read_xml_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
if (field->type() == FIELD_TYPE_TIMESTAMP)
field->set_time();
else if (field != table->next_number_field)
field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
field->set_warning(Sql_condition::WARN_LEVEL_WARN,
ER_WARN_NULL_TO_NOTNULL, 1);
}
/* Do not auto-update this field. */
@ -1259,10 +1259,10 @@ read_xml_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
in the end ?)
*/
thd->cuted_fields++;
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_WARN_TOO_FEW_RECORDS,
ER(ER_WARN_TOO_FEW_RECORDS),
thd->warning_info->current_row_for_warning());
thd->get_stmt_da()->current_row_for_warning());
}
else
((Item_user_var_as_out_param *)item)->set_null_value(cs);
@ -1293,7 +1293,7 @@ read_xml_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
its default value at the beginning of each loop iteration.
*/
thd->transaction.stmt.modified_non_trans_table= no_trans_update_stmt;
thd->warning_info->inc_current_row_for_warning();
thd->get_stmt_da()->inc_current_row_for_warning();
continue_loop:;
}
DBUG_RETURN(test(read_info.error) || thd->is_error());

View file

@ -3422,7 +3422,7 @@ MY_LOCALE *my_locale_by_name(const char *name)
if (thd)
{
// Send a warning to the client
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_WARN_DEPRECATED_SYNTAX, ER(ER_WARN_DEPRECATED_SYNTAX),
name, locale->name);
}

Some files were not shown because too many files have changed in this diff Show more