mirror of
https://github.com/MariaDB/server.git
synced 2025-01-28 17:54:16 +01:00
Temporary commit of merge of MariaDB 10.0-base and MySQL 5.6
This commit is contained in:
parent
5a86a61219
commit
1d0f70c2f8
557 changed files with 124450 additions and 30236 deletions
|
@ -800,14 +800,32 @@ static void print_line(char* line)
|
|||
static int run_sql_fix_privilege_tables(void)
|
||||
{
|
||||
int found_real_errors= 0;
|
||||
const char **query_ptr;
|
||||
DYNAMIC_STRING ds_script;
|
||||
DYNAMIC_STRING ds_result;
|
||||
DBUG_ENTER("run_sql_fix_privilege_tables");
|
||||
|
||||
if (init_dynamic_string(&ds_script, "", 65536, 1024))
|
||||
die("Out of memory");
|
||||
|
||||
if (init_dynamic_string(&ds_result, "", 512, 512))
|
||||
die("Out of memory");
|
||||
|
||||
verbose("Phase 3/3: Running 'mysql_fix_privilege_tables'...");
|
||||
run_query(mysql_fix_privilege_tables,
|
||||
/*
|
||||
Individual queries can not be executed independently by invoking
|
||||
a forked mysql client, because the script uses session variables
|
||||
and prepared statements.
|
||||
*/
|
||||
for ( query_ptr= &mysql_fix_privilege_tables[0];
|
||||
*query_ptr != NULL;
|
||||
query_ptr++
|
||||
)
|
||||
{
|
||||
dynstr_append(&ds_script, *query_ptr);
|
||||
}
|
||||
|
||||
run_query(ds_script.str,
|
||||
&ds_result, /* Collect result */
|
||||
TRUE);
|
||||
|
||||
|
@ -835,6 +853,7 @@ static int run_sql_fix_privilege_tables(void)
|
|||
}
|
||||
|
||||
dynstr_free(&ds_result);
|
||||
dynstr_free(&ds_script);
|
||||
DBUG_RETURN(found_real_errors);
|
||||
}
|
||||
|
||||
|
|
|
@ -67,14 +67,7 @@ IF(CMAKE_COMPILER_IS_GNUCXX)
|
|||
# MySQL "canonical" GCC flags. At least -fno-rtti flag affects
|
||||
# ABI and cannot be simply removed.
|
||||
SET(CMAKE_CXX_FLAGS
|
||||
"${CMAKE_CXX_FLAGS} -fno-implicit-templates -fno-exceptions -fno-rtti")
|
||||
IF(CMAKE_CXX_FLAGS)
|
||||
STRING(REGEX MATCH "fno-implicit-templates" NO_IMPLICIT_TEMPLATES
|
||||
${CMAKE_CXX_FLAGS})
|
||||
IF (NO_IMPLICIT_TEMPLATES)
|
||||
SET(HAVE_EXPLICIT_TEMPLATE_INSTANTIATION TRUE)
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
"${CMAKE_CXX_FLAGS} -fno-exceptions -fno-rtti")
|
||||
|
||||
IF (CMAKE_EXE_LINKER_FLAGS MATCHES " -static "
|
||||
OR CMAKE_EXE_LINKER_FLAGS MATCHES " -static$")
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
#ifndef _global_h
|
||||
#define _global_h
|
||||
#define MY_GLOBAL_INCLUDED
|
||||
|
||||
/* Client library users on Windows need this macro defined here. */
|
||||
#if !defined(__WIN__) && defined(_WIN32)
|
||||
|
@ -1438,6 +1439,8 @@ static inline char *dlerror(void)
|
|||
#define max(a, b) ((a) > (b) ? (a) : (b))
|
||||
#define min(a, b) ((a) < (b) ? (a) : (b))
|
||||
#endif
|
||||
#define MY_MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||
#define MY_MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||
|
||||
#define CMP_NUM(a,b) (((a) < (b)) ? -1 : ((a) == (b)) ? 0 : 1)
|
||||
|
||||
|
|
|
@ -22,6 +22,36 @@
|
|||
* $FreeBSD: src/contrib/cvs/lib/md5.h,v 1.2 1999/12/11 15:10:02 peter Exp $
|
||||
*/
|
||||
|
||||
#if defined(HAVE_YASSL) || defined(HAVE_OPENSSL)
|
||||
/*
|
||||
Use MD5 implementation provided by the SSL libraries.
|
||||
*/
|
||||
|
||||
#if defined(HAVE_YASSL)
|
||||
|
||||
C_MODE_START
|
||||
|
||||
void my_md5_hash(char *digest, const char *buf, int len);
|
||||
|
||||
C_MODE_END
|
||||
|
||||
#else /* HAVE_YASSL */
|
||||
|
||||
#include <openssl/md5.h>
|
||||
|
||||
#define MY_MD5_HASH(digest, buf, len) \
|
||||
do { \
|
||||
MD5_CTX ctx; \
|
||||
MD5_Init (&ctx); \
|
||||
MD5_Update (&ctx, buf, len); \
|
||||
MD5_Final (digest, &ctx); \
|
||||
} while (0)
|
||||
|
||||
#endif /* HAVE_YASSL */
|
||||
|
||||
#else /* HAVE_YASSL || HAVE_OPENSSL */
|
||||
/* Fallback to the MySQL's implementation. */
|
||||
|
||||
/* Unlike previous versions of this code, uint32 need not be exactly
|
||||
32 bits, merely 32 bits or more. Choosing a data type which is 32
|
||||
bits instead of 64 is not important; speed is considerably more
|
||||
|
@ -35,18 +65,15 @@ typedef struct {
|
|||
unsigned char in[64];
|
||||
} my_MD5Context;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
C_MODE_START
|
||||
|
||||
void my_MD5Init (my_MD5Context *context);
|
||||
void my_MD5Update (my_MD5Context *context,
|
||||
unsigned char const *buf, unsigned len);
|
||||
void my_MD5Final (unsigned char digest[16],
|
||||
my_MD5Context *context);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
C_MODE_END
|
||||
|
||||
#define MY_MD5_HASH(digest,buf,len) \
|
||||
do { \
|
||||
|
@ -56,4 +83,12 @@ do { \
|
|||
my_MD5Final (digest, &ctx); \
|
||||
} while (0)
|
||||
|
||||
#endif /* MY_MD__INCLUDED */
|
||||
#endif /* defined(HAVE_YASSL) || defined(HAVE_OPENSSL) */
|
||||
|
||||
C_MODE_START
|
||||
|
||||
void compute_md5_hash(char *digest, const char *buf, int len);
|
||||
|
||||
C_MODE_END
|
||||
|
||||
#endif /* MY_MD5_INCLUDED */
|
||||
|
|
|
@ -498,13 +498,22 @@ void safe_mutex_free_deadlock_data(safe_mutex_t *mp);
|
|||
DBUG_ASSERT(! (mp)->count || \
|
||||
! pthread_equal(pthread_self(), (mp)->thread))
|
||||
#define safe_mutex_setflags(mp, F) do { (mp)->create_flags|= (F); } while (0)
|
||||
#define my_cond_timedwait(A,B,C) safe_cond_timedwait((A),(B),(C),__FILE__,__LINE__)
|
||||
#define my_cond_wait(A,B) safe_cond_wait((A), (B), __FILE__, __LINE__)
|
||||
#else
|
||||
#define my_pthread_mutex_init(A,B,C,D) pthread_mutex_init((A),(B))
|
||||
#define safe_mutex_assert_owner(mp) do {} while(0)
|
||||
#define safe_mutex_assert_not_owner(mp) do {} while(0)
|
||||
#define safe_mutex_free_deadlock_data(mp) do {} while(0)
|
||||
|
||||
#define safe_mutex_assert_owner(mp) do {} while (0)
|
||||
#define safe_mutex_assert_not_owner(mp) do {} while (0)
|
||||
#define safe_mutex_setflags(mp, F) do {} while (0)
|
||||
#endif /* SAFE_MUTEX */
|
||||
|
||||
#if defined(MY_PTHREAD_FASTMUTEX)
|
||||
#define my_cond_timedwait(A,B,C) pthread_cond_timedwait((A), &(B)->mutex, (C))
|
||||
#define my_cond_wait(A,B) pthread_cond_wait((A), &(B)->mutex)
|
||||
#else
|
||||
#define my_cond_timedwait(A,B,C) pthread_cond_timedwait((A),(B),(C))
|
||||
#define my_cond_wait(A,B) pthread_cond_wait((A), (B))
|
||||
#endif /* MY_PTHREAD_FASTMUTEX */
|
||||
#endif /* !SAFE_MUTEX */
|
||||
|
||||
#if defined(MY_PTHREAD_FASTMUTEX) && !defined(SAFE_MUTEX)
|
||||
typedef struct st_my_pthread_fastmutex_t
|
||||
|
|
|
@ -252,7 +252,9 @@ extern const char *my_defaults_extra_file;
|
|||
extern const char *my_defaults_group_suffix;
|
||||
extern const char *my_defaults_file;
|
||||
|
||||
#ifndef timed_mutexes
|
||||
extern my_bool timed_mutexes;
|
||||
#endif
|
||||
|
||||
enum loglevel {
|
||||
ERROR_LEVEL,
|
||||
|
@ -772,16 +774,17 @@ extern my_bool init_dynamic_array2(DYNAMIC_ARRAY *array, uint element_size,
|
|||
/* init_dynamic_array() function is deprecated */
|
||||
extern my_bool init_dynamic_array(DYNAMIC_ARRAY *array, uint element_size,
|
||||
uint init_alloc, uint alloc_increment);
|
||||
extern my_bool insert_dynamic(DYNAMIC_ARRAY *array, const uchar * element);
|
||||
extern uchar *alloc_dynamic(DYNAMIC_ARRAY *array);
|
||||
extern uchar *pop_dynamic(DYNAMIC_ARRAY*);
|
||||
extern my_bool set_dynamic(DYNAMIC_ARRAY *array,uchar * element,uint array_index);
|
||||
extern my_bool insert_dynamic(DYNAMIC_ARRAY *array, const void* element);
|
||||
extern void *alloc_dynamic(DYNAMIC_ARRAY *array);
|
||||
extern void *pop_dynamic(DYNAMIC_ARRAY*);
|
||||
extern my_bool set_dynamic(DYNAMIC_ARRAY *array, const void *element,
|
||||
uint array_index);
|
||||
extern my_bool allocate_dynamic(DYNAMIC_ARRAY *array, uint max_elements);
|
||||
extern void get_dynamic(DYNAMIC_ARRAY *array,uchar * element,uint array_index);
|
||||
extern void get_dynamic(DYNAMIC_ARRAY *array, void *element, uint array_index);
|
||||
extern void delete_dynamic(DYNAMIC_ARRAY *array);
|
||||
extern void delete_dynamic_element(DYNAMIC_ARRAY *array, uint array_index);
|
||||
extern void freeze_size(DYNAMIC_ARRAY *array);
|
||||
extern int get_index_dynamic(DYNAMIC_ARRAY *array, uchar * element);
|
||||
extern int get_index_dynamic(DYNAMIC_ARRAY *array, void *element);
|
||||
#define dynamic_array_ptr(array,array_index) ((array)->buffer+(array_index)*(array)->size_of_element)
|
||||
#define dynamic_element(array,array_index,type) ((type)((array)->buffer) +(array_index))
|
||||
#define push_dynamic(A,B) insert_dynamic((A),(B))
|
||||
|
|
|
@ -37,9 +37,9 @@
|
|||
#endif /* HAVE_VALGRIND */
|
||||
|
||||
#ifndef DBUG_OFF
|
||||
#define TRASH_FILL(A,B,C) do { bfill(A, B, C); MEM_UNDEFINED(A, B); } while (0)
|
||||
#define TRASH_FILL(A,B,C) do { const size_t trash_tmp= (B) ; bfill(A, trash_tmp, C); MEM_UNDEFINED(A, trash_tmp); } while (0)
|
||||
#else
|
||||
#define TRASH_FILL(A,B,C) do{ MEM_CHECK_ADDRESSABLE(A,B);MEM_UNDEFINED(A,B);} while (0)
|
||||
#define TRASH_FILL(A,B,C) do{ const size_t trash_tmp= (B) ; MEM_CHECK_ADDRESSABLE(A,trash_tmp);MEM_UNDEFINED(A,trash_tmp);} while (0)
|
||||
#endif
|
||||
#define TRASH_ALLOC(A,B) TRASH_FILL(A,B,0xA5)
|
||||
#define TRASH_FREE(A,B) TRASH_FILL(A,B,0x8F)
|
||||
|
|
File diff suppressed because it is too large
Load diff
92
include/mysql/psi/mysql_idle.h
Normal file
92
include/mysql/psi/mysql_idle.h
Normal file
|
@ -0,0 +1,92 @@
|
|||
/* 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,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
|
||||
|
||||
#ifndef MYSQL_IDLE_H
|
||||
#define MYSQL_IDLE_H
|
||||
|
||||
/**
|
||||
@file mysql/psi/mysql_idle.h
|
||||
Instrumentation helpers for idle waits.
|
||||
*/
|
||||
|
||||
#include "mysql/psi/psi.h"
|
||||
|
||||
/**
|
||||
@defgroup Idle_instrumentation Idle Instrumentation
|
||||
@ingroup Instrumentation_interface
|
||||
@{
|
||||
*/
|
||||
|
||||
/**
|
||||
@def MYSQL_START_IDLE_WAIT
|
||||
Instrumentation helper for table io_waits.
|
||||
This instrumentation marks the start of a wait event.
|
||||
@param LOCKER the locker
|
||||
@param STATE the locker state
|
||||
@sa MYSQL_END_IDLE_WAIT.
|
||||
*/
|
||||
#ifdef HAVE_PSI_IDLE_INTERFACE
|
||||
#define MYSQL_START_IDLE_WAIT(LOCKER, STATE) \
|
||||
LOCKER= inline_mysql_start_idle_wait(STATE, __FILE__, __LINE__)
|
||||
#else
|
||||
#define MYSQL_START_IDLE_WAIT(LOCKER, STATE) \
|
||||
do {} while (0)
|
||||
#endif
|
||||
|
||||
/**
|
||||
@def MYSQL_END_IDLE_WAIT
|
||||
Instrumentation helper for idle waits.
|
||||
This instrumentation marks the end of a wait event.
|
||||
@param LOCKER the locker
|
||||
@sa MYSQL_START_IDLE_WAIT.
|
||||
*/
|
||||
#ifdef HAVE_PSI_IDLE_INTERFACE
|
||||
#define MYSQL_END_IDLE_WAIT(LOCKER) \
|
||||
inline_mysql_end_idle_wait(LOCKER)
|
||||
#else
|
||||
#define MYSQL_END_IDLE_WAIT(LOCKER) \
|
||||
do {} while (0)
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_PSI_IDLE_INTERFACE
|
||||
/**
|
||||
Instrumentation calls for MYSQL_START_IDLE_WAIT.
|
||||
@sa MYSQL_END_IDLE_WAIT.
|
||||
*/
|
||||
static inline struct PSI_idle_locker *
|
||||
inline_mysql_start_idle_wait(PSI_idle_locker_state *state,
|
||||
const char *src_file, int src_line)
|
||||
{
|
||||
struct PSI_idle_locker *locker;
|
||||
locker= PSI_CALL(start_idle_wait)(state, src_file, src_line);
|
||||
return locker;
|
||||
}
|
||||
|
||||
/**
|
||||
Instrumentation calls for MYSQL_END_IDLE_WAIT.
|
||||
@sa MYSQL_START_IDLE_WAIT.
|
||||
*/
|
||||
static inline void
|
||||
inline_mysql_end_idle_wait(struct PSI_idle_locker *locker)
|
||||
{
|
||||
if (likely(locker != NULL))
|
||||
PSI_CALL(end_idle_wait)(locker);
|
||||
}
|
||||
#endif
|
||||
|
||||
/** @} (end of group Idle_instrumentation) */
|
||||
|
||||
#endif
|
||||
|
1137
include/mysql/psi/mysql_socket.h
Normal file
1137
include/mysql/psi/mysql_socket.h
Normal file
File diff suppressed because it is too large
Load diff
72
include/mysql/psi/mysql_stage.h
Normal file
72
include/mysql/psi/mysql_stage.h
Normal file
|
@ -0,0 +1,72 @@
|
|||
/* Copyright (c) 2010, 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 02110-1301 USA */
|
||||
|
||||
#ifndef MYSQL_STAGE_H
|
||||
#define MYSQL_STAGE_H
|
||||
|
||||
/**
|
||||
@file mysql/psi/mysql_stage.h
|
||||
Instrumentation helpers for stages.
|
||||
*/
|
||||
|
||||
#include "mysql/psi/psi.h"
|
||||
|
||||
/**
|
||||
@defgroup Stage_instrumentation Stage Instrumentation
|
||||
@ingroup Instrumentation_interface
|
||||
@{
|
||||
*/
|
||||
|
||||
/**
|
||||
@def mysql_stage_register(P1, P2, P3)
|
||||
Stage registration.
|
||||
*/
|
||||
#ifdef HAVE_PSI_STAGE_INTERFACE
|
||||
#define mysql_stage_register(P1, P2, P3) \
|
||||
inline_mysql_stage_register(P1, P2, P3)
|
||||
#else
|
||||
#define mysql_stage_register(P1, P2, P3) \
|
||||
do {} while (0)
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_PSI_STAGE_INTERFACE
|
||||
#define MYSQL_SET_STAGE(K, F, L) \
|
||||
inline_mysql_set_stage(K, F, L)
|
||||
#else
|
||||
#define MYSQL_SET_STAGE(K, F, L) \
|
||||
do {} while (0)
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_PSI_STAGE_INTERFACE
|
||||
static inline void inline_mysql_stage_register(
|
||||
const char *category, PSI_stage_info **info, int count)
|
||||
{
|
||||
PSI_CALL(register_stage)(category, info, count);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_PSI_STAGE_INTERFACE
|
||||
static inline void
|
||||
inline_mysql_set_stage(PSI_stage_key key,
|
||||
const char *src_file, int src_line)
|
||||
{
|
||||
PSI_CALL(start_stage)(key, src_file, src_line);
|
||||
}
|
||||
#endif
|
||||
|
||||
/** @} (end of group Stage_instrumentation) */
|
||||
|
||||
#endif
|
||||
|
229
include/mysql/psi/mysql_statement.h
Normal file
229
include/mysql/psi/mysql_statement.h
Normal file
|
@ -0,0 +1,229 @@
|
|||
/* Copyright (c) 2010, 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 02110-1301 USA */
|
||||
|
||||
#ifndef MYSQL_STATEMENT_H
|
||||
#define MYSQL_STATEMENT_H
|
||||
|
||||
/**
|
||||
@file mysql/psi/mysql_statement.h
|
||||
Instrumentation helpers for statements.
|
||||
*/
|
||||
|
||||
#include "mysql/psi/psi.h"
|
||||
|
||||
/**
|
||||
@defgroup Statement_instrumentation Statement Instrumentation
|
||||
@ingroup Instrumentation_interface
|
||||
@{
|
||||
*/
|
||||
|
||||
/**
|
||||
@def mysql_statement_register(P1, P2, P3)
|
||||
Statement registration.
|
||||
*/
|
||||
#ifdef HAVE_PSI_STATEMENT_INTERFACE
|
||||
#define mysql_statement_register(P1, P2, P3) \
|
||||
inline_mysql_statement_register(P1, P2, P3)
|
||||
#else
|
||||
#define mysql_statement_register(P1, P2, P3) \
|
||||
do {} while (0)
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_PSI_STATEMENT_INTERFACE
|
||||
#ifdef HAVE_PSI_STATEMENT_DIGEST_INTERFACE
|
||||
#define MYSQL_DIGEST_START(LOCKER) \
|
||||
inline_mysql_digest_start(LOCKER)
|
||||
#else
|
||||
#define MYSQL_DIGEST_START(LOCKER) \
|
||||
NULL
|
||||
#endif
|
||||
#else
|
||||
#define MYSQL_DIGEST_START(LOCKER) \
|
||||
NULL
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_PSI_STATEMENT_DIGEST_INTERFACE
|
||||
#define MYSQL_ADD_TOKEN(LOCKER, T, Y) \
|
||||
inline_mysql_add_token(LOCKER, T, Y)
|
||||
#else
|
||||
#define MYSQL_ADD_TOKEN(LOCKER, T, Y) \
|
||||
NULL
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_PSI_STATEMENT_INTERFACE
|
||||
#define MYSQL_START_STATEMENT(STATE, K, DB, DB_LEN) \
|
||||
inline_mysql_start_statement(STATE, K, DB, DB_LEN, __FILE__, __LINE__)
|
||||
#else
|
||||
#define MYSQL_START_STATEMENT(STATE, K, DB, DB_LEN) \
|
||||
NULL
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_PSI_STATEMENT_INTERFACE
|
||||
#define MYSQL_REFINE_STATEMENT(LOCKER, K) \
|
||||
inline_mysql_refine_statement(LOCKER, K)
|
||||
#else
|
||||
#define MYSQL_REFINE_STATEMENT(LOCKER, K) \
|
||||
NULL
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_PSI_STATEMENT_INTERFACE
|
||||
#define MYSQL_SET_STATEMENT_TEXT(LOCKER, P1, P2) \
|
||||
inline_mysql_set_statement_text(LOCKER, P1, P2)
|
||||
#else
|
||||
#define MYSQL_SET_STATEMENT_TEXT(LOCKER, P1, P2) \
|
||||
do {} while (0)
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_PSI_STATEMENT_INTERFACE
|
||||
#define MYSQL_SET_STATEMENT_LOCK_TIME(LOCKER, P1) \
|
||||
inline_mysql_set_statement_lock_time(LOCKER, P1)
|
||||
#else
|
||||
#define MYSQL_SET_STATEMENT_LOCK_TIME(LOCKER, P1) \
|
||||
do {} while (0)
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_PSI_STATEMENT_INTERFACE
|
||||
#define MYSQL_SET_STATEMENT_ROWS_SENT(LOCKER, P1) \
|
||||
inline_mysql_set_statement_rows_sent(LOCKER, P1)
|
||||
#else
|
||||
#define MYSQL_SET_STATEMENT_ROWS_SENT(LOCKER, P1) \
|
||||
do {} while (0)
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_PSI_STATEMENT_INTERFACE
|
||||
#define MYSQL_SET_STATEMENT_ROWS_EXAMINED(LOCKER, P1) \
|
||||
inline_mysql_set_statement_rows_examined(LOCKER, P1)
|
||||
#else
|
||||
#define MYSQL_SET_STATEMENT_ROWS_EXAMINED(LOCKER, P1) \
|
||||
do {} while (0)
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_PSI_STATEMENT_INTERFACE
|
||||
#define MYSQL_END_STATEMENT(LOCKER, DA) \
|
||||
inline_mysql_end_statement(LOCKER, DA)
|
||||
#else
|
||||
#define MYSQL_END_STATEMENT(LOCKER, DA) \
|
||||
do {} while (0)
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_PSI_STATEMENT_INTERFACE
|
||||
static inline void inline_mysql_statement_register(
|
||||
const char *category, PSI_statement_info *info, int count)
|
||||
{
|
||||
PSI_CALL(register_statement)(category, info, count);
|
||||
}
|
||||
|
||||
#ifdef HAVE_PSI_STATEMENT_DIGEST_INTERFACE
|
||||
static inline struct PSI_digest_locker *
|
||||
inline_mysql_digest_start(PSI_statement_locker *locker)
|
||||
{
|
||||
PSI_digest_locker* digest_locker= NULL;
|
||||
|
||||
if (likely(locker != NULL))
|
||||
digest_locker= PSI_CALL(digest_start)(locker);
|
||||
return digest_locker;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_PSI_STATEMENT_DIGEST_INTERFACE
|
||||
static inline struct PSI_digest_locker *
|
||||
inline_mysql_add_token(PSI_digest_locker *locker, uint token,
|
||||
void *yylval)
|
||||
{
|
||||
if (likely(locker != NULL))
|
||||
locker= PSI_CALL(digest_add_token)(locker, token,
|
||||
(OPAQUE_LEX_YYSTYPE*)yylval);
|
||||
return locker;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline struct PSI_statement_locker *
|
||||
inline_mysql_start_statement(PSI_statement_locker_state *state,
|
||||
PSI_statement_key key,
|
||||
const char *db, uint db_len,
|
||||
const char *src_file, int src_line)
|
||||
{
|
||||
PSI_statement_locker *locker;
|
||||
locker= PSI_CALL(get_thread_statement_locker)(state, key);
|
||||
if (likely(locker != NULL))
|
||||
PSI_CALL(start_statement)(locker, db, db_len, src_file, src_line);
|
||||
return locker;
|
||||
}
|
||||
|
||||
static inline struct PSI_statement_locker *
|
||||
inline_mysql_refine_statement(PSI_statement_locker *locker,
|
||||
PSI_statement_key key)
|
||||
{
|
||||
if (likely(locker != NULL))
|
||||
{
|
||||
locker= PSI_CALL(refine_statement)(locker, key);
|
||||
}
|
||||
return locker;
|
||||
}
|
||||
|
||||
static inline void
|
||||
inline_mysql_set_statement_text(PSI_statement_locker *locker,
|
||||
const char *text, uint text_len)
|
||||
{
|
||||
if (likely(locker != NULL))
|
||||
{
|
||||
PSI_CALL(set_statement_text)(locker, text, text_len);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
inline_mysql_set_statement_lock_time(PSI_statement_locker *locker,
|
||||
ulonglong count)
|
||||
{
|
||||
if (likely(locker != NULL))
|
||||
{
|
||||
PSI_CALL(set_statement_lock_time)(locker, count);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
inline_mysql_set_statement_rows_sent(PSI_statement_locker *locker,
|
||||
ulonglong count)
|
||||
{
|
||||
if (likely(locker != NULL))
|
||||
{
|
||||
PSI_CALL(set_statement_rows_sent)(locker, count);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
inline_mysql_set_statement_rows_examined(PSI_statement_locker *locker,
|
||||
ulonglong count)
|
||||
{
|
||||
if (likely(locker != NULL))
|
||||
{
|
||||
PSI_CALL(set_statement_rows_examined)(locker, count);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
inline_mysql_end_statement(struct PSI_statement_locker *locker,
|
||||
Diagnostics_area *stmt_da)
|
||||
{
|
||||
PSI_CALL(end_stage)();
|
||||
if (likely(locker != NULL))
|
||||
PSI_CALL(end_statement)(locker, stmt_da);
|
||||
}
|
||||
#endif
|
||||
|
||||
/** @} (end of group Statement_instrumentation) */
|
||||
|
||||
#endif
|
||||
|
188
include/mysql/psi/mysql_table.h
Normal file
188
include/mysql/psi/mysql_table.h
Normal file
|
@ -0,0 +1,188 @@
|
|||
/* Copyright (c) 2010, 2012, 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,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
|
||||
|
||||
#ifndef MYSQL_TABLE_H
|
||||
#define MYSQL_TABLE_H
|
||||
|
||||
/**
|
||||
@file mysql/psi/mysql_table.h
|
||||
Instrumentation helpers for table io.
|
||||
*/
|
||||
|
||||
#include "mysql/psi/psi.h"
|
||||
|
||||
/**
|
||||
@defgroup Table_instrumentation Table Instrumentation
|
||||
@ingroup Instrumentation_interface
|
||||
@{
|
||||
*/
|
||||
|
||||
/**
|
||||
@def MYSQL_TABLE_WAIT_VARIABLES
|
||||
Instrumentation helper for table waits.
|
||||
This instrumentation declares local variables.
|
||||
Do not use a ';' after this macro
|
||||
@param LOCKER the locker
|
||||
@param STATE the locker state
|
||||
@sa MYSQL_START_TABLE_IO_WAIT.
|
||||
@sa MYSQL_END_TABLE_IO_WAIT.
|
||||
@sa MYSQL_START_TABLE_LOCK_WAIT.
|
||||
@sa MYSQL_END_TABLE_LOCK_WAIT.
|
||||
*/
|
||||
#ifdef HAVE_PSI_TABLE_INTERFACE
|
||||
#define MYSQL_TABLE_WAIT_VARIABLES(LOCKER, STATE) \
|
||||
struct PSI_table_locker* LOCKER; \
|
||||
PSI_table_locker_state STATE;
|
||||
#else
|
||||
#define MYSQL_TABLE_WAIT_VARIABLES(LOCKER, STATE)
|
||||
#endif
|
||||
|
||||
/**
|
||||
@def MYSQL_TABLE_IO_WAIT
|
||||
Instrumentation helper for table io_waits.
|
||||
This instrumentation marks the start of a wait event.
|
||||
@param PSI the instrumented table
|
||||
@param OP the table operation to be performed
|
||||
@param INDEX the table index used if any, or MAY_KEY.
|
||||
@param FLAGS per table operation flags.
|
||||
@sa MYSQL_END_TABLE_WAIT.
|
||||
*/
|
||||
#ifdef HAVE_PSI_TABLE_INTERFACE
|
||||
#define MYSQL_TABLE_IO_WAIT(PSI, OP, INDEX, FLAGS, PAYLOAD) \
|
||||
{ \
|
||||
if (PSI != NULL) \
|
||||
{ \
|
||||
PSI_table_locker *locker; \
|
||||
PSI_table_locker_state state; \
|
||||
locker= PSI_CALL(start_table_io_wait)(& state, PSI, OP, INDEX, \
|
||||
__FILE__, __LINE__); \
|
||||
PAYLOAD \
|
||||
if (locker != NULL) \
|
||||
PSI_CALL(end_table_io_wait)(locker); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
PAYLOAD \
|
||||
} \
|
||||
}
|
||||
#else
|
||||
#define MYSQL_TABLE_IO_WAIT(PSI, OP, INDEX, FLAGS, PAYLOAD) \
|
||||
PAYLOAD
|
||||
#endif
|
||||
|
||||
/**
|
||||
@def MYSQL_TABLE_LOCK_WAIT
|
||||
Instrumentation helper for table io_waits.
|
||||
This instrumentation marks the start of a wait event.
|
||||
@param PSI the instrumented table
|
||||
@param OP the table operation to be performed
|
||||
@param INDEX the table index used if any, or MAY_KEY.
|
||||
@param FLAGS per table operation flags.
|
||||
@sa MYSQL_END_TABLE_WAIT.
|
||||
*/
|
||||
#ifdef HAVE_PSI_TABLE_INTERFACE
|
||||
#define MYSQL_TABLE_LOCK_WAIT(PSI, OP, FLAGS, PAYLOAD) \
|
||||
{ \
|
||||
if (PSI != NULL) \
|
||||
{ \
|
||||
PSI_table_locker *locker; \
|
||||
PSI_table_locker_state state; \
|
||||
locker= PSI_CALL(start_table_lock_wait)(& state, PSI, OP, FLAGS, \
|
||||
__FILE__, __LINE__); \
|
||||
PAYLOAD \
|
||||
if (locker != NULL) \
|
||||
PSI_CALL(end_table_lock_wait)(locker); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
PAYLOAD \
|
||||
} \
|
||||
}
|
||||
#else
|
||||
#define MYSQL_TABLE_LOCK_WAIT(PSI, OP, FLAGS, PAYLOAD) \
|
||||
PAYLOAD
|
||||
#endif
|
||||
|
||||
/**
|
||||
@def MYSQL_START_TABLE_LOCK_WAIT
|
||||
Instrumentation helper for table lock waits.
|
||||
This instrumentation marks the start of a wait event.
|
||||
@param LOCKER the locker
|
||||
@param STATE the locker state
|
||||
@param PSI the instrumented table
|
||||
@param OP the table operation to be performed
|
||||
@param FLAGS per table operation flags.
|
||||
@sa MYSQL_END_TABLE_LOCK_WAIT.
|
||||
*/
|
||||
#ifdef HAVE_PSI_TABLE_INTERFACE
|
||||
#define MYSQL_START_TABLE_LOCK_WAIT(LOCKER, STATE, PSI, OP, FLAGS) \
|
||||
LOCKER= inline_mysql_start_table_lock_wait(STATE, PSI, \
|
||||
OP, FLAGS, __FILE__, __LINE__)
|
||||
#else
|
||||
#define MYSQL_START_TABLE_LOCK_WAIT(LOCKER, STATE, PSI, OP, FLAGS) \
|
||||
do {} while (0)
|
||||
#endif
|
||||
|
||||
/**
|
||||
@def MYSQL_END_TABLE_LOCK_WAIT
|
||||
Instrumentation helper for table lock waits.
|
||||
This instrumentation marks the end of a wait event.
|
||||
@param LOCKER the locker
|
||||
@sa MYSQL_START_TABLE_LOCK_WAIT.
|
||||
*/
|
||||
#ifdef HAVE_PSI_TABLE_INTERFACE
|
||||
#define MYSQL_END_TABLE_LOCK_WAIT(LOCKER) \
|
||||
inline_mysql_end_table_lock_wait(LOCKER)
|
||||
#else
|
||||
#define MYSQL_END_TABLE_LOCK_WAIT(LOCKER) \
|
||||
do {} while (0)
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_PSI_TABLE_INTERFACE
|
||||
/**
|
||||
Instrumentation calls for MYSQL_START_TABLE_LOCK_WAIT.
|
||||
@sa MYSQL_END_TABLE_LOCK_WAIT.
|
||||
*/
|
||||
static inline struct PSI_table_locker *
|
||||
inline_mysql_start_table_lock_wait(PSI_table_locker_state *state,
|
||||
struct PSI_table *psi,
|
||||
enum PSI_table_lock_operation op,
|
||||
ulong flags, const char *src_file, int src_line)
|
||||
{
|
||||
if (psi != NULL)
|
||||
{
|
||||
struct PSI_table_locker *locker;
|
||||
locker= PSI_CALL(start_table_lock_wait)(state, psi, op, flags, src_file, src_line);
|
||||
return locker;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
Instrumentation calls for MYSQL_END_TABLE_LOCK_WAIT.
|
||||
@sa MYSQL_START_TABLE_LOCK_WAIT.
|
||||
*/
|
||||
static inline void
|
||||
inline_mysql_end_table_lock_wait(struct PSI_table_locker *locker)
|
||||
{
|
||||
if (locker != NULL)
|
||||
PSI_CALL(end_table_lock_wait)(locker);
|
||||
}
|
||||
#endif
|
||||
|
||||
/** @} (end of group Table_instrumentation) */
|
||||
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
24
include/mysql/psi/psi_abi_v0.h
Normal file
24
include/mysql/psi/psi_abi_v0.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
/* 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,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
|
||||
|
||||
/**
|
||||
@file mysql/psi/psi_abi_v0.h
|
||||
ABI check for mysql/psi/psi.h, when compiling without instrumentation.
|
||||
This file is only used to automate detection of changes between versions.
|
||||
Do not include this file, include mysql/psi/psi.h instead.
|
||||
*/
|
||||
#define _global_h
|
||||
#include "mysql/psi/psi.h"
|
||||
|
47
include/mysql/psi/psi_abi_v0.h.pp
Normal file
47
include/mysql/psi/psi_abi_v0.h.pp
Normal file
|
@ -0,0 +1,47 @@
|
|||
#include "mysql/psi/psi.h"
|
||||
C_MODE_START
|
||||
struct TABLE_SHARE;
|
||||
struct OPAQUE_LEX_YYSTYPE;
|
||||
struct PSI_mutex;
|
||||
typedef struct PSI_mutex PSI_mutex;
|
||||
struct PSI_rwlock;
|
||||
typedef struct PSI_rwlock PSI_rwlock;
|
||||
struct PSI_cond;
|
||||
typedef struct PSI_cond PSI_cond;
|
||||
struct PSI_table_share;
|
||||
typedef struct PSI_table_share PSI_table_share;
|
||||
struct PSI_table;
|
||||
typedef struct PSI_table PSI_table;
|
||||
struct PSI_thread;
|
||||
typedef struct PSI_thread PSI_thread;
|
||||
struct PSI_file;
|
||||
typedef struct PSI_file PSI_file;
|
||||
struct PSI_socket;
|
||||
typedef struct PSI_socket PSI_socket;
|
||||
struct PSI_table_locker;
|
||||
typedef struct PSI_table_locker PSI_table_locker;
|
||||
struct PSI_statement_locker;
|
||||
typedef struct PSI_statement_locker PSI_statement_locker;
|
||||
struct PSI_idle_locker;
|
||||
typedef struct PSI_idle_locker PSI_idle_locker;
|
||||
struct PSI_digest_locker;
|
||||
typedef struct PSI_digest_locker PSI_digest_locker;
|
||||
struct PSI_bootstrap
|
||||
{
|
||||
void* (*get_interface)(int version);
|
||||
};
|
||||
typedef struct PSI_bootstrap PSI_bootstrap;
|
||||
struct PSI_none
|
||||
{
|
||||
int opaque;
|
||||
};
|
||||
typedef struct PSI_none PSI;
|
||||
struct PSI_stage_info_none
|
||||
{
|
||||
unsigned int m_key;
|
||||
const char *m_name;
|
||||
int m_flags;
|
||||
};
|
||||
typedef struct PSI_stage_info_none PSI_stage_info;
|
||||
extern MYSQL_PLUGIN_IMPORT PSI *PSI_server;
|
||||
C_MODE_END
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
/* Copyright (c) 2008, 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
|
||||
|
@ -21,6 +21,6 @@
|
|||
*/
|
||||
#define USE_PSI_1
|
||||
#define HAVE_PSI_INTERFACE
|
||||
#define _global_h
|
||||
#define MY_GLOBAL_INCLUDED
|
||||
#include "mysql/psi/psi.h"
|
||||
|
||||
|
|
|
@ -1,25 +1,52 @@
|
|||
#include "mysql/psi/psi.h"
|
||||
C_MODE_START
|
||||
struct TABLE_SHARE;
|
||||
struct OPAQUE_LEX_YYSTYPE;
|
||||
struct PSI_mutex;
|
||||
typedef struct PSI_mutex PSI_mutex;
|
||||
struct PSI_rwlock;
|
||||
typedef struct PSI_rwlock PSI_rwlock;
|
||||
struct PSI_cond;
|
||||
typedef struct PSI_cond PSI_cond;
|
||||
struct PSI_table_share;
|
||||
typedef struct PSI_table_share PSI_table_share;
|
||||
struct PSI_table;
|
||||
typedef struct PSI_table PSI_table;
|
||||
struct PSI_thread;
|
||||
typedef struct PSI_thread PSI_thread;
|
||||
struct PSI_file;
|
||||
typedef struct PSI_file PSI_file;
|
||||
struct PSI_socket;
|
||||
typedef struct PSI_socket PSI_socket;
|
||||
struct PSI_table_locker;
|
||||
typedef struct PSI_table_locker PSI_table_locker;
|
||||
struct PSI_statement_locker;
|
||||
typedef struct PSI_statement_locker PSI_statement_locker;
|
||||
struct PSI_idle_locker;
|
||||
typedef struct PSI_idle_locker PSI_idle_locker;
|
||||
struct PSI_digest_locker;
|
||||
typedef struct PSI_digest_locker PSI_digest_locker;
|
||||
struct PSI_bootstrap
|
||||
{
|
||||
void* (*get_interface)(int version);
|
||||
};
|
||||
typedef struct PSI_bootstrap PSI_bootstrap;
|
||||
struct PSI_mutex_locker;
|
||||
typedef struct PSI_mutex_locker PSI_mutex_locker;
|
||||
struct PSI_rwlock_locker;
|
||||
typedef struct PSI_rwlock_locker PSI_rwlock_locker;
|
||||
struct PSI_cond_locker;
|
||||
typedef struct PSI_cond_locker PSI_cond_locker;
|
||||
struct PSI_file_locker;
|
||||
typedef struct PSI_file_locker PSI_file_locker;
|
||||
struct PSI_socket_locker;
|
||||
typedef struct PSI_socket_locker PSI_socket_locker;
|
||||
enum PSI_mutex_operation
|
||||
{
|
||||
PSI_MUTEX_LOCK= 0,
|
||||
PSI_MUTEX_TRYLOCK= 1
|
||||
};
|
||||
typedef enum PSI_mutex_operation PSI_mutex_operation;
|
||||
enum PSI_rwlock_operation
|
||||
{
|
||||
PSI_RWLOCK_READLOCK= 0,
|
||||
|
@ -27,11 +54,13 @@ enum PSI_rwlock_operation
|
|||
PSI_RWLOCK_TRYREADLOCK= 2,
|
||||
PSI_RWLOCK_TRYWRITELOCK= 3
|
||||
};
|
||||
typedef enum PSI_rwlock_operation PSI_rwlock_operation;
|
||||
enum PSI_cond_operation
|
||||
{
|
||||
PSI_COND_WAIT= 0,
|
||||
PSI_COND_TIMEDWAIT= 1
|
||||
};
|
||||
typedef enum PSI_cond_operation PSI_cond_operation;
|
||||
enum PSI_file_operation
|
||||
{
|
||||
PSI_FILE_CREATE= 0,
|
||||
|
@ -52,12 +81,54 @@ enum PSI_file_operation
|
|||
PSI_FILE_RENAME= 15,
|
||||
PSI_FILE_SYNC= 16
|
||||
};
|
||||
struct PSI_table_locker;
|
||||
typedef enum PSI_file_operation PSI_file_operation;
|
||||
enum PSI_table_io_operation
|
||||
{
|
||||
PSI_TABLE_FETCH_ROW= 0,
|
||||
PSI_TABLE_WRITE_ROW= 1,
|
||||
PSI_TABLE_UPDATE_ROW= 2,
|
||||
PSI_TABLE_DELETE_ROW= 3
|
||||
};
|
||||
typedef enum PSI_table_io_operation PSI_table_io_operation;
|
||||
enum PSI_table_lock_operation
|
||||
{
|
||||
PSI_TABLE_LOCK= 0,
|
||||
PSI_TABLE_EXTERNAL_LOCK= 1
|
||||
};
|
||||
typedef enum PSI_table_lock_operation PSI_table_lock_operation;
|
||||
enum PSI_socket_state
|
||||
{
|
||||
PSI_SOCKET_STATE_IDLE= 1,
|
||||
PSI_SOCKET_STATE_ACTIVE= 2
|
||||
};
|
||||
typedef enum PSI_socket_state PSI_socket_state;
|
||||
enum PSI_socket_operation
|
||||
{
|
||||
PSI_SOCKET_CREATE= 0,
|
||||
PSI_SOCKET_CONNECT= 1,
|
||||
PSI_SOCKET_BIND= 2,
|
||||
PSI_SOCKET_CLOSE= 3,
|
||||
PSI_SOCKET_SEND= 4,
|
||||
PSI_SOCKET_RECV= 5,
|
||||
PSI_SOCKET_SENDTO= 6,
|
||||
PSI_SOCKET_RECVFROM= 7,
|
||||
PSI_SOCKET_SENDMSG= 8,
|
||||
PSI_SOCKET_RECVMSG= 9,
|
||||
PSI_SOCKET_SEEK= 10,
|
||||
PSI_SOCKET_OPT= 11,
|
||||
PSI_SOCKET_STAT= 12,
|
||||
PSI_SOCKET_SHUTDOWN= 13,
|
||||
PSI_SOCKET_SELECT= 14
|
||||
};
|
||||
typedef enum PSI_socket_operation PSI_socket_operation;
|
||||
typedef unsigned int PSI_mutex_key;
|
||||
typedef unsigned int PSI_rwlock_key;
|
||||
typedef unsigned int PSI_cond_key;
|
||||
typedef unsigned int PSI_thread_key;
|
||||
typedef unsigned int PSI_file_key;
|
||||
typedef unsigned int PSI_stage_key;
|
||||
typedef unsigned int PSI_statement_key;
|
||||
typedef unsigned int PSI_socket_key;
|
||||
struct PSI_mutex_info_v1
|
||||
{
|
||||
PSI_mutex_key *m_key;
|
||||
|
@ -88,67 +159,135 @@ struct PSI_file_info_v1
|
|||
const char *m_name;
|
||||
int m_flags;
|
||||
};
|
||||
struct PSI_stage_info_v1
|
||||
{
|
||||
PSI_stage_key m_key;
|
||||
const char *m_name;
|
||||
int m_flags;
|
||||
};
|
||||
struct PSI_statement_info_v1
|
||||
{
|
||||
PSI_statement_key m_key;
|
||||
const char *m_name;
|
||||
int m_flags;
|
||||
};
|
||||
struct PSI_socket_info_v1
|
||||
{
|
||||
PSI_socket_key *m_key;
|
||||
const char *m_name;
|
||||
int m_flags;
|
||||
};
|
||||
struct PSI_idle_locker_state_v1
|
||||
{
|
||||
uint m_flags;
|
||||
struct PSI_thread *m_thread;
|
||||
ulonglong m_timer_start;
|
||||
ulonglong (*m_timer)(void);
|
||||
void *m_wait;
|
||||
};
|
||||
struct PSI_mutex_locker_state_v1
|
||||
{
|
||||
uint m_flags;
|
||||
enum PSI_mutex_operation m_operation;
|
||||
struct PSI_mutex *m_mutex;
|
||||
struct PSI_thread *m_thread;
|
||||
ulonglong m_timer_start;
|
||||
ulonglong (*m_timer)(void);
|
||||
enum PSI_mutex_operation m_operation;
|
||||
const char* m_src_file;
|
||||
int m_src_line;
|
||||
void *m_wait;
|
||||
};
|
||||
struct PSI_rwlock_locker_state_v1
|
||||
{
|
||||
uint m_flags;
|
||||
enum PSI_rwlock_operation m_operation;
|
||||
struct PSI_rwlock *m_rwlock;
|
||||
struct PSI_thread *m_thread;
|
||||
ulonglong m_timer_start;
|
||||
ulonglong (*m_timer)(void);
|
||||
enum PSI_rwlock_operation m_operation;
|
||||
const char* m_src_file;
|
||||
int m_src_line;
|
||||
void *m_wait;
|
||||
};
|
||||
struct PSI_cond_locker_state_v1
|
||||
{
|
||||
uint m_flags;
|
||||
enum PSI_cond_operation m_operation;
|
||||
struct PSI_cond *m_cond;
|
||||
struct PSI_mutex *m_mutex;
|
||||
struct PSI_thread *m_thread;
|
||||
ulonglong m_timer_start;
|
||||
ulonglong (*m_timer)(void);
|
||||
enum PSI_cond_operation m_operation;
|
||||
const char* m_src_file;
|
||||
int m_src_line;
|
||||
void *m_wait;
|
||||
};
|
||||
struct PSI_file_locker_state_v1
|
||||
{
|
||||
uint m_flags;
|
||||
enum PSI_file_operation m_operation;
|
||||
struct PSI_file *m_file;
|
||||
struct PSI_thread *m_thread;
|
||||
size_t m_number_of_bytes;
|
||||
ulonglong m_timer_start;
|
||||
ulonglong (*m_timer)(void);
|
||||
enum PSI_file_operation m_operation;
|
||||
const char* m_src_file;
|
||||
int m_src_line;
|
||||
void *m_wait;
|
||||
};
|
||||
struct PSI_table_locker_state_v1
|
||||
{
|
||||
uint m_flags;
|
||||
enum PSI_table_io_operation m_io_operation;
|
||||
struct PSI_table *m_table;
|
||||
struct PSI_table_share *m_table_share;
|
||||
struct PSI_thread *m_thread;
|
||||
ulonglong m_timer_start;
|
||||
ulonglong (*m_timer)(void);
|
||||
void *m_wait;
|
||||
uint m_index;
|
||||
};
|
||||
struct PSI_digest_storage
|
||||
{
|
||||
my_bool m_full;
|
||||
int m_byte_count;
|
||||
unsigned char m_token_array[1024];
|
||||
};
|
||||
typedef struct PSI_digest_storage PSI_digest_storage;
|
||||
struct PSI_digest_locker_state
|
||||
{
|
||||
int m_last_id_index;
|
||||
PSI_digest_storage m_digest_storage;
|
||||
};
|
||||
typedef struct PSI_digest_locker_state PSI_digest_locker_state;
|
||||
struct PSI_statement_locker_state_v1
|
||||
{
|
||||
my_bool m_discarded;
|
||||
uchar m_no_index_used;
|
||||
uchar m_no_good_index_used;
|
||||
uint m_flags;
|
||||
void *m_class;
|
||||
struct PSI_thread *m_thread;
|
||||
ulonglong m_timer_start;
|
||||
ulonglong (*m_timer)(void);
|
||||
uint m_index;
|
||||
uint m_lock_index;
|
||||
void *m_statement;
|
||||
ulonglong m_lock_time;
|
||||
ulonglong m_rows_sent;
|
||||
ulonglong m_rows_examined;
|
||||
ulong m_created_tmp_disk_tables;
|
||||
ulong m_created_tmp_tables;
|
||||
ulong m_select_full_join;
|
||||
ulong m_select_full_range_join;
|
||||
ulong m_select_range;
|
||||
ulong m_select_range_check;
|
||||
ulong m_select_scan;
|
||||
ulong m_sort_merge_passes;
|
||||
ulong m_sort_range;
|
||||
ulong m_sort_rows;
|
||||
ulong m_sort_scan;
|
||||
PSI_digest_locker_state m_digest_state;
|
||||
};
|
||||
struct PSI_socket_locker_state_v1
|
||||
{
|
||||
uint m_flags;
|
||||
struct PSI_socket *m_socket;
|
||||
struct PSI_thread *m_thread;
|
||||
size_t m_number_of_bytes;
|
||||
ulonglong m_timer_start;
|
||||
ulonglong (*m_timer)(void);
|
||||
enum PSI_socket_operation m_operation;
|
||||
const char* m_src_file;
|
||||
int m_src_line;
|
||||
void *m_wait;
|
||||
|
@ -163,6 +302,12 @@ typedef void (*register_thread_v1_t)
|
|||
(const char *category, struct PSI_thread_info_v1 *info, int count);
|
||||
typedef void (*register_file_v1_t)
|
||||
(const char *category, struct PSI_file_info_v1 *info, int count);
|
||||
typedef void (*register_stage_v1_t)
|
||||
(const char *category, struct PSI_stage_info_v1 **info, int count);
|
||||
typedef void (*register_statement_v1_t)
|
||||
(const char *category, struct PSI_statement_info_v1 *info, int count);
|
||||
typedef void (*register_socket_v1_t)
|
||||
(const char *category, struct PSI_socket_info_v1 *info, int count);
|
||||
typedef struct PSI_mutex* (*init_mutex_v1_t)
|
||||
(PSI_mutex_key key, const void *identity);
|
||||
typedef void (*destroy_mutex_v1_t)(struct PSI_mutex *mutex);
|
||||
|
@ -172,12 +317,21 @@ typedef void (*destroy_rwlock_v1_t)(struct PSI_rwlock *rwlock);
|
|||
typedef struct PSI_cond* (*init_cond_v1_t)
|
||||
(PSI_cond_key key, const void *identity);
|
||||
typedef void (*destroy_cond_v1_t)(struct PSI_cond *cond);
|
||||
typedef struct PSI_socket* (*init_socket_v1_t)
|
||||
(PSI_socket_key key, const my_socket *fd);
|
||||
typedef void (*destroy_socket_v1_t)(struct PSI_socket *socket);
|
||||
typedef struct PSI_table_share* (*get_table_share_v1_t)
|
||||
(const char *schema_name, int schema_name_length, const char *table_name,
|
||||
int table_name_length, const void *identity);
|
||||
(my_bool temporary, struct TABLE_SHARE *share);
|
||||
typedef void (*release_table_share_v1_t)(struct PSI_table_share *share);
|
||||
typedef void (*drop_table_share_v1_t)
|
||||
(my_bool temporary, const char *schema_name, int schema_name_length,
|
||||
const char *table_name, int table_name_length);
|
||||
typedef struct PSI_table* (*open_table_v1_t)
|
||||
(struct PSI_table_share *share, const void *identity);
|
||||
typedef void (*unbind_table_v1_t)
|
||||
(struct PSI_table *table);
|
||||
typedef PSI_table* (*rebind_table_v1_t)
|
||||
(PSI_table_share *share, const void *identity, PSI_table *table);
|
||||
typedef void (*close_table_v1_t)(struct PSI_table *table);
|
||||
typedef void (*create_file_v1_t)(PSI_file_key key, const char *name,
|
||||
File file);
|
||||
|
@ -190,24 +344,17 @@ typedef struct PSI_thread* (*new_thread_v1_t)
|
|||
typedef void (*set_thread_id_v1_t)(struct PSI_thread *thread,
|
||||
unsigned long id);
|
||||
typedef struct PSI_thread* (*get_thread_v1_t)(void);
|
||||
typedef void (*set_thread_user_v1_t)(const char *user, int user_len);
|
||||
typedef void (*set_thread_user_host_v1_t)(const char *user, int user_len,
|
||||
const char *host, int host_len);
|
||||
typedef void (*set_thread_db_v1_t)(const char* db, int db_len);
|
||||
typedef void (*set_thread_command_v1_t)(int command);
|
||||
typedef void (*set_thread_start_time_v1_t)(time_t start_time);
|
||||
typedef void (*set_thread_state_v1_t)(const char* state);
|
||||
typedef void (*set_thread_info_v1_t)(const char* info, int info_len);
|
||||
typedef void (*set_thread_v1_t)(struct PSI_thread *thread);
|
||||
typedef void (*delete_current_thread_v1_t)(void);
|
||||
typedef void (*delete_thread_v1_t)(struct PSI_thread *thread);
|
||||
typedef struct PSI_mutex_locker* (*get_thread_mutex_locker_v1_t)
|
||||
(struct PSI_mutex_locker_state_v1 *state,
|
||||
struct PSI_mutex *mutex,
|
||||
enum PSI_mutex_operation op);
|
||||
typedef struct PSI_rwlock_locker* (*get_thread_rwlock_locker_v1_t)
|
||||
(struct PSI_rwlock_locker_state_v1 *state,
|
||||
struct PSI_rwlock *rwlock,
|
||||
enum PSI_rwlock_operation op);
|
||||
typedef struct PSI_cond_locker* (*get_thread_cond_locker_v1_t)
|
||||
(struct PSI_cond_locker_state_v1 *state,
|
||||
struct PSI_cond *cond, struct PSI_mutex *mutex,
|
||||
enum PSI_cond_operation op);
|
||||
typedef struct PSI_table_locker* (*get_thread_table_locker_v1_t)
|
||||
(struct PSI_table_locker_state_v1 *state,
|
||||
struct PSI_table *table);
|
||||
typedef struct PSI_file_locker* (*get_thread_file_name_locker_v1_t)
|
||||
(struct PSI_file_locker_state_v1 *state,
|
||||
PSI_file_key key, enum PSI_file_operation op, const char *name,
|
||||
|
@ -226,25 +373,53 @@ typedef void (*signal_cond_v1_t)
|
|||
(struct PSI_cond *cond);
|
||||
typedef void (*broadcast_cond_v1_t)
|
||||
(struct PSI_cond *cond);
|
||||
typedef void (*start_mutex_wait_v1_t)
|
||||
(struct PSI_mutex_locker *locker, const char *src_file, uint src_line);
|
||||
typedef struct PSI_idle_locker* (*start_idle_wait_v1_t)
|
||||
(struct PSI_idle_locker_state_v1 *state, const char *src_file, uint src_line);
|
||||
typedef void (*end_idle_wait_v1_t)
|
||||
(struct PSI_idle_locker *locker);
|
||||
typedef struct PSI_mutex_locker* (*start_mutex_wait_v1_t)
|
||||
(struct PSI_mutex_locker_state_v1 *state,
|
||||
struct PSI_mutex *mutex,
|
||||
enum PSI_mutex_operation op,
|
||||
const char *src_file, uint src_line);
|
||||
typedef void (*end_mutex_wait_v1_t)
|
||||
(struct PSI_mutex_locker *locker, int rc);
|
||||
typedef void (*start_rwlock_rdwait_v1_t)
|
||||
(struct PSI_rwlock_locker *locker, const char *src_file, uint src_line);
|
||||
typedef struct PSI_rwlock_locker* (*start_rwlock_rdwait_v1_t)
|
||||
(struct PSI_rwlock_locker_state_v1 *state,
|
||||
struct PSI_rwlock *rwlock,
|
||||
enum PSI_rwlock_operation op,
|
||||
const char *src_file, uint src_line);
|
||||
typedef void (*end_rwlock_rdwait_v1_t)
|
||||
(struct PSI_rwlock_locker *locker, int rc);
|
||||
typedef void (*start_rwlock_wrwait_v1_t)
|
||||
(struct PSI_rwlock_locker *locker, const char *src_file, uint src_line);
|
||||
typedef struct PSI_rwlock_locker* (*start_rwlock_wrwait_v1_t)
|
||||
(struct PSI_rwlock_locker_state_v1 *state,
|
||||
struct PSI_rwlock *rwlock,
|
||||
enum PSI_rwlock_operation op,
|
||||
const char *src_file, uint src_line);
|
||||
typedef void (*end_rwlock_wrwait_v1_t)
|
||||
(struct PSI_rwlock_locker *locker, int rc);
|
||||
typedef void (*start_cond_wait_v1_t)
|
||||
(struct PSI_cond_locker *locker, const char *src_file, uint src_line);
|
||||
typedef struct PSI_cond_locker* (*start_cond_wait_v1_t)
|
||||
(struct PSI_cond_locker_state_v1 *state,
|
||||
struct PSI_cond *cond,
|
||||
struct PSI_mutex *mutex,
|
||||
enum PSI_cond_operation op,
|
||||
const char *src_file, uint src_line);
|
||||
typedef void (*end_cond_wait_v1_t)
|
||||
(struct PSI_cond_locker *locker, int rc);
|
||||
typedef void (*start_table_wait_v1_t)
|
||||
(struct PSI_table_locker *locker, const char *src_file, uint src_line);
|
||||
typedef void (*end_table_wait_v1_t)(struct PSI_table_locker *locker);
|
||||
typedef struct PSI_table_locker* (*start_table_io_wait_v1_t)
|
||||
(struct PSI_table_locker_state_v1 *state,
|
||||
struct PSI_table *table,
|
||||
enum PSI_table_io_operation op,
|
||||
uint index,
|
||||
const char *src_file, uint src_line);
|
||||
typedef void (*end_table_io_wait_v1_t)(struct PSI_table_locker *locker);
|
||||
typedef struct PSI_table_locker* (*start_table_lock_wait_v1_t)
|
||||
(struct PSI_table_locker_state_v1 *state,
|
||||
struct PSI_table *table,
|
||||
enum PSI_table_lock_operation op,
|
||||
ulong flags,
|
||||
const char *src_file, uint src_line);
|
||||
typedef void (*end_table_lock_wait_v1_t)(struct PSI_table_locker *locker);
|
||||
typedef struct PSI_file* (*start_file_open_wait_v1_t)
|
||||
(struct PSI_file_locker *locker, const char *src_file, uint src_line);
|
||||
typedef void (*end_file_open_wait_v1_t)(struct PSI_file_locker *locker);
|
||||
|
@ -255,6 +430,75 @@ typedef void (*start_file_wait_v1_t)
|
|||
const char *src_file, uint src_line);
|
||||
typedef void (*end_file_wait_v1_t)
|
||||
(struct PSI_file_locker *locker, size_t count);
|
||||
typedef void (*start_stage_v1_t)
|
||||
(PSI_stage_key key, const char *src_file, int src_line);
|
||||
typedef void (*end_stage_v1_t) (void);
|
||||
typedef struct PSI_statement_locker* (*get_thread_statement_locker_v1_t)
|
||||
(struct PSI_statement_locker_state_v1 *state,
|
||||
PSI_statement_key key);
|
||||
typedef struct PSI_statement_locker* (*refine_statement_v1_t)
|
||||
(struct PSI_statement_locker *locker,
|
||||
PSI_statement_key key);
|
||||
typedef void (*start_statement_v1_t)
|
||||
(struct PSI_statement_locker *locker,
|
||||
const char *db, uint db_length,
|
||||
const char *src_file, uint src_line);
|
||||
typedef void (*set_statement_text_v1_t)
|
||||
(struct PSI_statement_locker *locker,
|
||||
const char *text, uint text_len);
|
||||
typedef void (*set_statement_lock_time_t)
|
||||
(struct PSI_statement_locker *locker, ulonglong lock_time);
|
||||
typedef void (*set_statement_rows_sent_t)
|
||||
(struct PSI_statement_locker *locker, ulonglong count);
|
||||
typedef void (*set_statement_rows_examined_t)
|
||||
(struct PSI_statement_locker *locker, ulonglong count);
|
||||
typedef void (*inc_statement_created_tmp_disk_tables_t)
|
||||
(struct PSI_statement_locker *locker, ulong count);
|
||||
typedef void (*inc_statement_created_tmp_tables_t)
|
||||
(struct PSI_statement_locker *locker, ulong count);
|
||||
typedef void (*inc_statement_select_full_join_t)
|
||||
(struct PSI_statement_locker *locker, ulong count);
|
||||
typedef void (*inc_statement_select_full_range_join_t)
|
||||
(struct PSI_statement_locker *locker, ulong count);
|
||||
typedef void (*inc_statement_select_range_t)
|
||||
(struct PSI_statement_locker *locker, ulong count);
|
||||
typedef void (*inc_statement_select_range_check_t)
|
||||
(struct PSI_statement_locker *locker, ulong count);
|
||||
typedef void (*inc_statement_select_scan_t)
|
||||
(struct PSI_statement_locker *locker, ulong count);
|
||||
typedef void (*inc_statement_sort_merge_passes_t)
|
||||
(struct PSI_statement_locker *locker, ulong count);
|
||||
typedef void (*inc_statement_sort_range_t)
|
||||
(struct PSI_statement_locker *locker, ulong count);
|
||||
typedef void (*inc_statement_sort_rows_t)
|
||||
(struct PSI_statement_locker *locker, ulong count);
|
||||
typedef void (*inc_statement_sort_scan_t)
|
||||
(struct PSI_statement_locker *locker, ulong count);
|
||||
typedef void (*set_statement_no_index_used_t)
|
||||
(struct PSI_statement_locker *locker);
|
||||
typedef void (*set_statement_no_good_index_used_t)
|
||||
(struct PSI_statement_locker *locker);
|
||||
typedef void (*end_statement_v1_t)
|
||||
(struct PSI_statement_locker *locker, void *stmt_da);
|
||||
typedef struct PSI_socket_locker* (*start_socket_wait_v1_t)
|
||||
(struct PSI_socket_locker_state_v1 *state,
|
||||
struct PSI_socket *socket,
|
||||
enum PSI_socket_operation op,
|
||||
size_t count,
|
||||
const char *src_file, uint src_line);
|
||||
typedef void (*end_socket_wait_v1_t)
|
||||
(struct PSI_socket_locker *locker, size_t count);
|
||||
typedef void (*set_socket_state_v1_t)(struct PSI_socket *socket,
|
||||
enum PSI_socket_state state);
|
||||
typedef void (*set_socket_info_v1_t)(struct PSI_socket *socket,
|
||||
const my_socket *fd,
|
||||
const struct sockaddr *addr,
|
||||
socklen_t addr_len);
|
||||
typedef void (*set_socket_thread_owner_v1_t)(struct PSI_socket *socket);
|
||||
typedef struct PSI_digest_locker * (*digest_start_v1_t)
|
||||
(struct PSI_statement_locker *locker);
|
||||
typedef struct PSI_digest_locker* (*digest_add_token_v1_t)
|
||||
(struct PSI_digest_locker *locker, uint token, struct OPAQUE_LEX_YYSTYPE *yylval);
|
||||
struct PSI_v1
|
||||
{
|
||||
register_mutex_v1_t register_mutex;
|
||||
|
@ -262,28 +506,39 @@ struct PSI_v1
|
|||
register_cond_v1_t register_cond;
|
||||
register_thread_v1_t register_thread;
|
||||
register_file_v1_t register_file;
|
||||
register_stage_v1_t register_stage;
|
||||
register_statement_v1_t register_statement;
|
||||
register_socket_v1_t register_socket;
|
||||
init_mutex_v1_t init_mutex;
|
||||
destroy_mutex_v1_t destroy_mutex;
|
||||
init_rwlock_v1_t init_rwlock;
|
||||
destroy_rwlock_v1_t destroy_rwlock;
|
||||
init_cond_v1_t init_cond;
|
||||
destroy_cond_v1_t destroy_cond;
|
||||
init_socket_v1_t init_socket;
|
||||
destroy_socket_v1_t destroy_socket;
|
||||
get_table_share_v1_t get_table_share;
|
||||
release_table_share_v1_t release_table_share;
|
||||
drop_table_share_v1_t drop_table_share;
|
||||
open_table_v1_t open_table;
|
||||
unbind_table_v1_t unbind_table;
|
||||
rebind_table_v1_t rebind_table;
|
||||
close_table_v1_t close_table;
|
||||
create_file_v1_t create_file;
|
||||
spawn_thread_v1_t spawn_thread;
|
||||
new_thread_v1_t new_thread;
|
||||
set_thread_id_v1_t set_thread_id;
|
||||
get_thread_v1_t get_thread;
|
||||
set_thread_user_v1_t set_thread_user;
|
||||
set_thread_user_host_v1_t set_thread_user_host;
|
||||
set_thread_db_v1_t set_thread_db;
|
||||
set_thread_command_v1_t set_thread_command;
|
||||
set_thread_start_time_v1_t set_thread_start_time;
|
||||
set_thread_state_v1_t set_thread_state;
|
||||
set_thread_info_v1_t set_thread_info;
|
||||
set_thread_v1_t set_thread;
|
||||
delete_current_thread_v1_t delete_current_thread;
|
||||
delete_thread_v1_t delete_thread;
|
||||
get_thread_mutex_locker_v1_t get_thread_mutex_locker;
|
||||
get_thread_rwlock_locker_v1_t get_thread_rwlock_locker;
|
||||
get_thread_cond_locker_v1_t get_thread_cond_locker;
|
||||
get_thread_table_locker_v1_t get_thread_table_locker;
|
||||
get_thread_file_name_locker_v1_t get_thread_file_name_locker;
|
||||
get_thread_file_stream_locker_v1_t get_thread_file_stream_locker;
|
||||
get_thread_file_descriptor_locker_v1_t get_thread_file_descriptor_locker;
|
||||
|
@ -291,6 +546,8 @@ struct PSI_v1
|
|||
unlock_rwlock_v1_t unlock_rwlock;
|
||||
signal_cond_v1_t signal_cond;
|
||||
broadcast_cond_v1_t broadcast_cond;
|
||||
start_idle_wait_v1_t start_idle_wait;
|
||||
end_idle_wait_v1_t end_idle_wait;
|
||||
start_mutex_wait_v1_t start_mutex_wait;
|
||||
end_mutex_wait_v1_t end_mutex_wait;
|
||||
start_rwlock_rdwait_v1_t start_rwlock_rdwait;
|
||||
|
@ -299,14 +556,46 @@ struct PSI_v1
|
|||
end_rwlock_wrwait_v1_t end_rwlock_wrwait;
|
||||
start_cond_wait_v1_t start_cond_wait;
|
||||
end_cond_wait_v1_t end_cond_wait;
|
||||
start_table_wait_v1_t start_table_wait;
|
||||
end_table_wait_v1_t end_table_wait;
|
||||
start_table_io_wait_v1_t start_table_io_wait;
|
||||
end_table_io_wait_v1_t end_table_io_wait;
|
||||
start_table_lock_wait_v1_t start_table_lock_wait;
|
||||
end_table_lock_wait_v1_t end_table_lock_wait;
|
||||
start_file_open_wait_v1_t start_file_open_wait;
|
||||
end_file_open_wait_v1_t end_file_open_wait;
|
||||
end_file_open_wait_and_bind_to_descriptor_v1_t
|
||||
end_file_open_wait_and_bind_to_descriptor;
|
||||
start_file_wait_v1_t start_file_wait;
|
||||
end_file_wait_v1_t end_file_wait;
|
||||
start_stage_v1_t start_stage;
|
||||
end_stage_v1_t end_stage;
|
||||
get_thread_statement_locker_v1_t get_thread_statement_locker;
|
||||
refine_statement_v1_t refine_statement;
|
||||
start_statement_v1_t start_statement;
|
||||
set_statement_text_v1_t set_statement_text;
|
||||
set_statement_lock_time_t set_statement_lock_time;
|
||||
set_statement_rows_sent_t set_statement_rows_sent;
|
||||
set_statement_rows_examined_t set_statement_rows_examined;
|
||||
inc_statement_created_tmp_disk_tables_t inc_statement_created_tmp_disk_tables;
|
||||
inc_statement_created_tmp_tables_t inc_statement_created_tmp_tables;
|
||||
inc_statement_select_full_join_t inc_statement_select_full_join;
|
||||
inc_statement_select_full_range_join_t inc_statement_select_full_range_join;
|
||||
inc_statement_select_range_t inc_statement_select_range;
|
||||
inc_statement_select_range_check_t inc_statement_select_range_check;
|
||||
inc_statement_select_scan_t inc_statement_select_scan;
|
||||
inc_statement_sort_merge_passes_t inc_statement_sort_merge_passes;
|
||||
inc_statement_sort_range_t inc_statement_sort_range;
|
||||
inc_statement_sort_rows_t inc_statement_sort_rows;
|
||||
inc_statement_sort_scan_t inc_statement_sort_scan;
|
||||
set_statement_no_index_used_t set_statement_no_index_used;
|
||||
set_statement_no_good_index_used_t set_statement_no_good_index_used;
|
||||
end_statement_v1_t end_statement;
|
||||
start_socket_wait_v1_t start_socket_wait;
|
||||
end_socket_wait_v1_t end_socket_wait;
|
||||
set_socket_state_v1_t set_socket_state;
|
||||
set_socket_info_v1_t set_socket_info;
|
||||
set_socket_thread_owner_v1_t set_socket_thread_owner;
|
||||
digest_start_v1_t digest_start;
|
||||
digest_add_token_v1_t digest_add_token;
|
||||
};
|
||||
typedef struct PSI_v1 PSI;
|
||||
typedef struct PSI_mutex_info_v1 PSI_mutex_info;
|
||||
|
@ -314,10 +603,16 @@ typedef struct PSI_rwlock_info_v1 PSI_rwlock_info;
|
|||
typedef struct PSI_cond_info_v1 PSI_cond_info;
|
||||
typedef struct PSI_thread_info_v1 PSI_thread_info;
|
||||
typedef struct PSI_file_info_v1 PSI_file_info;
|
||||
typedef struct PSI_stage_info_v1 PSI_stage_info;
|
||||
typedef struct PSI_statement_info_v1 PSI_statement_info;
|
||||
typedef struct PSI_socket_info_v1 PSI_socket_info;
|
||||
typedef struct PSI_idle_locker_state_v1 PSI_idle_locker_state;
|
||||
typedef struct PSI_mutex_locker_state_v1 PSI_mutex_locker_state;
|
||||
typedef struct PSI_rwlock_locker_state_v1 PSI_rwlock_locker_state;
|
||||
typedef struct PSI_cond_locker_state_v1 PSI_cond_locker_state;
|
||||
typedef struct PSI_file_locker_state_v1 PSI_file_locker_state;
|
||||
typedef struct PSI_table_locker_state_v1 PSI_table_locker_state;
|
||||
typedef struct PSI_statement_locker_state_v1 PSI_statement_locker_state;
|
||||
typedef struct PSI_socket_locker_state_v1 PSI_socket_locker_state;
|
||||
extern MYSQL_PLUGIN_IMPORT PSI *PSI_server;
|
||||
C_MODE_END
|
||||
|
|
|
@ -1,25 +1,52 @@
|
|||
#include "mysql/psi/psi.h"
|
||||
C_MODE_START
|
||||
struct TABLE_SHARE;
|
||||
struct OPAQUE_LEX_YYSTYPE;
|
||||
struct PSI_mutex;
|
||||
typedef struct PSI_mutex PSI_mutex;
|
||||
struct PSI_rwlock;
|
||||
typedef struct PSI_rwlock PSI_rwlock;
|
||||
struct PSI_cond;
|
||||
typedef struct PSI_cond PSI_cond;
|
||||
struct PSI_table_share;
|
||||
typedef struct PSI_table_share PSI_table_share;
|
||||
struct PSI_table;
|
||||
typedef struct PSI_table PSI_table;
|
||||
struct PSI_thread;
|
||||
typedef struct PSI_thread PSI_thread;
|
||||
struct PSI_file;
|
||||
typedef struct PSI_file PSI_file;
|
||||
struct PSI_socket;
|
||||
typedef struct PSI_socket PSI_socket;
|
||||
struct PSI_table_locker;
|
||||
typedef struct PSI_table_locker PSI_table_locker;
|
||||
struct PSI_statement_locker;
|
||||
typedef struct PSI_statement_locker PSI_statement_locker;
|
||||
struct PSI_idle_locker;
|
||||
typedef struct PSI_idle_locker PSI_idle_locker;
|
||||
struct PSI_digest_locker;
|
||||
typedef struct PSI_digest_locker PSI_digest_locker;
|
||||
struct PSI_bootstrap
|
||||
{
|
||||
void* (*get_interface)(int version);
|
||||
};
|
||||
typedef struct PSI_bootstrap PSI_bootstrap;
|
||||
struct PSI_mutex_locker;
|
||||
typedef struct PSI_mutex_locker PSI_mutex_locker;
|
||||
struct PSI_rwlock_locker;
|
||||
typedef struct PSI_rwlock_locker PSI_rwlock_locker;
|
||||
struct PSI_cond_locker;
|
||||
typedef struct PSI_cond_locker PSI_cond_locker;
|
||||
struct PSI_file_locker;
|
||||
typedef struct PSI_file_locker PSI_file_locker;
|
||||
struct PSI_socket_locker;
|
||||
typedef struct PSI_socket_locker PSI_socket_locker;
|
||||
enum PSI_mutex_operation
|
||||
{
|
||||
PSI_MUTEX_LOCK= 0,
|
||||
PSI_MUTEX_TRYLOCK= 1
|
||||
};
|
||||
typedef enum PSI_mutex_operation PSI_mutex_operation;
|
||||
enum PSI_rwlock_operation
|
||||
{
|
||||
PSI_RWLOCK_READLOCK= 0,
|
||||
|
@ -27,11 +54,13 @@ enum PSI_rwlock_operation
|
|||
PSI_RWLOCK_TRYREADLOCK= 2,
|
||||
PSI_RWLOCK_TRYWRITELOCK= 3
|
||||
};
|
||||
typedef enum PSI_rwlock_operation PSI_rwlock_operation;
|
||||
enum PSI_cond_operation
|
||||
{
|
||||
PSI_COND_WAIT= 0,
|
||||
PSI_COND_TIMEDWAIT= 1
|
||||
};
|
||||
typedef enum PSI_cond_operation PSI_cond_operation;
|
||||
enum PSI_file_operation
|
||||
{
|
||||
PSI_FILE_CREATE= 0,
|
||||
|
@ -52,12 +81,54 @@ enum PSI_file_operation
|
|||
PSI_FILE_RENAME= 15,
|
||||
PSI_FILE_SYNC= 16
|
||||
};
|
||||
struct PSI_table_locker;
|
||||
typedef enum PSI_file_operation PSI_file_operation;
|
||||
enum PSI_table_io_operation
|
||||
{
|
||||
PSI_TABLE_FETCH_ROW= 0,
|
||||
PSI_TABLE_WRITE_ROW= 1,
|
||||
PSI_TABLE_UPDATE_ROW= 2,
|
||||
PSI_TABLE_DELETE_ROW= 3
|
||||
};
|
||||
typedef enum PSI_table_io_operation PSI_table_io_operation;
|
||||
enum PSI_table_lock_operation
|
||||
{
|
||||
PSI_TABLE_LOCK= 0,
|
||||
PSI_TABLE_EXTERNAL_LOCK= 1
|
||||
};
|
||||
typedef enum PSI_table_lock_operation PSI_table_lock_operation;
|
||||
enum PSI_socket_state
|
||||
{
|
||||
PSI_SOCKET_STATE_IDLE= 1,
|
||||
PSI_SOCKET_STATE_ACTIVE= 2
|
||||
};
|
||||
typedef enum PSI_socket_state PSI_socket_state;
|
||||
enum PSI_socket_operation
|
||||
{
|
||||
PSI_SOCKET_CREATE= 0,
|
||||
PSI_SOCKET_CONNECT= 1,
|
||||
PSI_SOCKET_BIND= 2,
|
||||
PSI_SOCKET_CLOSE= 3,
|
||||
PSI_SOCKET_SEND= 4,
|
||||
PSI_SOCKET_RECV= 5,
|
||||
PSI_SOCKET_SENDTO= 6,
|
||||
PSI_SOCKET_RECVFROM= 7,
|
||||
PSI_SOCKET_SENDMSG= 8,
|
||||
PSI_SOCKET_RECVMSG= 9,
|
||||
PSI_SOCKET_SEEK= 10,
|
||||
PSI_SOCKET_OPT= 11,
|
||||
PSI_SOCKET_STAT= 12,
|
||||
PSI_SOCKET_SHUTDOWN= 13,
|
||||
PSI_SOCKET_SELECT= 14
|
||||
};
|
||||
typedef enum PSI_socket_operation PSI_socket_operation;
|
||||
typedef unsigned int PSI_mutex_key;
|
||||
typedef unsigned int PSI_rwlock_key;
|
||||
typedef unsigned int PSI_cond_key;
|
||||
typedef unsigned int PSI_thread_key;
|
||||
typedef unsigned int PSI_file_key;
|
||||
typedef unsigned int PSI_stage_key;
|
||||
typedef unsigned int PSI_statement_key;
|
||||
typedef unsigned int PSI_socket_key;
|
||||
struct PSI_v2
|
||||
{
|
||||
int placeholder;
|
||||
|
@ -82,6 +153,18 @@ struct PSI_file_info_v2
|
|||
{
|
||||
int placeholder;
|
||||
};
|
||||
struct PSI_stage_info_v2
|
||||
{
|
||||
int placeholder;
|
||||
};
|
||||
struct PSI_statement_info_v2
|
||||
{
|
||||
int placeholder;
|
||||
};
|
||||
struct PSI_idle_locker_state_v2
|
||||
{
|
||||
int placeholder;
|
||||
};
|
||||
struct PSI_mutex_locker_state_v2
|
||||
{
|
||||
int placeholder;
|
||||
|
@ -102,16 +185,30 @@ struct PSI_table_locker_state_v2
|
|||
{
|
||||
int placeholder;
|
||||
};
|
||||
struct PSI_statement_locker_state_v2
|
||||
{
|
||||
int placeholder;
|
||||
};
|
||||
struct PSI_socket_locker_state_v2
|
||||
{
|
||||
int placeholder;
|
||||
};
|
||||
typedef struct PSI_v2 PSI;
|
||||
typedef struct PSI_mutex_info_v2 PSI_mutex_info;
|
||||
typedef struct PSI_rwlock_info_v2 PSI_rwlock_info;
|
||||
typedef struct PSI_cond_info_v2 PSI_cond_info;
|
||||
typedef struct PSI_thread_info_v2 PSI_thread_info;
|
||||
typedef struct PSI_file_info_v2 PSI_file_info;
|
||||
typedef struct PSI_stage_info_v2 PSI_stage_info;
|
||||
typedef struct PSI_statement_info_v2 PSI_statement_info;
|
||||
typedef struct PSI_socket_info_v2 PSI_socket_info;
|
||||
typedef struct PSI_idle_locker_state_v2 PSI_idle_locker_state;
|
||||
typedef struct PSI_mutex_locker_state_v2 PSI_mutex_locker_state;
|
||||
typedef struct PSI_rwlock_locker_state_v2 PSI_rwlock_locker_state;
|
||||
typedef struct PSI_cond_locker_state_v2 PSI_cond_locker_state;
|
||||
typedef struct PSI_file_locker_state_v2 PSI_file_locker_state;
|
||||
typedef struct PSI_table_locker_state_v2 PSI_table_locker_state;
|
||||
typedef struct PSI_statement_locker_state_v2 PSI_statement_locker_state;
|
||||
typedef struct PSI_socket_locker_state_v2 PSI_socket_locker_state;
|
||||
extern MYSQL_PLUGIN_IMPORT PSI *PSI_server;
|
||||
C_MODE_END
|
||||
|
|
|
@ -337,10 +337,16 @@ extern void (*debug_sync_C_callback_ptr)(MYSQL_THD, const char *, size_t);
|
|||
#define DEBUG_SYNC(thd, name) \
|
||||
do { \
|
||||
if (debug_sync_service) \
|
||||
debug_sync_service(thd, name, sizeof(name)-1); \
|
||||
debug_sync_service(thd, STRING_WITH_LEN(name)); \
|
||||
} while(0)
|
||||
#define DEBUG_SYNC_C_IF_THD(thd, name) \
|
||||
do { \
|
||||
if (debug_sync_service && thd) \
|
||||
(*debug_sync_service)(thd, STRING_WITH_LEN(name)); } \
|
||||
while(0)
|
||||
#else
|
||||
#define DEBUG_SYNC(thd,name) do { } while(0)
|
||||
#define DEBUG_SYNC(thd,name) do { } while(0)
|
||||
#define DEBUG_SYNC_C_IF_THD(thd, name) do { } while(0)
|
||||
#endif
|
||||
|
||||
/* compatibility macro */
|
||||
|
|
|
@ -69,7 +69,8 @@ SET(SQL_EMBEDDED_SOURCES emb_qcache.cc libmysqld.c lib_sql.cc
|
|||
../sql/sql_lex.cc ../sql/keycaches.cc
|
||||
../sql/sql_list.cc ../sql/sql_load.cc ../sql/sql_locale.cc
|
||||
../sql/sql_binlog.cc ../sql/sql_manager.cc
|
||||
../sql/sql_parse.cc ../sql/sql_partition.cc ../sql/sql_plugin.cc
|
||||
../sql/sql_parse.cc ../sql/sql_bootstrap.cc
|
||||
../sql/sql_partition.cc ../sql/sql_plugin.cc
|
||||
../sql/debug_sync.cc ../sql/opt_table_elimination.cc
|
||||
../sql/sql_prepare.cc ../sql/sql_rename.cc ../sql/sql_repl.cc
|
||||
../sql/sql_select.cc ../sql/sql_servers.cc
|
||||
|
|
|
@ -3516,7 +3516,7 @@ sub mysql_install_db {
|
|||
{
|
||||
my $sql_dir= dirname($path_sql);
|
||||
# Use the mysql database for system tables
|
||||
mtr_tofile($bootstrap_sql_file, "use mysql\n");
|
||||
mtr_tofile($bootstrap_sql_file, "use mysql;\n");
|
||||
|
||||
# Add the offical mysql system tables
|
||||
# for a production system
|
||||
|
|
|
@ -16,7 +16,9 @@
|
|||
INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIR} ${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/mysys)
|
||||
|
||||
SET(MYSYS_SOURCES array.c charset-def.c charset.c checksum.c default.c
|
||||
errors.c hash.c list.c md5.c mf_cache.c mf_dirname.c mf_fn_ext.c
|
||||
errors.c hash.c list.c
|
||||
md5.c md5_compute.cc
|
||||
mf_cache.c mf_dirname.c mf_fn_ext.c
|
||||
mf_format.c mf_getdate.c mf_iocache.c mf_iocache2.c mf_keycache.c
|
||||
mf_keycaches.c mf_loadpath.c mf_pack.c mf_path.c mf_qsort.c mf_qsort2.c
|
||||
mf_radix.c mf_same.c mf_sort.c mf_soundex.c mf_arr_appstr.c mf_tempdir.c
|
||||
|
@ -37,7 +39,7 @@ SET(MYSYS_SOURCES array.c charset-def.c charset.c checksum.c default.c
|
|||
safemalloc.c my_new.cc
|
||||
my_atomic.c my_getncpus.c my_safehash.c my_chmod.c my_rnd.c
|
||||
my_uuid.c wqueue.c waiting_threads.c ma_dyncol.c
|
||||
my_rdtsc.c my_context.c)
|
||||
my_rdtsc.c my_context.c psi_noop.c)
|
||||
|
||||
IF (WIN32)
|
||||
SET (MYSYS_SOURCES ${MYSYS_SOURCES} my_winthread.c my_wincond.c my_winerr.c my_winfile.c my_windac.c my_conio.c)
|
||||
|
|
|
@ -87,9 +87,9 @@ my_bool init_dynamic_array(DYNAMIC_ARRAY *array, uint element_size,
|
|||
FALSE Ok
|
||||
*/
|
||||
|
||||
my_bool insert_dynamic(DYNAMIC_ARRAY *array, const uchar* element)
|
||||
my_bool insert_dynamic(DYNAMIC_ARRAY *array, const void * element)
|
||||
{
|
||||
uchar* buffer;
|
||||
void *buffer;
|
||||
if (array->elements == array->max_element)
|
||||
{ /* Call only when nessesary */
|
||||
if (!(buffer=alloc_dynamic(array)))
|
||||
|
@ -122,7 +122,7 @@ my_bool insert_dynamic(DYNAMIC_ARRAY *array, const uchar* element)
|
|||
0 Error
|
||||
*/
|
||||
|
||||
uchar *alloc_dynamic(DYNAMIC_ARRAY *array)
|
||||
void *alloc_dynamic(DYNAMIC_ARRAY *array)
|
||||
{
|
||||
DBUG_ENTER("alloc_dynamic");
|
||||
if (array->elements == array->max_element)
|
||||
|
@ -167,7 +167,7 @@ uchar *alloc_dynamic(DYNAMIC_ARRAY *array)
|
|||
0 Array is empty
|
||||
*/
|
||||
|
||||
uchar *pop_dynamic(DYNAMIC_ARRAY *array)
|
||||
void *pop_dynamic(DYNAMIC_ARRAY *array)
|
||||
{
|
||||
if (array->elements)
|
||||
return array->buffer+(--array->elements * array->size_of_element);
|
||||
|
@ -192,7 +192,7 @@ uchar *pop_dynamic(DYNAMIC_ARRAY *array)
|
|||
FALSE Ok
|
||||
*/
|
||||
|
||||
my_bool set_dynamic(DYNAMIC_ARRAY *array, uchar* element, uint idx)
|
||||
my_bool set_dynamic(DYNAMIC_ARRAY *array, const void *element, uint idx)
|
||||
{
|
||||
if (idx >= array->elements)
|
||||
{
|
||||
|
@ -268,7 +268,7 @@ my_bool allocate_dynamic(DYNAMIC_ARRAY *array, uint max_elements)
|
|||
idx Index of element wanted.
|
||||
*/
|
||||
|
||||
void get_dynamic(DYNAMIC_ARRAY *array, uchar* element, uint idx)
|
||||
void get_dynamic(DYNAMIC_ARRAY *array, void *element, uint idx)
|
||||
{
|
||||
if (idx >= array->elements)
|
||||
{
|
||||
|
@ -363,13 +363,13 @@ void freeze_size(DYNAMIC_ARRAY *array)
|
|||
|
||||
*/
|
||||
|
||||
int get_index_dynamic(DYNAMIC_ARRAY *array, uchar* element)
|
||||
int get_index_dynamic(DYNAMIC_ARRAY *array, void* element)
|
||||
{
|
||||
size_t ret;
|
||||
if (array->buffer > element)
|
||||
if (array->buffer > (uchar*) element)
|
||||
return -1;
|
||||
|
||||
ret= (element - array->buffer) / array->size_of_element;
|
||||
ret= ((uchar*) element - array->buffer) / array->size_of_element;
|
||||
if (ret > array->elements)
|
||||
return -1;
|
||||
|
||||
|
|
10
mysys/md5.c
10
mysys/md5.c
|
@ -38,13 +38,15 @@
|
|||
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"
|
||||
|
||||
#include <string.h> /* for memcpy() and memset() */
|
||||
|
||||
|
||||
static void
|
||||
my_MD5Transform (cvs_uint32 buf[4], const unsigned char in[64]);
|
||||
|
||||
|
@ -323,3 +325,5 @@ main (int argc, char **argv)
|
|||
return 0;
|
||||
}
|
||||
#endif /* TEST */
|
||||
|
||||
#endif /* !defined(HAVE_OPENSSL) && !defined(HAVE_YASSL) */
|
||||
|
|
68
mysys/md5_compute.cc
Normal file
68
mysys/md5_compute.cc
Normal file
|
@ -0,0 +1,68 @@
|
|||
/* Copyright (c) 2012, 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,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
|
||||
|
||||
|
||||
/**
|
||||
@file
|
||||
|
||||
@brief
|
||||
Wrapper functions for OpenSSL, YaSSL and MySQL's MD5
|
||||
implementations. Also provides a Compatibility layer
|
||||
to make available YaSSL's MD5 implementation.
|
||||
*/
|
||||
|
||||
#include <my_global.h>
|
||||
#include <my_md5.h>
|
||||
|
||||
#ifdef HAVE_YASSL
|
||||
|
||||
#include "md5.hpp"
|
||||
|
||||
/**
|
||||
Compute MD5 message digest.
|
||||
|
||||
@param digest [out] Computed MD5 digest
|
||||
@param buf [in] Message to be computed
|
||||
@param len [in] Length of the message
|
||||
|
||||
@return void
|
||||
*/
|
||||
void my_md5_hash(char *digest, const char *buf, int len)
|
||||
{
|
||||
TaoCrypt::MD5 hasher;
|
||||
hasher.Update((TaoCrypt::byte *) buf, len);
|
||||
hasher.Final((TaoCrypt::byte *) digest);
|
||||
}
|
||||
#endif /* HAVE_YASSL */
|
||||
|
||||
|
||||
/**
|
||||
Wrapper function to compute MD5 message digest.
|
||||
|
||||
@param digest [out] Computed MD5 digest
|
||||
@param buf [in] Message to be computed
|
||||
@param len [in] Length of the message
|
||||
|
||||
@return void
|
||||
*/
|
||||
void compute_md5_hash(char *digest, const char *buf, int len)
|
||||
{
|
||||
#ifdef HAVE_YASSL
|
||||
my_md5_hash(digest, buf, len);
|
||||
#else
|
||||
MY_MD5_HASH((unsigned char *) digest, (unsigned char const *) buf, len);
|
||||
#endif /* HAVE_YASSL */
|
||||
}
|
||||
|
|
@ -21,6 +21,7 @@
|
|||
#include <m_string.h>
|
||||
#include <m_ctype.h>
|
||||
#include <signal.h>
|
||||
#include <mysql/psi/mysql_stage.h>
|
||||
#ifdef __WIN__
|
||||
#ifdef _MSC_VER
|
||||
#include <locale.h>
|
||||
|
@ -442,6 +443,9 @@ static my_bool win32_init_tcp_ip()
|
|||
|
||||
#ifdef HAVE_PSI_INTERFACE
|
||||
|
||||
PSI_stage_info stage_waiting_for_table_level_lock=
|
||||
{0, "Waiting for table level lock", 0};
|
||||
|
||||
#if !defined(HAVE_PREAD) && !defined(_WIN32)
|
||||
PSI_mutex_key key_my_file_info_mutex;
|
||||
#endif /* !defined(HAVE_PREAD) && !defined(_WIN32) */
|
||||
|
@ -531,30 +535,34 @@ static PSI_file_info all_mysys_files[]=
|
|||
{ &key_file_cnf, "cnf", 0}
|
||||
};
|
||||
|
||||
PSI_stage_info *all_mysys_stages[]=
|
||||
{
|
||||
& stage_waiting_for_table_level_lock
|
||||
};
|
||||
|
||||
void my_init_mysys_psi_keys()
|
||||
{
|
||||
const char* category= "mysys";
|
||||
int count;
|
||||
|
||||
if (PSI_server == NULL)
|
||||
return;
|
||||
|
||||
count= sizeof(all_mysys_mutexes)/sizeof(all_mysys_mutexes[0]);
|
||||
PSI_server->register_mutex(category, all_mysys_mutexes, count);
|
||||
mysql_mutex_register(category, all_mysys_mutexes, count);
|
||||
|
||||
count= sizeof(all_mysys_conds)/sizeof(all_mysys_conds[0]);
|
||||
PSI_server->register_cond(category, all_mysys_conds, count);
|
||||
mysql_cond_register(category, all_mysys_conds, count);
|
||||
|
||||
count= sizeof(all_mysys_rwlocks)/sizeof(all_mysys_rwlocks[0]);
|
||||
PSI_server->register_rwlock(category, all_mysys_rwlocks, count);
|
||||
mysql_rwlock_register(category, all_mysys_rwlocks, count);
|
||||
|
||||
#ifdef USE_ALARM_THREAD
|
||||
count= sizeof(all_mysys_threads)/sizeof(all_mysys_threads[0]);
|
||||
PSI_server->register_thread(category, all_mysys_threads, count);
|
||||
mysql_thread_register(category, all_mysys_threads, count);
|
||||
#endif /* USE_ALARM_THREAD */
|
||||
|
||||
count= sizeof(all_mysys_files)/sizeof(all_mysys_files[0]);
|
||||
PSI_server->register_file(category, all_mysys_files, count);
|
||||
mysql_file_register(category, all_mysys_files, count);
|
||||
|
||||
count= array_elements(all_mysys_stages);
|
||||
mysql_stage_register(category, all_mysys_stages, count);
|
||||
}
|
||||
#endif /* HAVE_PSI_INTERFACE */
|
||||
|
||||
|
|
|
@ -98,31 +98,3 @@ my_bool my_disable_sync=0;
|
|||
my_bool my_disable_async_io=0;
|
||||
my_bool my_disable_flush_key_blocks=0;
|
||||
my_bool my_disable_symlinks=0;
|
||||
|
||||
/*
|
||||
Note that PSI_hook and PSI_server are unconditionally
|
||||
(no ifdef HAVE_PSI_INTERFACE) defined.
|
||||
This is to ensure binary compatibility between the server and plugins,
|
||||
in the case when:
|
||||
- the server is not compiled with HAVE_PSI_INTERFACE
|
||||
- a plugin is compiled with HAVE_PSI_INTERFACE
|
||||
See the doxygen documentation for the performance schema.
|
||||
*/
|
||||
|
||||
/**
|
||||
Hook for the instrumentation interface.
|
||||
Code implementing the instrumentation interface should register here.
|
||||
*/
|
||||
struct PSI_bootstrap *PSI_hook= NULL;
|
||||
|
||||
/**
|
||||
Instance of the instrumentation interface for the MySQL server.
|
||||
@todo This is currently a global variable, which is handy when
|
||||
compiling instrumented code that is bundled with the server.
|
||||
When dynamic plugin are truly supported, this variable will need
|
||||
to be replaced by a macro, so that each XYZ plugin can have it's own
|
||||
xyz_psi_server variable, obtained from PSI_bootstrap::get_interface()
|
||||
with the version used at compile time for plugin XYZ.
|
||||
*/
|
||||
PSI *PSI_server= NULL;
|
||||
|
||||
|
|
746
mysys/psi_noop.c
Normal file
746
mysys/psi_noop.c
Normal file
|
@ -0,0 +1,746 @@
|
|||
/* 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,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
|
||||
|
||||
/*
|
||||
Always provide the noop performance interface, for plugins.
|
||||
*/
|
||||
|
||||
#define USE_PSI_V1
|
||||
#define HAVE_PSI_INTERFACE
|
||||
|
||||
#include "my_global.h"
|
||||
#include "my_pthread.h"
|
||||
#include "my_sys.h"
|
||||
#include "mysql/psi/psi.h"
|
||||
|
||||
C_MODE_START
|
||||
|
||||
#define NNN __attribute__((unused))
|
||||
|
||||
static void register_mutex_noop(const char *category NNN,
|
||||
PSI_mutex_info *info NNN,
|
||||
int count NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void register_rwlock_noop(const char *category NNN,
|
||||
PSI_rwlock_info *info NNN,
|
||||
int count NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void register_cond_noop(const char *category NNN,
|
||||
PSI_cond_info *info NNN,
|
||||
int count NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void register_thread_noop(const char *category NNN,
|
||||
PSI_thread_info *info NNN,
|
||||
int count NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void register_file_noop(const char *category NNN,
|
||||
PSI_file_info *info NNN,
|
||||
int count NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void register_stage_noop(const char *category NNN,
|
||||
PSI_stage_info **info_array NNN,
|
||||
int count NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void register_statement_noop(const char *category NNN,
|
||||
PSI_statement_info *info NNN,
|
||||
int count NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void register_socket_noop(const char *category NNN,
|
||||
PSI_socket_info *info NNN,
|
||||
int count NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static PSI_mutex*
|
||||
init_mutex_noop(PSI_mutex_key key NNN, const void *identity NNN)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void destroy_mutex_noop(PSI_mutex* mutex NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static PSI_rwlock*
|
||||
init_rwlock_noop(PSI_rwlock_key key NNN, const void *identity NNN)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void destroy_rwlock_noop(PSI_rwlock* rwlock NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static PSI_cond*
|
||||
init_cond_noop(PSI_cond_key key NNN, const void *identity NNN)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void destroy_cond_noop(PSI_cond* cond NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static PSI_socket*
|
||||
init_socket_noop(PSI_socket_key key NNN, const my_socket *fd NNN)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void destroy_socket_noop(PSI_socket* socket NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static PSI_table_share*
|
||||
get_table_share_noop(my_bool temporary NNN, struct TABLE_SHARE *share NNN)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void release_table_share_noop(PSI_table_share* share NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
drop_table_share_noop(my_bool temporary NNN, const char *schema_name NNN,
|
||||
int schema_name_length NNN, const char *table_name NNN,
|
||||
int table_name_length NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static PSI_table*
|
||||
open_table_noop(PSI_table_share *share NNN, const void *identity NNN)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void unbind_table_noop(PSI_table *table NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static PSI_table*
|
||||
rebind_table_noop(PSI_table_share *share NNN,
|
||||
const void *identity NNN,
|
||||
PSI_table *table NNN)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void close_table_noop(PSI_table *table NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void create_file_noop(PSI_file_key key NNN,
|
||||
const char *name NNN, File file NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static int spawn_thread_noop(PSI_thread_key key NNN,
|
||||
pthread_t *thread NNN,
|
||||
const pthread_attr_t *attr NNN,
|
||||
void *(*start_routine)(void*) NNN, void *arg NNN)
|
||||
{
|
||||
return pthread_create(thread, attr, start_routine, arg);
|
||||
}
|
||||
|
||||
static PSI_thread*
|
||||
new_thread_noop(PSI_thread_key key NNN,
|
||||
const void *identity NNN, ulong thread_id NNN)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void set_thread_id_noop(PSI_thread *thread NNN, unsigned long id NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static PSI_thread*
|
||||
get_thread_noop(void NNN)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void set_thread_user_noop(const char *user NNN, int user_len NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void set_thread_user_host_noop(const char *user NNN, int user_len NNN,
|
||||
const char *host NNN, int host_len NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void set_thread_db_noop(const char* db NNN, int db_len NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void set_thread_command_noop(int command NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void set_thread_start_time_noop(time_t start_time NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void set_thread_state_noop(const char* state NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void set_thread_info_noop(const char* info NNN, int info_len NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void set_thread_noop(PSI_thread* thread NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void delete_current_thread_noop(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void delete_thread_noop(PSI_thread *thread NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static PSI_file_locker*
|
||||
get_thread_file_name_locker_noop(PSI_file_locker_state *state NNN,
|
||||
PSI_file_key key NNN,
|
||||
enum PSI_file_operation op NNN,
|
||||
const char *name NNN, const void *identity NNN)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static PSI_file_locker*
|
||||
get_thread_file_stream_locker_noop(PSI_file_locker_state *state NNN,
|
||||
PSI_file *file NNN,
|
||||
enum PSI_file_operation op NNN)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static PSI_file_locker*
|
||||
get_thread_file_descriptor_locker_noop(PSI_file_locker_state *state NNN,
|
||||
File file NNN,
|
||||
enum PSI_file_operation op NNN)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void unlock_mutex_noop(PSI_mutex *mutex NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void unlock_rwlock_noop(PSI_rwlock *rwlock NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void signal_cond_noop(PSI_cond* cond NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void broadcast_cond_noop(PSI_cond* cond NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static PSI_idle_locker*
|
||||
start_idle_wait_noop(PSI_idle_locker_state* state NNN,
|
||||
const char *src_file NNN, uint src_line NNN)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void end_idle_wait_noop(PSI_idle_locker* locker NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static PSI_mutex_locker*
|
||||
start_mutex_wait_noop(PSI_mutex_locker_state *state NNN,
|
||||
PSI_mutex *mutex NNN,
|
||||
PSI_mutex_operation op NNN,
|
||||
const char *src_file NNN, uint src_line NNN)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void end_mutex_wait_noop(PSI_mutex_locker* locker NNN, int rc NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static PSI_rwlock_locker*
|
||||
start_rwlock_rdwait_noop(struct PSI_rwlock_locker_state_v1 *state NNN,
|
||||
struct PSI_rwlock *rwlock NNN,
|
||||
enum PSI_rwlock_operation op NNN,
|
||||
const char *src_file NNN, uint src_line NNN)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void end_rwlock_rdwait_noop(PSI_rwlock_locker* locker NNN, int rc NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static struct PSI_rwlock_locker*
|
||||
start_rwlock_wrwait_noop(struct PSI_rwlock_locker_state_v1 *state NNN,
|
||||
struct PSI_rwlock *rwlock NNN,
|
||||
enum PSI_rwlock_operation op NNN,
|
||||
const char *src_file NNN, uint src_line NNN)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void end_rwlock_wrwait_noop(PSI_rwlock_locker* locker NNN, int rc NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static struct PSI_cond_locker*
|
||||
start_cond_wait_noop(struct PSI_cond_locker_state_v1 *state NNN,
|
||||
struct PSI_cond *cond NNN,
|
||||
struct PSI_mutex *mutex NNN,
|
||||
enum PSI_cond_operation op NNN,
|
||||
const char *src_file NNN, uint src_line NNN)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void end_cond_wait_noop(PSI_cond_locker* locker NNN, int rc NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static struct PSI_table_locker*
|
||||
start_table_io_wait_noop(struct PSI_table_locker_state_v1 *state NNN,
|
||||
struct PSI_table *table NNN,
|
||||
enum PSI_table_io_operation op NNN,
|
||||
uint index NNN,
|
||||
const char *src_file NNN, uint src_line NNN)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void end_table_io_wait_noop(PSI_table_locker* locker NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static struct PSI_table_locker*
|
||||
start_table_lock_wait_noop(struct PSI_table_locker_state_v1 *state NNN,
|
||||
struct PSI_table *table NNN,
|
||||
enum PSI_table_lock_operation op NNN,
|
||||
ulong flags NNN,
|
||||
const char *src_file NNN, uint src_line NNN)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void end_table_lock_wait_noop(PSI_table_locker* locker NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static PSI_file* start_file_open_wait_noop(PSI_file_locker *locker NNN,
|
||||
const char *src_file NNN,
|
||||
uint src_line NNN)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void end_file_open_wait_noop(PSI_file_locker *locker NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void end_file_open_wait_and_bind_to_descriptor_noop
|
||||
(PSI_file_locker *locker NNN, File file NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void start_file_wait_noop(PSI_file_locker *locker NNN,
|
||||
size_t count NNN,
|
||||
const char *src_file NNN,
|
||||
uint src_line NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void end_file_wait_noop(PSI_file_locker *locker NNN,
|
||||
size_t count NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void start_stage_noop(PSI_stage_key key NNN,
|
||||
const char *src_file NNN, int src_line NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void end_stage_noop(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static PSI_statement_locker*
|
||||
get_thread_statement_locker_noop(PSI_statement_locker_state *state NNN,
|
||||
PSI_statement_key key NNN)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static PSI_statement_locker*
|
||||
refine_statement_noop(PSI_statement_locker *locker NNN,
|
||||
PSI_statement_key key NNN)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void start_statement_noop(PSI_statement_locker *locker NNN,
|
||||
const char *db NNN, uint db_len NNN,
|
||||
const char *src_file NNN, uint src_line NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void set_statement_text_noop(PSI_statement_locker *locker NNN,
|
||||
const char *text NNN, uint text_len NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void set_statement_lock_time_noop(PSI_statement_locker *locker NNN,
|
||||
ulonglong count NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void set_statement_rows_sent_noop(PSI_statement_locker *locker NNN,
|
||||
ulonglong count NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void set_statement_rows_examined_noop(PSI_statement_locker *locker NNN,
|
||||
ulonglong count NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void inc_statement_created_tmp_disk_tables_noop(PSI_statement_locker *locker NNN,
|
||||
ulong count NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void inc_statement_created_tmp_tables_noop(PSI_statement_locker *locker NNN,
|
||||
ulong count NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void inc_statement_select_full_join_noop(PSI_statement_locker *locker NNN,
|
||||
ulong count NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void inc_statement_select_full_range_join_noop(PSI_statement_locker *locker NNN,
|
||||
ulong count NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void inc_statement_select_range_noop(PSI_statement_locker *locker NNN,
|
||||
ulong count NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void inc_statement_select_range_check_noop(PSI_statement_locker *locker NNN,
|
||||
ulong count NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void inc_statement_select_scan_noop(PSI_statement_locker *locker NNN,
|
||||
ulong count NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void inc_statement_sort_merge_passes_noop(PSI_statement_locker *locker NNN,
|
||||
ulong count NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void inc_statement_sort_range_noop(PSI_statement_locker *locker NNN,
|
||||
ulong count NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void inc_statement_sort_rows_noop(PSI_statement_locker *locker NNN,
|
||||
ulong count NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void inc_statement_sort_scan_noop(PSI_statement_locker *locker NNN,
|
||||
ulong count NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void set_statement_no_index_used_noop(PSI_statement_locker *locker NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void set_statement_no_good_index_used_noop(PSI_statement_locker *locker NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void end_statement_noop(PSI_statement_locker *locker NNN,
|
||||
void *stmt_da NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static PSI_socket_locker*
|
||||
start_socket_wait_noop(PSI_socket_locker_state *state NNN,
|
||||
PSI_socket *socket NNN,
|
||||
PSI_socket_operation op NNN,
|
||||
size_t count NNN,
|
||||
const char *src_file NNN,
|
||||
uint src_line NNN)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void end_socket_wait_noop(PSI_socket_locker *locker NNN,
|
||||
size_t count NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void set_socket_state_noop(PSI_socket *socket NNN,
|
||||
enum PSI_socket_state state NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void set_socket_info_noop(PSI_socket *socket NNN,
|
||||
const my_socket *fd NNN,
|
||||
const struct sockaddr *addr NNN,
|
||||
socklen_t addr_len NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void set_socket_thread_owner_noop(PSI_socket *socket NNN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static struct PSI_digest_locker*
|
||||
digest_start_noop(PSI_statement_locker *locker NNN)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static PSI_digest_locker*
|
||||
digest_add_token_noop(PSI_digest_locker *locker NNN,
|
||||
uint token NNN,
|
||||
struct OPAQUE_LEX_YYSTYPE *yylval NNN)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static PSI PSI_noop=
|
||||
{
|
||||
register_mutex_noop,
|
||||
register_rwlock_noop,
|
||||
register_cond_noop,
|
||||
register_thread_noop,
|
||||
register_file_noop,
|
||||
register_stage_noop,
|
||||
register_statement_noop,
|
||||
register_socket_noop,
|
||||
init_mutex_noop,
|
||||
destroy_mutex_noop,
|
||||
init_rwlock_noop,
|
||||
destroy_rwlock_noop,
|
||||
init_cond_noop,
|
||||
destroy_cond_noop,
|
||||
init_socket_noop,
|
||||
destroy_socket_noop,
|
||||
get_table_share_noop,
|
||||
release_table_share_noop,
|
||||
drop_table_share_noop,
|
||||
open_table_noop,
|
||||
unbind_table_noop,
|
||||
rebind_table_noop,
|
||||
close_table_noop,
|
||||
create_file_noop,
|
||||
spawn_thread_noop,
|
||||
new_thread_noop,
|
||||
set_thread_id_noop,
|
||||
get_thread_noop,
|
||||
set_thread_user_noop,
|
||||
set_thread_user_host_noop,
|
||||
set_thread_db_noop,
|
||||
set_thread_command_noop,
|
||||
set_thread_start_time_noop,
|
||||
set_thread_state_noop,
|
||||
set_thread_info_noop,
|
||||
set_thread_noop,
|
||||
delete_current_thread_noop,
|
||||
delete_thread_noop,
|
||||
get_thread_file_name_locker_noop,
|
||||
get_thread_file_stream_locker_noop,
|
||||
get_thread_file_descriptor_locker_noop,
|
||||
unlock_mutex_noop,
|
||||
unlock_rwlock_noop,
|
||||
signal_cond_noop,
|
||||
broadcast_cond_noop,
|
||||
start_idle_wait_noop,
|
||||
end_idle_wait_noop,
|
||||
start_mutex_wait_noop,
|
||||
end_mutex_wait_noop,
|
||||
start_rwlock_rdwait_noop,
|
||||
end_rwlock_rdwait_noop,
|
||||
start_rwlock_wrwait_noop,
|
||||
end_rwlock_wrwait_noop,
|
||||
start_cond_wait_noop,
|
||||
end_cond_wait_noop,
|
||||
start_table_io_wait_noop,
|
||||
end_table_io_wait_noop,
|
||||
start_table_lock_wait_noop,
|
||||
end_table_lock_wait_noop,
|
||||
start_file_open_wait_noop,
|
||||
end_file_open_wait_noop,
|
||||
end_file_open_wait_and_bind_to_descriptor_noop,
|
||||
start_file_wait_noop,
|
||||
end_file_wait_noop,
|
||||
start_stage_noop,
|
||||
end_stage_noop,
|
||||
get_thread_statement_locker_noop,
|
||||
refine_statement_noop,
|
||||
start_statement_noop,
|
||||
set_statement_text_noop,
|
||||
set_statement_lock_time_noop,
|
||||
set_statement_rows_sent_noop,
|
||||
set_statement_rows_examined_noop,
|
||||
inc_statement_created_tmp_disk_tables_noop,
|
||||
inc_statement_created_tmp_tables_noop,
|
||||
inc_statement_select_full_join_noop,
|
||||
inc_statement_select_full_range_join_noop,
|
||||
inc_statement_select_range_noop,
|
||||
inc_statement_select_range_check_noop,
|
||||
inc_statement_select_scan_noop,
|
||||
inc_statement_sort_merge_passes_noop,
|
||||
inc_statement_sort_range_noop,
|
||||
inc_statement_sort_rows_noop,
|
||||
inc_statement_sort_scan_noop,
|
||||
set_statement_no_index_used_noop,
|
||||
set_statement_no_good_index_used_noop,
|
||||
end_statement_noop,
|
||||
start_socket_wait_noop,
|
||||
end_socket_wait_noop,
|
||||
set_socket_state_noop,
|
||||
set_socket_info_noop,
|
||||
set_socket_thread_owner_noop,
|
||||
digest_start_noop,
|
||||
digest_add_token_noop
|
||||
};
|
||||
|
||||
/**
|
||||
Hook for the instrumentation interface.
|
||||
Code implementing the instrumentation interface should register here.
|
||||
*/
|
||||
struct PSI_bootstrap *PSI_hook= NULL;
|
||||
|
||||
/**
|
||||
Instance of the instrumentation interface for the MySQL server.
|
||||
@todo This is currently a global variable, which is handy when
|
||||
compiling instrumented code that is bundled with the server.
|
||||
When dynamic plugin are truly supported, this variable will need
|
||||
to be replaced by a macro, so that each XYZ plugin can have it's own
|
||||
xyz_psi_server variable, obtained from PSI_bootstrap::get_interface()
|
||||
with the version used at compile time for plugin XYZ.
|
||||
*/
|
||||
|
||||
PSI *PSI_server= & PSI_noop;
|
||||
|
||||
void set_psi_server(PSI *psi)
|
||||
{
|
||||
PSI_server= psi;
|
||||
}
|
||||
|
||||
C_MODE_END
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
/* Copyright (C) 2004 MySQL AB
|
||||
/* Copyright (c) 2004, 2010, Oracle and/or its affiliates.
|
||||
Copyright (c) 2012 Monty Program 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
|
||||
|
@ -11,10 +12,10 @@
|
|||
|
||||
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 */
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
|
||||
|
||||
/*
|
||||
Written by Magnus Svensson
|
||||
Originally written by Magnus Svensson
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -25,10 +26,18 @@
|
|||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
/* Compiler-dependent constant for maximum string constant */
|
||||
#define MAX_STRING_CONSTANT_LENGTH 65535
|
||||
#include "../sql/sql_bootstrap.h"
|
||||
|
||||
/*
|
||||
This is an internal tool used during the build process only,
|
||||
- do not make a library just for this,
|
||||
which would make the Makefiles and the server link
|
||||
more complex than necessary,
|
||||
- do not duplicate the code either.
|
||||
so just add the sql_bootstrap.cc code as is.
|
||||
*/
|
||||
#include "../sql/sql_bootstrap.cc"
|
||||
|
||||
FILE *in, *out;
|
||||
|
||||
|
@ -58,15 +67,60 @@ static void die(const char *fmt, ...)
|
|||
exit(1);
|
||||
}
|
||||
|
||||
char *fgets_fn(char *buffer, size_t size, fgets_input_t input)
|
||||
{
|
||||
return fgets(buffer, size, (FILE*) input);
|
||||
}
|
||||
|
||||
static void print_query(FILE *out, const char *query)
|
||||
{
|
||||
const char *ptr= query;
|
||||
int column= 0;
|
||||
|
||||
fprintf(out, "\"");
|
||||
while (*ptr)
|
||||
{
|
||||
if (column >= 120)
|
||||
{
|
||||
/* Wrap to the next line, tabulated. */
|
||||
fprintf(out, "\"\n \"");
|
||||
column= 2;
|
||||
}
|
||||
switch(*ptr)
|
||||
{
|
||||
case '\n':
|
||||
/*
|
||||
Preserve the \n character in the query text,
|
||||
and wrap to the next line, tabulated.
|
||||
*/
|
||||
fprintf(out, "\\n\"\n \"");
|
||||
column= 2;
|
||||
break;
|
||||
case '\r':
|
||||
/* Skipped */
|
||||
break;
|
||||
case '\"':
|
||||
fprintf(out, "\\\"");
|
||||
column++;
|
||||
break;
|
||||
default:
|
||||
putc(*ptr, out);
|
||||
column++;
|
||||
break;
|
||||
}
|
||||
ptr++;
|
||||
}
|
||||
fprintf(out, "\\n\",\n");
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char buff[512];
|
||||
struct stat st;
|
||||
char query[MAX_BOOTSTRAP_QUERY_SIZE];
|
||||
char* struct_name= argv[1];
|
||||
char* infile_name= argv[2];
|
||||
char* outfile_name= argv[3];
|
||||
|
||||
int rc;
|
||||
int query_length;
|
||||
|
||||
if (argc != 4)
|
||||
die("Usage: comp_sql <struct_name> <sql_filename> <c_filename>");
|
||||
|
@ -74,86 +128,31 @@ int main(int argc, char *argv[])
|
|||
/* Open input and output file */
|
||||
if (!(in= fopen(infile_name, "r")))
|
||||
die("Failed to open SQL file '%s'", infile_name);
|
||||
|
||||
|
||||
if (!(out= fopen(outfile_name, "w")))
|
||||
die("Failed to open output file '%s'", outfile_name);
|
||||
fprintf(out, "const char %s[]={\n",struct_name);
|
||||
|
||||
/*
|
||||
Some compilers have limitations how long a string constant can be.
|
||||
We'll output very long strings as hexadecimal arrays, and short ones
|
||||
as strings (prettier)
|
||||
*/
|
||||
stat(infile_name, &st);
|
||||
if (st.st_size > MAX_STRING_CONSTANT_LENGTH)
|
||||
fprintf(out, "/*\n");
|
||||
fprintf(out, " Do not edit this file, it is automatically generated from:\n");
|
||||
fprintf(out, " <%s>\n", infile_name);
|
||||
fprintf(out, "*/\n");
|
||||
fprintf(out, "const char* %s[]={\n", struct_name);
|
||||
|
||||
for ( ; ; )
|
||||
{
|
||||
int cnt=0;
|
||||
int c;
|
||||
for(cnt=0;;cnt++)
|
||||
{
|
||||
c= fgetc(in);
|
||||
if (c== -1)
|
||||
break;
|
||||
rc= read_bootstrap_query(query, &query_length,
|
||||
(fgets_input_t) in, fgets_fn);
|
||||
|
||||
if(cnt != 0)
|
||||
fputc(',', out);
|
||||
if (rc == READ_BOOTSTRAP_ERROR)
|
||||
die("Failed to read the bootstrap input file.\n");
|
||||
|
||||
if (rc == READ_BOOTSTRAP_EOF)
|
||||
break;
|
||||
|
||||
/* Put line break after each 16 hex characters */
|
||||
if(cnt && (cnt%16 == 0))
|
||||
fputc('\n', out);
|
||||
|
||||
fprintf(out,"0x%02x",c);
|
||||
}
|
||||
fprintf(out,",0x00");
|
||||
print_query(out, query);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(out,"\"");
|
||||
while (fgets(buff, sizeof(buff), in))
|
||||
{
|
||||
char *curr= buff;
|
||||
while (*curr)
|
||||
{
|
||||
if (*curr == '\n')
|
||||
{
|
||||
/*
|
||||
Reached end of line, add escaped newline, escaped
|
||||
backslash and a newline to outfile
|
||||
*/
|
||||
fprintf(out, "\\n \"\n\"");
|
||||
curr++;
|
||||
}
|
||||
else if (*curr == '\r')
|
||||
{
|
||||
curr++; /* Skip */
|
||||
}
|
||||
else
|
||||
{
|
||||
if (*curr == '"')
|
||||
{
|
||||
/* Needs escape */
|
||||
fputc('\\', out);
|
||||
}
|
||||
|
||||
fputc(*curr, out);
|
||||
curr++;
|
||||
}
|
||||
}
|
||||
if (*(curr-1) != '\n')
|
||||
{
|
||||
/*
|
||||
Some compilers have a max string length,
|
||||
insert a newline at every 512th char in long
|
||||
strings
|
||||
*/
|
||||
fprintf(out, "\"\n\"");
|
||||
}
|
||||
}
|
||||
fprintf(out, "\\\n\"");
|
||||
}
|
||||
|
||||
fprintf(out, "};\n");
|
||||
fprintf(out, "NULL\n};\n");
|
||||
|
||||
fclose(in);
|
||||
fclose(out);
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -59,7 +59,8 @@ SET (SQL_SOURCE
|
|||
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_list.cc sql_load.cc sql_manager.cc sql_parse.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
|
||||
debug_sync.cc debug_sync.h
|
||||
sql_repl.cc sql_select.cc sql_show.cc sql_state.c sql_string.cc
|
||||
|
|
|
@ -1069,7 +1069,22 @@ inline LEX_STRING *hton_name(const handlerton *hton)
|
|||
#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
|
||||
#define HTON_NO_PARTITION (1 << 8) //You can not partition these tables
|
||||
#define HTON_NO_PARTITION (1 << 8) //Not partition of these tables
|
||||
|
||||
/*
|
||||
This flag should be set when deciding that the engine does not allow
|
||||
row based binary logging (RBL) optimizations.
|
||||
|
||||
Currently, setting this flag, means that table's read/write_set will
|
||||
be left untouched when logging changes to tables in this engine. In
|
||||
practice this means that the server will not mess around with
|
||||
table->write_set and/or table->read_set when using RBL and deciding
|
||||
whether to log full or minimal rows.
|
||||
|
||||
It's valuable for instance for virtual tables, eg: Performance
|
||||
Schema which have no meaning for replication.
|
||||
*/
|
||||
#define HTON_NO_BINLOG_ROW_OPT (1 << 9)
|
||||
|
||||
class Ha_trx_info;
|
||||
|
||||
|
@ -1446,21 +1461,24 @@ typedef struct st_range_seq_if
|
|||
|
||||
typedef bool (*SKIP_INDEX_TUPLE_FUNC) (range_seq_t seq, range_id_t range_info);
|
||||
|
||||
class COST_VECT
|
||||
class Cost_estimate
|
||||
{
|
||||
public:
|
||||
double io_count; /* number of I/O */
|
||||
double avg_io_cost; /* cost of an average I/O oper. */
|
||||
double cpu_cost; /* cost of operations in CPU */
|
||||
double mem_cost; /* cost of used memory */
|
||||
double import_cost; /* cost of remote operations */
|
||||
double mem_cost; /* cost of used memory */
|
||||
|
||||
enum { IO_COEFF=1 };
|
||||
enum { CPU_COEFF=1 };
|
||||
enum { MEM_COEFF=1 };
|
||||
enum { IMPORT_COEFF=1 };
|
||||
|
||||
COST_VECT() {} // keep gcc happy
|
||||
Cost_estimate()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
double total_cost()
|
||||
{
|
||||
|
@ -1468,7 +1486,17 @@ public:
|
|||
MEM_COEFF*mem_cost + IMPORT_COEFF*import_cost;
|
||||
}
|
||||
|
||||
void zero()
|
||||
/**
|
||||
Whether or not all costs in the object are zero
|
||||
|
||||
@return true if all costs are zero, false otherwise
|
||||
*/
|
||||
bool is_zero() const
|
||||
{
|
||||
return !(io_count || cpu_cost || import_cost || mem_cost);
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
avg_io_cost= 1.0;
|
||||
io_count= cpu_cost= mem_cost= import_cost= 0.0;
|
||||
|
@ -1482,13 +1510,14 @@ public:
|
|||
/* Don't multiply mem_cost */
|
||||
}
|
||||
|
||||
void add(const COST_VECT* cost)
|
||||
void add(const Cost_estimate* cost)
|
||||
{
|
||||
double io_count_sum= io_count + cost->io_count;
|
||||
add_io(cost->io_count, cost->avg_io_cost);
|
||||
io_count= io_count_sum;
|
||||
cpu_cost += cost->cpu_cost;
|
||||
}
|
||||
|
||||
void add_io(double add_io_cnt, double add_avg_cost)
|
||||
{
|
||||
/* In edge cases add_io_cnt may be zero */
|
||||
|
@ -1501,20 +1530,28 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
/// Add to CPU cost
|
||||
void add_cpu(double add_cpu_cost) { cpu_cost+= add_cpu_cost; }
|
||||
|
||||
/// Add to import cost
|
||||
void add_import(double add_import_cost) { import_cost+= add_import_cost; }
|
||||
|
||||
/// Add to memory cost
|
||||
void add_mem(double add_mem_cost) { mem_cost+= add_mem_cost; }
|
||||
|
||||
/*
|
||||
To be used when we go from old single value-based cost calculations to
|
||||
the new COST_VECT-based.
|
||||
the new Cost_estimate-based.
|
||||
*/
|
||||
void convert_from_cost(double cost)
|
||||
{
|
||||
zero();
|
||||
avg_io_cost= 1.0;
|
||||
reset();
|
||||
io_count= cost;
|
||||
}
|
||||
};
|
||||
|
||||
void get_sweep_read_cost(TABLE *table, ha_rows nrows, bool interrupted,
|
||||
COST_VECT *cost);
|
||||
Cost_estimate *cost);
|
||||
|
||||
/*
|
||||
Indicates that all scanned ranges will be singlepoint (aka equality) ranges.
|
||||
|
@ -2156,10 +2193,11 @@ public:
|
|||
virtual ha_rows multi_range_read_info_const(uint keyno, RANGE_SEQ_IF *seq,
|
||||
void *seq_init_param,
|
||||
uint n_ranges, uint *bufsz,
|
||||
uint *mrr_mode, COST_VECT *cost);
|
||||
uint *mrr_mode,
|
||||
Cost_estimate *cost);
|
||||
virtual ha_rows multi_range_read_info(uint keyno, uint n_ranges, uint keys,
|
||||
uint key_parts, uint *bufsz,
|
||||
uint *mrr_mode, COST_VECT *cost);
|
||||
uint *mrr_mode, Cost_estimate *cost);
|
||||
virtual int multi_range_read_init(RANGE_SEQ_IF *seq, void *seq_init_param,
|
||||
uint n_ranges, uint mrr_mode,
|
||||
HANDLER_BUFFER *buf);
|
||||
|
|
|
@ -32,9 +32,15 @@
|
|||
|
||||
class hash_filo_element
|
||||
{
|
||||
private:
|
||||
hash_filo_element *next_used,*prev_used;
|
||||
public:
|
||||
hash_filo_element() {}
|
||||
hash_filo_element *next()
|
||||
{ return next_used; }
|
||||
hash_filo_element *prev()
|
||||
{ return prev_used; }
|
||||
|
||||
friend class hash_filo;
|
||||
};
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@
|
|||
#include "password.h" // my_make_scrambled_password,
|
||||
// my_make_scrambled_password_323
|
||||
#include <m_ctype.h>
|
||||
#include "my_md5.h"
|
||||
#include <my_md5.h>
|
||||
#include "sha1.h"
|
||||
#include "my_aes.h"
|
||||
#include <zlib.h>
|
||||
|
@ -180,7 +180,8 @@ String *Item_func_md5::val_str_ascii(String *str)
|
|||
uchar digest[16];
|
||||
|
||||
null_value=0;
|
||||
MY_MD5_HASH(digest,(uchar *) sptr->ptr(), sptr->length());
|
||||
compute_md5_hash((char *) digest, (const char *) sptr->ptr(),
|
||||
sptr->length());
|
||||
if (str->alloc(32)) // Ensure that memory is free
|
||||
{
|
||||
null_value=1;
|
||||
|
|
|
@ -56,7 +56,7 @@
|
|||
ha_rows
|
||||
handler::multi_range_read_info_const(uint keyno, RANGE_SEQ_IF *seq,
|
||||
void *seq_init_param, uint n_ranges_arg,
|
||||
uint *bufsz, uint *flags, COST_VECT *cost)
|
||||
uint *bufsz, uint *flags, Cost_estimate *cost)
|
||||
{
|
||||
KEY_MULTI_RANGE range;
|
||||
range_seq_t seq_it;
|
||||
|
@ -106,7 +106,7 @@ handler::multi_range_read_info_const(uint keyno, RANGE_SEQ_IF *seq,
|
|||
{
|
||||
/* The following calculation is the same as in multi_range_read_info(): */
|
||||
*flags |= HA_MRR_USE_DEFAULT_IMPL;
|
||||
cost->zero();
|
||||
cost->reset();
|
||||
cost->avg_io_cost= 1; /* assume random seeks */
|
||||
if ((*flags & HA_MRR_INDEX_ONLY) && total_rows > 2)
|
||||
cost->io_count= keyread_time(keyno, n_ranges, (uint)total_rows);
|
||||
|
@ -154,7 +154,7 @@ handler::multi_range_read_info_const(uint keyno, RANGE_SEQ_IF *seq,
|
|||
|
||||
ha_rows handler::multi_range_read_info(uint keyno, uint n_ranges, uint n_rows,
|
||||
uint key_parts, uint *bufsz,
|
||||
uint *flags, COST_VECT *cost)
|
||||
uint *flags, Cost_estimate *cost)
|
||||
{
|
||||
/*
|
||||
Currently we expect this function to be called only in preparation of scan
|
||||
|
@ -165,7 +165,7 @@ ha_rows handler::multi_range_read_info(uint keyno, uint n_ranges, uint n_rows,
|
|||
*bufsz= 0; /* Default implementation doesn't need a buffer */
|
||||
*flags |= HA_MRR_USE_DEFAULT_IMPL;
|
||||
|
||||
cost->zero();
|
||||
cost->reset();
|
||||
cost->avg_io_cost= 1; /* assume random seeks */
|
||||
|
||||
/* Produce the same cost as non-MRR code does */
|
||||
|
@ -1402,7 +1402,7 @@ int DsMrr_impl::dsmrr_next(range_id_t *range_info)
|
|||
*/
|
||||
ha_rows DsMrr_impl::dsmrr_info(uint keyno, uint n_ranges, uint rows,
|
||||
uint key_parts,
|
||||
uint *bufsz, uint *flags, COST_VECT *cost)
|
||||
uint *bufsz, uint *flags, Cost_estimate *cost)
|
||||
{
|
||||
ha_rows __attribute__((unused)) res;
|
||||
uint def_flags= *flags;
|
||||
|
@ -1437,7 +1437,7 @@ ha_rows DsMrr_impl::dsmrr_info(uint keyno, uint n_ranges, uint rows,
|
|||
|
||||
ha_rows DsMrr_impl::dsmrr_info_const(uint keyno, RANGE_SEQ_IF *seq,
|
||||
void *seq_init_param, uint n_ranges,
|
||||
uint *bufsz, uint *flags, COST_VECT *cost)
|
||||
uint *bufsz, uint *flags, Cost_estimate *cost)
|
||||
{
|
||||
ha_rows rows;
|
||||
uint def_flags= *flags;
|
||||
|
@ -1551,9 +1551,9 @@ bool DsMrr_impl::check_cpk_scan(THD *thd, uint keyno, uint mrr_flags)
|
|||
|
||||
|
||||
bool DsMrr_impl::choose_mrr_impl(uint keyno, ha_rows rows, uint *flags,
|
||||
uint *bufsz, COST_VECT *cost)
|
||||
uint *bufsz, Cost_estimate *cost)
|
||||
{
|
||||
COST_VECT dsmrr_cost;
|
||||
Cost_estimate dsmrr_cost;
|
||||
bool res;
|
||||
THD *thd= current_thd;
|
||||
|
||||
|
@ -1655,7 +1655,7 @@ int DsMrr_impl::dsmrr_explain_info(uint mrr_mode, char *str, size_t size)
|
|||
}
|
||||
|
||||
|
||||
static void get_sort_and_sweep_cost(TABLE *table, ha_rows nrows, COST_VECT *cost);
|
||||
static void get_sort_and_sweep_cost(TABLE *table, ha_rows nrows, Cost_estimate *cost);
|
||||
|
||||
|
||||
/**
|
||||
|
@ -1673,7 +1673,7 @@ static void get_sort_and_sweep_cost(TABLE *table, ha_rows nrows, COST_VECT *cost
|
|||
*/
|
||||
|
||||
bool DsMrr_impl::get_disk_sweep_mrr_cost(uint keynr, ha_rows rows, uint flags,
|
||||
uint *buffer_size, COST_VECT *cost)
|
||||
uint *buffer_size, Cost_estimate *cost)
|
||||
{
|
||||
ulong max_buff_entries, elem_size;
|
||||
ha_rows rows_in_full_step;
|
||||
|
@ -1707,13 +1707,13 @@ bool DsMrr_impl::get_disk_sweep_mrr_cost(uint keynr, ha_rows rows, uint flags,
|
|||
}
|
||||
else
|
||||
{
|
||||
cost->zero();
|
||||
cost->reset();
|
||||
*buffer_size= max(*buffer_size,
|
||||
(size_t)(1.2*rows_in_last_step) * elem_size +
|
||||
primary_file->ref_length + table->key_info[keynr].key_length);
|
||||
}
|
||||
|
||||
COST_VECT last_step_cost;
|
||||
Cost_estimate last_step_cost;
|
||||
get_sort_and_sweep_cost(table, rows_in_last_step, &last_step_cost);
|
||||
cost->add(&last_step_cost);
|
||||
|
||||
|
@ -1742,7 +1742,7 @@ bool DsMrr_impl::get_disk_sweep_mrr_cost(uint keynr, ha_rows rows, uint flags,
|
|||
*/
|
||||
|
||||
static
|
||||
void get_sort_and_sweep_cost(TABLE *table, ha_rows nrows, COST_VECT *cost)
|
||||
void get_sort_and_sweep_cost(TABLE *table, ha_rows nrows, Cost_estimate *cost)
|
||||
{
|
||||
if (nrows)
|
||||
{
|
||||
|
@ -1754,7 +1754,7 @@ void get_sort_and_sweep_cost(TABLE *table, ha_rows nrows, COST_VECT *cost)
|
|||
cost->cpu_cost += cmp_op * log2(cmp_op);
|
||||
}
|
||||
else
|
||||
cost->zero();
|
||||
cost->reset();
|
||||
}
|
||||
|
||||
|
||||
|
@ -1802,11 +1802,11 @@ void get_sort_and_sweep_cost(TABLE *table, ha_rows nrows, COST_VECT *cost)
|
|||
*/
|
||||
|
||||
void get_sweep_read_cost(TABLE *table, ha_rows nrows, bool interrupted,
|
||||
COST_VECT *cost)
|
||||
Cost_estimate *cost)
|
||||
{
|
||||
DBUG_ENTER("get_sweep_read_cost");
|
||||
|
||||
cost->zero();
|
||||
cost->reset();
|
||||
if (table->file->primary_key_is_clustered())
|
||||
{
|
||||
cost->io_count= table->file->read_time(table->s->primary_key,
|
||||
|
|
|
@ -562,11 +562,11 @@ public:
|
|||
int dsmrr_next(range_id_t *range_info);
|
||||
|
||||
ha_rows dsmrr_info(uint keyno, uint n_ranges, uint keys, uint key_parts,
|
||||
uint *bufsz, uint *flags, COST_VECT *cost);
|
||||
uint *bufsz, uint *flags, Cost_estimate *cost);
|
||||
|
||||
ha_rows dsmrr_info_const(uint keyno, RANGE_SEQ_IF *seq,
|
||||
void *seq_init_param, uint n_ranges, uint *bufsz,
|
||||
uint *flags, COST_VECT *cost);
|
||||
uint *flags, Cost_estimate *cost);
|
||||
|
||||
int dsmrr_explain_info(uint mrr_mode, char *str, size_t size);
|
||||
private:
|
||||
|
@ -624,9 +624,9 @@ private:
|
|||
Forward_lifo_buffer rowid_buffer;
|
||||
|
||||
bool choose_mrr_impl(uint keyno, ha_rows rows, uint *flags, uint *bufsz,
|
||||
COST_VECT *cost);
|
||||
Cost_estimate *cost);
|
||||
bool get_disk_sweep_mrr_cost(uint keynr, ha_rows rows, uint flags,
|
||||
uint *buffer_size, COST_VECT *cost);
|
||||
uint *buffer_size, Cost_estimate *cost);
|
||||
bool check_cpk_scan(THD *thd, uint keyno, uint mrr_flags);
|
||||
|
||||
bool setup_buffer_sharing(uint key_size_in_keybuf, key_part_map key_tuple_map);
|
||||
|
|
|
@ -207,6 +207,7 @@ extern int bootstrap_error;
|
|||
extern I_List<THD> threads;
|
||||
extern char err_shared_dir[];
|
||||
extern TYPELIB thread_handling_typelib;
|
||||
extern ulong log_warnings;
|
||||
|
||||
/*
|
||||
THR_MALLOC is a key which will be used to set/get MEM_ROOT** for a thread,
|
||||
|
|
|
@ -890,7 +890,7 @@ static bool is_key_scan_ror(PARAM *param, uint keynr, uint8 nparts);
|
|||
static ha_rows check_quick_select(PARAM *param, uint idx, bool index_only,
|
||||
SEL_ARG *tree, bool update_tbl_stats,
|
||||
uint *mrr_flags, uint *bufsize,
|
||||
COST_VECT *cost);
|
||||
Cost_estimate *cost);
|
||||
|
||||
QUICK_RANGE_SELECT *get_quick_select(PARAM *param,uint index,
|
||||
SEL_ARG *key_tree, uint mrr_flags,
|
||||
|
@ -6691,7 +6691,7 @@ static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree,
|
|||
if (*key)
|
||||
{
|
||||
ha_rows found_records;
|
||||
COST_VECT cost;
|
||||
Cost_estimate cost;
|
||||
double found_read_time;
|
||||
uint mrr_flags, buf_size;
|
||||
INDEX_SCAN_INFO *index_scan;
|
||||
|
@ -9941,7 +9941,7 @@ void SEL_ARG::test_use_count(SEL_ARG *root)
|
|||
static
|
||||
ha_rows check_quick_select(PARAM *param, uint idx, bool index_only,
|
||||
SEL_ARG *tree, bool update_tbl_stats,
|
||||
uint *mrr_flags, uint *bufsize, COST_VECT *cost)
|
||||
uint *mrr_flags, uint *bufsize, Cost_estimate *cost)
|
||||
{
|
||||
SEL_ARG_RANGE_SEQ seq;
|
||||
RANGE_SEQ_IF seq_if = {NULL, sel_arg_range_seq_init, sel_arg_range_seq_next, 0, 0};
|
||||
|
@ -10430,7 +10430,7 @@ QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table,
|
|||
QUICK_RANGE *range;
|
||||
uint part;
|
||||
bool create_err= FALSE;
|
||||
COST_VECT cost;
|
||||
Cost_estimate cost;
|
||||
|
||||
old_root= thd->mem_root;
|
||||
/* The following call may change thd->mem_root */
|
||||
|
@ -12103,7 +12103,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time)
|
|||
cur_index_tree= get_index_range_tree(cur_index, tree, param,
|
||||
&cur_param_idx);
|
||||
/* Check if this range tree can be used for prefix retrieval. */
|
||||
COST_VECT dummy_cost;
|
||||
Cost_estimate dummy_cost;
|
||||
uint mrr_flags= HA_MRR_USE_DEFAULT_IMPL;
|
||||
uint mrr_bufsize=0;
|
||||
cur_quick_prefix_records= check_quick_select(param, cur_param_idx,
|
||||
|
|
|
@ -2198,7 +2198,7 @@ bool optimize_semijoin_nests(JOIN *join, table_map all_table_map)
|
|||
Set the cost to do a full scan of the temptable (will need this to
|
||||
consider doing sjm-scan):
|
||||
*/
|
||||
sjm->scan_cost.zero();
|
||||
sjm->scan_cost.reset();
|
||||
sjm->scan_cost.add_io(sjm->rows, lookup_cost);
|
||||
|
||||
sjm->lookup_cost.convert_from_cost(lookup_cost);
|
||||
|
@ -2633,12 +2633,12 @@ bool Sj_materialization_picker::check_qep(JOIN *join,
|
|||
else
|
||||
{
|
||||
/* This is SJ-Materialization with lookups */
|
||||
COST_VECT prefix_cost;
|
||||
Cost_estimate prefix_cost;
|
||||
signed int first_tab= (int)idx - mat_info->tables;
|
||||
double prefix_rec_count;
|
||||
if (first_tab < (int)join->const_tables)
|
||||
{
|
||||
prefix_cost.zero();
|
||||
prefix_cost.reset();
|
||||
prefix_rec_count= 1.0;
|
||||
}
|
||||
else
|
||||
|
|
|
@ -6508,6 +6508,225 @@ ER_BINLOG_UNSAFE_AUTOINC_NOT_FIRST
|
|||
# End of 5.5 error messages.
|
||||
#
|
||||
|
||||
ER_COL_COUNT_DOESNT_MATCH_CORRUPTED_V2
|
||||
eng "Column count of %s.%s is wrong. Expected %d, found %d. The table is probably corrupted"
|
||||
ger "Spaltenanzahl von %s.%s falsch. %d erwartet, aber %d gefunden. Tabelle ist wahrscheinlich beschädigt"
|
||||
|
||||
ER_CANNOT_LOAD_FROM_TABLE_V2
|
||||
eng "Cannot load from %s.%s. The table is probably corrupted"
|
||||
ger "Kann %s.%s nicht einlesen. Tabelle ist wahrscheinlich beschädigt"
|
||||
|
||||
ER_MASTER_DELAY_VALUE_OUT_OF_RANGE
|
||||
eng "The requested value %u for the master delay exceeds the maximum %u"
|
||||
ER_ONLY_FD_AND_RBR_EVENTS_ALLOWED_IN_BINLOG_STATEMENT
|
||||
eng "Only Format_description_log_event and row events are allowed in BINLOG statements (but %s was provided)"
|
||||
|
||||
ER_PARTITION_EXCHANGE_DIFFERENT_OPTION
|
||||
eng "Non matching attribute '%-.64s' between partition and table"
|
||||
swe "Attributet '%-.64s' är olika mellan partition och tabell"
|
||||
ER_PARTITION_EXCHANGE_PART_TABLE
|
||||
eng "Table to exchange with partition is partitioned: '%-.64s'"
|
||||
swe "Tabellen att byta ut mot partition är partitionerad: '%-.64s'"
|
||||
ER_PARTITION_EXCHANGE_TEMP_TABLE
|
||||
eng "Table to exchange with partition is temporary: '%-.64s'"
|
||||
swe "Tabellen att byta ut mot partition är temporär: '%-.64s'"
|
||||
ER_PARTITION_INSTEAD_OF_SUBPARTITION
|
||||
eng "Subpartitioned table, use subpartition instead of partition"
|
||||
swe "Subpartitionerad tabell, använd subpartition istället för partition"
|
||||
ER_UNKNOWN_PARTITION
|
||||
eng "Unknown partition '%-.64s' in table '%-.64s'"
|
||||
swe "Okänd partition '%-.64s' i tabell '%-.64s'"
|
||||
ER_TABLES_DIFFERENT_METADATA
|
||||
eng "Tables have different definitions"
|
||||
swe "Tabellerna har olika definitioner"
|
||||
ER_ROW_DOES_NOT_MATCH_PARTITION
|
||||
eng "Found a row that does not match the partition"
|
||||
swe "Hittade en rad som inte passar i partitionen"
|
||||
ER_BINLOG_CACHE_SIZE_GREATER_THAN_MAX
|
||||
eng "Option binlog_cache_size (%lu) is greater than max_binlog_cache_size (%lu); setting binlog_cache_size equal to max_binlog_cache_size."
|
||||
ER_WARN_INDEX_NOT_APPLICABLE
|
||||
eng "Cannot use %-.64s access on index '%-.64s' due to type or collation conversion on field '%-.64s'"
|
||||
|
||||
ER_PARTITION_EXCHANGE_FOREIGN_KEY
|
||||
eng "Table to exchange with partition has foreign key references: '%-.64s'"
|
||||
swe "Tabellen att byta ut mot partition har foreign key referenser: '%-.64s'"
|
||||
ER_NO_SUCH_KEY_VALUE
|
||||
eng "Key value '%-.192s' was not found in table '%-.192s.%-.192s'"
|
||||
ER_RPL_INFO_DATA_TOO_LONG
|
||||
eng "Data for column '%s' too long"
|
||||
ER_NETWORK_READ_EVENT_CHECKSUM_FAILURE
|
||||
eng "Replication event checksum verification failed while reading from network."
|
||||
ER_BINLOG_READ_EVENT_CHECKSUM_FAILURE
|
||||
eng "Replication event checksum verification failed while reading from a log file."
|
||||
|
||||
ER_BINLOG_STMT_CACHE_SIZE_GREATER_THAN_MAX
|
||||
eng "Option binlog_stmt_cache_size (%lu) is greater than max_binlog_stmt_cache_size (%lu); setting binlog_stmt_cache_size equal to max_binlog_stmt_cache_size."
|
||||
ER_CANT_UPDATE_TABLE_IN_CREATE_TABLE_SELECT
|
||||
eng "Can't update table '%-.192s' while '%-.192s' is being created."
|
||||
|
||||
ER_PARTITION_CLAUSE_ON_NONPARTITIONED
|
||||
eng "PARTITION () clause on non partitioned table"
|
||||
swe "PARTITION () klausul för en icke partitionerad tabell"
|
||||
ER_ROW_DOES_NOT_MATCH_GIVEN_PARTITION_SET
|
||||
eng "Found a row not matching the given partition set"
|
||||
swe "Hittade en rad som inte passar i någon given partition"
|
||||
ER_NO_SUCH_PARTITION
|
||||
cze "partion '%-.64s' neexistuje"
|
||||
dan "partition '%-.64s' eksisterer ikke"
|
||||
nla "partition '%-.64s' bestaat niet"
|
||||
eng "partition '%-.64s' doesn't exist"
|
||||
est "partition '%-.64s' ei eksisteeri"
|
||||
fre "La partition '%-.64s' n'existe pas"
|
||||
ger "Die partition '%-.64s' existiert nicht"
|
||||
hun "A '%-.64s' partition nem letezik"
|
||||
ita "La tabella particione '%-.64s' non esiste"
|
||||
nor "Partition '%-.64s' doesn't exist"
|
||||
norwegian-ny "Partition '%-.64s' doesn't exist"
|
||||
pol "Partition '%-.64s' doesn't exist"
|
||||
por "Particion '%-.64s' n<>o existe"
|
||||
rum "Partition '%-.64s' nu exista"
|
||||
serbian "Partition '%-.64s' ne postoji"
|
||||
slo "Partition '%-.64s' doesn't exist"
|
||||
spa "Particion '%-.64s' no existe"
|
||||
swe "Det finns ingen partition som heter '%-.64s'"
|
||||
|
||||
ER_CHANGE_RPL_INFO_REPOSITORY_FAILURE
|
||||
eng "Failure while changing the type of replication repository: %s."
|
||||
|
||||
ER_WARNING_NOT_COMPLETE_ROLLBACK_WITH_CREATED_TEMP_TABLE
|
||||
eng "The creation of some temporary tables could not be rolled back."
|
||||
ER_WARNING_NOT_COMPLETE_ROLLBACK_WITH_DROPPED_TEMP_TABLE
|
||||
eng "Some temporary tables were dropped, but these operations could not be rolled back."
|
||||
|
||||
ER_MTS_FEATURE_IS_NOT_SUPPORTED
|
||||
eng "%s is not supported in multi-threaded slave mode. %s"
|
||||
ER_MTS_UPDATED_DBS_GREATER_MAX
|
||||
eng "The number of modified databases exceeds the maximum %d; the database names will not be included in the replication event metadata."
|
||||
ER_MTS_CANT_PARALLEL
|
||||
eng "Cannot execute the current event group in the parallel mode. Encountered event %s, relay-log name %s, position %s which prevents execution of this event group in parallel mode. Reason: %s."
|
||||
ER_MTS_INCONSISTENT_DATA
|
||||
eng "%s"
|
||||
|
||||
ER_FULLTEXT_NOT_SUPPORTED_WITH_PARTITIONING
|
||||
eng "FULLTEXT index is not supported for partitioned tables."
|
||||
swe "FULLTEXT index stöds ej för partitionerade tabeller."
|
||||
|
||||
ER_DA_INVALID_CONDITION_NUMBER 35000
|
||||
eng "Invalid condition number"
|
||||
por "Número de condição inválido"
|
||||
|
||||
ER_INSECURE_PLAIN_TEXT
|
||||
eng "Sending passwords in plain text without SSL/TLS is extremely insecure."
|
||||
|
||||
ER_INSECURE_CHANGE_MASTER
|
||||
eng "Storing MySQL user name or password information in the master.info repository is not secure and is therefore not recommended. Please see the MySQL Manual for more about this issue and possible alternatives."
|
||||
|
||||
ER_FOREIGN_DUPLICATE_KEY_WITH_CHILD_INFO 23000 S1009
|
||||
eng "Foreign key constraint for table '%.192s', record '%-.192s' would lead to a duplicate entry in table '%.192s', key '%.192s'"
|
||||
ger "Fremdschlüssel-Beschränkung für Tabelle '%.192s', Datensatz '%-.192s' würde zu einem doppelten Eintrag in Tabelle '%.192s', Schlüssel '%.192s' führen"
|
||||
swe "FOREIGN KEY constraint för tabell '%.192s', posten '%-.192s' kan inte uppdatera barntabell '%.192s' på grund av nyckel '%.192s'"
|
||||
|
||||
ER_FOREIGN_DUPLICATE_KEY_WITHOUT_CHILD_INFO 23000 S1009
|
||||
eng "Foreign key constraint for table '%.192s', record '%-.192s' would lead to a duplicate entry in a child table"
|
||||
ger "Fremdschlüssel-Beschränkung für Tabelle '%.192s', Datensatz '%-.192s' würde zu einem doppelten Eintrag in einer Kind-Tabelle führen"
|
||||
swe "FOREIGN KEY constraint för tabell '%.192s', posten '%-.192s' kan inte uppdatera en barntabell på grund av UNIQUE-test"
|
||||
ER_SQLTHREAD_WITH_SECURE_SLAVE
|
||||
eng "Setting authentication options is not possible when only the Slave SQL Thread is being started."
|
||||
|
||||
ER_TABLE_HAS_NO_FT
|
||||
eng "The table does not have FULLTEXT index to support this query"
|
||||
|
||||
ER_INNODB_FT_LIMIT
|
||||
eng "InnoDB presently supports one FULLTEXT index per table"
|
||||
|
||||
ER_INNODB_NO_FT_TEMP_TABLE
|
||||
eng "Cannot create FULLTEXT index on temporary InnoDB table"
|
||||
|
||||
ER_VARIABLE_NOT_SETTABLE_IN_SF_OR_TRIGGER
|
||||
eng "The system variable %.200s cannot be set in stored functions or triggers."
|
||||
|
||||
ER_VARIABLE_NOT_SETTABLE_IN_TRANSACTION
|
||||
eng "The system variable %.200s cannot be set when there is an ongoing transaction."
|
||||
|
||||
ER_GTID_NEXT_IS_NOT_IN_GTID_NEXT_LIST
|
||||
eng "The system variable @@SESSION.GTID_NEXT has the value %.200s, which is not listed in @@SESSION.GTID_NEXT_LIST."
|
||||
|
||||
ER_CANT_CHANGE_GTID_NEXT_IN_TRANSACTION_WHEN_GTID_NEXT_LIST_IS_NULL
|
||||
eng "When @@SESSION.GTID_NEXT_LIST == NULL, the system variable @@SESSION.GTID_NEXT cannot change inside a transaction."
|
||||
|
||||
ER_SET_STATEMENT_CANNOT_INVOKE_FUNCTION
|
||||
eng "The statement 'SET %.200s' cannot invoke a stored function."
|
||||
|
||||
ER_GTID_NEXT_CANT_BE_AUTOMATIC_IF_GTID_NEXT_LIST_IS_NON_NULL
|
||||
eng "The system variable @@SESSION.GTID_NEXT cannot be 'AUTOMATIC' when @@SESSION.GTID_NEXT_LIST is non-NULL."
|
||||
|
||||
ER_SKIPPING_LOGGED_TRANSACTION
|
||||
eng "Skipping transaction %.200s because it has already been executed and logged."
|
||||
|
||||
ER_MALFORMED_GTID_SET_SPECIFICATION
|
||||
eng "Malformed GTID set specification '%.200s'."
|
||||
|
||||
ER_MALFORMED_GTID_SET_ENCODING
|
||||
eng "Malformed GTID set encoding."
|
||||
|
||||
ER_MALFORMED_GTID_SPECIFICATION
|
||||
eng "Malformed GTID specification '%.200s'."
|
||||
|
||||
ER_GNO_EXHAUSTED
|
||||
eng "Impossible to generate Global Transaction Identifier: the integer component reached the maximal value. Restart the server with a new server_uuid."
|
||||
|
||||
ER_BAD_SLAVE_AUTO_POSITION
|
||||
eng "Parameters MASTER_LOG_FILE, MASTER_LOG_POS, RELAY_LOG_FILE and RELAY_LOG_POS cannot be set when MASTER_AUTO_POSITION is active."
|
||||
|
||||
ER_AUTO_POSITION_REQUIRES_GTID_MODE_ON
|
||||
eng "CHANGE MASTER TO AUTO_POSITION = 1 can only be executed when GTID_MODE = ON."
|
||||
|
||||
ER_CANT_DO_IMPLICIT_COMMIT_IN_TRX_WHEN_GTID_NEXT_IS_SET
|
||||
eng "Cannot execute statements with implicit commit inside a transaction when GTID_NEXT != AUTOMATIC or GTID_NEXT_LIST != NULL."
|
||||
|
||||
ER_GTID_MODE_2_OR_3_REQUIRES_DISABLE_GTID_UNSAFE_STATEMENTS_ON
|
||||
eng "GTID_MODE = ON or GTID_MODE = UPGRADE_STEP_2 requires DISABLE_GTID_UNSAFE_STATEMENTS = 1."
|
||||
|
||||
ER_GTID_MODE_REQUIRES_BINLOG
|
||||
eng "GTID_MODE = ON or UPGRADE_STEP_1 or UPGRADE_STEP_2 requires --log-bin and --log-slave-updates."
|
||||
|
||||
ER_CANT_SET_GTID_NEXT_TO_GTID_WHEN_GTID_MODE_IS_OFF
|
||||
eng "GTID_NEXT cannot be set to UUID:NUMBER when GTID_MODE = OFF."
|
||||
|
||||
ER_CANT_SET_GTID_NEXT_TO_ANONYMOUS_WHEN_GTID_MODE_IS_ON
|
||||
eng "GTID_NEXT cannot be set to ANONYMOUS when GTID_MODE = ON."
|
||||
|
||||
ER_CANT_SET_GTID_NEXT_LIST_TO_NON_NULL_WHEN_GTID_MODE_IS_OFF
|
||||
eng "GTID_NEXT_LIST cannot be set to a non-NULL value when GTID_MODE = OFF."
|
||||
|
||||
ER_FOUND_GTID_EVENT_WHEN_GTID_MODE_IS_OFF
|
||||
eng "Found a Gtid_log_event or Previous_gtids_log_event when GTID_MODE = OFF."
|
||||
|
||||
ER_GTID_UNSAFE_NON_TRANSACTIONAL_TABLE
|
||||
eng "Updates to non-transactional tables are forbidden when DISABLE_GTID_UNSAFE_STATEMENTS = 1."
|
||||
|
||||
ER_GTID_UNSAFE_CREATE_SELECT
|
||||
eng "CREATE TABLE ... SELECT is forbidden when DISABLE_GTID_UNSAFE_STATEMENTS = 1."
|
||||
|
||||
ER_GTID_UNSAFE_CREATE_DROP_TEMPORARY_TABLE_IN_TRANSACTION
|
||||
eng "When DISABLE_GTID_UNSAFE_STATEMENTS = 1, the statements CREATE TEMPORARY TABLE and DROP TEMPORARY TABLE can be executed in a non-transactional context only, and require that AUTOCOMMIT = 1."
|
||||
|
||||
ER_GTID_MODE_CAN_ONLY_CHANGE_ONE_STEP_AT_A_TIME
|
||||
eng "The value of GTID_MODE can only change one step at a time: OFF <-> UPGRADE_STEP_1 <-> UPGRADE_STEP_2 <-> ON. Also note that this value must be stepped up or down simultaneously on all servers; see the Manual for instructions."
|
||||
|
||||
ER_MASTER_HAS_PURGED_REQUIRED_GTIDS
|
||||
eng "The slave is connecting using CHANGE MASTER TO MASTER_AUTO_POSITION = 1, but the master has purged binary logs containing GTIDs that the slave requires."
|
||||
|
||||
ER_CANT_SET_GTID_NEXT_WHEN_OWNING_GTID
|
||||
eng "GTID_NEXT cannot be changed by a client that owns a GTID. The client owns %s. Ownership is released on COMMIT or ROLLBACK."
|
||||
|
||||
ER_UNKNOWN_EXPLAIN_FORMAT
|
||||
eng "Unknown EXPLAIN format name: '%s'"
|
||||
rus "Неизвестное имя формата команды EXPLAIN: '%s'"
|
||||
|
||||
ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION 25006
|
||||
eng "Cannot execute statement in a READ ONLY transaction."
|
||||
|
||||
#
|
||||
# MariaDB error messages section starts here
|
||||
#
|
||||
|
@ -6547,10 +6766,10 @@ ER_UNKNOWN_OPTION
|
|||
eng "Unknown option '%-.64s'"
|
||||
ER_BAD_OPTION_VALUE
|
||||
eng "Incorrect value '%-.64s' for option '%-.64s'"
|
||||
ER_NETWORK_READ_EVENT_CHECKSUM_FAILURE
|
||||
eng "Replication event checksum verification failed while reading from network."
|
||||
ER_BINLOG_READ_EVENT_CHECKSUM_FAILURE
|
||||
eng "Replication event checksum verification failed while reading from a log file."
|
||||
ER_NOT_USED_ERROR_MESSAGE
|
||||
eng ""
|
||||
ER_NOT_USED_ERROR_MESSAGE2
|
||||
eng ""
|
||||
ER_CANT_DO_ONLINE
|
||||
eng "Can't execute the given '%s' command as online"
|
||||
ER_DATA_OVERFLOW 22003
|
||||
|
|
99
sql/sql_bootstrap.cc
Normal file
99
sql/sql_bootstrap.cc
Normal file
|
@ -0,0 +1,99 @@
|
|||
/* Copyright (c) 2010, Oracle and/or its affiliates.
|
||||
|
||||
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,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
|
||||
|
||||
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include "sql_bootstrap.h"
|
||||
|
||||
int read_bootstrap_query(char *query, int *query_length,
|
||||
fgets_input_t input, fgets_fn_t fgets_fn)
|
||||
{
|
||||
char line_buffer[MAX_BOOTSTRAP_LINE_SIZE];
|
||||
const char *line;
|
||||
int len;
|
||||
int query_len= 0;
|
||||
|
||||
for ( ; ; )
|
||||
{
|
||||
line= (*fgets_fn)(line_buffer, sizeof(line_buffer), input);
|
||||
|
||||
if (line == NULL)
|
||||
return (query_len ? READ_BOOTSTRAP_ERROR : READ_BOOTSTRAP_EOF);
|
||||
|
||||
len= strlen(line);
|
||||
|
||||
/*
|
||||
Remove trailing whitespace characters.
|
||||
This assumes:
|
||||
- no multibyte encoded character can be found at the very end of a line,
|
||||
- whitespace characters from the "C" locale only.
|
||||
which is sufficient for the kind of queries found
|
||||
in the bootstrap scripts.
|
||||
*/
|
||||
while (len && (isspace(line[len - 1])))
|
||||
len--;
|
||||
/*
|
||||
Cleanly end the string, so we don't have to test len > x
|
||||
all the time before reading line[x], in the code below.
|
||||
*/
|
||||
line_buffer[len]= '\0';
|
||||
|
||||
/* Skip blank lines */
|
||||
if (len == 0)
|
||||
continue;
|
||||
|
||||
/* Skip # comments */
|
||||
if (line[0] == '#')
|
||||
continue;
|
||||
|
||||
/* Skip -- comments */
|
||||
if ((line[0] == '-') && (line[1] == '-'))
|
||||
continue;
|
||||
|
||||
/* Skip delimiter, ignored. */
|
||||
if (strncmp(line, "delimiter", 9) == 0)
|
||||
continue;
|
||||
|
||||
/* Append the current line to a multi line query. */
|
||||
|
||||
if (query_len + len + 1 >= MAX_BOOTSTRAP_QUERY_SIZE)
|
||||
return READ_BOOTSTRAP_ERROR;
|
||||
|
||||
if (query_len != 0)
|
||||
{
|
||||
/*
|
||||
Append a \n to the current line, if any,
|
||||
to preserve the intended presentation.
|
||||
*/
|
||||
query[query_len]= '\n';
|
||||
query_len++;
|
||||
}
|
||||
memcpy(query + query_len, line, len);
|
||||
query_len+= len;
|
||||
|
||||
if (line[len - 1] == ';')
|
||||
{
|
||||
/*
|
||||
The last line is terminated by ';'.
|
||||
Return the query found.
|
||||
*/
|
||||
query[query_len]= '\0';
|
||||
*query_length= query_len;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
44
sql/sql_bootstrap.h
Normal file
44
sql/sql_bootstrap.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
/* Copyright (c) 2010, 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,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
|
||||
|
||||
|
||||
#ifndef SQL_BOOTSTRAP_H
|
||||
#define SQL_BOOTSTRAP_H
|
||||
|
||||
/**
|
||||
The maximum size of a bootstrap query.
|
||||
Increase this size if parsing a longer query during bootstrap is necessary.
|
||||
The longest query in use depends on the documentation content,
|
||||
see the file fill_help_tables.sql
|
||||
*/
|
||||
#define MAX_BOOTSTRAP_QUERY_SIZE 20000
|
||||
/**
|
||||
The maximum size of a bootstrap query, expressed in a single line.
|
||||
Do not increase this size, use the multiline syntax instead.
|
||||
*/
|
||||
#define MAX_BOOTSTRAP_LINE_SIZE 20000
|
||||
|
||||
#define READ_BOOTSTRAP_EOF 1
|
||||
#define READ_BOOTSTRAP_ERROR 2
|
||||
|
||||
typedef void *fgets_input_t;
|
||||
typedef char * (*fgets_fn_t)(char *, size_t, fgets_input_t);
|
||||
|
||||
int read_bootstrap_query(char *query, int *query_length,
|
||||
fgets_input_t input, fgets_fn_t fgets_fn);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -3695,13 +3695,13 @@ public:
|
|||
/*
|
||||
Cost to materialize - execute the sub-join and write rows into temp.table
|
||||
*/
|
||||
COST_VECT materialization_cost;
|
||||
Cost_estimate materialization_cost;
|
||||
|
||||
/* Cost to make one lookup in the temptable */
|
||||
COST_VECT lookup_cost;
|
||||
Cost_estimate lookup_cost;
|
||||
|
||||
/* Cost of scanning the materialized table */
|
||||
COST_VECT scan_cost;
|
||||
Cost_estimate scan_cost;
|
||||
|
||||
/* --- Execution structures ---------- */
|
||||
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
#include "m_string.h" /* LEX_STRING */
|
||||
#include "sql_string.h" /* String */
|
||||
#include "mysql_com.h" /* MYSQL_ERRMSG_SIZE */
|
||||
#include "my_time.h" /* MYSQL_TIME */
|
||||
#include "decimal.h"
|
||||
|
||||
class THD;
|
||||
|
||||
|
@ -319,6 +321,14 @@ private:
|
|||
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
|
||||
*/
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
|
|
|
@ -95,6 +95,7 @@
|
|||
#include "probes_mysql.h"
|
||||
#include "set_var.h"
|
||||
#include "log_slow.h"
|
||||
#include "sql_bootstrap.h"
|
||||
|
||||
#define FLAGSTR(V,F) ((V)&(F)?#F" ":"")
|
||||
|
||||
|
@ -481,11 +482,16 @@ void execute_init_command(THD *thd, LEX_STRING *init_command,
|
|||
}
|
||||
|
||||
|
||||
static char *fgets_fn(char *buffer, size_t size, fgets_input_t input)
|
||||
{
|
||||
MYSQL_FILE *in= static_cast<MYSQL_FILE*> (input);
|
||||
return mysql_file_fgets(buffer, size, in);
|
||||
}
|
||||
|
||||
|
||||
static void handle_bootstrap_impl(THD *thd)
|
||||
{
|
||||
MYSQL_FILE *file= bootstrap_file;
|
||||
char *buff, *res;
|
||||
|
||||
DBUG_ENTER("handle_bootstrap");
|
||||
|
||||
#ifndef EMBEDDED_LIBRARY
|
||||
|
@ -503,50 +509,30 @@ static void handle_bootstrap_impl(THD *thd)
|
|||
*/
|
||||
thd->client_capabilities|= CLIENT_MULTI_RESULTS;
|
||||
|
||||
buff= (char*) thd->net.buff;
|
||||
thd->init_for_queries();
|
||||
while (mysql_file_fgets(buff, thd->net.max_packet, file))
|
||||
|
||||
for ( ; ; )
|
||||
{
|
||||
char buffer[MAX_BOOTSTRAP_QUERY_SIZE];
|
||||
int rc, length;
|
||||
char *query;
|
||||
/* strlen() can't be deleted because mysql_file_fgets() doesn't return length */
|
||||
ulong length= (ulong) strlen(buff);
|
||||
while (buff[length-1] != '\n' && !mysql_file_feof(file))
|
||||
|
||||
rc= read_bootstrap_query(buffer, &length, file, fgets_fn);
|
||||
|
||||
if (rc == READ_BOOTSTRAP_ERROR)
|
||||
{
|
||||
/*
|
||||
We got only a part of the current string. Will try to increase
|
||||
net buffer then read the rest of the current string.
|
||||
*/
|
||||
/* purecov: begin tested */
|
||||
if (net_realloc(&(thd->net), 2 * thd->net.max_packet))
|
||||
{
|
||||
thd->protocol->end_statement();
|
||||
bootstrap_error= 1;
|
||||
break;
|
||||
}
|
||||
buff= (char*) thd->net.buff;
|
||||
res= mysql_file_fgets(buff + length, thd->net.max_packet - length, file);
|
||||
if (!res && !mysql_file_feof(file))
|
||||
{
|
||||
thd->protocol->end_statement();
|
||||
bootstrap_error= 1;
|
||||
break;
|
||||
}
|
||||
length+= (ulong) strlen(buff + length);
|
||||
/* purecov: end */
|
||||
thd->raise_error(ER_SYNTAX_ERROR);
|
||||
thd->protocol->end_statement();
|
||||
bootstrap_error= 1;
|
||||
break;
|
||||
}
|
||||
if (bootstrap_error)
|
||||
break; /* purecov: inspected */
|
||||
|
||||
while (length && (my_isspace(thd->charset(), buff[length-1]) ||
|
||||
buff[length-1] == ';'))
|
||||
length--;
|
||||
buff[length]=0;
|
||||
if (rc == READ_BOOTSTRAP_EOF)
|
||||
break;
|
||||
|
||||
/* Skip lines starting with delimiter */
|
||||
if (strncmp(buff, STRING_WITH_LEN("delimiter")) == 0)
|
||||
continue;
|
||||
DBUG_ASSERT(rc == 0);
|
||||
|
||||
query= (char *) thd->memdup_w_gap(buff, length + 1,
|
||||
query= (char *) thd->memdup_w_gap(buffer, length + 1,
|
||||
thd->db_length + 1 +
|
||||
QUERY_CACHE_DB_LENGTH_SIZE +
|
||||
QUERY_CACHE_FLAGS_SIZE);
|
||||
|
|
|
@ -9588,7 +9588,7 @@ uint check_join_cache_usage(JOIN_TAB *tab,
|
|||
uint table_index,
|
||||
JOIN_TAB *prev_tab)
|
||||
{
|
||||
COST_VECT cost;
|
||||
Cost_estimate cost;
|
||||
uint flags= 0;
|
||||
ha_rows rows= 0;
|
||||
uint bufsz= 4096;
|
||||
|
|
|
@ -763,7 +763,7 @@ typedef struct st_position :public Sql_alloc
|
|||
double read_time;
|
||||
|
||||
/* Cumulative cost and record count for the join prefix */
|
||||
COST_VECT prefix_cost;
|
||||
Cost_estimate prefix_cost;
|
||||
double prefix_record_count;
|
||||
|
||||
/*
|
||||
|
|
|
@ -4018,7 +4018,8 @@ void TABLE::reset_item_list(List<Item> *item_list) const
|
|||
void TABLE_LIST::calc_md5(char *buffer)
|
||||
{
|
||||
uchar digest[16];
|
||||
MY_MD5_HASH(digest, (uchar *) select_stmt.str, select_stmt.length);
|
||||
compute_md5_hash((char*) digest, select_stmt.str,
|
||||
select_stmt.length);
|
||||
sprintf((char *) buffer,
|
||||
"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
|
||||
digest[0], digest[1], digest[2], digest[3],
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
# Copyright (c) 2006, 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 02110-1301 USA
|
||||
|
@ -30,19 +30,29 @@ IF(UNIX)
|
|||
LINK_LIBRARIES(aio)
|
||||
ENDIF()
|
||||
ELSEIF(CMAKE_SYSTEM_NAME MATCHES "HP*")
|
||||
ADD_DEFINITIONS("-DUNIV_HPUX -DUNIV_MUST_NOT_INLINE")
|
||||
ADD_DEFINITIONS("-DUNIV_HPUX")
|
||||
ELSEIF(CMAKE_SYSTEM_NAME STREQUAL "AIX")
|
||||
ADD_DEFINITIONS("-DUNIV_AIX -DUNIX_MUST_NOT_INLINE")
|
||||
ADD_DEFINITIONS("-DUNIV_AIX")
|
||||
ELSEIF(CMAKE_SYSTEM_NAME STREQUAL "SunOS")
|
||||
ADD_DEFINITIONS("-DUNIV_SOLARIS")
|
||||
ELSE()
|
||||
ADD_DEFINITIONS("-DUNIV_MUST_NOT_INLINE")
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
# Enable InnoDB's UNIV_DEBUG for debug builds
|
||||
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DUNIV_DEBUG")
|
||||
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DUNIV_DEBUG")
|
||||
IF(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
|
||||
# After: WL#5825 Using C++ Standard Library with MySQL code
|
||||
# we no longer use -fno-exceptions
|
||||
# SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions")
|
||||
ENDIF()
|
||||
|
||||
# Enable InnoDB's UNIV_DEBUG and UNIV_SYNC_DEBUG in debug builds
|
||||
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DUNIV_DEBUG -DUNIV_SYNC_DEBUG")
|
||||
|
||||
# Add -Wconversion if compiling with GCC
|
||||
## As of Mar 15 2011 this flag causes 3573+ warnings. If you are reading this
|
||||
## please fix them and enable the following code:
|
||||
#IF(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
|
||||
#SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wconversion")
|
||||
#ENDIF()
|
||||
|
||||
IF(NOT MSVC)
|
||||
# either define HAVE_IB_GCC_ATOMIC_BUILTINS or not
|
||||
|
@ -119,6 +129,8 @@ ENDIF()
|
|||
|
||||
ENDIF(NOT MSVC)
|
||||
|
||||
SET(LINKER_SCRIPT)
|
||||
|
||||
# Solaris atomics
|
||||
IF(CMAKE_SYSTEM_NAME STREQUAL "SunOS")
|
||||
CHECK_FUNCTION_EXISTS(atomic_cas_ulong HAVE_ATOMIC_CAS_ULONG)
|
||||
|
@ -133,11 +145,15 @@ IF(CMAKE_SYSTEM_NAME STREQUAL "SunOS")
|
|||
HAVE_ATOMIC_SWAP_UCHAR)
|
||||
SET(HAVE_IB_SOLARIS_ATOMICS 1)
|
||||
ENDIF()
|
||||
|
||||
|
||||
IF(HAVE_IB_SOLARIS_ATOMICS)
|
||||
ADD_DEFINITIONS(-DHAVE_IB_SOLARIS_ATOMICS=1)
|
||||
ENDIF()
|
||||
|
||||
IF(CMAKE_COMPILER_IS_GNUCC AND NOT HAVE_VISIBILITY_HIDDEN)
|
||||
SET(LINKER_SCRIPT "-Wl,-M${CMAKE_CURRENT_SOURCE_DIR}/plugin_exports")
|
||||
ENDIF()
|
||||
|
||||
IF(NOT CMAKE_CROSSCOMPILING)
|
||||
# either define HAVE_IB_ATOMIC_PTHREAD_T_SOLARIS or not
|
||||
CHECK_C_SOURCE_COMPILES(
|
||||
|
@ -154,15 +170,15 @@ IF(CMAKE_SYSTEM_NAME STREQUAL "SunOS")
|
|||
memset(&x3, 0x0, sizeof(x3));
|
||||
|
||||
if (sizeof(pthread_t) == 4) {
|
||||
|
||||
|
||||
atomic_cas_32(&x1, x2, x3);
|
||||
|
||||
|
||||
} else if (sizeof(pthread_t) == 8) {
|
||||
|
||||
|
||||
atomic_cas_64(&x1, x2, x3);
|
||||
|
||||
|
||||
} else {
|
||||
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
@ -198,81 +214,148 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/storage/innobase/include
|
|||
${CMAKE_SOURCE_DIR}/storage/innobase/handler)
|
||||
|
||||
# Sun Studio bug with -xO2
|
||||
IF(CMAKE_C_COMPILER_ID MATCHES "SunPro"
|
||||
AND CMAKE_C_FLAGS_RELEASE MATCHES "O2"
|
||||
IF(CMAKE_CXX_COMPILER_ID MATCHES "SunPro"
|
||||
AND CMAKE_CXX_FLAGS_RELEASE MATCHES "O2"
|
||||
AND NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
# Sun Studio 12 crashes with -xO2 flag, but not with higher optimization
|
||||
# -xO3
|
||||
SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_SOURCE_DIR}/rem/rem0rec.c
|
||||
SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_SOURCE_DIR}/rem/rem0rec.cc
|
||||
PROPERTIES COMPILE_FLAGS -xO3)
|
||||
ENDIF()
|
||||
|
||||
# Removing compiler optimizations for innodb/mem/* files on 64-bit Windows
|
||||
# due to 64-bit compiler error, See MySQL Bug #19424, #36366, #34297
|
||||
IF (MSVC AND CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
SET_SOURCE_FILES_PROPERTIES(mem/mem0mem.c mem/mem0pool.c
|
||||
SET_SOURCE_FILES_PROPERTIES(mem/mem0mem.cc mem/mem0pool.cc
|
||||
PROPERTIES COMPILE_FLAGS -Od)
|
||||
ENDIF()
|
||||
|
||||
IF(MSVC)
|
||||
# Avoid "unreferenced label" warning in generated file
|
||||
GET_FILENAME_COMPONENT(_SRC_DIR ${CMAKE_CURRENT_LIST_FILE} PATH)
|
||||
SET_SOURCE_FILES_PROPERTIES(${_SRC_DIR}/pars/pars0grm.c
|
||||
SET_SOURCE_FILES_PROPERTIES(${_SRC_DIR}/pars/pars0grm.cc
|
||||
PROPERTIES COMPILE_FLAGS "/wd4102")
|
||||
SET_SOURCE_FILES_PROPERTIES(${_SRC_DIR}/pars/lexyy.c
|
||||
SET_SOURCE_FILES_PROPERTIES(${_SRC_DIR}/pars/lexyy.cc
|
||||
PROPERTIES COMPILE_FLAGS "/wd4003")
|
||||
ENDIF()
|
||||
|
||||
SET(INNOBASE_SOURCES btr/btr0btr.c btr/btr0cur.c btr/btr0pcur.c btr/btr0sea.c
|
||||
buf/buf0buddy.c buf/buf0buf.c buf/buf0flu.c buf/buf0lru.c buf/buf0rea.c
|
||||
data/data0data.c data/data0type.c
|
||||
dict/dict0boot.c dict/dict0crea.c dict/dict0dict.c dict/dict0load.c dict/dict0mem.c
|
||||
dyn/dyn0dyn.c
|
||||
eval/eval0eval.c eval/eval0proc.c
|
||||
fil/fil0fil.c
|
||||
fsp/fsp0fsp.c
|
||||
fut/fut0fut.c fut/fut0lst.c
|
||||
ha/ha0ha.c ha/hash0hash.c ha/ha0storage.c
|
||||
ibuf/ibuf0ibuf.c
|
||||
pars/lexyy.c pars/pars0grm.c pars/pars0opt.c pars/pars0pars.c pars/pars0sym.c
|
||||
lock/lock0lock.c lock/lock0iter.c
|
||||
log/log0log.c log/log0recv.c
|
||||
mach/mach0data.c
|
||||
mem/mem0mem.c mem/mem0pool.c
|
||||
mtr/mtr0log.c mtr/mtr0mtr.c
|
||||
os/os0file.c os/os0proc.c os/os0sync.c os/os0thread.c
|
||||
page/page0cur.c page/page0page.c page/page0zip.c
|
||||
que/que0que.c
|
||||
handler/ha_innodb.cc handler/handler0alter.cc handler/i_s.cc
|
||||
read/read0read.c
|
||||
rem/rem0cmp.c rem/rem0rec.c
|
||||
row/row0ext.c row/row0ins.c row/row0merge.c row/row0mysql.c row/row0purge.c row/row0row.c
|
||||
row/row0sel.c row/row0uins.c row/row0umod.c row/row0undo.c row/row0upd.c row/row0vers.c
|
||||
srv/srv0srv.c srv/srv0start.c
|
||||
sync/sync0arr.c sync/sync0rw.c sync/sync0sync.c
|
||||
trx/trx0i_s.c trx/trx0purge.c trx/trx0rec.c trx/trx0roll.c trx/trx0rseg.c
|
||||
trx/trx0sys.c trx/trx0trx.c trx/trx0undo.c
|
||||
usr/usr0sess.c
|
||||
ut/ut0byte.c ut/ut0dbg.c ut/ut0list.c ut/ut0mem.c ut/ut0rbt.c ut/ut0rnd.c
|
||||
ut/ut0ut.c ut/ut0vec.c ut/ut0wqueue.c ut/ut0bh.c)
|
||||
|
||||
SET(INNOBASE_SOURCES
|
||||
btr/btr0btr.cc
|
||||
btr/btr0cur.cc
|
||||
btr/btr0pcur.cc
|
||||
btr/btr0sea.cc
|
||||
buf/buf0buddy.cc
|
||||
buf/buf0buf.cc
|
||||
buf/buf0dblwr.cc
|
||||
buf/buf0checksum.cc
|
||||
buf/buf0dump.cc
|
||||
buf/buf0flu.cc
|
||||
buf/buf0lru.cc
|
||||
buf/buf0rea.cc
|
||||
data/data0data.cc
|
||||
data/data0type.cc
|
||||
dict/dict0boot.cc
|
||||
dict/dict0crea.cc
|
||||
dict/dict0dict.cc
|
||||
dict/dict0load.cc
|
||||
dict/dict0mem.cc
|
||||
dict/dict0stats.cc
|
||||
dyn/dyn0dyn.cc
|
||||
eval/eval0eval.cc
|
||||
eval/eval0proc.cc
|
||||
fil/fil0fil.cc
|
||||
fsp/fsp0fsp.cc
|
||||
fut/fut0fut.cc
|
||||
fut/fut0lst.cc
|
||||
ha/ha0ha.cc
|
||||
ha/ha0storage.cc
|
||||
ha/hash0hash.cc
|
||||
fts/fts0fts.cc
|
||||
fts/fts0ast.cc
|
||||
fts/fts0blex.cc
|
||||
fts/fts0config.cc
|
||||
fts/fts0opt.cc
|
||||
fts/fts0pars.cc
|
||||
fts/fts0que.cc
|
||||
fts/fts0sql.cc
|
||||
fts/fts0tlex.cc
|
||||
handler/ha_innodb.cc
|
||||
handler/handler0alter.cc
|
||||
handler/i_s.cc
|
||||
ibuf/ibuf0ibuf.cc
|
||||
lock/lock0iter.cc
|
||||
lock/lock0lock.cc
|
||||
lock/lock0wait.cc
|
||||
log/log0log.cc
|
||||
log/log0recv.cc
|
||||
mach/mach0data.cc
|
||||
mem/mem0mem.cc
|
||||
mem/mem0pool.cc
|
||||
mtr/mtr0log.cc
|
||||
mtr/mtr0mtr.cc
|
||||
os/os0file.cc
|
||||
os/os0proc.cc
|
||||
os/os0sync.cc
|
||||
os/os0thread.cc
|
||||
page/page0cur.cc
|
||||
page/page0page.cc
|
||||
page/page0zip.cc
|
||||
pars/lexyy.cc
|
||||
pars/pars0grm.cc
|
||||
pars/pars0opt.cc
|
||||
pars/pars0pars.cc
|
||||
pars/pars0sym.cc
|
||||
que/que0que.cc
|
||||
read/read0read.cc
|
||||
rem/rem0cmp.cc
|
||||
rem/rem0rec.cc
|
||||
row/row0ext.cc
|
||||
row/row0ftsort.cc
|
||||
row/row0ins.cc
|
||||
row/row0merge.cc
|
||||
row/row0mysql.cc
|
||||
row/row0purge.cc
|
||||
row/row0row.cc
|
||||
row/row0sel.cc
|
||||
row/row0uins.cc
|
||||
row/row0umod.cc
|
||||
row/row0undo.cc
|
||||
row/row0upd.cc
|
||||
row/row0vers.cc
|
||||
srv/srv0conc.cc
|
||||
srv/srv0mon.cc
|
||||
srv/srv0srv.cc
|
||||
srv/srv0start.cc
|
||||
sync/sync0arr.cc
|
||||
sync/sync0rw.cc
|
||||
sync/sync0sync.cc
|
||||
trx/trx0i_s.cc
|
||||
trx/trx0purge.cc
|
||||
trx/trx0rec.cc
|
||||
trx/trx0roll.cc
|
||||
trx/trx0rseg.cc
|
||||
trx/trx0sys.cc
|
||||
trx/trx0trx.cc
|
||||
trx/trx0undo.cc
|
||||
usr/usr0sess.cc
|
||||
ut/ut0bh.cc
|
||||
ut/ut0byte.cc
|
||||
ut/ut0crc32.cc
|
||||
ut/ut0dbg.cc
|
||||
ut/ut0list.cc
|
||||
ut/ut0mem.cc
|
||||
ut/ut0rbt.cc
|
||||
ut/ut0rnd.cc
|
||||
ut/ut0ut.cc
|
||||
ut/ut0vec.cc
|
||||
ut/ut0wqueue.cc)
|
||||
|
||||
IF(WITH_INNODB)
|
||||
# Legacy option
|
||||
SET(WITH_INNOBASE_STORAGE_ENGINE TRUE)
|
||||
ENDIF()
|
||||
|
||||
|
||||
# On solaris, reduce symbol visibility, so loader does not mix
|
||||
# the same symbols from builtin innodb and from shared one.
|
||||
# Only required for old GCC (3.4.3) that does not support hidden visibility
|
||||
IF(CMAKE_SYSTEM_NAME MATCHES "SunOS" AND CMAKE_COMPILER_IS_GNUCC
|
||||
AND NOT HAVE_VISIBILITY_HIDDEN)
|
||||
SET(LINKER_SCRIPT "-Wl,-M${CMAKE_CURRENT_SOURCE_DIR}/plugin_exports")
|
||||
ELSE()
|
||||
SET(LINKER_SCRIPT)
|
||||
ENDIF()
|
||||
|
||||
MYSQL_ADD_PLUGIN(innobase ${INNOBASE_SOURCES} STORAGE_ENGINE
|
||||
MODULE_ONLY
|
||||
MYSQL_ADD_PLUGIN(innobase ${INNOBASE_SOURCES} STORAGE_ENGINE
|
||||
DEFAULT
|
||||
MODULE_OUTPUT_NAME ha_innodb
|
||||
LINK_LIBRARIES ${ZLIB_LIBRARY} ${LINKER_SCRIPT})
|
||||
LINK_LIBRARIES ${ZLIB_LIBRARY})
|
||||
|
|
|
@ -17,7 +17,7 @@ this program; if not, write to the Free Software Foundation, Inc.,
|
|||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file btr/btr0btr.c
|
||||
@file btr/btr0btr.cc
|
||||
The B-tree
|
||||
|
||||
Created 6/2/1994 Heikki Tuuri
|
||||
|
@ -41,6 +41,7 @@ Created 6/2/1994 Heikki Tuuri
|
|||
#include "lock0lock.h"
|
||||
#include "ibuf0ibuf.h"
|
||||
#include "trx0trx.h"
|
||||
#include "srv0mon.h"
|
||||
|
||||
/**************************************************************//**
|
||||
Report that an index page is corrupted. */
|
||||
|
@ -132,8 +133,8 @@ btr_blob_dbg_cmp(
|
|||
const void* a, /*!< in: first btr_blob_dbg_t to compare */
|
||||
const void* b) /*!< in: second btr_blob_dbg_t to compare */
|
||||
{
|
||||
const btr_blob_dbg_t* aa = a;
|
||||
const btr_blob_dbg_t* bb = b;
|
||||
const btr_blob_dbg_t* aa = static_cast<const btr_blob_dbg_t*>(a);
|
||||
const btr_blob_dbg_t* bb = static_cast<const btr_blob_dbg_t*>(b);
|
||||
|
||||
ut_ad(aa != NULL);
|
||||
ut_ad(bb != NULL);
|
||||
|
@ -418,7 +419,7 @@ btr_blob_dbg_op(
|
|||
rec = page_rec_get_next_const(rec);
|
||||
} while (!page_rec_is_supremum(rec));
|
||||
|
||||
if (UNIV_LIKELY_NULL(heap)) {
|
||||
if (heap) {
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
|
||||
|
@ -874,7 +875,7 @@ btr_page_create(
|
|||
ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
|
||||
btr_blob_dbg_assert_empty(index, buf_block_get_page_no(block));
|
||||
|
||||
if (UNIV_LIKELY_NULL(page_zip)) {
|
||||
if (page_zip) {
|
||||
page_create_zip(block, index, level, mtr);
|
||||
} else {
|
||||
page_create(block, mtr, dict_table_is_comp(index->table));
|
||||
|
@ -1123,6 +1124,15 @@ btr_page_free_low(
|
|||
fseg_free_page(seg_header,
|
||||
buf_block_get_space(block),
|
||||
buf_block_get_page_no(block), mtr);
|
||||
|
||||
/* The page was marked free in the allocation bitmap, but it
|
||||
should remain buffer-fixed until mtr_commit(mtr) or until it
|
||||
is explicitly freed from the mini-transaction. */
|
||||
ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
|
||||
/* TODO: Discard any operations on the page from the redo log
|
||||
and remove the block from the flush list and the buffer pool.
|
||||
This would free up buffer pool earlier and reduce writes to
|
||||
both the tablespace and the redo log. */
|
||||
}
|
||||
|
||||
/**************************************************************//**
|
||||
|
@ -1169,7 +1179,7 @@ btr_node_ptr_set_child_page_no(
|
|||
|
||||
ut_ad(len == REC_NODE_PTR_SIZE);
|
||||
|
||||
if (UNIV_LIKELY_NULL(page_zip)) {
|
||||
if (page_zip) {
|
||||
page_zip_write_node_ptr(page_zip, rec,
|
||||
rec_offs_data_size(offsets),
|
||||
page_no, mtr);
|
||||
|
@ -1249,8 +1259,7 @@ btr_page_get_father_node_ptr_func(
|
|||
offsets = rec_get_offsets(node_ptr, index, offsets,
|
||||
ULINT_UNDEFINED, &heap);
|
||||
|
||||
if (UNIV_UNLIKELY(btr_node_ptr_get_child_page_no(node_ptr, offsets)
|
||||
!= page_no)) {
|
||||
if (btr_node_ptr_get_child_page_no(node_ptr, offsets) != page_no) {
|
||||
rec_t* print_rec;
|
||||
fputs("InnoDB: Dump of the child page:\n", stderr);
|
||||
buf_page_print(page_align(user_rec), 0,
|
||||
|
@ -1437,7 +1446,7 @@ btr_create(
|
|||
/* Create a new index page on the allocated segment page */
|
||||
page_zip = buf_block_get_page_zip(block);
|
||||
|
||||
if (UNIV_LIKELY_NULL(page_zip)) {
|
||||
if (page_zip) {
|
||||
page = page_create_zip(block, index, 0, mtr);
|
||||
} else {
|
||||
page = page_create(block, mtr,
|
||||
|
@ -1556,7 +1565,9 @@ btr_free_root(
|
|||
ut_a(btr_root_fseg_validate(header, space));
|
||||
#endif /* UNIV_BTR_DEBUG */
|
||||
|
||||
while (!fseg_free_step(header, mtr));
|
||||
while (!fseg_free_step(header, mtr)) {
|
||||
/* Free the entire segment in small steps. */
|
||||
}
|
||||
}
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
|
@ -1575,7 +1586,9 @@ btr_page_reorganize_low(
|
|||
dict_index_t* index, /*!< in: record descriptor */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
{
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
buf_pool_t* buf_pool = buf_pool_from_bpage(&block->page);
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
page_t* page = buf_block_get_frame(block);
|
||||
page_zip_des_t* page_zip = buf_block_get_page_zip(block);
|
||||
buf_block_t* temp_block;
|
||||
|
@ -1617,7 +1630,7 @@ btr_page_reorganize_low(
|
|||
buf_frame_copy(temp_page, page);
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
if (UNIV_LIKELY(!recovery)) {
|
||||
if (!recovery) {
|
||||
btr_search_drop_page_hash_index(block);
|
||||
}
|
||||
|
||||
|
@ -1647,9 +1660,7 @@ btr_page_reorganize_low(
|
|||
ut_ad(max_trx_id != 0 || recovery);
|
||||
}
|
||||
|
||||
if (UNIV_LIKELY_NULL(page_zip)
|
||||
&& UNIV_UNLIKELY
|
||||
(!page_zip_compress(page_zip, page, index, NULL))) {
|
||||
if (page_zip && !page_zip_compress(page_zip, page, index, NULL)) {
|
||||
|
||||
/* Restore the old page and exit. */
|
||||
btr_blob_dbg_restore(page, temp_page, index,
|
||||
|
@ -1679,7 +1690,7 @@ btr_page_reorganize_low(
|
|||
}
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
if (UNIV_LIKELY(!recovery)) {
|
||||
if (!recovery) {
|
||||
/* Update the record lock bitmaps */
|
||||
lock_move_reorganize_page(block, temp_block);
|
||||
}
|
||||
|
@ -1688,10 +1699,10 @@ btr_page_reorganize_low(
|
|||
data_size2 = page_get_data_size(page);
|
||||
max_ins_size2 = page_get_max_insert_size_after_reorganize(page, 1);
|
||||
|
||||
if (UNIV_UNLIKELY(data_size1 != data_size2)
|
||||
|| UNIV_UNLIKELY(max_ins_size1 != max_ins_size2)) {
|
||||
if (data_size1 != data_size2 || max_ins_size1 != max_ins_size2) {
|
||||
buf_page_print(page, 0, BUF_PAGE_PRINT_NO_CRASH);
|
||||
buf_page_print(temp_page, 0, BUF_PAGE_PRINT_NO_CRASH);
|
||||
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: page old data size %lu"
|
||||
" new data size %lu\n"
|
||||
|
@ -1759,7 +1770,7 @@ btr_parse_page_reorganize(
|
|||
|
||||
/* The record is empty, except for the record initial part */
|
||||
|
||||
if (UNIV_LIKELY(block != NULL)) {
|
||||
if (block != NULL) {
|
||||
btr_page_reorganize_low(TRUE, block, index, mtr);
|
||||
}
|
||||
|
||||
|
@ -1793,7 +1804,7 @@ btr_page_empty(
|
|||
/* Recreate the page: note that global data on page (possible
|
||||
segment headers, next page-field, etc.) is preserved intact */
|
||||
|
||||
if (UNIV_LIKELY_NULL(page_zip)) {
|
||||
if (page_zip) {
|
||||
page_create_zip(block, index, level, mtr);
|
||||
} else {
|
||||
page_create(block, mtr, dict_table_is_comp(index->table));
|
||||
|
@ -1886,10 +1897,9 @@ btr_root_raise_and_insert(
|
|||
#ifdef UNIV_ZIP_COPY
|
||||
|| new_page_zip
|
||||
#endif /* UNIV_ZIP_COPY */
|
||||
|| UNIV_UNLIKELY
|
||||
(!page_copy_rec_list_end(new_block, root_block,
|
||||
|| !page_copy_rec_list_end(new_block, root_block,
|
||||
page_get_infimum_rec(root),
|
||||
index, mtr))) {
|
||||
index, mtr)) {
|
||||
ut_a(new_page_zip);
|
||||
|
||||
/* Copy the page byte for byte. */
|
||||
|
@ -2044,8 +2054,7 @@ btr_page_get_split_rec_to_right(
|
|||
the previous insert on the same page, we assume that there is a
|
||||
pattern of sequential inserts here. */
|
||||
|
||||
if (UNIV_LIKELY(page_header_get_ptr(page, PAGE_LAST_INSERT)
|
||||
== insert_point)) {
|
||||
if (page_header_get_ptr(page, PAGE_LAST_INSERT) == insert_point) {
|
||||
|
||||
rec_t* next_rec;
|
||||
|
||||
|
@ -2113,13 +2122,13 @@ btr_page_get_split_rec(
|
|||
free_space = page_get_free_space_of_empty(page_is_comp(page));
|
||||
|
||||
page_zip = btr_cur_get_page_zip(cursor);
|
||||
if (UNIV_LIKELY_NULL(page_zip)) {
|
||||
if (page_zip) {
|
||||
/* Estimate the free space of an empty compressed page. */
|
||||
ulint free_space_zip = page_zip_empty_size(
|
||||
cursor->index->n_fields,
|
||||
page_zip_get_size(page_zip));
|
||||
|
||||
if (UNIV_LIKELY(free_space > (ulint) free_space_zip)) {
|
||||
if (free_space > (ulint) free_space_zip) {
|
||||
free_space = (ulint) free_space_zip;
|
||||
}
|
||||
}
|
||||
|
@ -2192,7 +2201,7 @@ btr_page_get_split_rec(
|
|||
}
|
||||
|
||||
func_exit:
|
||||
if (UNIV_LIKELY_NULL(heap)) {
|
||||
if (heap) {
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
return(rec);
|
||||
|
@ -2337,7 +2346,7 @@ btr_attach_half_pages(
|
|||
/*==================*/
|
||||
dict_index_t* index, /*!< in: the index tree */
|
||||
buf_block_t* block, /*!< in/out: page to be split */
|
||||
rec_t* split_rec, /*!< in: first record on upper
|
||||
const rec_t* split_rec, /*!< in: first record on upper
|
||||
half page */
|
||||
buf_block_t* new_block, /*!< in/out: the new half page */
|
||||
ulint direction, /*!< in: FSP_UP or FSP_DOWN */
|
||||
|
@ -2568,7 +2577,7 @@ func_start:
|
|||
hint_page_no = page_no + 1;
|
||||
split_rec = btr_page_get_split_rec(cursor, tuple, n_ext);
|
||||
|
||||
if (UNIV_UNLIKELY(split_rec == NULL)) {
|
||||
if (split_rec == NULL) {
|
||||
insert_left = btr_page_tuple_smaller(
|
||||
cursor, tuple, offsets, n_uniq, &heap);
|
||||
}
|
||||
|
@ -2620,15 +2629,14 @@ func_start:
|
|||
|
||||
insert_left = cmp_dtuple_rec(tuple, split_rec, offsets) < 0;
|
||||
|
||||
if (UNIV_UNLIKELY(!insert_left && new_page_zip
|
||||
&& n_iterations > 0)) {
|
||||
if (!insert_left && new_page_zip && n_iterations > 0) {
|
||||
/* If a compressed page has already been split,
|
||||
avoid further splits by inserting the record
|
||||
to an empty page. */
|
||||
split_rec = NULL;
|
||||
goto insert_empty;
|
||||
}
|
||||
} else if (UNIV_UNLIKELY(insert_left)) {
|
||||
} else if (insert_left) {
|
||||
ut_a(n_iterations > 0);
|
||||
first_rec = page_rec_get_next(page_get_infimum_rec(page));
|
||||
move_limit = page_rec_get_next(btr_cur_get_rec(cursor));
|
||||
|
@ -2636,8 +2644,8 @@ func_start:
|
|||
insert_empty:
|
||||
ut_ad(!split_rec);
|
||||
ut_ad(!insert_left);
|
||||
buf = mem_alloc(rec_get_converted_size(cursor->index,
|
||||
tuple, n_ext));
|
||||
buf = (byte*) mem_alloc(rec_get_converted_size(cursor->index,
|
||||
tuple, n_ext));
|
||||
|
||||
first_rec = rec_convert_dtuple_to_rec(buf, cursor->index,
|
||||
tuple, n_ext);
|
||||
|
@ -2683,9 +2691,8 @@ insert_empty:
|
|||
#ifdef UNIV_ZIP_COPY
|
||||
|| page_zip
|
||||
#endif /* UNIV_ZIP_COPY */
|
||||
|| UNIV_UNLIKELY
|
||||
(!page_move_rec_list_start(new_block, block, move_limit,
|
||||
cursor->index, mtr))) {
|
||||
|| !page_move_rec_list_start(new_block, block, move_limit,
|
||||
cursor->index, mtr)) {
|
||||
/* For some reason, compressing new_page failed,
|
||||
even though it should contain fewer records than
|
||||
the original page. Copy the page byte for byte
|
||||
|
@ -2726,9 +2733,8 @@ insert_empty:
|
|||
#ifdef UNIV_ZIP_COPY
|
||||
|| page_zip
|
||||
#endif /* UNIV_ZIP_COPY */
|
||||
|| UNIV_UNLIKELY
|
||||
(!page_move_rec_list_end(new_block, block, move_limit,
|
||||
cursor->index, mtr))) {
|
||||
|| !page_move_rec_list_end(new_block, block, move_limit,
|
||||
cursor->index, mtr)) {
|
||||
/* For some reason, compressing new_page failed,
|
||||
even though it should contain fewer records than
|
||||
the original page. Copy the page byte for byte
|
||||
|
@ -2764,7 +2770,7 @@ insert_empty:
|
|||
}
|
||||
|
||||
#ifdef UNIV_ZIP_DEBUG
|
||||
if (UNIV_LIKELY_NULL(page_zip)) {
|
||||
if (page_zip) {
|
||||
ut_a(page_zip_validate(page_zip, page));
|
||||
ut_a(page_zip_validate(new_page_zip, new_page));
|
||||
}
|
||||
|
@ -2804,15 +2810,14 @@ insert_empty:
|
|||
}
|
||||
#endif /* UNIV_ZIP_DEBUG */
|
||||
|
||||
if (UNIV_LIKELY(rec != NULL)) {
|
||||
if (rec != NULL) {
|
||||
|
||||
goto func_exit;
|
||||
}
|
||||
|
||||
/* 8. If insert did not fit, try page reorganization */
|
||||
|
||||
if (UNIV_UNLIKELY
|
||||
(!btr_page_reorganize(insert_block, cursor->index, mtr))) {
|
||||
if (!btr_page_reorganize(insert_block, cursor->index, mtr)) {
|
||||
|
||||
goto insert_failed;
|
||||
}
|
||||
|
@ -2822,7 +2827,7 @@ insert_empty:
|
|||
rec = page_cur_tuple_insert(page_cursor, tuple, cursor->index,
|
||||
n_ext, mtr);
|
||||
|
||||
if (UNIV_UNLIKELY(rec == NULL)) {
|
||||
if (rec == NULL) {
|
||||
/* The insert did not fit on the page: loop back to the
|
||||
start of the function for a new split */
|
||||
insert_failed:
|
||||
|
@ -2856,6 +2861,7 @@ func_exit:
|
|||
buf_block_get_page_no(left_block),
|
||||
buf_block_get_page_no(right_block));
|
||||
#endif
|
||||
MONITOR_INC(MONITOR_INDEX_SPLIT);
|
||||
|
||||
ut_ad(page_validate(buf_block_get_frame(left_block), cursor->index));
|
||||
ut_ad(page_validate(buf_block_get_frame(right_block), cursor->index));
|
||||
|
@ -3012,7 +3018,7 @@ btr_set_min_rec_mark(
|
|||
{
|
||||
ulint info_bits;
|
||||
|
||||
if (UNIV_LIKELY(page_rec_is_comp(rec))) {
|
||||
if (page_rec_is_comp(rec)) {
|
||||
info_bits = rec_get_info_bits(rec, TRUE);
|
||||
|
||||
rec_set_info_bits_new(rec, info_bits | REC_INFO_MIN_REC_FLAG);
|
||||
|
@ -3131,10 +3137,9 @@ btr_lift_page_up(
|
|||
#ifdef UNIV_ZIP_COPY
|
||||
|| father_page_zip
|
||||
#endif /* UNIV_ZIP_COPY */
|
||||
|| UNIV_UNLIKELY
|
||||
(!page_copy_rec_list_end(father_block, block,
|
||||
page_get_infimum_rec(page),
|
||||
index, mtr))) {
|
||||
|| !page_copy_rec_list_end(father_block, block,
|
||||
page_get_infimum_rec(page),
|
||||
index, mtr)) {
|
||||
const page_zip_des_t* page_zip
|
||||
= buf_block_get_page_zip(block);
|
||||
ut_a(father_page_zip);
|
||||
|
@ -3310,12 +3315,11 @@ err_exit:
|
|||
|
||||
max_ins_size = page_get_max_insert_size(merge_page, n_recs);
|
||||
|
||||
if (UNIV_UNLIKELY(data_size > max_ins_size)) {
|
||||
if (data_size > max_ins_size) {
|
||||
|
||||
/* We have to reorganize merge_page */
|
||||
|
||||
if (UNIV_UNLIKELY(!btr_page_reorganize(merge_block,
|
||||
index, mtr))) {
|
||||
if (!btr_page_reorganize(merge_block, index, mtr)) {
|
||||
|
||||
goto err_exit;
|
||||
}
|
||||
|
@ -3325,7 +3329,7 @@ err_exit:
|
|||
ut_ad(page_validate(merge_page, index));
|
||||
ut_ad(max_ins_size == max_ins_size_reorg);
|
||||
|
||||
if (UNIV_UNLIKELY(data_size > max_ins_size)) {
|
||||
if (data_size > max_ins_size) {
|
||||
|
||||
/* Add fault tolerance, though this should
|
||||
never happen */
|
||||
|
@ -3336,7 +3340,7 @@ err_exit:
|
|||
|
||||
merge_page_zip = buf_block_get_page_zip(merge_block);
|
||||
#ifdef UNIV_ZIP_DEBUG
|
||||
if (UNIV_LIKELY_NULL(merge_page_zip)) {
|
||||
if (merge_page_zip) {
|
||||
const page_zip_des_t* page_zip
|
||||
= buf_block_get_page_zip(block);
|
||||
ut_a(page_zip);
|
||||
|
@ -3351,7 +3355,7 @@ err_exit:
|
|||
merge_block, block, page_get_supremum_rec(page),
|
||||
index, mtr);
|
||||
|
||||
if (UNIV_UNLIKELY(!orig_pred)) {
|
||||
if (!orig_pred) {
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
|
@ -3372,7 +3376,7 @@ err_exit:
|
|||
byte fil_page_prev[4];
|
||||
#endif /* UNIV_BTR_DEBUG */
|
||||
|
||||
if (UNIV_LIKELY_NULL(merge_page_zip)) {
|
||||
if (merge_page_zip) {
|
||||
/* The function page_zip_compress(), which will be
|
||||
invoked by page_copy_rec_list_end() below,
|
||||
requires that FIL_PAGE_PREV be FIL_NULL.
|
||||
|
@ -3390,7 +3394,7 @@ err_exit:
|
|||
page_get_infimum_rec(page),
|
||||
cursor->index, mtr);
|
||||
|
||||
if (UNIV_UNLIKELY(!orig_succ)) {
|
||||
if (!orig_succ) {
|
||||
ut_a(merge_page_zip);
|
||||
#ifdef UNIV_BTR_DEBUG
|
||||
/* FIL_PAGE_PREV was restored from merge_page_zip. */
|
||||
|
@ -3403,7 +3407,7 @@ err_exit:
|
|||
btr_search_drop_page_hash_index(block);
|
||||
|
||||
#ifdef UNIV_BTR_DEBUG
|
||||
if (UNIV_LIKELY_NULL(merge_page_zip)) {
|
||||
if (merge_page_zip) {
|
||||
/* Restore FIL_PAGE_PREV in order to avoid an assertion
|
||||
failure in btr_level_list_remove(), which will set
|
||||
the field again to FIL_NULL. Even though this makes
|
||||
|
@ -3706,7 +3710,7 @@ btr_print_size(
|
|||
fputs("INFO OF THE NON-LEAF PAGE SEGMENT\n", stderr);
|
||||
fseg_print(seg, &mtr);
|
||||
|
||||
if (!(index->type & DICT_UNIVERSAL)) {
|
||||
if (!dict_index_is_univ(index)) {
|
||||
|
||||
seg = root + PAGE_HEADER + PAGE_BTR_SEG_LEAF;
|
||||
|
||||
|
@ -3804,7 +3808,7 @@ btr_print_index(
|
|||
root = btr_root_block_get(index, &mtr);
|
||||
|
||||
btr_print_recursive(index, root, width, &heap, &offsets, &mtr);
|
||||
if (UNIV_LIKELY_NULL(heap)) {
|
||||
if (heap) {
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
|
||||
|
@ -3900,7 +3904,7 @@ btr_index_rec_validate(
|
|||
|
||||
page = page_align(rec);
|
||||
|
||||
if (UNIV_UNLIKELY(index->type & DICT_UNIVERSAL)) {
|
||||
if (dict_index_is_univ(index)) {
|
||||
/* The insert buffer index tree can contain records from any
|
||||
other index: we cannot check the number of fields or
|
||||
their length */
|
||||
|
@ -3908,8 +3912,7 @@ btr_index_rec_validate(
|
|||
return(TRUE);
|
||||
}
|
||||
|
||||
if (UNIV_UNLIKELY((ibool)!!page_is_comp(page)
|
||||
!= dict_table_is_comp(index->table))) {
|
||||
if ((ibool)!!page_is_comp(page) != dict_table_is_comp(index->table)) {
|
||||
btr_index_rec_validate_report(page, rec, index);
|
||||
fprintf(stderr, "InnoDB: compact flag=%lu, should be %lu\n",
|
||||
(ulong) !!page_is_comp(page),
|
||||
|
@ -3920,8 +3923,7 @@ btr_index_rec_validate(
|
|||
|
||||
n = dict_index_get_n_fields(index);
|
||||
|
||||
if (!page_is_comp(page)
|
||||
&& UNIV_UNLIKELY(rec_get_n_fields_old(rec) != n)) {
|
||||
if (!page_is_comp(page) && rec_get_n_fields_old(rec) != n) {
|
||||
btr_index_rec_validate_report(page, rec, index);
|
||||
fprintf(stderr, "InnoDB: has %lu fields, should have %lu\n",
|
||||
(ulong) rec_get_n_fields_old(rec), (ulong) n);
|
||||
|
@ -3972,14 +3974,14 @@ btr_index_rec_validate(
|
|||
rec_print_new(stderr, rec, offsets);
|
||||
putc('\n', stderr);
|
||||
}
|
||||
if (UNIV_LIKELY_NULL(heap)) {
|
||||
if (heap) {
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
return(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
if (UNIV_LIKELY_NULL(heap)) {
|
||||
if (heap) {
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
return(TRUE);
|
||||
|
@ -4171,8 +4173,9 @@ loop:
|
|||
right_block = btr_block_get(space, zip_size, right_page_no,
|
||||
RW_X_LATCH, index, &mtr);
|
||||
right_page = buf_block_get_frame(right_block);
|
||||
if (UNIV_UNLIKELY(btr_page_get_prev(right_page, &mtr)
|
||||
!= page_get_page_no(page))) {
|
||||
if (btr_page_get_prev(right_page, &mtr)
|
||||
!= page_get_page_no(page)) {
|
||||
|
||||
btr_validate_report2(index, level, block, right_block);
|
||||
fputs("InnoDB: broken FIL_PAGE_NEXT"
|
||||
" or FIL_PAGE_PREV links\n", stderr);
|
||||
|
@ -4182,8 +4185,7 @@ loop:
|
|||
ret = FALSE;
|
||||
}
|
||||
|
||||
if (UNIV_UNLIKELY(page_is_comp(right_page)
|
||||
!= page_is_comp(page))) {
|
||||
if (page_is_comp(right_page) != page_is_comp(page)) {
|
||||
btr_validate_report2(index, level, block, right_block);
|
||||
fputs("InnoDB: 'compact' flag mismatch\n", stderr);
|
||||
buf_page_print(page, 0, BUF_PAGE_PRINT_NO_CRASH);
|
||||
|
@ -4201,9 +4203,8 @@ loop:
|
|||
offsets, ULINT_UNDEFINED, &heap);
|
||||
offsets2 = rec_get_offsets(right_rec, index,
|
||||
offsets2, ULINT_UNDEFINED, &heap);
|
||||
if (UNIV_UNLIKELY(cmp_rec_rec(rec, right_rec,
|
||||
offsets, offsets2,
|
||||
index) >= 0)) {
|
||||
if (cmp_rec_rec(rec, right_rec, offsets, offsets2,
|
||||
index) >= 0) {
|
||||
|
||||
btr_validate_report2(index, level, block, right_block);
|
||||
|
||||
|
@ -4250,10 +4251,9 @@ loop:
|
|||
offsets = btr_page_get_father_node_ptr(offsets, heap,
|
||||
&node_cur, &mtr);
|
||||
|
||||
if (UNIV_UNLIKELY(node_ptr != btr_cur_get_rec(&node_cur))
|
||||
|| UNIV_UNLIKELY(btr_node_ptr_get_child_page_no(node_ptr,
|
||||
offsets)
|
||||
!= buf_block_get_page_no(block))) {
|
||||
if (node_ptr != btr_cur_get_rec(&node_cur)
|
||||
|| btr_node_ptr_get_child_page_no(node_ptr, offsets)
|
||||
!= buf_block_get_page_no(block)) {
|
||||
|
||||
btr_validate_report1(index, level, block);
|
||||
|
||||
|
@ -4444,6 +4444,12 @@ btr_validate_index(
|
|||
ulint i;
|
||||
ulint n;
|
||||
|
||||
/* Full Text index are implemented by auxiliary tables,
|
||||
not the B-tree */
|
||||
if (index->type & DICT_FTS) {
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
mtr_start(&mtr);
|
||||
mtr_x_lock(dict_index_get_lock(index), &mtr);
|
||||
|
|
@ -24,7 +24,7 @@ this program; if not, write to the Free Software Foundation, Inc.,
|
|||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file btr/btr0cur.c
|
||||
@file btr/btr0cur.cc
|
||||
The index tree cursor
|
||||
|
||||
All changes that row operations make to a B-tree or the records
|
||||
|
@ -129,7 +129,12 @@ can be released by page reorganize, then it is reorganized */
|
|||
/** A BLOB field reference full of zero, for use in assertions and tests.
|
||||
Initially, BLOB field references are set to zero, in
|
||||
dtuple_convert_big_rec(). */
|
||||
UNIV_INTERN const byte field_ref_zero[BTR_EXTERN_FIELD_REF_SIZE];
|
||||
const byte field_ref_zero[BTR_EXTERN_FIELD_REF_SIZE] = {
|
||||
0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0,
|
||||
};
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
/*******************************************************************//**
|
||||
|
@ -408,6 +413,7 @@ btr_cur_search_to_nth_level(
|
|||
ut_ad(dict_index_check_search_tuple(index, tuple));
|
||||
ut_ad(!dict_index_is_ibuf(index) || ibuf_inside(mtr));
|
||||
ut_ad(dtuple_check_typed(tuple));
|
||||
ut_ad(!(index->type & DICT_FTS));
|
||||
ut_ad(index->page != FIL_NULL);
|
||||
|
||||
UNIV_MEM_INVALID(&cursor->up_match, sizeof cursor->up_match);
|
||||
|
@ -930,7 +936,7 @@ btr_cur_open_at_index_side_func(
|
|||
page_no = btr_node_ptr_get_child_page_no(node_ptr, offsets);
|
||||
}
|
||||
|
||||
if (UNIV_LIKELY_NULL(heap)) {
|
||||
if (heap) {
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
}
|
||||
|
@ -1101,29 +1107,27 @@ btr_cur_ins_lock_and_undo(
|
|||
btr_cur_get_block(cursor),
|
||||
index, thr, mtr, inherit);
|
||||
|
||||
if (err != DB_SUCCESS
|
||||
|| !dict_index_is_clust(index) || dict_index_is_ibuf(index)) {
|
||||
|
||||
return(err);
|
||||
}
|
||||
|
||||
err = trx_undo_report_row_operation(flags, TRX_UNDO_INSERT_OP,
|
||||
thr, index, entry,
|
||||
NULL, 0, NULL,
|
||||
&roll_ptr);
|
||||
if (err != DB_SUCCESS) {
|
||||
|
||||
return(err);
|
||||
}
|
||||
|
||||
if (dict_index_is_clust(index) && !dict_index_is_ibuf(index)) {
|
||||
/* Now we can fill in the roll ptr field in entry */
|
||||
|
||||
err = trx_undo_report_row_operation(flags, TRX_UNDO_INSERT_OP,
|
||||
thr, index, entry,
|
||||
NULL, 0, NULL,
|
||||
&roll_ptr);
|
||||
if (err != DB_SUCCESS) {
|
||||
if (!(flags & BTR_KEEP_SYS_FLAG)) {
|
||||
|
||||
return(err);
|
||||
}
|
||||
|
||||
/* Now we can fill in the roll ptr field in entry */
|
||||
|
||||
if (!(flags & BTR_KEEP_SYS_FLAG)) {
|
||||
|
||||
row_upd_index_entry_sys_field(entry, index,
|
||||
DATA_ROLL_PTR, roll_ptr);
|
||||
}
|
||||
row_upd_index_entry_sys_field(entry, index,
|
||||
DATA_ROLL_PTR, roll_ptr);
|
||||
}
|
||||
|
||||
return(DB_SUCCESS);
|
||||
|
@ -1140,8 +1144,7 @@ btr_cur_trx_report(
|
|||
const dict_index_t* index, /*!< in: index */
|
||||
const char* op) /*!< in: operation */
|
||||
{
|
||||
fprintf(stderr, "Trx with id " TRX_ID_FMT " going to ",
|
||||
(ullint) trx->id);
|
||||
fprintf(stderr, "Trx with id " TRX_ID_FMT " going to ", trx->id);
|
||||
fputs(op, stderr);
|
||||
dict_index_name_print(stderr, trx, index);
|
||||
putc('\n', stderr);
|
||||
|
@ -1238,7 +1241,7 @@ btr_cur_optimistic_insert(
|
|||
rec_size = rec_get_converted_size(index, entry, n_ext);
|
||||
}
|
||||
|
||||
if (UNIV_UNLIKELY(zip_size)) {
|
||||
if (zip_size) {
|
||||
/* Estimate the free space of an empty compressed page.
|
||||
Subtract one byte for the encoded heap_no in the
|
||||
modification log. */
|
||||
|
@ -1346,7 +1349,7 @@ fail_err:
|
|||
n_ext, mtr);
|
||||
|
||||
if (UNIV_UNLIKELY(!*rec)) {
|
||||
if (UNIV_LIKELY(zip_size != 0)) {
|
||||
if (zip_size != 0) {
|
||||
|
||||
goto fail;
|
||||
}
|
||||
|
@ -1498,7 +1501,7 @@ btr_cur_pessimistic_insert(
|
|||
|
||||
if (page_zip_rec_needs_ext(rec_get_converted_size(index, entry, n_ext),
|
||||
dict_table_is_comp(index->table),
|
||||
dict_index_get_n_fields(index),
|
||||
dtuple_get_n_fields(entry),
|
||||
zip_size)) {
|
||||
/* The record is so big that we have to store some fields
|
||||
externally on separate database pages */
|
||||
|
@ -1923,8 +1926,8 @@ btr_cur_update_in_place(
|
|||
trx, roll_ptr, mtr);
|
||||
|
||||
if (was_delete_marked
|
||||
&& !rec_get_deleted_flag(rec, page_is_comp(
|
||||
buf_block_get_frame(block)))) {
|
||||
&& !rec_get_deleted_flag(
|
||||
rec, page_is_comp(buf_block_get_frame(block)))) {
|
||||
/* The new updated record owns its possible externally
|
||||
stored fields */
|
||||
|
||||
|
@ -1975,7 +1978,6 @@ btr_cur_optimistic_update(
|
|||
ulint old_rec_size;
|
||||
dtuple_t* new_entry;
|
||||
roll_ptr_t roll_ptr;
|
||||
trx_t* trx;
|
||||
mem_heap_t* heap;
|
||||
ulint i;
|
||||
ulint n_ext;
|
||||
|
@ -1992,9 +1994,10 @@ btr_cur_optimistic_update(
|
|||
|
||||
heap = mem_heap_create(1024);
|
||||
offsets = rec_get_offsets(rec, index, NULL, ULINT_UNDEFINED, &heap);
|
||||
#ifdef UNIV_BLOB_NULL_DEBUG
|
||||
ut_a(!rec_offs_any_null_extern(rec, offsets));
|
||||
#endif /* UNIV_BLOB_NULL_DEBUG */
|
||||
#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
|
||||
ut_a(!rec_offs_any_null_extern(rec, offsets)
|
||||
|| trx_is_recv(thr_get_trx(thr)));
|
||||
#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
if (btr_cur_print_record_ops && thr) {
|
||||
|
@ -2117,13 +2120,11 @@ any_extern:
|
|||
|
||||
page_cur_move_to_prev(page_cursor);
|
||||
|
||||
trx = thr_get_trx(thr);
|
||||
|
||||
if (!(flags & BTR_KEEP_SYS_FLAG)) {
|
||||
row_upd_index_entry_sys_field(new_entry, index, DATA_ROLL_PTR,
|
||||
roll_ptr);
|
||||
row_upd_index_entry_sys_field(new_entry, index, DATA_TRX_ID,
|
||||
trx->id);
|
||||
thr_get_trx(thr)->id);
|
||||
}
|
||||
|
||||
/* There are no externally stored columns in new_entry */
|
||||
|
@ -3463,8 +3464,6 @@ btr_estimate_n_rows_in_range(
|
|||
n_rows = n_rows * 2;
|
||||
}
|
||||
|
||||
DBUG_EXECUTE_IF("bug14007649", return(n_rows););
|
||||
|
||||
/* Do not estimate the number of rows in the range
|
||||
to over 1 / 2 of the estimated rows in the whole
|
||||
table */
|
||||
|
@ -3574,7 +3573,8 @@ btr_record_not_null_field_in_rec(
|
|||
/*******************************************************************//**
|
||||
Estimates the number of different key values in a given index, for
|
||||
each n-column prefix of the index where n <= dict_index_get_n_unique(index).
|
||||
The estimates are stored in the array index->stat_n_diff_key_vals.
|
||||
The estimates are stored in the array index->stat_n_diff_key_vals[] and
|
||||
the number of pages that were sampled is saved in index->stat_n_sample_sizes[].
|
||||
If innodb_stats_method is "nulls_ignored", we also record the number of
|
||||
non-null values for each prefix and store the estimates in
|
||||
array index->stat_n_non_null_key_vals. */
|
||||
|
@ -3612,7 +3612,8 @@ btr_estimate_number_of_different_key_vals(
|
|||
* (sizeof *offsets_rec
|
||||
+ sizeof *offsets_next_rec));
|
||||
|
||||
n_diff = mem_heap_zalloc(heap, (n_cols + 1) * sizeof(ib_int64_t));
|
||||
n_diff = (ib_int64_t*) mem_heap_zalloc(heap, (n_cols + 1)
|
||||
* sizeof(ib_int64_t));
|
||||
|
||||
n_not_null = NULL;
|
||||
|
||||
|
@ -3621,7 +3622,7 @@ btr_estimate_number_of_different_key_vals(
|
|||
considered equal (by setting stats_null_not_equal value) */
|
||||
switch (srv_innodb_stats_method) {
|
||||
case SRV_STATS_NULLS_IGNORED:
|
||||
n_not_null = mem_heap_zalloc(heap, (n_cols + 1)
|
||||
n_not_null = (ib_int64_t*) mem_heap_zalloc(heap, (n_cols + 1)
|
||||
* sizeof *n_not_null);
|
||||
/* fall through */
|
||||
|
||||
|
@ -3641,14 +3642,14 @@ btr_estimate_number_of_different_key_vals(
|
|||
|
||||
/* It makes no sense to test more pages than are contained
|
||||
in the index, thus we lower the number if it is too high */
|
||||
if (srv_stats_sample_pages > index->stat_index_size) {
|
||||
if (srv_stats_transient_sample_pages > index->stat_index_size) {
|
||||
if (index->stat_index_size > 0) {
|
||||
n_sample_pages = index->stat_index_size;
|
||||
} else {
|
||||
n_sample_pages = 1;
|
||||
}
|
||||
} else {
|
||||
n_sample_pages = srv_stats_sample_pages;
|
||||
n_sample_pages = srv_stats_transient_sample_pages;
|
||||
}
|
||||
|
||||
/* We sample some pages in the index to get an estimate */
|
||||
|
@ -3762,7 +3763,7 @@ btr_estimate_number_of_different_key_vals(
|
|||
index->stat_n_diff_key_vals[j]
|
||||
= BTR_TABLE_STATS_FROM_SAMPLE(
|
||||
n_diff[j], index, n_sample_pages,
|
||||
total_external_size, not_empty_flag);
|
||||
total_external_size, not_empty_flag);
|
||||
|
||||
/* If the tree is small, smaller than
|
||||
10 * n_sample_pages + total_external_size, then
|
||||
|
@ -3782,6 +3783,8 @@ btr_estimate_number_of_different_key_vals(
|
|||
|
||||
index->stat_n_diff_key_vals[j] += add_on;
|
||||
|
||||
index->stat_n_sample_sizes[j] = n_sample_pages;
|
||||
|
||||
/* Update the stat_n_non_null_key_vals[] with our
|
||||
sampled result. stat_n_non_null_key_vals[] is created
|
||||
and initialized to zero in dict_index_add_to_cache(),
|
||||
|
@ -4040,10 +4043,11 @@ btr_push_update_extern_fields(
|
|||
will have to be copied. */
|
||||
ut_a(uf->orig_len > BTR_EXTERN_FIELD_REF_SIZE);
|
||||
|
||||
data = dfield_get_data(field);
|
||||
data = (byte*) dfield_get_data(field);
|
||||
len = dfield_get_len(field);
|
||||
|
||||
buf = mem_heap_alloc(heap, uf->orig_len);
|
||||
buf = (byte*) mem_heap_alloc(heap,
|
||||
uf->orig_len);
|
||||
/* Copy the locally stored prefix. */
|
||||
memcpy(buf, data,
|
||||
uf->orig_len
|
||||
|
@ -4107,7 +4111,6 @@ btr_blob_free(
|
|||
mtr_commit(mtr);
|
||||
|
||||
buf_pool_mutex_enter(buf_pool);
|
||||
mutex_enter(&block->mutex);
|
||||
|
||||
/* Only free the block if it is still allocated to
|
||||
the same file page. */
|
||||
|
@ -4127,7 +4130,6 @@ btr_blob_free(
|
|||
}
|
||||
|
||||
buf_pool_mutex_exit(buf_pool);
|
||||
mutex_exit(&block->mutex);
|
||||
}
|
||||
|
||||
/*******************************************************************//**
|
||||
|
@ -4217,10 +4219,11 @@ btr_store_big_rec_extern_fields(
|
|||
* sizeof *freed_pages);
|
||||
}
|
||||
|
||||
freed_pages = mem_heap_alloc(
|
||||
heap,
|
||||
btr_mtr->n_freed_pages
|
||||
* sizeof *freed_pages);
|
||||
freed_pages = static_cast<buf_block_t**>(
|
||||
mem_heap_alloc(
|
||||
heap,
|
||||
btr_mtr->n_freed_pages
|
||||
* sizeof *freed_pages));
|
||||
n_freed_pages = 0;
|
||||
}
|
||||
|
||||
|
@ -4286,7 +4289,8 @@ btr_store_big_rec_extern_fields(
|
|||
int err = deflateReset(&c_stream);
|
||||
ut_a(err == Z_OK);
|
||||
|
||||
c_stream.next_in = (void*) big_rec_vec->fields[i].data;
|
||||
c_stream.next_in = (Bytef*)
|
||||
big_rec_vec->fields[i].data;
|
||||
c_stream.avail_in = extern_len;
|
||||
}
|
||||
|
||||
|
@ -4636,8 +4640,7 @@ btr_check_blob_fil_page_type(
|
|||
ulint flags = fil_space_get_flags(space_id);
|
||||
|
||||
#ifndef UNIV_DEBUG /* Improve debug test coverage */
|
||||
if (UNIV_LIKELY
|
||||
((flags & DICT_TF_FORMAT_MASK) == DICT_TF_FORMAT_51)) {
|
||||
if (dict_tf_get_format(flags) == UNIV_FORMAT_A) {
|
||||
/* Old versions of InnoDB did not initialize
|
||||
FIL_PAGE_TYPE on BLOB pages. Do not print
|
||||
anything about the type mismatch when reading
|
||||
|
@ -4816,7 +4819,7 @@ btr_free_externally_stored_field(
|
|||
|
||||
btr_page_free_low(index, ext_block, 0, &mtr);
|
||||
|
||||
if (page_zip) {
|
||||
if (page_zip != NULL) {
|
||||
mach_write_to_4(field_ref + BTR_EXTERN_PAGE_NO,
|
||||
next_page_no);
|
||||
mach_write_to_4(field_ref + BTR_EXTERN_LEN + 4,
|
||||
|
@ -5037,8 +5040,8 @@ btr_copy_zblob_prefix(
|
|||
page_zip_set_alloc(&d_stream, heap);
|
||||
|
||||
ut_ad(ut_is_2pow(zip_size));
|
||||
ut_ad(zip_size >= PAGE_ZIP_MIN_SIZE);
|
||||
ut_ad(zip_size <= UNIV_PAGE_SIZE);
|
||||
ut_ad(zip_size >= UNIV_ZIP_SIZE_MIN);
|
||||
ut_ad(zip_size <= UNIV_ZIP_SIZE_MAX);
|
||||
ut_ad(space_id);
|
||||
|
||||
err = inflateInit(&d_stream);
|
||||
|
@ -5179,7 +5182,7 @@ btr_copy_externally_stored_field_prefix_low(
|
|||
return(0);
|
||||
}
|
||||
|
||||
if (UNIV_UNLIKELY(zip_size)) {
|
||||
if (zip_size) {
|
||||
return(btr_copy_zblob_prefix(buf, len, zip_size,
|
||||
space_id, page_no, offset));
|
||||
} else {
|
||||
|
@ -5251,7 +5254,7 @@ btr_copy_externally_stored_field_prefix(
|
|||
Copies an externally stored field of a record to mem heap. The
|
||||
clustered index record must be protected by a lock or a page latch.
|
||||
@return the whole field copied to heap */
|
||||
static
|
||||
UNIV_INTERN
|
||||
byte*
|
||||
btr_copy_externally_stored_field(
|
||||
/*=============================*/
|
||||
|
@ -5286,7 +5289,7 @@ btr_copy_externally_stored_field(
|
|||
|
||||
extern_len = mach_read_from_4(data + local_len + BTR_EXTERN_LEN + 4);
|
||||
|
||||
buf = mem_heap_alloc(heap, local_len + extern_len);
|
||||
buf = (byte*) mem_heap_alloc(heap, local_len + extern_len);
|
||||
|
||||
memcpy(buf, data, local_len);
|
||||
*len = local_len
|
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 1996, 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
|
||||
|
@ -11,13 +11,13 @@ 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 program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file btr/btr0pcur.c
|
||||
@file btr/btr0pcur.cc
|
||||
The index tree persistent cursor
|
||||
|
||||
Created 2/23/1996 Heikki Tuuri
|
||||
|
@ -43,7 +43,7 @@ btr_pcur_create_for_mysql(void)
|
|||
{
|
||||
btr_pcur_t* pcur;
|
||||
|
||||
pcur = mem_alloc(sizeof(btr_pcur_t));
|
||||
pcur = (btr_pcur_t*) mem_alloc(sizeof(btr_pcur_t));
|
||||
|
||||
pcur->btr_cur.index = NULL;
|
||||
btr_pcur_init(pcur);
|
||||
|
@ -133,8 +133,6 @@ btr_pcur_store_position(
|
|||
|
||||
ut_a(btr_page_get_next(page, mtr) == FIL_NULL);
|
||||
ut_a(btr_page_get_prev(page, mtr) == FIL_NULL);
|
||||
ut_ad(page_is_leaf(page));
|
||||
ut_ad(page_get_page_no(page) == index->page);
|
||||
|
||||
cursor->old_stored = BTR_PCUR_OLD_STORED;
|
||||
|
||||
|
@ -191,7 +189,8 @@ btr_pcur_copy_stored_position(
|
|||
|
||||
if (pcur_donate->old_rec_buf) {
|
||||
|
||||
pcur_receive->old_rec_buf = mem_alloc(pcur_donate->buf_size);
|
||||
pcur_receive->old_rec_buf = (byte*)
|
||||
mem_alloc(pcur_donate->buf_size);
|
||||
|
||||
ut_memcpy(pcur_receive->old_rec_buf, pcur_donate->old_rec_buf,
|
||||
pcur_donate->buf_size);
|
||||
|
@ -327,19 +326,13 @@ btr_pcur_restore_position_func(
|
|||
/* Save the old search mode of the cursor */
|
||||
old_mode = cursor->search_mode;
|
||||
|
||||
switch (cursor->rel_pos) {
|
||||
case BTR_PCUR_ON:
|
||||
if (UNIV_LIKELY(cursor->rel_pos == BTR_PCUR_ON)) {
|
||||
mode = PAGE_CUR_LE;
|
||||
break;
|
||||
case BTR_PCUR_AFTER:
|
||||
} else if (cursor->rel_pos == BTR_PCUR_AFTER) {
|
||||
mode = PAGE_CUR_G;
|
||||
break;
|
||||
case BTR_PCUR_BEFORE:
|
||||
} else {
|
||||
ut_ad(cursor->rel_pos == BTR_PCUR_BEFORE);
|
||||
mode = PAGE_CUR_L;
|
||||
break;
|
||||
default:
|
||||
ut_error;
|
||||
mode = 0;
|
||||
}
|
||||
|
||||
btr_pcur_open_with_no_init_func(index, tuple, mode, latch_mode,
|
||||
|
@ -348,44 +341,25 @@ btr_pcur_restore_position_func(
|
|||
/* Restore the old search mode */
|
||||
cursor->search_mode = old_mode;
|
||||
|
||||
if (btr_pcur_is_on_user_rec(cursor)) {
|
||||
switch (cursor->rel_pos) {
|
||||
case BTR_PCUR_ON:
|
||||
if (!cmp_dtuple_rec(
|
||||
tuple, btr_pcur_get_rec(cursor),
|
||||
rec_get_offsets(btr_pcur_get_rec(cursor),
|
||||
index, NULL,
|
||||
ULINT_UNDEFINED, &heap))) {
|
||||
if (cursor->rel_pos == BTR_PCUR_ON
|
||||
&& btr_pcur_is_on_user_rec(cursor)
|
||||
&& 0 == cmp_dtuple_rec(tuple, btr_pcur_get_rec(cursor),
|
||||
rec_get_offsets(
|
||||
btr_pcur_get_rec(cursor), index,
|
||||
NULL, ULINT_UNDEFINED, &heap))) {
|
||||
|
||||
/* We have to store the NEW value for
|
||||
the modify clock, since the cursor can
|
||||
now be on a different page! But we can
|
||||
retain the value of old_rec */
|
||||
/* We have to store the NEW value for the modify clock, since
|
||||
the cursor can now be on a different page! But we can retain
|
||||
the value of old_rec */
|
||||
|
||||
cursor->block_when_stored =
|
||||
btr_pcur_get_block(cursor);
|
||||
cursor->modify_clock =
|
||||
buf_block_get_modify_clock(
|
||||
cursor->block_when_stored);
|
||||
cursor->old_stored = BTR_PCUR_OLD_STORED;
|
||||
cursor->block_when_stored = btr_pcur_get_block(cursor);
|
||||
cursor->modify_clock = buf_block_get_modify_clock(
|
||||
cursor->block_when_stored);
|
||||
cursor->old_stored = BTR_PCUR_OLD_STORED;
|
||||
|
||||
mem_heap_free(heap);
|
||||
mem_heap_free(heap);
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
break;
|
||||
case BTR_PCUR_BEFORE:
|
||||
page_cur_move_to_next(btr_pcur_get_page_cur(cursor));
|
||||
break;
|
||||
case BTR_PCUR_AFTER:
|
||||
page_cur_move_to_prev(btr_pcur_get_page_cur(cursor));
|
||||
break;
|
||||
#ifdef UNIV_DEBUG
|
||||
default:
|
||||
ut_error;
|
||||
#endif /* UNIV_DEBUG */
|
||||
}
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
mem_heap_free(heap);
|
||||
|
@ -587,8 +561,8 @@ btr_pcur_open_on_user_rec_func(
|
|||
ulint line, /*!< in: line where called */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
{
|
||||
btr_pcur_open_func(index, tuple, mode, latch_mode, cursor,
|
||||
file, line, mtr);
|
||||
btr_pcur_open_low(index, 0, tuple, mode, latch_mode, cursor,
|
||||
file, line, mtr);
|
||||
|
||||
if ((mode == PAGE_CUR_GE) || (mode == PAGE_CUR_G)) {
|
||||
|
|
@ -18,13 +18,13 @@ 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 program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/********************************************************************//**
|
||||
@file btr/btr0sea.c
|
||||
@file btr/btr0sea.cc
|
||||
The index tree adaptive search
|
||||
|
||||
Created 2/17/1996 Heikki Tuuri
|
||||
|
@ -42,16 +42,12 @@ Created 2/17/1996 Heikki Tuuri
|
|||
#include "btr0pcur.h"
|
||||
#include "btr0btr.h"
|
||||
#include "ha0ha.h"
|
||||
#include "srv0mon.h"
|
||||
|
||||
/** Flag: has the search system been enabled?
|
||||
Protected by btr_search_latch. */
|
||||
UNIV_INTERN char btr_search_enabled = TRUE;
|
||||
|
||||
#ifdef UNIV_PFS_MUTEX
|
||||
/* Key to register btr_search_enabled_mutex with performance schema */
|
||||
UNIV_INTERN mysql_pfs_key_t btr_search_enabled_mutex_key;
|
||||
#endif /* UNIV_PFS_MUTEX */
|
||||
|
||||
/** A dummy variable to fool the compiler */
|
||||
UNIV_INTERN ulint btr_search_this_is_zero = 0;
|
||||
|
||||
|
@ -172,14 +168,20 @@ btr_search_sys_create(
|
|||
/* We allocate the search latch from dynamic memory:
|
||||
see above at the global variable definition */
|
||||
|
||||
btr_search_latch_temp = mem_alloc(sizeof(rw_lock_t));
|
||||
btr_search_latch_temp = (rw_lock_t*) mem_alloc(sizeof(rw_lock_t));
|
||||
|
||||
rw_lock_create(btr_search_latch_key, &btr_search_latch,
|
||||
SYNC_SEARCH_SYS);
|
||||
|
||||
btr_search_sys = mem_alloc(sizeof(btr_search_sys_t));
|
||||
btr_search_sys = (btr_search_sys_t*)
|
||||
mem_alloc(sizeof(btr_search_sys_t));
|
||||
|
||||
btr_search_sys->hash_index = ha_create(hash_size, 0,
|
||||
MEM_HEAP_FOR_BTR_SEARCH, 0);
|
||||
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
|
||||
btr_search_sys->hash_index->adaptive = TRUE;
|
||||
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
|
||||
|
||||
btr_search_sys->hash_index = ha_create(hash_size, 0, 0);
|
||||
}
|
||||
|
||||
/*****************************************************************//**
|
||||
|
@ -198,6 +200,28 @@ btr_search_sys_free(void)
|
|||
btr_search_sys = NULL;
|
||||
}
|
||||
|
||||
/********************************************************************//**
|
||||
Set index->ref_count = 0 on all indexes of a table. */
|
||||
static
|
||||
void
|
||||
btr_search_disable_ref_count(
|
||||
/*=========================*/
|
||||
dict_table_t* table) /*!< in/out: table */
|
||||
{
|
||||
dict_index_t* index;
|
||||
|
||||
ut_ad(mutex_own(&dict_sys->mutex));
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
|
||||
for (index = dict_table_get_first_index(table); index;
|
||||
index = dict_table_get_next_index(index)) {
|
||||
|
||||
index->search_info->ref_count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************//**
|
||||
Disable the adaptive hash search system and empty the index. */
|
||||
UNIV_INTERN
|
||||
|
@ -217,13 +241,13 @@ btr_search_disable(void)
|
|||
for (table = UT_LIST_GET_FIRST(dict_sys->table_LRU); table;
|
||||
table = UT_LIST_GET_NEXT(table_LRU, table)) {
|
||||
|
||||
dict_index_t* index;
|
||||
btr_search_disable_ref_count(table);
|
||||
}
|
||||
|
||||
for (index = dict_table_get_first_index(table); index;
|
||||
index = dict_table_get_next_index(index)) {
|
||||
for (table = UT_LIST_GET_FIRST(dict_sys->table_non_LRU); table;
|
||||
table = UT_LIST_GET_NEXT(table_LRU, table)) {
|
||||
|
||||
index->search_info->ref_count = 0;
|
||||
}
|
||||
btr_search_disable_ref_count(table);
|
||||
}
|
||||
|
||||
mutex_exit(&dict_sys->mutex);
|
||||
|
@ -263,7 +287,7 @@ btr_search_info_create(
|
|||
{
|
||||
btr_search_t* info;
|
||||
|
||||
info = mem_heap_alloc(heap, sizeof(btr_search_t));
|
||||
info = (btr_search_t*) mem_heap_alloc(heap, sizeof(btr_search_t));
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
info->magic_n = BTR_SEARCH_MAGIC_N;
|
||||
|
@ -585,6 +609,8 @@ btr_search_update_hash_ref(
|
|||
|
||||
ha_insert_for_fold(btr_search_sys->hash_index, fold,
|
||||
block, rec);
|
||||
|
||||
MONITOR_INC(MONITOR_ADAPTIVE_HASH_ROW_ADDED);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -646,7 +672,7 @@ btr_search_info_update_slow(
|
|||
inside the called function. It might be that the compiler
|
||||
would optimize the call just to pass pointers to block. */
|
||||
|
||||
params = mem_alloc(3 * sizeof(ulint));
|
||||
params = (ulint*) mem_alloc(3 * sizeof(ulint));
|
||||
params[0] = block->n_fields;
|
||||
params[1] = block->n_bytes;
|
||||
params[2] = block->left_side;
|
||||
|
@ -889,7 +915,7 @@ btr_search_guess_on_hash(
|
|||
ut_ad(rw_lock_get_writer(&btr_search_latch) != RW_LOCK_EX);
|
||||
ut_ad(rw_lock_get_reader_count(&btr_search_latch) > 0);
|
||||
|
||||
rec = ha_search_and_get_data(btr_search_sys->hash_index, fold);
|
||||
rec = (rec_t*) ha_search_and_get_data(btr_search_sys->hash_index, fold);
|
||||
|
||||
if (UNIV_UNLIKELY(!rec)) {
|
||||
goto failure_unlock;
|
||||
|
@ -1030,7 +1056,11 @@ btr_search_drop_page_hash_index(
|
|||
buf_block_t* block) /*!< in: block containing index page,
|
||||
s- or x-latched, or an index page
|
||||
for which we know that
|
||||
block->buf_fix_count == 0 */
|
||||
block->buf_fix_count == 0 or it is an
|
||||
index page which has already been
|
||||
removed from the buf_pool->page_hash
|
||||
i.e.: it is in state
|
||||
BUF_BLOCK_REMOVE_HASH */
|
||||
{
|
||||
hash_table_t* table;
|
||||
ulint n_fields;
|
||||
|
@ -1053,6 +1083,13 @@ btr_search_drop_page_hash_index(
|
|||
ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
|
||||
/* Do a dirty check on block->index, return if the block is
|
||||
not in the adaptive hash index. This is to avoid acquiring
|
||||
shared btr_search_latch for performance consideration. */
|
||||
if (!block->index) {
|
||||
return;
|
||||
}
|
||||
|
||||
retry:
|
||||
rw_lock_s_lock(&btr_search_latch);
|
||||
index = block->index;
|
||||
|
@ -1070,7 +1107,8 @@ retry:
|
|||
#ifdef UNIV_SYNC_DEBUG
|
||||
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED)
|
||||
|| rw_lock_own(&(block->lock), RW_LOCK_EX)
|
||||
|| (block->page.buf_fix_count == 0));
|
||||
|| block->page.buf_fix_count == 0
|
||||
|| buf_block_get_state(block) == BUF_BLOCK_REMOVE_HASH);
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
|
||||
n_fields = block->curr_n_fields;
|
||||
|
@ -1090,7 +1128,7 @@ retry:
|
|||
/* Calculate and cache fold values into an array for fast deletion
|
||||
from the hash index */
|
||||
|
||||
folds = mem_alloc(n_recs * sizeof(ulint));
|
||||
folds = (ulint*) mem_alloc(n_recs * sizeof(ulint));
|
||||
|
||||
n_cached = 0;
|
||||
|
||||
|
@ -1163,6 +1201,9 @@ next_rec:
|
|||
|
||||
block->index = NULL;
|
||||
|
||||
MONITOR_INC(MONITOR_ADAPTIVE_HASH_PAGE_REMOVED);
|
||||
MONITOR_INC_VALUE(MONITOR_ADAPTIVE_HASH_ROW_REMOVED, n_cached);
|
||||
|
||||
cleanup:
|
||||
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
|
||||
if (UNIV_UNLIKELY(block->n_pointers)) {
|
||||
|
@ -1309,8 +1350,8 @@ btr_search_build_page_hash_index(
|
|||
/* Calculate and cache fold values and corresponding records into
|
||||
an array for fast insertion to the hash index */
|
||||
|
||||
folds = mem_alloc(n_recs * sizeof(ulint));
|
||||
recs = mem_alloc(n_recs * sizeof(rec_t*));
|
||||
folds = (ulint*) mem_alloc(n_recs * sizeof(ulint));
|
||||
recs = (rec_t**) mem_alloc(n_recs * sizeof(rec_t*));
|
||||
|
||||
n_cached = 0;
|
||||
|
||||
|
@ -1412,6 +1453,8 @@ btr_search_build_page_hash_index(
|
|||
ha_insert_for_fold(table, folds[i], block, recs[i]);
|
||||
}
|
||||
|
||||
MONITOR_INC(MONITOR_ADAPTIVE_HASH_PAGE_ADDED);
|
||||
MONITOR_INC_VALUE(MONITOR_ADAPTIVE_HASH_ROW_ADDED, n_cached);
|
||||
exit_func:
|
||||
rw_lock_x_unlock(&btr_search_latch);
|
||||
|
||||
|
@ -1541,7 +1584,12 @@ btr_search_update_hash_on_delete(
|
|||
if (block->index) {
|
||||
ut_a(block->index == index);
|
||||
|
||||
ha_search_and_delete_if_found(table, fold, rec);
|
||||
if (ha_search_and_delete_if_found(table, fold, rec)) {
|
||||
MONITOR_INC(MONITOR_ADAPTIVE_HASH_ROW_REMOVED);
|
||||
} else {
|
||||
MONITOR_INC(
|
||||
MONITOR_ADAPTIVE_HASH_ROW_REMOVE_NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
rw_lock_x_unlock(&btr_search_latch);
|
||||
|
@ -1597,8 +1645,11 @@ btr_search_update_hash_node_on_insert(
|
|||
|
||||
table = btr_search_sys->hash_index;
|
||||
|
||||
ha_search_and_update_if_found(table, cursor->fold, rec,
|
||||
block, page_rec_get_next(rec));
|
||||
if (ha_search_and_update_if_found(
|
||||
table, cursor->fold, rec, block,
|
||||
page_rec_get_next(rec))) {
|
||||
MONITOR_INC(MONITOR_ADAPTIVE_HASH_ROW_UPDATED);
|
||||
}
|
||||
|
||||
func_exit:
|
||||
rw_lock_x_unlock(&btr_search_latch);
|
||||
|
@ -1623,9 +1674,9 @@ btr_search_update_hash_on_insert(
|
|||
hash_table_t* table;
|
||||
buf_block_t* block;
|
||||
dict_index_t* index;
|
||||
rec_t* rec;
|
||||
rec_t* ins_rec;
|
||||
rec_t* next_rec;
|
||||
const rec_t* rec;
|
||||
const rec_t* ins_rec;
|
||||
const rec_t* next_rec;
|
||||
ulint fold;
|
||||
ulint ins_fold;
|
||||
ulint next_fold = 0; /* remove warning (??? bug ???) */
|
||||
|
@ -1638,12 +1689,6 @@ btr_search_update_hash_on_insert(
|
|||
ulint* offsets = offsets_;
|
||||
rec_offs_init(offsets_);
|
||||
|
||||
table = btr_search_sys->hash_index;
|
||||
|
||||
btr_search_check_free_space_in_heap();
|
||||
|
||||
rec = btr_cur_get_rec(cursor);
|
||||
|
||||
block = btr_cur_get_block(cursor);
|
||||
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
|
@ -1657,6 +1702,12 @@ btr_search_update_hash_on_insert(
|
|||
return;
|
||||
}
|
||||
|
||||
btr_search_check_free_space_in_heap();
|
||||
|
||||
table = btr_search_sys->hash_index;
|
||||
|
||||
rec = btr_cur_get_rec(cursor);
|
||||
|
||||
ut_a(index == cursor->index);
|
||||
ut_a(!dict_index_is_ibuf(index));
|
||||
|
||||
|
@ -1664,8 +1715,8 @@ btr_search_update_hash_on_insert(
|
|||
n_bytes = block->curr_n_bytes;
|
||||
left_side = block->curr_left_side;
|
||||
|
||||
ins_rec = page_rec_get_next(rec);
|
||||
next_rec = page_rec_get_next(ins_rec);
|
||||
ins_rec = page_rec_get_next_const(rec);
|
||||
next_rec = page_rec_get_next_const(ins_rec);
|
||||
|
||||
offsets = rec_get_offsets(ins_rec, index, offsets,
|
||||
ULINT_UNDEFINED, &heap);
|
||||
|
@ -1815,11 +1866,12 @@ btr_search_validate(void)
|
|||
buf_pool_mutex_enter_all();
|
||||
}
|
||||
|
||||
node = hash_get_nth_cell(btr_search_sys->hash_index, i)->node;
|
||||
node = (ha_node_t*)
|
||||
hash_get_nth_cell(btr_search_sys->hash_index, i)->node;
|
||||
|
||||
for (; node != NULL; node = node->next) {
|
||||
const buf_block_t* block
|
||||
= buf_block_align(node->data);
|
||||
= buf_block_align((byte*) node->data);
|
||||
const buf_block_t* hash_block;
|
||||
buf_pool_t* buf_pool;
|
||||
index_id_t page_index_id;
|
|
@ -11,13 +11,13 @@ 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 program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file buf/buf0buddy.c
|
||||
@file buf/buf0buddy.cc
|
||||
Binary buddy allocator for compressed pages
|
||||
|
||||
Created December 2006 by Marko Makela
|
||||
|
@ -46,7 +46,9 @@ buf_buddy_get(
|
|||
{
|
||||
ut_ad(ut_is_2pow(size));
|
||||
ut_ad(size >= BUF_BUDDY_LOW);
|
||||
ut_ad(BUF_BUDDY_LOW <= UNIV_ZIP_SIZE_MIN);
|
||||
ut_ad(size < BUF_BUDDY_HIGH);
|
||||
ut_ad(BUF_BUDDY_HIGH == UNIV_PAGE_SIZE);
|
||||
ut_ad(!ut_align_offset(page, size));
|
||||
|
||||
if (((ulint) page) & size) {
|
||||
|
@ -57,12 +59,15 @@ buf_buddy_get(
|
|||
}
|
||||
|
||||
/** Validate a given zip_free list. */
|
||||
#define BUF_BUDDY_LIST_VALIDATE(b, i) \
|
||||
UT_LIST_VALIDATE(list, buf_page_t, \
|
||||
b->zip_free[i], \
|
||||
ut_ad(buf_page_get_state( \
|
||||
ut_list_node_313) \
|
||||
== BUF_BLOCK_ZIP_FREE))
|
||||
struct CheckZipFree {
|
||||
void operator()(const buf_page_t* elem) const
|
||||
{
|
||||
ut_a(buf_page_get_state(elem) == BUF_BLOCK_ZIP_FREE);
|
||||
}
|
||||
};
|
||||
|
||||
#define BUF_BUDDY_LIST_VALIDATE(bp, i) \
|
||||
UT_LIST_VALIDATE(list, buf_page_t, bp->zip_free[i], CheckZipFree())
|
||||
|
||||
/**********************************************************************//**
|
||||
Add a block to the head of the appropriate buddy free list. */
|
||||
|
@ -119,7 +124,7 @@ buf_buddy_alloc_zip(
|
|||
|
||||
ut_ad(buf_pool_mutex_own(buf_pool));
|
||||
ut_a(i < BUF_BUDDY_SIZES);
|
||||
ut_a(i >= buf_buddy_get_slot(PAGE_ZIP_MIN_SIZE));
|
||||
ut_a(i >= buf_buddy_get_slot(UNIV_ZIP_SIZE_MIN));
|
||||
|
||||
ut_d(BUF_BUDDY_LIST_VALIDATE(buf_pool, i));
|
||||
|
||||
|
@ -131,7 +136,7 @@ buf_buddy_alloc_zip(
|
|||
buf_buddy_remove_from_free(buf_pool, bpage, i);
|
||||
} else if (i + 1 < BUF_BUDDY_SIZES) {
|
||||
/* Attempt to split. */
|
||||
bpage = buf_buddy_alloc_zip(buf_pool, i + 1);
|
||||
bpage = (buf_page_t*) buf_buddy_alloc_zip(buf_pool, i + 1);
|
||||
|
||||
if (bpage) {
|
||||
buf_page_t* buddy = (buf_page_t*)
|
||||
|
@ -235,7 +240,7 @@ buf_buddy_alloc_from(
|
|||
{
|
||||
ulint offs = BUF_BUDDY_LOW << j;
|
||||
ut_ad(j <= BUF_BUDDY_SIZES);
|
||||
ut_ad(i >= buf_buddy_get_slot(PAGE_ZIP_MIN_SIZE));
|
||||
ut_ad(i >= buf_buddy_get_slot(UNIV_ZIP_SIZE_MIN));
|
||||
ut_ad(j >= i);
|
||||
ut_ad(!ut_align_offset(buf, offs));
|
||||
|
||||
|
@ -279,11 +284,11 @@ buf_buddy_alloc_low(
|
|||
ut_ad(lru);
|
||||
ut_ad(buf_pool_mutex_own(buf_pool));
|
||||
ut_ad(!mutex_own(&buf_pool->zip_mutex));
|
||||
ut_ad(i >= buf_buddy_get_slot(PAGE_ZIP_MIN_SIZE));
|
||||
ut_ad(i >= buf_buddy_get_slot(UNIV_ZIP_SIZE_MIN));
|
||||
|
||||
if (i < BUF_BUDDY_SIZES) {
|
||||
/* Try to allocate from the buddy system. */
|
||||
block = buf_buddy_alloc_zip(buf_pool, i);
|
||||
block = (buf_block_t*) buf_buddy_alloc_zip(buf_pool, i);
|
||||
|
||||
if (block) {
|
||||
goto func_exit;
|
||||
|
@ -307,7 +312,7 @@ buf_buddy_alloc_low(
|
|||
alloc_big:
|
||||
buf_buddy_block_register(block);
|
||||
|
||||
block = buf_buddy_alloc_from(
|
||||
block = (buf_block_t*) buf_buddy_alloc_from(
|
||||
buf_pool, block->frame, i, BUF_BUDDY_SIZES);
|
||||
|
||||
func_exit:
|
||||
|
@ -338,7 +343,7 @@ buf_buddy_relocate(
|
|||
ut_ad(!mutex_own(&buf_pool->zip_mutex));
|
||||
ut_ad(!ut_align_offset(src, size));
|
||||
ut_ad(!ut_align_offset(dst, size));
|
||||
ut_ad(i >= buf_buddy_get_slot(PAGE_ZIP_MIN_SIZE));
|
||||
ut_ad(i >= buf_buddy_get_slot(UNIV_ZIP_SIZE_MIN));
|
||||
UNIV_MEM_ASSERT_W(dst, size);
|
||||
|
||||
/* We assume that all memory from buf_buddy_alloc()
|
||||
|
@ -358,9 +363,9 @@ buf_buddy_relocate(
|
|||
pool), so there is nothing wrong about this. The
|
||||
mach_read_from_4() calls here will only trigger bogus
|
||||
Valgrind memcheck warnings in UNIV_DEBUG_VALGRIND builds. */
|
||||
space = mach_read_from_4((const byte *) src
|
||||
space = mach_read_from_4((const byte*) src
|
||||
+ FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
|
||||
page_no = mach_read_from_4((const byte *) src
|
||||
page_no = mach_read_from_4((const byte*) src
|
||||
+ FIL_PAGE_OFFSET);
|
||||
/* Suppress Valgrind warnings about conditional jump
|
||||
on uninitialized value. */
|
||||
|
@ -399,7 +404,7 @@ buf_buddy_relocate(
|
|||
ullint usec = ut_time_us(NULL);
|
||||
ut_a(bpage->zip.data == src);
|
||||
memcpy(dst, src, size);
|
||||
bpage->zip.data = dst;
|
||||
bpage->zip.data = (page_zip_t*) dst;
|
||||
mutex_exit(mutex);
|
||||
UNIV_MEM_INVALID(src, size);
|
||||
{
|
||||
|
@ -434,7 +439,7 @@ buf_buddy_free_low(
|
|||
ut_ad(buf_pool_mutex_own(buf_pool));
|
||||
ut_ad(!mutex_own(&buf_pool->zip_mutex));
|
||||
ut_ad(i <= BUF_BUDDY_SIZES);
|
||||
ut_ad(i >= buf_buddy_get_slot(PAGE_ZIP_MIN_SIZE));
|
||||
ut_ad(i >= buf_buddy_get_slot(UNIV_ZIP_SIZE_MIN));
|
||||
ut_ad(buf_pool->buddy_stat[i].used > 0);
|
||||
|
||||
buf_pool->buddy_stat[i].used--;
|
||||
|
@ -521,7 +526,7 @@ buddy_nonfree:
|
|||
|
||||
func_exit:
|
||||
/* Free the block to the buddy list. */
|
||||
bpage = buf;
|
||||
bpage = (buf_page_t*) buf;
|
||||
|
||||
/* Fill large blocks with a constant pattern. */
|
||||
ut_d(memset(bpage, i, BUF_BUDDY_LOW << i));
|
File diff suppressed because it is too large
Load diff
155
storage/innobase/buf/buf0checksum.cc
Normal file
155
storage/innobase/buf/buf0checksum.cc
Normal file
|
@ -0,0 +1,155 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1995, 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 Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file buf/buf0checksum.cc
|
||||
Buffer pool checksum functions, also linked from /extra/innochecksum.cc
|
||||
|
||||
Created Aug 11, 2011 Vasil Dimov
|
||||
*******************************************************/
|
||||
|
||||
#include "univ.i"
|
||||
#include "fil0fil.h" /* FIL_* */
|
||||
#include "ut0crc32.h" /* ut_crc32() */
|
||||
#include "ut0rnd.h" /* ut_fold_binary() */
|
||||
|
||||
#ifndef UNIV_INNOCHECKSUM
|
||||
|
||||
#include "srv0srv.h" /* SRV_CHECKSUM_* */
|
||||
#include "buf0types.h"
|
||||
|
||||
/** the macro MYSQL_SYSVAR_ENUM() requires "long unsigned int" and if we
|
||||
use srv_checksum_algorithm_t here then we get a compiler error:
|
||||
ha_innodb.cc:12251: error: cannot convert 'srv_checksum_algorithm_t*' to
|
||||
'long unsigned int*' in initialization */
|
||||
UNIV_INTERN ulong srv_checksum_algorithm = SRV_CHECKSUM_ALGORITHM_INNODB;
|
||||
|
||||
#endif /* !UNIV_INNOCHECKSUM */
|
||||
|
||||
/********************************************************************//**
|
||||
Calculates a page CRC32 which is stored to the page when it is written
|
||||
to a file. Note that we must be careful to calculate the same value on
|
||||
32-bit and 64-bit architectures.
|
||||
@return checksum */
|
||||
UNIV_INTERN
|
||||
ib_uint32_t
|
||||
buf_calc_page_crc32(
|
||||
/*================*/
|
||||
const byte* page) /*!< in: buffer page */
|
||||
{
|
||||
ib_uint32_t checksum;
|
||||
|
||||
/* Since the field FIL_PAGE_FILE_FLUSH_LSN, and in versions <= 4.1.x
|
||||
FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, are written outside the buffer pool
|
||||
to the first pages of data files, we have to skip them in the page
|
||||
checksum calculation.
|
||||
We must also skip the field FIL_PAGE_SPACE_OR_CHKSUM where the
|
||||
checksum is stored, and also the last 8 bytes of page because
|
||||
there we store the old formula checksum. */
|
||||
|
||||
checksum = ut_crc32(page + FIL_PAGE_OFFSET,
|
||||
FIL_PAGE_FILE_FLUSH_LSN - FIL_PAGE_OFFSET)
|
||||
^ ut_crc32(page + FIL_PAGE_DATA,
|
||||
UNIV_PAGE_SIZE - FIL_PAGE_DATA
|
||||
- FIL_PAGE_END_LSN_OLD_CHKSUM);
|
||||
|
||||
return(checksum);
|
||||
}
|
||||
|
||||
/********************************************************************//**
|
||||
Calculates a page checksum which is stored to the page when it is written
|
||||
to a file. Note that we must be careful to calculate the same value on
|
||||
32-bit and 64-bit architectures.
|
||||
@return checksum */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
buf_calc_page_new_checksum(
|
||||
/*=======================*/
|
||||
const byte* page) /*!< in: buffer page */
|
||||
{
|
||||
ulint checksum;
|
||||
|
||||
/* Since the field FIL_PAGE_FILE_FLUSH_LSN, and in versions <= 4.1.x
|
||||
FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, are written outside the buffer pool
|
||||
to the first pages of data files, we have to skip them in the page
|
||||
checksum calculation.
|
||||
We must also skip the field FIL_PAGE_SPACE_OR_CHKSUM where the
|
||||
checksum is stored, and also the last 8 bytes of page because
|
||||
there we store the old formula checksum. */
|
||||
|
||||
checksum = ut_fold_binary(page + FIL_PAGE_OFFSET,
|
||||
FIL_PAGE_FILE_FLUSH_LSN - FIL_PAGE_OFFSET)
|
||||
+ ut_fold_binary(page + FIL_PAGE_DATA,
|
||||
UNIV_PAGE_SIZE - FIL_PAGE_DATA
|
||||
- FIL_PAGE_END_LSN_OLD_CHKSUM);
|
||||
checksum = checksum & 0xFFFFFFFFUL;
|
||||
|
||||
return(checksum);
|
||||
}
|
||||
|
||||
/********************************************************************//**
|
||||
In versions < 4.0.14 and < 4.1.1 there was a bug that the checksum only
|
||||
looked at the first few bytes of the page. This calculates that old
|
||||
checksum.
|
||||
NOTE: we must first store the new formula checksum to
|
||||
FIL_PAGE_SPACE_OR_CHKSUM before calculating and storing this old checksum
|
||||
because this takes that field as an input!
|
||||
@return checksum */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
buf_calc_page_old_checksum(
|
||||
/*=======================*/
|
||||
const byte* page) /*!< in: buffer page */
|
||||
{
|
||||
ulint checksum;
|
||||
|
||||
checksum = ut_fold_binary(page, FIL_PAGE_FILE_FLUSH_LSN);
|
||||
|
||||
checksum = checksum & 0xFFFFFFFFUL;
|
||||
|
||||
return(checksum);
|
||||
}
|
||||
|
||||
#ifndef UNIV_INNOCHECKSUM
|
||||
|
||||
/********************************************************************//**
|
||||
Return a printable string describing the checksum algorithm.
|
||||
@return algorithm name */
|
||||
UNIV_INTERN
|
||||
const char*
|
||||
buf_checksum_algorithm_name(
|
||||
/*========================*/
|
||||
srv_checksum_algorithm_t algo) /*!< in: algorithm */
|
||||
{
|
||||
switch (algo) {
|
||||
case SRV_CHECKSUM_ALGORITHM_CRC32:
|
||||
case SRV_CHECKSUM_ALGORITHM_STRICT_CRC32:
|
||||
return("crc32");
|
||||
case SRV_CHECKSUM_ALGORITHM_INNODB:
|
||||
case SRV_CHECKSUM_ALGORITHM_STRICT_INNODB:
|
||||
return("innodb");
|
||||
case SRV_CHECKSUM_ALGORITHM_NONE:
|
||||
case SRV_CHECKSUM_ALGORITHM_STRICT_NONE:
|
||||
return("none");
|
||||
}
|
||||
|
||||
ut_error;
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
#endif /* !UNIV_INNOCHECKSUM */
|
1086
storage/innobase/buf/buf0dblwr.cc
Normal file
1086
storage/innobase/buf/buf0dblwr.cc
Normal file
File diff suppressed because it is too large
Load diff
620
storage/innobase/buf/buf0dump.cc
Normal file
620
storage/innobase/buf/buf0dump.cc
Normal file
|
@ -0,0 +1,620 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2011, 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 Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file buf/buf0dump.cc
|
||||
Implements a buffer pool dump/load.
|
||||
|
||||
Created April 08, 2011 Vasil Dimov
|
||||
*******************************************************/
|
||||
|
||||
#include <stdarg.h> /* va_* */
|
||||
#include <string.h> /* strerror() */
|
||||
|
||||
#include "univ.i"
|
||||
|
||||
#include "buf0buf.h" /* buf_pool_mutex_enter(), srv_buf_pool_instances */
|
||||
#include "buf0dump.h"
|
||||
#include "db0err.h" /* enum db_err */
|
||||
#include "dict0dict.h" /* dict_operation_lock */
|
||||
#include "os0file.h" /* OS_FILE_MAX_PATH */
|
||||
#include "os0sync.h" /* os_event* */
|
||||
#include "os0thread.h" /* os_thread_* */
|
||||
#include "srv0srv.h" /* srv_fast_shutdown, srv_buf_dump* */
|
||||
#include "srv0start.h" /* srv_shutdown_state */
|
||||
#include "sync0rw.h" /* rw_lock_s_lock() */
|
||||
#include "ut0byte.h" /* ut_ull_create() */
|
||||
#include "ut0sort.h" /* UT_SORT_FUNCTION_BODY */
|
||||
#include "buf0rea.h" /* buf_read_page_async() */
|
||||
|
||||
enum status_severity {
|
||||
STATUS_INFO,
|
||||
STATUS_NOTICE,
|
||||
STATUS_ERR
|
||||
};
|
||||
|
||||
#define SHUTTING_DOWN() (UNIV_UNLIKELY(srv_shutdown_state \
|
||||
!= SRV_SHUTDOWN_NONE))
|
||||
|
||||
/* Flags that tell the buffer pool dump/load thread which action should it
|
||||
take after being waked up. */
|
||||
static ibool buf_dump_should_start = FALSE;
|
||||
static ibool buf_load_should_start = FALSE;
|
||||
|
||||
static ibool buf_load_abort_flag = FALSE;
|
||||
|
||||
/* Used to temporary store dump info in order to avoid IO while holding
|
||||
buffer pool mutex during dump and also to sort the contents of the dump
|
||||
before reading the pages from disk during load.
|
||||
We store the space id in the high 32 bits and page no in low 32 bits. */
|
||||
typedef ib_uint64_t buf_dump_t;
|
||||
|
||||
/* Aux macros to create buf_dump_t and to extract space and page from it */
|
||||
#define BUF_DUMP_CREATE(space, page) ut_ull_create(space, page)
|
||||
#define BUF_DUMP_SPACE(a) ((ulint) ((a) >> 32))
|
||||
#define BUF_DUMP_PAGE(a) ((ulint) ((a) & 0xFFFFFFFFUL))
|
||||
|
||||
/*****************************************************************//**
|
||||
Wakes up the buffer pool dump/load thread and instructs it to start
|
||||
a dump. This function is called by MySQL code via buffer_pool_dump_now()
|
||||
and it should return immediately because the whole MySQL is frozen during
|
||||
its execution. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
buf_dump_start()
|
||||
/*============*/
|
||||
{
|
||||
buf_dump_should_start = TRUE;
|
||||
os_event_set(srv_buf_dump_event);
|
||||
}
|
||||
|
||||
/*****************************************************************//**
|
||||
Wakes up the buffer pool dump/load thread and instructs it to start
|
||||
a load. This function is called by MySQL code via buffer_pool_load_now()
|
||||
and it should return immediately because the whole MySQL is frozen during
|
||||
its execution. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
buf_load_start()
|
||||
/*============*/
|
||||
{
|
||||
buf_load_should_start = TRUE;
|
||||
os_event_set(srv_buf_dump_event);
|
||||
}
|
||||
|
||||
/*****************************************************************//**
|
||||
Sets the global variable that feeds MySQL's innodb_buffer_pool_dump_status
|
||||
to the specified string. The format and the following parameters are the
|
||||
same as the ones used for printf(3). The value of this variable can be
|
||||
retrieved by:
|
||||
SELECT variable_value FROM information_schema.global_status WHERE
|
||||
variable_name = 'INNODB_BUFFER_POOL_DUMP_STATUS';
|
||||
or by:
|
||||
SHOW STATUS LIKE 'innodb_buffer_pool_dump_status'; */
|
||||
static __attribute__((nonnull, format(printf, 2, 3)))
|
||||
void
|
||||
buf_dump_status(
|
||||
/*============*/
|
||||
enum status_severity severity,/*!< in: status severity */
|
||||
const char* fmt, /*!< in: format */
|
||||
...) /*!< in: extra parameters according
|
||||
to fmt */
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
|
||||
ut_vsnprintf(
|
||||
export_vars.innodb_buffer_pool_dump_status,
|
||||
sizeof(export_vars.innodb_buffer_pool_dump_status),
|
||||
fmt, ap);
|
||||
|
||||
if (severity == STATUS_NOTICE || severity == STATUS_ERR) {
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr, " InnoDB: %s\n",
|
||||
export_vars.innodb_buffer_pool_dump_status);
|
||||
}
|
||||
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/*****************************************************************//**
|
||||
Sets the global variable that feeds MySQL's innodb_buffer_pool_load_status
|
||||
to the specified string. The format and the following parameters are the
|
||||
same as the ones used for printf(3). The value of this variable can be
|
||||
retrieved by:
|
||||
SELECT variable_value FROM information_schema.global_status WHERE
|
||||
variable_name = 'INNODB_BUFFER_POOL_LOAD_STATUS';
|
||||
or by:
|
||||
SHOW STATUS LIKE 'innodb_buffer_pool_load_status'; */
|
||||
static __attribute__((nonnull, format(printf, 2, 3)))
|
||||
void
|
||||
buf_load_status(
|
||||
/*============*/
|
||||
enum status_severity severity,/*!< in: status severity */
|
||||
const char* fmt, /*!< in: format */
|
||||
...) /*!< in: extra parameters according to fmt */
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
|
||||
ut_vsnprintf(
|
||||
export_vars.innodb_buffer_pool_load_status,
|
||||
sizeof(export_vars.innodb_buffer_pool_load_status),
|
||||
fmt, ap);
|
||||
|
||||
if (severity == STATUS_NOTICE || severity == STATUS_ERR) {
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr, " InnoDB: %s\n",
|
||||
export_vars.innodb_buffer_pool_load_status);
|
||||
}
|
||||
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/*****************************************************************//**
|
||||
Perform a buffer pool dump into the file specified by
|
||||
innodb_buffer_pool_filename. If any errors occur then the value of
|
||||
innodb_buffer_pool_dump_status will be set accordingly, see buf_dump_status().
|
||||
The dump filename can be specified by (relative to srv_data_home):
|
||||
SET GLOBAL innodb_buffer_pool_filename='filename'; */
|
||||
static
|
||||
void
|
||||
buf_dump(
|
||||
/*=====*/
|
||||
ibool obey_shutdown) /*!< in: quit if we are in a shutting down
|
||||
state */
|
||||
{
|
||||
#define SHOULD_QUIT() (SHUTTING_DOWN() && obey_shutdown)
|
||||
|
||||
char full_filename[OS_FILE_MAX_PATH];
|
||||
char tmp_filename[OS_FILE_MAX_PATH];
|
||||
char now[32];
|
||||
FILE* f;
|
||||
ulint i;
|
||||
int ret;
|
||||
|
||||
ut_snprintf(full_filename, sizeof(full_filename),
|
||||
"%s%c%s", srv_data_home, SRV_PATH_SEPARATOR,
|
||||
srv_buf_dump_filename);
|
||||
|
||||
ut_snprintf(tmp_filename, sizeof(tmp_filename),
|
||||
"%s.incomplete", full_filename);
|
||||
|
||||
buf_dump_status(STATUS_NOTICE, "Dumping buffer pool(s) to %s",
|
||||
full_filename);
|
||||
|
||||
f = fopen(tmp_filename, "w");
|
||||
if (f == NULL) {
|
||||
buf_dump_status(STATUS_ERR,
|
||||
"Cannot open '%s' for writing: %s",
|
||||
tmp_filename, strerror(errno));
|
||||
return;
|
||||
}
|
||||
/* else */
|
||||
|
||||
/* walk through each buffer pool */
|
||||
for (i = 0; i < srv_buf_pool_instances && !SHOULD_QUIT(); i++) {
|
||||
buf_pool_t* buf_pool;
|
||||
const buf_page_t* bpage;
|
||||
buf_dump_t* dump;
|
||||
ulint n_pages;
|
||||
ulint j;
|
||||
|
||||
buf_pool = buf_pool_from_array(i);
|
||||
|
||||
/* obtain buf_pool mutex before allocate, since
|
||||
UT_LIST_GET_LEN(buf_pool->LRU) could change */
|
||||
buf_pool_mutex_enter(buf_pool);
|
||||
|
||||
n_pages = UT_LIST_GET_LEN(buf_pool->LRU);
|
||||
|
||||
/* skip empty buffer pools */
|
||||
if (n_pages == 0) {
|
||||
buf_pool_mutex_exit(buf_pool);
|
||||
continue;
|
||||
}
|
||||
|
||||
dump = static_cast<buf_dump_t*>(
|
||||
ut_malloc(n_pages * sizeof(*dump))) ;
|
||||
|
||||
if (dump == NULL) {
|
||||
buf_pool_mutex_exit(buf_pool);
|
||||
fclose(f);
|
||||
buf_dump_status(STATUS_ERR,
|
||||
"Cannot allocate " ULINTPF " bytes: %s",
|
||||
(ulint) (n_pages * sizeof(*dump)),
|
||||
strerror(errno));
|
||||
/* leave tmp_filename to exist */
|
||||
return;
|
||||
}
|
||||
|
||||
for (bpage = UT_LIST_GET_LAST(buf_pool->LRU), j = 0;
|
||||
bpage != NULL;
|
||||
bpage = UT_LIST_GET_PREV(LRU, bpage), j++) {
|
||||
|
||||
ut_a(buf_page_in_file(bpage));
|
||||
|
||||
dump[j] = BUF_DUMP_CREATE(buf_page_get_space(bpage),
|
||||
buf_page_get_page_no(bpage));
|
||||
}
|
||||
|
||||
ut_a(j == n_pages);
|
||||
|
||||
buf_pool_mutex_exit(buf_pool);
|
||||
|
||||
for (j = 0; j < n_pages && !SHOULD_QUIT(); j++) {
|
||||
ret = fprintf(f, ULINTPF "," ULINTPF "\n",
|
||||
BUF_DUMP_SPACE(dump[j]),
|
||||
BUF_DUMP_PAGE(dump[j]));
|
||||
if (ret < 0) {
|
||||
ut_free(dump);
|
||||
fclose(f);
|
||||
buf_dump_status(STATUS_ERR,
|
||||
"Cannot write to '%s': %s",
|
||||
tmp_filename, strerror(errno));
|
||||
/* leave tmp_filename to exist */
|
||||
return;
|
||||
}
|
||||
|
||||
if (j % 128 == 0) {
|
||||
buf_dump_status(
|
||||
STATUS_INFO,
|
||||
"Dumping buffer pool "
|
||||
ULINTPF "/" ULINTPF ", "
|
||||
"page " ULINTPF "/" ULINTPF,
|
||||
i + 1, srv_buf_pool_instances,
|
||||
j + 1, n_pages);
|
||||
}
|
||||
}
|
||||
|
||||
ut_free(dump);
|
||||
}
|
||||
|
||||
ret = fclose(f);
|
||||
if (ret != 0) {
|
||||
buf_dump_status(STATUS_ERR,
|
||||
"Cannot close '%s': %s",
|
||||
tmp_filename, strerror(errno));
|
||||
return;
|
||||
}
|
||||
/* else */
|
||||
|
||||
ret = unlink(full_filename);
|
||||
if (ret != 0 && errno != ENOENT) {
|
||||
buf_dump_status(STATUS_ERR,
|
||||
"Cannot delete '%s': %s",
|
||||
full_filename, strerror(errno));
|
||||
/* leave tmp_filename to exist */
|
||||
return;
|
||||
}
|
||||
/* else */
|
||||
|
||||
ret = rename(tmp_filename, full_filename);
|
||||
if (ret != 0) {
|
||||
buf_dump_status(STATUS_ERR,
|
||||
"Cannot rename '%s' to '%s': %s",
|
||||
tmp_filename, full_filename,
|
||||
strerror(errno));
|
||||
/* leave tmp_filename to exist */
|
||||
return;
|
||||
}
|
||||
/* else */
|
||||
|
||||
/* success */
|
||||
|
||||
ut_sprintf_timestamp(now);
|
||||
|
||||
buf_dump_status(STATUS_NOTICE,
|
||||
"Buffer pool(s) dump completed at %s", now);
|
||||
}
|
||||
|
||||
/*****************************************************************//**
|
||||
Compare two buffer pool dump entries, used to sort the dump on
|
||||
space_no,page_no before loading in order to increase the chance for
|
||||
sequential IO.
|
||||
@return -1/0/1 if entry 1 is smaller/equal/bigger than entry 2 */
|
||||
static
|
||||
lint
|
||||
buf_dump_cmp(
|
||||
/*=========*/
|
||||
const buf_dump_t d1, /*!< in: buffer pool dump entry 1 */
|
||||
const buf_dump_t d2) /*!< in: buffer pool dump entry 2 */
|
||||
{
|
||||
if (d1 < d2) {
|
||||
return(-1);
|
||||
} else if (d1 == d2) {
|
||||
return(0);
|
||||
} else {
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************//**
|
||||
Sort a buffer pool dump on space_no, page_no. */
|
||||
static
|
||||
void
|
||||
buf_dump_sort(
|
||||
/*==========*/
|
||||
buf_dump_t* dump, /*!< in/out: buffer pool dump to sort */
|
||||
buf_dump_t* tmp, /*!< in/out: temp storage */
|
||||
ulint low, /*!< in: lowest index (inclusive) */
|
||||
ulint high) /*!< in: highest index (non-inclusive) */
|
||||
{
|
||||
UT_SORT_FUNCTION_BODY(buf_dump_sort, dump, tmp, low, high,
|
||||
buf_dump_cmp);
|
||||
}
|
||||
|
||||
/*****************************************************************//**
|
||||
Perform a buffer pool load from the file specified by
|
||||
innodb_buffer_pool_filename. If any errors occur then the value of
|
||||
innodb_buffer_pool_load_status will be set accordingly, see buf_load_status().
|
||||
The dump filename can be specified by (relative to srv_data_home):
|
||||
SET GLOBAL innodb_buffer_pool_filename='filename'; */
|
||||
static
|
||||
void
|
||||
buf_load()
|
||||
/*======*/
|
||||
{
|
||||
char full_filename[OS_FILE_MAX_PATH];
|
||||
char now[32];
|
||||
FILE* f;
|
||||
buf_dump_t* dump;
|
||||
buf_dump_t* dump_tmp;
|
||||
ulint dump_n;
|
||||
ulint total_buffer_pools_pages;
|
||||
ulint i;
|
||||
ulint space_id;
|
||||
ulint page_no;
|
||||
int fscanf_ret;
|
||||
|
||||
/* Ignore any leftovers from before */
|
||||
buf_load_abort_flag = FALSE;
|
||||
|
||||
ut_snprintf(full_filename, sizeof(full_filename),
|
||||
"%s%c%s", srv_data_home, SRV_PATH_SEPARATOR,
|
||||
srv_buf_dump_filename);
|
||||
|
||||
buf_load_status(STATUS_NOTICE,
|
||||
"Loading buffer pool(s) from %s", full_filename);
|
||||
|
||||
f = fopen(full_filename, "r");
|
||||
if (f == NULL) {
|
||||
buf_load_status(STATUS_ERR,
|
||||
"Cannot open '%s' for reading: %s",
|
||||
full_filename, strerror(errno));
|
||||
return;
|
||||
}
|
||||
/* else */
|
||||
|
||||
/* First scan the file to estimate how many entries are in it.
|
||||
This file is tiny (approx 500KB per 1GB buffer pool), reading it
|
||||
two times is fine. */
|
||||
dump_n = 0;
|
||||
while (fscanf(f, ULINTPF "," ULINTPF, &space_id, &page_no) == 2
|
||||
&& !SHUTTING_DOWN()) {
|
||||
dump_n++;
|
||||
}
|
||||
|
||||
if (!SHUTTING_DOWN() && !feof(f)) {
|
||||
/* fscanf() returned != 2 */
|
||||
const char* what;
|
||||
if (ferror(f)) {
|
||||
what = "reading";
|
||||
} else {
|
||||
what = "parsing";
|
||||
}
|
||||
fclose(f);
|
||||
buf_load_status(STATUS_ERR, "Error %s '%s', "
|
||||
"unable to load buffer pool (stage 1)",
|
||||
what, full_filename);
|
||||
return;
|
||||
}
|
||||
|
||||
/* If dump is larger than the buffer pool(s), then we ignore the
|
||||
extra trailing. This could happen if a dump is made, then buffer
|
||||
pool is shrunk and then load it attempted. */
|
||||
total_buffer_pools_pages = buf_pool_get_n_pages()
|
||||
* srv_buf_pool_instances;
|
||||
if (dump_n > total_buffer_pools_pages) {
|
||||
dump_n = total_buffer_pools_pages;
|
||||
}
|
||||
|
||||
dump = static_cast<buf_dump_t*>(ut_malloc(dump_n * sizeof(*dump)));
|
||||
|
||||
if (dump == NULL) {
|
||||
fclose(f);
|
||||
buf_load_status(STATUS_ERR,
|
||||
"Cannot allocate " ULINTPF " bytes: %s",
|
||||
(ulint) (dump_n * sizeof(*dump)),
|
||||
strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
dump_tmp = static_cast<buf_dump_t*>(
|
||||
ut_malloc(dump_n * sizeof(*dump_tmp)));
|
||||
|
||||
if (dump_tmp == NULL) {
|
||||
ut_free(dump);
|
||||
fclose(f);
|
||||
buf_load_status(STATUS_ERR,
|
||||
"Cannot allocate " ULINTPF " bytes: %s",
|
||||
(ulint) (dump_n * sizeof(*dump_tmp)),
|
||||
strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
rewind(f);
|
||||
|
||||
for (i = 0; i < dump_n && !SHUTTING_DOWN(); i++) {
|
||||
fscanf_ret = fscanf(f, ULINTPF "," ULINTPF,
|
||||
&space_id, &page_no);
|
||||
|
||||
if (fscanf_ret != 2) {
|
||||
if (feof(f)) {
|
||||
break;
|
||||
}
|
||||
/* else */
|
||||
|
||||
ut_free(dump);
|
||||
ut_free(dump_tmp);
|
||||
fclose(f);
|
||||
buf_load_status(STATUS_ERR,
|
||||
"Error parsing '%s', unable "
|
||||
"to load buffer pool (stage 2)",
|
||||
full_filename);
|
||||
return;
|
||||
}
|
||||
|
||||
if (space_id > ULINT32_MASK || page_no > ULINT32_MASK) {
|
||||
ut_free(dump);
|
||||
ut_free(dump_tmp);
|
||||
fclose(f);
|
||||
buf_load_status(STATUS_ERR,
|
||||
"Error parsing '%s': bogus "
|
||||
"space,page " ULINTPF "," ULINTPF
|
||||
" at line " ULINTPF ", "
|
||||
"unable to load buffer pool",
|
||||
full_filename,
|
||||
space_id, page_no,
|
||||
i);
|
||||
return;
|
||||
}
|
||||
|
||||
dump[i] = BUF_DUMP_CREATE(space_id, page_no);
|
||||
}
|
||||
|
||||
/* Set dump_n to the actual number of initialized elements,
|
||||
i could be smaller than dump_n here if the file got truncated after
|
||||
we read it the first time. */
|
||||
dump_n = i;
|
||||
|
||||
fclose(f);
|
||||
|
||||
if (dump_n == 0) {
|
||||
ut_free(dump);
|
||||
ut_sprintf_timestamp(now);
|
||||
buf_load_status(STATUS_NOTICE,
|
||||
"Buffer pool(s) load completed at %s "
|
||||
"(%s was empty)", now, full_filename);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!SHUTTING_DOWN()) {
|
||||
buf_dump_sort(dump, dump_tmp, 0, dump_n);
|
||||
}
|
||||
|
||||
ut_free(dump_tmp);
|
||||
|
||||
for (i = 0; i < dump_n && !SHUTTING_DOWN(); i++) {
|
||||
|
||||
buf_read_page_async(BUF_DUMP_SPACE(dump[i]),
|
||||
BUF_DUMP_PAGE(dump[i]));
|
||||
|
||||
if (i % 64 == 63) {
|
||||
os_aio_simulated_wake_handler_threads();
|
||||
}
|
||||
|
||||
if (i % 128 == 0) {
|
||||
buf_load_status(STATUS_INFO,
|
||||
"Loaded " ULINTPF "/" ULINTPF " pages",
|
||||
i + 1, dump_n);
|
||||
}
|
||||
|
||||
if (buf_load_abort_flag) {
|
||||
buf_load_abort_flag = FALSE;
|
||||
ut_free(dump);
|
||||
buf_load_status(
|
||||
STATUS_NOTICE,
|
||||
"Buffer pool(s) load aborted on request");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ut_free(dump);
|
||||
|
||||
ut_sprintf_timestamp(now);
|
||||
|
||||
buf_load_status(STATUS_NOTICE,
|
||||
"Buffer pool(s) load completed at %s", now);
|
||||
}
|
||||
|
||||
/*****************************************************************//**
|
||||
Aborts a currently running buffer pool load. This function is called by
|
||||
MySQL code via buffer_pool_load_abort() and it should return immediately
|
||||
because the whole MySQL is frozen during its execution. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
buf_load_abort()
|
||||
/*============*/
|
||||
{
|
||||
buf_load_abort_flag = TRUE;
|
||||
}
|
||||
|
||||
/*****************************************************************//**
|
||||
This is the main thread for buffer pool dump/load. It waits for an
|
||||
event and when waked up either performs a dump or load and sleeps
|
||||
again.
|
||||
@return this function does not return, it calls os_thread_exit() */
|
||||
extern "C" UNIV_INTERN
|
||||
os_thread_ret_t
|
||||
DECLARE_THREAD(buf_dump_thread)(
|
||||
/*============================*/
|
||||
void* arg __attribute__((unused))) /*!< in: a dummy parameter
|
||||
required by os_thread_create */
|
||||
{
|
||||
srv_buf_dump_thread_active = TRUE;
|
||||
|
||||
buf_dump_status(STATUS_INFO, "not started");
|
||||
buf_load_status(STATUS_INFO, "not started");
|
||||
|
||||
if (srv_buffer_pool_load_at_startup) {
|
||||
buf_load();
|
||||
}
|
||||
|
||||
while (!SHUTTING_DOWN()) {
|
||||
|
||||
os_event_wait(srv_buf_dump_event);
|
||||
|
||||
if (buf_dump_should_start) {
|
||||
buf_dump_should_start = FALSE;
|
||||
buf_dump(TRUE /* quit on shutdown */);
|
||||
}
|
||||
|
||||
if (buf_load_should_start) {
|
||||
buf_load_should_start = FALSE;
|
||||
buf_load();
|
||||
}
|
||||
|
||||
os_event_reset(srv_buf_dump_event);
|
||||
}
|
||||
|
||||
if (srv_buffer_pool_dump_at_shutdown && srv_fast_shutdown != 2) {
|
||||
buf_dump(FALSE /* ignore shutdown down flag,
|
||||
keep going even if we are in a shutdown state */);
|
||||
}
|
||||
|
||||
srv_buf_dump_thread_active = FALSE;
|
||||
|
||||
/* We count the number of threads in os_thread_exit(). A created
|
||||
thread should always use that to exit and not use return() to exit. */
|
||||
os_thread_exit(NULL);
|
||||
|
||||
OS_THREAD_DUMMY_RETURN;
|
||||
}
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
|
||||
Copyright (c) 1995, 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
|
||||
|
@ -11,13 +11,13 @@ 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 program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file buf/buf0rea.c
|
||||
@file buf/buf0rea.cc
|
||||
The database buffer read
|
||||
|
||||
Created 11/5/1995 Heikki Tuuri
|
||||
|
@ -31,6 +31,7 @@ Created 11/5/1995 Heikki Tuuri
|
|||
#include "buf0buf.h"
|
||||
#include "buf0flu.h"
|
||||
#include "buf0lru.h"
|
||||
#include "buf0dblwr.h"
|
||||
#include "ibuf0ibuf.h"
|
||||
#include "log0recv.h"
|
||||
#include "trx0sys.h"
|
||||
|
@ -58,7 +59,7 @@ flag is cleared and the x-lock released by an i/o-handler thread.
|
|||
@return 1 if a read request was queued, 0 if the page already resided
|
||||
in buf_pool, or if the page is in the doublewrite buffer blocks in
|
||||
which case it is never read into the pool, or if the tablespace does
|
||||
not exist or is being dropped
|
||||
not exist or is being dropped
|
||||
@return 1 if read request is issued. 0 if it is not */
|
||||
static
|
||||
ulint
|
||||
|
@ -83,19 +84,17 @@ buf_read_page_low(
|
|||
{
|
||||
buf_page_t* bpage;
|
||||
ulint wake_later;
|
||||
ibool ignore_nonexistent_pages;
|
||||
|
||||
*err = DB_SUCCESS;
|
||||
|
||||
wake_later = mode & OS_AIO_SIMULATED_WAKE_LATER;
|
||||
mode = mode & ~OS_AIO_SIMULATED_WAKE_LATER;
|
||||
|
||||
if (trx_doublewrite && space == TRX_SYS_SPACE
|
||||
&& ( (offset >= trx_doublewrite->block1
|
||||
&& offset < trx_doublewrite->block1
|
||||
+ TRX_SYS_DOUBLEWRITE_BLOCK_SIZE)
|
||||
|| (offset >= trx_doublewrite->block2
|
||||
&& offset < trx_doublewrite->block2
|
||||
+ TRX_SYS_DOUBLEWRITE_BLOCK_SIZE))) {
|
||||
ignore_nonexistent_pages = mode & BUF_READ_IGNORE_NONEXISTENT_PAGES;
|
||||
mode &= ~BUF_READ_IGNORE_NONEXISTENT_PAGES;
|
||||
|
||||
if (space == TRX_SYS_SPACE && buf_dblwr_page_inside(offset)) {
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr,
|
||||
" InnoDB: Warning: trying to read"
|
||||
|
@ -141,18 +140,27 @@ buf_read_page_low(
|
|||
|
||||
thd_wait_begin(NULL, THD_WAIT_DISKIO);
|
||||
if (zip_size) {
|
||||
*err = fil_io(OS_FILE_READ | wake_later,
|
||||
*err = fil_io(OS_FILE_READ | wake_later
|
||||
| ignore_nonexistent_pages,
|
||||
sync, space, zip_size, offset, 0, zip_size,
|
||||
bpage->zip.data, bpage);
|
||||
} else {
|
||||
ut_a(buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE);
|
||||
|
||||
*err = fil_io(OS_FILE_READ | wake_later,
|
||||
*err = fil_io(OS_FILE_READ | wake_later
|
||||
| ignore_nonexistent_pages,
|
||||
sync, space, 0, offset, 0, UNIV_PAGE_SIZE,
|
||||
((buf_block_t*) bpage)->frame, bpage);
|
||||
}
|
||||
thd_wait_end(NULL);
|
||||
ut_a(*err == DB_SUCCESS);
|
||||
|
||||
if (*err != DB_SUCCESS) {
|
||||
if (ignore_nonexistent_pages) {
|
||||
return(0);
|
||||
}
|
||||
/* else */
|
||||
ut_error;
|
||||
}
|
||||
|
||||
if (sync) {
|
||||
/* The i/o is already completed when we arrive from
|
||||
|
@ -342,7 +350,6 @@ buf_read_page(
|
|||
ulint zip_size,/*!< in: compressed page size in bytes, or 0 */
|
||||
ulint offset) /*!< in: page number */
|
||||
{
|
||||
buf_pool_t* buf_pool = buf_pool_get(space, offset);
|
||||
ib_int64_t tablespace_version;
|
||||
ulint count;
|
||||
ulint err;
|
||||
|
@ -366,15 +373,55 @@ buf_read_page(
|
|||
(ulong) space, (ulong) offset);
|
||||
}
|
||||
|
||||
/* Flush pages from the end of the LRU list if necessary */
|
||||
buf_flush_free_margin(buf_pool);
|
||||
|
||||
/* Increment number of I/O operations used for LRU policy. */
|
||||
buf_LRU_stat_inc_io();
|
||||
|
||||
return(count > 0);
|
||||
}
|
||||
|
||||
/********************************************************************//**
|
||||
High-level function which reads a page asynchronously from a file to the
|
||||
buffer buf_pool if it is not already there. Sets the io_fix flag and sets
|
||||
an exclusive lock on the buffer frame. The flag is cleared and the x-lock
|
||||
released by the i/o-handler thread.
|
||||
@return TRUE if page has been read in, FALSE in case of failure */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
buf_read_page_async(
|
||||
/*================*/
|
||||
ulint space, /*!< in: space id */
|
||||
ulint offset) /*!< in: page number */
|
||||
{
|
||||
ulint zip_size;
|
||||
ib_int64_t tablespace_version;
|
||||
ulint count;
|
||||
ulint err;
|
||||
|
||||
zip_size = fil_space_get_zip_size(space);
|
||||
|
||||
if (zip_size == ULINT_UNDEFINED) {
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
tablespace_version = fil_space_get_version(space);
|
||||
|
||||
count = buf_read_page_low(&err, TRUE, BUF_READ_ANY_PAGE
|
||||
| OS_AIO_SIMULATED_WAKE_LATER
|
||||
| BUF_READ_IGNORE_NONEXISTENT_PAGES,
|
||||
space, zip_size, FALSE,
|
||||
tablespace_version, offset);
|
||||
srv_buf_pool_reads += count;
|
||||
|
||||
/* We do not increment number of I/O operations used for LRU policy
|
||||
here (buf_LRU_stat_inc_io()). We use this in heuristics to decide
|
||||
about evicting uncompressed version of compressed pages from the
|
||||
buffer pool. Since this function is called from buffer pool load
|
||||
these IOs are deliberate and are not part of normal workload we can
|
||||
ignore these in our heuristics. */
|
||||
|
||||
return(count > 0);
|
||||
}
|
||||
|
||||
/********************************************************************//**
|
||||
Applies linear read-ahead if in the buf_pool the page is a border page of
|
||||
a linear read-ahead area and all the pages in the area have been accessed.
|
||||
|
@ -427,6 +474,11 @@ buf_read_ahead_linear(
|
|||
= BUF_READ_AHEAD_AREA(buf_pool);
|
||||
ulint threshold;
|
||||
|
||||
/* check if readahead is disabled */
|
||||
if (!srv_read_ahead_threshold) {
|
||||
return(0);
|
||||
}
|
||||
|
||||
if (UNIV_UNLIKELY(srv_startup_is_before_trx_rollback_phase)) {
|
||||
/* No read-ahead to avoid thread deadlocks */
|
||||
return(0);
|
||||
|
@ -636,9 +688,6 @@ buf_read_ahead_linear(
|
|||
|
||||
os_aio_simulated_wake_handler_threads();
|
||||
|
||||
/* Flush pages from the end of the LRU list if necessary */
|
||||
buf_flush_free_margin(buf_pool);
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
if (buf_debug_prints && (count > 0)) {
|
||||
fprintf(stderr,
|
||||
|
@ -724,9 +773,6 @@ tablespace_deleted:
|
|||
|
||||
os_aio_simulated_wake_handler_threads();
|
||||
|
||||
/* Flush pages from the end of all the LRU lists if necessary */
|
||||
buf_flush_free_margins();
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
if (buf_debug_prints) {
|
||||
fprintf(stderr,
|
||||
|
@ -796,7 +842,7 @@ buf_read_recv_pages(
|
|||
"InnoDB: Number of pending reads %lu,"
|
||||
" pending pread calls %lu\n",
|
||||
(ulong) buf_pool->n_pend_reads,
|
||||
(ulong)os_file_n_pending_preads);
|
||||
(ulong) os_file_n_pending_preads);
|
||||
|
||||
os_aio_print_debug = TRUE;
|
||||
}
|
||||
|
@ -818,9 +864,6 @@ buf_read_recv_pages(
|
|||
|
||||
os_aio_simulated_wake_handler_threads();
|
||||
|
||||
/* Flush pages from the end of all the LRU lists if necessary */
|
||||
buf_flush_free_margins();
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
if (buf_debug_prints) {
|
||||
fprintf(stderr,
|
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved.
|
||||
Copyright (c) 1994, 2012, 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
|
||||
|
@ -11,13 +11,13 @@ 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 program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/********************************************************************//**
|
||||
@file data/data0data.c
|
||||
@file data/data0data.cc
|
||||
SQL data field and tuple
|
||||
|
||||
Created 5/30/1994 Heikki Tuuri
|
||||
|
@ -53,35 +53,6 @@ UNIV_INTERN ulint data_dummy;
|
|||
#endif /* UNIV_DEBUG */
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
/*********************************************************************//**
|
||||
Tests if dfield data length and content is equal to the given.
|
||||
@return TRUE if equal */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
dfield_data_is_binary_equal(
|
||||
/*========================*/
|
||||
const dfield_t* field, /*!< in: field */
|
||||
ulint len, /*!< in: data length or UNIV_SQL_NULL */
|
||||
const byte* data) /*!< in: data */
|
||||
{
|
||||
if (len != dfield_get_len(field)) {
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
if (len == UNIV_SQL_NULL) {
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
if (0 != memcmp(dfield_get_data(field), data, len)) {
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/************************************************************//**
|
||||
Compare two data tuples, respecting the collation of character fields.
|
||||
@return 1, 0 , -1 if tuple1 is greater, equal, less, respectively,
|
||||
|
@ -274,7 +245,9 @@ dtuple_validate(
|
|||
|
||||
if (!dfield_is_null(field)) {
|
||||
|
||||
const byte* data = dfield_get_data(field);
|
||||
const byte* data;
|
||||
|
||||
data = static_cast<const byte*>(dfield_get_data(field));
|
||||
#ifndef UNIV_DEBUG_VALGRIND
|
||||
ulint j;
|
||||
|
||||
|
@ -311,7 +284,7 @@ dfield_print(
|
|||
ulint i;
|
||||
|
||||
len = dfield_get_len(dfield);
|
||||
data = dfield_get_data(dfield);
|
||||
data = static_cast<const byte*>(dfield_get_data(dfield));
|
||||
|
||||
if (dfield_is_null(dfield)) {
|
||||
fputs("NULL", stderr);
|
||||
|
@ -333,7 +306,7 @@ dfield_print(
|
|||
break;
|
||||
case DATA_INT:
|
||||
ut_a(len == 4); /* only works for 32-bit integers */
|
||||
fprintf(stderr, "%d", (int)mach_read_from_4(data));
|
||||
fprintf(stderr, "%d", (int) mach_read_from_4(data));
|
||||
break;
|
||||
default:
|
||||
ut_error;
|
||||
|
@ -356,7 +329,7 @@ dfield_print_also_hex(
|
|||
ibool print_also_hex;
|
||||
|
||||
len = dfield_get_len(dfield);
|
||||
data = dfield_get_data(dfield);
|
||||
data = static_cast<const byte*>(dfield_get_data(dfield));
|
||||
|
||||
if (dfield_is_null(dfield)) {
|
||||
fputs("NULL", stderr);
|
||||
|
@ -438,25 +411,25 @@ dfield_print_also_hex(
|
|||
case DATA_TRX_ID:
|
||||
id = mach_read_from_6(data);
|
||||
|
||||
fprintf(stderr, "trx_id " TRX_ID_FMT, (ullint) id);
|
||||
fprintf(stderr, "trx_id " TRX_ID_FMT, id);
|
||||
break;
|
||||
|
||||
case DATA_ROLL_PTR:
|
||||
id = mach_read_from_7(data);
|
||||
|
||||
fprintf(stderr, "roll_ptr " TRX_ID_FMT, (ullint) id);
|
||||
fprintf(stderr, "roll_ptr " TRX_ID_FMT, id);
|
||||
break;
|
||||
|
||||
case DATA_ROW_ID:
|
||||
id = mach_read_from_6(data);
|
||||
|
||||
fprintf(stderr, "row_id " TRX_ID_FMT, (ullint) id);
|
||||
fprintf(stderr, "row_id " TRX_ID_FMT, id);
|
||||
break;
|
||||
|
||||
default:
|
||||
id = mach_ull_read_compressed(data);
|
||||
|
||||
fprintf(stderr, "mix_id " TRX_ID_FMT, (ullint) id);
|
||||
fprintf(stderr, "mix_id " TRX_ID_FMT, id);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -484,7 +457,7 @@ dfield_print_also_hex(
|
|||
break;
|
||||
}
|
||||
|
||||
data = dfield_get_data(dfield);
|
||||
data = static_cast<byte*>(dfield_get_data(dfield));
|
||||
/* fall through */
|
||||
|
||||
case DATA_BINARY:
|
||||
|
@ -579,11 +552,11 @@ dtuple_convert_big_rec(
|
|||
ulint local_len;
|
||||
ulint local_prefix_len;
|
||||
|
||||
if (UNIV_UNLIKELY(!dict_index_is_clust(index))) {
|
||||
if (!dict_index_is_clust(index)) {
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
if (dict_table_get_format(index->table) < DICT_TF_FORMAT_ZIP) {
|
||||
if (dict_table_get_format(index->table) < UNIV_FORMAT_B) {
|
||||
/* up to MySQL 5.1: store a 768-byte prefix locally */
|
||||
local_len = BTR_EXTERN_FIELD_REF_SIZE
|
||||
+ DICT_ANTELOPE_MAX_INDEX_COL_LEN;
|
||||
|
@ -608,11 +581,15 @@ dtuple_convert_big_rec(
|
|||
heap = mem_heap_create(size + dtuple_get_n_fields(entry)
|
||||
* sizeof(big_rec_field_t) + 1000);
|
||||
|
||||
vector = mem_heap_alloc(heap, sizeof(big_rec_t));
|
||||
vector = static_cast<big_rec_t*>(
|
||||
mem_heap_alloc(heap, sizeof(big_rec_t)));
|
||||
|
||||
vector->heap = heap;
|
||||
vector->fields = mem_heap_alloc(heap, dtuple_get_n_fields(entry)
|
||||
* sizeof(big_rec_field_t));
|
||||
|
||||
vector->fields = static_cast<big_rec_field_t*>(
|
||||
mem_heap_alloc(
|
||||
heap,
|
||||
dtuple_get_n_fields(entry) * sizeof(big_rec_field_t)));
|
||||
|
||||
/* Decide which fields to shorten: the algorithm is to look for
|
||||
a variable-length field that yields the biggest savings when
|
||||
|
@ -703,7 +680,7 @@ skip_field:
|
|||
b->data = (char*) dfield_get_data(dfield) + local_prefix_len;
|
||||
|
||||
/* Allocate the locally stored part of the column. */
|
||||
data = mem_heap_alloc(heap, local_len);
|
||||
data = static_cast<byte*>(mem_heap_alloc(heap, local_len));
|
||||
|
||||
/* Copy the local prefix. */
|
||||
memcpy(data, dfield_get_data(dfield), local_prefix_len);
|
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
|
||||
Copyright (c) 1996, 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
|
||||
|
@ -11,13 +11,13 @@ 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 program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file data/data0type.c
|
||||
@file data/data0type.cc
|
||||
Data types
|
||||
|
||||
Created 1/16/1996 Heikki Tuuri
|
||||
|
@ -158,7 +158,7 @@ dtype_form_prtype(
|
|||
ulint charset_coll) /*!< in: MySQL charset-collation code */
|
||||
{
|
||||
ut_a(old_prtype < 256 * 256);
|
||||
ut_a(charset_coll < 256);
|
||||
ut_a(charset_coll <= MAX_CHAR_COLL_NUM);
|
||||
|
||||
return(old_prtype + (charset_coll << 16));
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
|
||||
Copyright (c) 1996, 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
|
||||
|
@ -11,13 +11,13 @@ 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 program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file dict/dict0boot.c
|
||||
@file dict/dict0boot.cc
|
||||
Data dictionary creation and booting
|
||||
|
||||
Created 4/18/1996 Heikki Tuuri
|
||||
|
@ -254,6 +254,24 @@ dict_boot(void)
|
|||
mtr_t mtr;
|
||||
ulint error;
|
||||
|
||||
/* Be sure these constants do not ever change. To avoid bloat,
|
||||
only check the *NUM_FIELDS* in each table */
|
||||
|
||||
ut_ad(DICT_NUM_COLS__SYS_TABLES == 8);
|
||||
ut_ad(DICT_NUM_FIELDS__SYS_TABLES == 10);
|
||||
ut_ad(DICT_NUM_FIELDS__SYS_TABLE_IDS == 2);
|
||||
ut_ad(DICT_NUM_COLS__SYS_COLUMNS == 7);
|
||||
ut_ad(DICT_NUM_FIELDS__SYS_COLUMNS == 9);
|
||||
ut_ad(DICT_NUM_COLS__SYS_INDEXES == 7);
|
||||
ut_ad(DICT_NUM_FIELDS__SYS_INDEXES == 9);
|
||||
ut_ad(DICT_NUM_COLS__SYS_FIELDS == 3);
|
||||
ut_ad(DICT_NUM_FIELDS__SYS_FIELDS == 5);
|
||||
ut_ad(DICT_NUM_COLS__SYS_FOREIGN == 4);
|
||||
ut_ad(DICT_NUM_FIELDS__SYS_FOREIGN == 6);
|
||||
ut_ad(DICT_NUM_FIELDS__SYS_FOREIGN_FOR_NAME == 2);
|
||||
ut_ad(DICT_NUM_COLS__SYS_FOREIGN_COLS == 4);
|
||||
ut_ad(DICT_NUM_FIELDS__SYS_FOREIGN_COLS == 6);
|
||||
|
||||
mtr_start(&mtr);
|
||||
|
||||
/* Create the hash tables etc. */
|
||||
|
@ -283,14 +301,16 @@ dict_boot(void)
|
|||
/* Insert into the dictionary cache the descriptions of the basic
|
||||
system tables */
|
||||
/*-------------------------*/
|
||||
table = dict_mem_table_create("SYS_TABLES", DICT_HDR_SPACE, 8, 0);
|
||||
table = dict_mem_table_create("SYS_TABLES", DICT_HDR_SPACE, 8, 0, 0);
|
||||
|
||||
dict_mem_table_add_col(table, heap, "NAME", DATA_BINARY, 0, 0);
|
||||
dict_mem_table_add_col(table, heap, "ID", DATA_BINARY, 0, 0);
|
||||
/* ROW_FORMAT = (N_COLS >> 31) ? COMPACT : REDUNDANT */
|
||||
dict_mem_table_add_col(table, heap, "N_COLS", DATA_INT, 0, 4);
|
||||
/* TYPE is either DICT_TABLE_ORDINARY, or (TYPE & DICT_TF_COMPACT)
|
||||
and (TYPE & DICT_TF_FORMAT_MASK) are nonzero and TYPE = table->flags */
|
||||
/* If the format is UNIV_FORMAT_A, table->flags == 0, and
|
||||
TYPE == 1, which is defined as SYS_TABLE_TYPE_ANTELOPE.
|
||||
The low order bit of TYPE is always set to 1. If the format
|
||||
is UNIV_FORMAT_B or higher, this field matches table->flags. */
|
||||
dict_mem_table_add_col(table, heap, "TYPE", DATA_INT, 0, 4);
|
||||
dict_mem_table_add_col(table, heap, "MIX_ID", DATA_BINARY, 0, 0);
|
||||
/* MIX_LEN may contain additional table flags when
|
||||
|
@ -302,7 +322,7 @@ dict_boot(void)
|
|||
|
||||
table->id = DICT_TABLES_ID;
|
||||
|
||||
dict_table_add_to_cache(table, heap);
|
||||
dict_table_add_to_cache(table, FALSE, heap);
|
||||
dict_sys->sys_tables = table;
|
||||
mem_heap_empty(heap);
|
||||
|
||||
|
@ -335,7 +355,7 @@ dict_boot(void)
|
|||
ut_a(error == DB_SUCCESS);
|
||||
|
||||
/*-------------------------*/
|
||||
table = dict_mem_table_create("SYS_COLUMNS", DICT_HDR_SPACE, 7, 0);
|
||||
table = dict_mem_table_create("SYS_COLUMNS", DICT_HDR_SPACE, 7, 0, 0);
|
||||
|
||||
dict_mem_table_add_col(table, heap, "TABLE_ID", DATA_BINARY, 0, 0);
|
||||
dict_mem_table_add_col(table, heap, "POS", DATA_INT, 0, 4);
|
||||
|
@ -347,7 +367,7 @@ dict_boot(void)
|
|||
|
||||
table->id = DICT_COLUMNS_ID;
|
||||
|
||||
dict_table_add_to_cache(table, heap);
|
||||
dict_table_add_to_cache(table, FALSE, heap);
|
||||
dict_sys->sys_columns = table;
|
||||
mem_heap_empty(heap);
|
||||
|
||||
|
@ -367,7 +387,7 @@ dict_boot(void)
|
|||
ut_a(error == DB_SUCCESS);
|
||||
|
||||
/*-------------------------*/
|
||||
table = dict_mem_table_create("SYS_INDEXES", DICT_HDR_SPACE, 7, 0);
|
||||
table = dict_mem_table_create("SYS_INDEXES", DICT_HDR_SPACE, 7, 0, 0);
|
||||
|
||||
dict_mem_table_add_col(table, heap, "TABLE_ID", DATA_BINARY, 0, 0);
|
||||
dict_mem_table_add_col(table, heap, "ID", DATA_BINARY, 0, 0);
|
||||
|
@ -377,22 +397,9 @@ dict_boot(void)
|
|||
dict_mem_table_add_col(table, heap, "SPACE", DATA_INT, 0, 4);
|
||||
dict_mem_table_add_col(table, heap, "PAGE_NO", DATA_INT, 0, 4);
|
||||
|
||||
/* The '+ 2' below comes from the fields DB_TRX_ID, DB_ROLL_PTR */
|
||||
#if DICT_SYS_INDEXES_PAGE_NO_FIELD != 6 + 2
|
||||
#error "DICT_SYS_INDEXES_PAGE_NO_FIELD != 6 + 2"
|
||||
#endif
|
||||
#if DICT_SYS_INDEXES_SPACE_NO_FIELD != 5 + 2
|
||||
#error "DICT_SYS_INDEXES_SPACE_NO_FIELD != 5 + 2"
|
||||
#endif
|
||||
#if DICT_SYS_INDEXES_TYPE_FIELD != 4 + 2
|
||||
#error "DICT_SYS_INDEXES_TYPE_FIELD != 4 + 2"
|
||||
#endif
|
||||
#if DICT_SYS_INDEXES_NAME_FIELD != 2 + 2
|
||||
#error "DICT_SYS_INDEXES_NAME_FIELD != 2 + 2"
|
||||
#endif
|
||||
|
||||
table->id = DICT_INDEXES_ID;
|
||||
dict_table_add_to_cache(table, heap);
|
||||
|
||||
dict_table_add_to_cache(table, FALSE, heap);
|
||||
dict_sys->sys_indexes = table;
|
||||
mem_heap_empty(heap);
|
||||
|
||||
|
@ -412,14 +419,15 @@ dict_boot(void)
|
|||
ut_a(error == DB_SUCCESS);
|
||||
|
||||
/*-------------------------*/
|
||||
table = dict_mem_table_create("SYS_FIELDS", DICT_HDR_SPACE, 3, 0);
|
||||
table = dict_mem_table_create("SYS_FIELDS", DICT_HDR_SPACE, 3, 0, 0);
|
||||
|
||||
dict_mem_table_add_col(table, heap, "INDEX_ID", DATA_BINARY, 0, 0);
|
||||
dict_mem_table_add_col(table, heap, "POS", DATA_INT, 0, 4);
|
||||
dict_mem_table_add_col(table, heap, "COL_NAME", DATA_BINARY, 0, 0);
|
||||
|
||||
table->id = DICT_FIELDS_ID;
|
||||
dict_table_add_to_cache(table, heap);
|
||||
|
||||
dict_table_add_to_cache(table, FALSE, heap);
|
||||
dict_sys->sys_fields = table;
|
||||
mem_heap_free(heap);
|
||||
|
||||
|
@ -439,6 +447,7 @@ dict_boot(void)
|
|||
ut_a(error == DB_SUCCESS);
|
||||
|
||||
mtr_commit(&mtr);
|
||||
|
||||
/*-------------------------*/
|
||||
|
||||
/* Initialize the insert buffer table and index for each tablespace */
|
|
@ -11,13 +11,13 @@ 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 program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file dict/dict0crea.c
|
||||
@file dict/dict0crea.cc
|
||||
Database object creation
|
||||
|
||||
Created 1/8/1996 Heikki Tuuri
|
||||
|
@ -42,6 +42,7 @@ Created 1/8/1996 Heikki Tuuri
|
|||
#include "trx0roll.h"
|
||||
#include "usr0sess.h"
|
||||
#include "ut0vec.h"
|
||||
#include "dict0priv.h"
|
||||
|
||||
/*****************************************************************//**
|
||||
Based on a table object, this function builds the entry to be inserted
|
||||
|
@ -60,6 +61,7 @@ dict_create_sys_tables_tuple(
|
|||
dtuple_t* entry;
|
||||
dfield_t* dfield;
|
||||
byte* ptr;
|
||||
ulint type;
|
||||
|
||||
ut_ad(table);
|
||||
ut_ad(heap);
|
||||
|
@ -71,65 +73,74 @@ dict_create_sys_tables_tuple(
|
|||
dict_table_copy_types(entry, sys_tables);
|
||||
|
||||
/* 0: NAME -----------------------------*/
|
||||
dfield = dtuple_get_nth_field(entry, 0/*NAME*/);
|
||||
dfield = dtuple_get_nth_field(
|
||||
entry, DICT_COL__SYS_TABLES__NAME);
|
||||
|
||||
dfield_set_data(dfield, table->name, ut_strlen(table->name));
|
||||
/* 3: ID -------------------------------*/
|
||||
dfield = dtuple_get_nth_field(entry, 1/*ID*/);
|
||||
|
||||
ptr = mem_heap_alloc(heap, 8);
|
||||
/* 1: DB_TRX_ID added later */
|
||||
/* 2: DB_ROLL_PTR added later */
|
||||
/* 3: ID -------------------------------*/
|
||||
dfield = dtuple_get_nth_field(
|
||||
entry, DICT_COL__SYS_TABLES__ID);
|
||||
|
||||
ptr = static_cast<byte*>(mem_heap_alloc(heap, 8));
|
||||
mach_write_to_8(ptr, table->id);
|
||||
|
||||
dfield_set_data(dfield, ptr, 8);
|
||||
|
||||
/* 4: N_COLS ---------------------------*/
|
||||
dfield = dtuple_get_nth_field(entry, 2/*N_COLS*/);
|
||||
dfield = dtuple_get_nth_field(
|
||||
entry, DICT_COL__SYS_TABLES__N_COLS);
|
||||
|
||||
#if DICT_TF_COMPACT != 1
|
||||
#error
|
||||
#endif
|
||||
|
||||
ptr = mem_heap_alloc(heap, 4);
|
||||
ptr = static_cast<byte*>(mem_heap_alloc(heap, 4));
|
||||
mach_write_to_4(ptr, table->n_def
|
||||
| ((table->flags & DICT_TF_COMPACT) << 31));
|
||||
dfield_set_data(dfield, ptr, 4);
|
||||
/* 5: TYPE -----------------------------*/
|
||||
dfield = dtuple_get_nth_field(entry, 3/*TYPE*/);
|
||||
|
||||
ptr = mem_heap_alloc(heap, 4);
|
||||
if (table->flags & (~DICT_TF_COMPACT & ~(~0 << DICT_TF_BITS))) {
|
||||
ut_a(table->flags & DICT_TF_COMPACT);
|
||||
ut_a(dict_table_get_format(table) >= DICT_TF_FORMAT_ZIP);
|
||||
ut_a((table->flags & DICT_TF_ZSSIZE_MASK)
|
||||
<= (DICT_TF_ZSSIZE_MAX << DICT_TF_ZSSIZE_SHIFT));
|
||||
ut_a(!(table->flags & (~0 << DICT_TF2_BITS)));
|
||||
mach_write_to_4(ptr, table->flags & ~(~0 << DICT_TF_BITS));
|
||||
} else {
|
||||
mach_write_to_4(ptr, DICT_TABLE_ORDINARY);
|
||||
}
|
||||
/* 5: TYPE (table flags) -----------------------------*/
|
||||
dfield = dtuple_get_nth_field(
|
||||
entry, DICT_COL__SYS_TABLES__TYPE);
|
||||
|
||||
ptr = static_cast<byte*>(mem_heap_alloc(heap, 4));
|
||||
|
||||
/* Validate the table flags and convert them to what is saved in
|
||||
SYS_TABLES.TYPE. Table flag values 0 and 1 are both written to
|
||||
SYS_TABLES.TYPE as 1. */
|
||||
type = dict_tf_to_sys_tables_type(table->flags);
|
||||
mach_write_to_4(ptr, type);
|
||||
|
||||
dfield_set_data(dfield, ptr, 4);
|
||||
/* 6: MIX_ID (obsolete) ---------------------------*/
|
||||
dfield = dtuple_get_nth_field(entry, 4/*MIX_ID*/);
|
||||
|
||||
ptr = mem_heap_zalloc(heap, 8);
|
||||
/* 6: MIX_ID (obsolete) ---------------------------*/
|
||||
dfield = dtuple_get_nth_field(
|
||||
entry, DICT_COL__SYS_TABLES__MIX_ID);
|
||||
|
||||
ptr = static_cast<byte*>(mem_heap_zalloc(heap, 8));
|
||||
|
||||
dfield_set_data(dfield, ptr, 8);
|
||||
|
||||
/* 7: MIX_LEN (additional flags) --------------------------*/
|
||||
dfield = dtuple_get_nth_field(
|
||||
entry, DICT_COL__SYS_TABLES__MIX_LEN);
|
||||
|
||||
dfield = dtuple_get_nth_field(entry, 5/*MIX_LEN*/);
|
||||
|
||||
ptr = mem_heap_alloc(heap, 4);
|
||||
mach_write_to_4(ptr, table->flags >> DICT_TF2_SHIFT);
|
||||
ptr = static_cast<byte*>(mem_heap_alloc(heap, 4));
|
||||
/* Be sure all non-used bits are zero. */
|
||||
ut_a(!(table->flags2 & ~DICT_TF2_BIT_MASK));
|
||||
mach_write_to_4(ptr, table->flags2);
|
||||
|
||||
dfield_set_data(dfield, ptr, 4);
|
||||
|
||||
/* 8: CLUSTER_NAME ---------------------*/
|
||||
dfield = dtuple_get_nth_field(entry, 6/*CLUSTER_NAME*/);
|
||||
dfield = dtuple_get_nth_field(
|
||||
entry, DICT_COL__SYS_TABLES__CLUSTER_ID);
|
||||
dfield_set_null(dfield); /* not supported */
|
||||
|
||||
/* 9: SPACE ----------------------------*/
|
||||
dfield = dtuple_get_nth_field(entry, 7/*SPACE*/);
|
||||
dfield = dtuple_get_nth_field(
|
||||
entry, DICT_COL__SYS_TABLES__SPACE);
|
||||
|
||||
ptr = mem_heap_alloc(heap, 4);
|
||||
ptr = static_cast<byte*>(mem_heap_alloc(heap, 4));
|
||||
mach_write_to_4(ptr, table->space);
|
||||
|
||||
dfield_set_data(dfield, ptr, 4);
|
||||
|
@ -171,49 +182,57 @@ dict_create_sys_columns_tuple(
|
|||
dict_table_copy_types(entry, sys_columns);
|
||||
|
||||
/* 0: TABLE_ID -----------------------*/
|
||||
dfield = dtuple_get_nth_field(entry, 0/*TABLE_ID*/);
|
||||
dfield = dtuple_get_nth_field(entry, DICT_COL__SYS_COLUMNS__TABLE_ID);
|
||||
|
||||
ptr = mem_heap_alloc(heap, 8);
|
||||
ptr = static_cast<byte*>(mem_heap_alloc(heap, 8));
|
||||
mach_write_to_8(ptr, table->id);
|
||||
|
||||
dfield_set_data(dfield, ptr, 8);
|
||||
/* 1: POS ----------------------------*/
|
||||
dfield = dtuple_get_nth_field(entry, 1/*POS*/);
|
||||
|
||||
ptr = mem_heap_alloc(heap, 4);
|
||||
/* 1: POS ----------------------------*/
|
||||
dfield = dtuple_get_nth_field(entry, DICT_COL__SYS_COLUMNS__POS);
|
||||
|
||||
ptr = static_cast<byte*>(mem_heap_alloc(heap, 4));
|
||||
mach_write_to_4(ptr, i);
|
||||
|
||||
dfield_set_data(dfield, ptr, 4);
|
||||
|
||||
/* 2: DB_TRX_ID added later */
|
||||
/* 3: DB_ROLL_PTR added later */
|
||||
/* 4: NAME ---------------------------*/
|
||||
dfield = dtuple_get_nth_field(entry, 2/*NAME*/);
|
||||
dfield = dtuple_get_nth_field(entry, DICT_COL__SYS_COLUMNS__NAME);
|
||||
|
||||
col_name = dict_table_get_col_name(table, i);
|
||||
dfield_set_data(dfield, col_name, ut_strlen(col_name));
|
||||
/* 5: MTYPE --------------------------*/
|
||||
dfield = dtuple_get_nth_field(entry, 3/*MTYPE*/);
|
||||
|
||||
ptr = mem_heap_alloc(heap, 4);
|
||||
/* 5: MTYPE --------------------------*/
|
||||
dfield = dtuple_get_nth_field(entry, DICT_COL__SYS_COLUMNS__MTYPE);
|
||||
|
||||
ptr = static_cast<byte*>(mem_heap_alloc(heap, 4));
|
||||
mach_write_to_4(ptr, column->mtype);
|
||||
|
||||
dfield_set_data(dfield, ptr, 4);
|
||||
/* 6: PRTYPE -------------------------*/
|
||||
dfield = dtuple_get_nth_field(entry, 4/*PRTYPE*/);
|
||||
|
||||
ptr = mem_heap_alloc(heap, 4);
|
||||
/* 6: PRTYPE -------------------------*/
|
||||
dfield = dtuple_get_nth_field(entry, DICT_COL__SYS_COLUMNS__PRTYPE);
|
||||
|
||||
ptr = static_cast<byte*>(mem_heap_alloc(heap, 4));
|
||||
mach_write_to_4(ptr, column->prtype);
|
||||
|
||||
dfield_set_data(dfield, ptr, 4);
|
||||
/* 7: LEN ----------------------------*/
|
||||
dfield = dtuple_get_nth_field(entry, 5/*LEN*/);
|
||||
|
||||
ptr = mem_heap_alloc(heap, 4);
|
||||
/* 7: LEN ----------------------------*/
|
||||
dfield = dtuple_get_nth_field(entry, DICT_COL__SYS_COLUMNS__LEN);
|
||||
|
||||
ptr = static_cast<byte*>(mem_heap_alloc(heap, 4));
|
||||
mach_write_to_4(ptr, column->len);
|
||||
|
||||
dfield_set_data(dfield, ptr, 4);
|
||||
/* 8: PREC ---------------------------*/
|
||||
dfield = dtuple_get_nth_field(entry, 6/*PREC*/);
|
||||
|
||||
ptr = mem_heap_alloc(heap, 4);
|
||||
/* 8: PREC ---------------------------*/
|
||||
dfield = dtuple_get_nth_field(entry, DICT_COL__SYS_COLUMNS__PREC);
|
||||
|
||||
ptr = static_cast<byte*>(mem_heap_alloc(heap, 4));
|
||||
mach_write_to_4(ptr, 0/* unused */);
|
||||
|
||||
dfield_set_data(dfield, ptr, 4);
|
||||
|
@ -235,32 +254,24 @@ dict_build_table_def_step(
|
|||
dict_table_t* table;
|
||||
dtuple_t* row;
|
||||
ulint error;
|
||||
ulint flags;
|
||||
const char* path_or_name;
|
||||
ibool is_path;
|
||||
mtr_t mtr;
|
||||
ulint space = 0;
|
||||
ibool file_per_table;
|
||||
bool use_tablespace;
|
||||
|
||||
ut_ad(mutex_own(&(dict_sys->mutex)));
|
||||
|
||||
table = node->table;
|
||||
|
||||
/* Cache the global variable "srv_file_per_table" to
|
||||
a local variable before using it. Please note
|
||||
"srv_file_per_table" is not under dict_sys mutex
|
||||
protection, and could be changed while executing
|
||||
this function. So better to cache the current value
|
||||
to a local variable, and all future reference to
|
||||
"srv_file_per_table" should use this local variable. */
|
||||
file_per_table = srv_file_per_table;
|
||||
use_tablespace = !!(table->flags2 & DICT_TF2_USE_TABLESPACE);
|
||||
|
||||
dict_hdr_get_new_id(&table->id, NULL, NULL);
|
||||
|
||||
thr_get_trx(thr)->table_id = table->id;
|
||||
|
||||
if (file_per_table) {
|
||||
/* Get a new space id if srv_file_per_table is set */
|
||||
if (use_tablespace) {
|
||||
/* This table will not use the system tablespace.
|
||||
Get a new space id. */
|
||||
dict_hdr_get_new_id(NULL, NULL, &space);
|
||||
|
||||
if (UNIV_UNLIKELY(space == ULINT_UNDEFINED)) {
|
||||
|
@ -286,14 +297,14 @@ dict_build_table_def_step(
|
|||
is_path = FALSE;
|
||||
}
|
||||
|
||||
ut_ad(dict_table_get_format(table) <= DICT_TF_FORMAT_MAX);
|
||||
ut_ad(dict_table_get_format(table) <= UNIV_FORMAT_MAX);
|
||||
ut_ad(!dict_table_zip_size(table)
|
||||
|| dict_table_get_format(table) >= DICT_TF_FORMAT_ZIP);
|
||||
|| dict_table_get_format(table) >= UNIV_FORMAT_B);
|
||||
|
||||
flags = table->flags & ~(~0 << DICT_TF_BITS);
|
||||
error = fil_create_new_single_table_tablespace(
|
||||
space, path_or_name, is_path,
|
||||
flags == DICT_TF_COMPACT ? 0 : flags,
|
||||
dict_tf_to_fsp_flags(table->flags),
|
||||
table->flags2,
|
||||
FIL_IBD_FILE_INITIAL_SIZE);
|
||||
table->space = (unsigned int) space;
|
||||
|
||||
|
@ -308,8 +319,10 @@ dict_build_table_def_step(
|
|||
|
||||
mtr_commit(&mtr);
|
||||
} else {
|
||||
/* Create in the system tablespace: disallow new features */
|
||||
table->flags &= (~0 << DICT_TF_BITS) | DICT_TF_COMPACT;
|
||||
/* Create in the system tablespace: disallow Barracuda
|
||||
features by keeping only the first bit which says whether
|
||||
the row format is redundant or compact */
|
||||
table->flags &= DICT_TF_COMPACT;
|
||||
}
|
||||
|
||||
row = dict_create_sys_tables_tuple(table, node->heap);
|
||||
|
@ -369,61 +382,69 @@ dict_create_sys_indexes_tuple(
|
|||
dict_table_copy_types(entry, sys_indexes);
|
||||
|
||||
/* 0: TABLE_ID -----------------------*/
|
||||
dfield = dtuple_get_nth_field(entry, 0/*TABLE_ID*/);
|
||||
dfield = dtuple_get_nth_field(
|
||||
entry, DICT_COL__SYS_INDEXES__TABLE_ID);
|
||||
|
||||
ptr = mem_heap_alloc(heap, 8);
|
||||
ptr = static_cast<byte*>(mem_heap_alloc(heap, 8));
|
||||
mach_write_to_8(ptr, table->id);
|
||||
|
||||
dfield_set_data(dfield, ptr, 8);
|
||||
/* 1: ID ----------------------------*/
|
||||
dfield = dtuple_get_nth_field(entry, 1/*ID*/);
|
||||
|
||||
ptr = mem_heap_alloc(heap, 8);
|
||||
/* 1: ID ----------------------------*/
|
||||
dfield = dtuple_get_nth_field(
|
||||
entry, DICT_COL__SYS_INDEXES__ID);
|
||||
|
||||
ptr = static_cast<byte*>(mem_heap_alloc(heap, 8));
|
||||
mach_write_to_8(ptr, index->id);
|
||||
|
||||
dfield_set_data(dfield, ptr, 8);
|
||||
|
||||
/* 2: DB_TRX_ID added later */
|
||||
/* 3: DB_ROLL_PTR added later */
|
||||
/* 4: NAME --------------------------*/
|
||||
dfield = dtuple_get_nth_field(entry, 2/*NAME*/);
|
||||
dfield = dtuple_get_nth_field(
|
||||
entry, DICT_COL__SYS_INDEXES__NAME);
|
||||
|
||||
dfield_set_data(dfield, index->name, ut_strlen(index->name));
|
||||
/* 5: N_FIELDS ----------------------*/
|
||||
dfield = dtuple_get_nth_field(entry, 3/*N_FIELDS*/);
|
||||
|
||||
ptr = mem_heap_alloc(heap, 4);
|
||||
/* 5: N_FIELDS ----------------------*/
|
||||
dfield = dtuple_get_nth_field(
|
||||
entry, DICT_COL__SYS_INDEXES__N_FIELDS);
|
||||
|
||||
ptr = static_cast<byte*>(mem_heap_alloc(heap, 4));
|
||||
mach_write_to_4(ptr, index->n_fields);
|
||||
|
||||
dfield_set_data(dfield, ptr, 4);
|
||||
/* 6: TYPE --------------------------*/
|
||||
dfield = dtuple_get_nth_field(entry, 4/*TYPE*/);
|
||||
|
||||
ptr = mem_heap_alloc(heap, 4);
|
||||
/* 6: TYPE --------------------------*/
|
||||
dfield = dtuple_get_nth_field(
|
||||
entry, DICT_COL__SYS_INDEXES__TYPE);
|
||||
|
||||
ptr = static_cast<byte*>(mem_heap_alloc(heap, 4));
|
||||
mach_write_to_4(ptr, index->type);
|
||||
|
||||
dfield_set_data(dfield, ptr, 4);
|
||||
|
||||
/* 7: SPACE --------------------------*/
|
||||
|
||||
#if DICT_SYS_INDEXES_SPACE_NO_FIELD != 7
|
||||
#error "DICT_SYS_INDEXES_SPACE_NO_FIELD != 7"
|
||||
#endif
|
||||
dfield = dtuple_get_nth_field(
|
||||
entry, DICT_COL__SYS_INDEXES__SPACE);
|
||||
|
||||
dfield = dtuple_get_nth_field(entry, 5/*SPACE*/);
|
||||
|
||||
ptr = mem_heap_alloc(heap, 4);
|
||||
ptr = static_cast<byte*>(mem_heap_alloc(heap, 4));
|
||||
mach_write_to_4(ptr, index->space);
|
||||
|
||||
dfield_set_data(dfield, ptr, 4);
|
||||
|
||||
/* 8: PAGE_NO --------------------------*/
|
||||
|
||||
#if DICT_SYS_INDEXES_PAGE_NO_FIELD != 8
|
||||
#error "DICT_SYS_INDEXES_PAGE_NO_FIELD != 8"
|
||||
#endif
|
||||
dfield = dtuple_get_nth_field(
|
||||
entry, DICT_COL__SYS_INDEXES__PAGE_NO);
|
||||
|
||||
dfield = dtuple_get_nth_field(entry, 6/*PAGE_NO*/);
|
||||
|
||||
ptr = mem_heap_alloc(heap, 4);
|
||||
ptr = static_cast<byte*>(mem_heap_alloc(heap, 4));
|
||||
mach_write_to_4(ptr, FIL_NULL);
|
||||
|
||||
dfield_set_data(dfield, ptr, 4);
|
||||
|
||||
/*--------------------------------*/
|
||||
|
||||
return(entry);
|
||||
|
@ -438,7 +459,7 @@ dtuple_t*
|
|||
dict_create_sys_fields_tuple(
|
||||
/*=========================*/
|
||||
const dict_index_t* index, /*!< in: index */
|
||||
ulint i, /*!< in: field number */
|
||||
ulint fld_no, /*!< in: field number */
|
||||
mem_heap_t* heap) /*!< in: memory heap from
|
||||
which the memory for the built
|
||||
tuple is allocated */
|
||||
|
@ -461,7 +482,7 @@ dict_create_sys_fields_tuple(
|
|||
}
|
||||
}
|
||||
|
||||
field = dict_index_get_nth_field(index, i);
|
||||
field = dict_index_get_nth_field(index, fld_no);
|
||||
|
||||
sys_fields = dict_sys->sys_fields;
|
||||
|
||||
|
@ -470,35 +491,39 @@ dict_create_sys_fields_tuple(
|
|||
dict_table_copy_types(entry, sys_fields);
|
||||
|
||||
/* 0: INDEX_ID -----------------------*/
|
||||
dfield = dtuple_get_nth_field(entry, 0/*INDEX_ID*/);
|
||||
dfield = dtuple_get_nth_field(entry, DICT_COL__SYS_FIELDS__INDEX_ID);
|
||||
|
||||
ptr = mem_heap_alloc(heap, 8);
|
||||
ptr = static_cast<byte*>(mem_heap_alloc(heap, 8));
|
||||
mach_write_to_8(ptr, index->id);
|
||||
|
||||
dfield_set_data(dfield, ptr, 8);
|
||||
/* 1: POS + PREFIX LENGTH ----------------------------*/
|
||||
|
||||
dfield = dtuple_get_nth_field(entry, 1/*POS*/);
|
||||
/* 1: POS; FIELD NUMBER & PREFIX LENGTH -----------------------*/
|
||||
|
||||
ptr = mem_heap_alloc(heap, 4);
|
||||
dfield = dtuple_get_nth_field(entry, DICT_COL__SYS_FIELDS__POS);
|
||||
|
||||
ptr = static_cast<byte*>(mem_heap_alloc(heap, 4));
|
||||
|
||||
if (index_contains_column_prefix_field) {
|
||||
/* If there are column prefix fields in the index, then
|
||||
we store the number of the field to the 2 HIGH bytes
|
||||
and the prefix length to the 2 low bytes, */
|
||||
|
||||
mach_write_to_4(ptr, (i << 16) + field->prefix_len);
|
||||
mach_write_to_4(ptr, (fld_no << 16) + field->prefix_len);
|
||||
} else {
|
||||
/* Else we store the number of the field to the 2 LOW bytes.
|
||||
This is to keep the storage format compatible with
|
||||
InnoDB versions < 4.0.14. */
|
||||
|
||||
mach_write_to_4(ptr, i);
|
||||
mach_write_to_4(ptr, fld_no);
|
||||
}
|
||||
|
||||
dfield_set_data(dfield, ptr, 4);
|
||||
|
||||
/* 2: DB_TRX_ID added later */
|
||||
/* 3: DB_ROLL_PTR added later */
|
||||
/* 4: COL_NAME -------------------------*/
|
||||
dfield = dtuple_get_nth_field(entry, 2/*COL_NAME*/);
|
||||
dfield = dtuple_get_nth_field(entry, DICT_COL__SYS_FIELDS__COL_NAME);
|
||||
|
||||
dfield_set_data(dfield, field->name,
|
||||
ut_strlen(field->name));
|
||||
|
@ -638,6 +663,11 @@ dict_create_index_tree_step(
|
|||
|
||||
sys_indexes = dict_sys->sys_indexes;
|
||||
|
||||
if (index->type == DICT_FTS) {
|
||||
/* FTS index does not need an index tree */
|
||||
return(DB_SUCCESS);
|
||||
}
|
||||
|
||||
/* Run a mini-transaction in which the index tree is allocated for
|
||||
the index and its root address is written to the index entry in
|
||||
sys_indexes */
|
||||
|
@ -657,10 +687,10 @@ dict_create_index_tree_step(
|
|||
node->page_no = btr_create(index->type, index->space, zip_size,
|
||||
index->id, index, &mtr);
|
||||
/* printf("Created a new index tree in space %lu root page %lu\n",
|
||||
index->space, index->page_no); */
|
||||
index->space, node->page_no); */
|
||||
|
||||
page_rec_write_field(btr_pcur_get_rec(&pcur),
|
||||
DICT_SYS_INDEXES_PAGE_NO_FIELD,
|
||||
DICT_FLD__SYS_INDEXES__PAGE_NO,
|
||||
node->page_no, &mtr);
|
||||
btr_pcur_close(&pcur);
|
||||
mtr_commit(&mtr);
|
||||
|
@ -691,7 +721,8 @@ dict_drop_index_tree(
|
|||
|
||||
ut_ad(mutex_own(&(dict_sys->mutex)));
|
||||
ut_a(!dict_table_is_comp(dict_sys->sys_indexes));
|
||||
ptr = rec_get_nth_field_old(rec, DICT_SYS_INDEXES_PAGE_NO_FIELD, &len);
|
||||
ptr = rec_get_nth_field_old(
|
||||
rec, DICT_FLD__SYS_INDEXES__PAGE_NO, &len);
|
||||
|
||||
ut_ad(len == 4);
|
||||
|
||||
|
@ -703,8 +734,8 @@ dict_drop_index_tree(
|
|||
return;
|
||||
}
|
||||
|
||||
ptr = rec_get_nth_field_old(rec,
|
||||
DICT_SYS_INDEXES_SPACE_NO_FIELD, &len);
|
||||
ptr = rec_get_nth_field_old(
|
||||
rec, DICT_FLD__SYS_INDEXES__SPACE, &len);
|
||||
|
||||
ut_ad(len == 4);
|
||||
|
||||
|
@ -731,7 +762,7 @@ dict_drop_index_tree(
|
|||
root_page_no); */
|
||||
btr_free_root(space, zip_size, root_page_no, mtr);
|
||||
|
||||
page_rec_write_field(rec, DICT_SYS_INDEXES_PAGE_NO_FIELD,
|
||||
page_rec_write_field(rec, DICT_FLD__SYS_INDEXES__PAGE_NO,
|
||||
FIL_NULL, mtr);
|
||||
}
|
||||
|
||||
|
@ -767,7 +798,8 @@ dict_truncate_index_tree(
|
|||
ut_ad(mutex_own(&(dict_sys->mutex)));
|
||||
ut_a(!dict_table_is_comp(dict_sys->sys_indexes));
|
||||
rec = btr_pcur_get_rec(pcur);
|
||||
ptr = rec_get_nth_field_old(rec, DICT_SYS_INDEXES_PAGE_NO_FIELD, &len);
|
||||
ptr = rec_get_nth_field_old(
|
||||
rec, DICT_FLD__SYS_INDEXES__PAGE_NO, &len);
|
||||
|
||||
ut_ad(len == 4);
|
||||
|
||||
|
@ -782,8 +814,8 @@ dict_truncate_index_tree(
|
|||
drop = FALSE;
|
||||
}
|
||||
|
||||
ptr = rec_get_nth_field_old(rec,
|
||||
DICT_SYS_INDEXES_SPACE_NO_FIELD, &len);
|
||||
ptr = rec_get_nth_field_old(
|
||||
rec, DICT_FLD__SYS_INDEXES__SPACE, &len);
|
||||
|
||||
ut_ad(len == 4);
|
||||
|
||||
|
@ -803,12 +835,12 @@ dict_truncate_index_tree(
|
|||
return(FIL_NULL);
|
||||
}
|
||||
|
||||
ptr = rec_get_nth_field_old(rec,
|
||||
DICT_SYS_INDEXES_TYPE_FIELD, &len);
|
||||
ptr = rec_get_nth_field_old(
|
||||
rec, DICT_FLD__SYS_INDEXES__TYPE, &len);
|
||||
ut_ad(len == 4);
|
||||
type = mach_read_from_4(ptr);
|
||||
|
||||
ptr = rec_get_nth_field_old(rec, 1, &len);
|
||||
ptr = rec_get_nth_field_old(rec, DICT_FLD__SYS_INDEXES__ID, &len);
|
||||
ut_ad(len == 8);
|
||||
index_id = mach_read_from_8(ptr);
|
||||
|
||||
|
@ -835,7 +867,7 @@ create:
|
|||
in SYS_INDEXES, so that the database will not get into an
|
||||
inconsistent state in case it crashes between the mtr_commit()
|
||||
below and the following mtr_commit() call. */
|
||||
page_rec_write_field(rec, DICT_SYS_INDEXES_PAGE_NO_FIELD,
|
||||
page_rec_write_field(rec, DICT_FLD__SYS_INDEXES__PAGE_NO,
|
||||
FIL_NULL, mtr);
|
||||
|
||||
/* We will need to commit the mini-transaction in order to avoid
|
||||
|
@ -882,7 +914,8 @@ tab_create_graph_create(
|
|||
{
|
||||
tab_node_t* node;
|
||||
|
||||
node = mem_heap_alloc(heap, sizeof(tab_node_t));
|
||||
node = static_cast<tab_node_t*>(
|
||||
mem_heap_alloc(heap, sizeof(tab_node_t)));
|
||||
|
||||
node->common.type = QUE_NODE_CREATE_TABLE;
|
||||
|
||||
|
@ -899,7 +932,7 @@ tab_create_graph_create(
|
|||
heap);
|
||||
node->col_def->common.parent = node;
|
||||
|
||||
node->commit_node = commit_node_create(heap);
|
||||
node->commit_node = trx_commit_node_create(heap);
|
||||
node->commit_node->common.parent = node;
|
||||
|
||||
return(node);
|
||||
|
@ -918,7 +951,8 @@ ind_create_graph_create(
|
|||
{
|
||||
ind_node_t* node;
|
||||
|
||||
node = mem_heap_alloc(heap, sizeof(ind_node_t));
|
||||
node = static_cast<ind_node_t*>(
|
||||
mem_heap_alloc(heap, sizeof(ind_node_t)));
|
||||
|
||||
node->common.type = QUE_NODE_CREATE_INDEX;
|
||||
|
||||
|
@ -936,7 +970,7 @@ ind_create_graph_create(
|
|||
dict_sys->sys_fields, heap);
|
||||
node->field_def->common.parent = node;
|
||||
|
||||
node->commit_node = commit_node_create(heap);
|
||||
node->commit_node = trx_commit_node_create(heap);
|
||||
node->commit_node->common.parent = node;
|
||||
|
||||
return(node);
|
||||
|
@ -960,7 +994,7 @@ dict_create_table_step(
|
|||
|
||||
trx = thr_get_trx(thr);
|
||||
|
||||
node = thr->run_node;
|
||||
node = static_cast<tab_node_t*>(thr->run_node);
|
||||
|
||||
ut_ad(que_node_get_type(node) == QUE_NODE_CREATE_TABLE);
|
||||
|
||||
|
@ -1023,13 +1057,13 @@ dict_create_table_step(
|
|||
|
||||
if (node->state == TABLE_ADD_TO_CACHE) {
|
||||
|
||||
dict_table_add_to_cache(node->table, node->heap);
|
||||
dict_table_add_to_cache(node->table, TRUE, node->heap);
|
||||
|
||||
err = DB_SUCCESS;
|
||||
}
|
||||
|
||||
function_exit:
|
||||
trx->error_state = err;
|
||||
trx->error_state = (enum db_err) err;
|
||||
|
||||
if (err == DB_SUCCESS) {
|
||||
/* Ok: do nothing */
|
||||
|
@ -1067,7 +1101,7 @@ dict_create_index_step(
|
|||
|
||||
trx = thr_get_trx(thr);
|
||||
|
||||
node = thr->run_node;
|
||||
node = static_cast<ind_node_t*>(thr->run_node);
|
||||
|
||||
ut_ad(que_node_get_type(node) == QUE_NODE_CREATE_INDEX);
|
||||
|
||||
|
@ -1121,7 +1155,7 @@ dict_create_index_step(
|
|||
node->table, node->index, FIL_NULL,
|
||||
trx_is_strict(trx)
|
||||
|| dict_table_get_format(node->table)
|
||||
>= DICT_TF_FORMAT_ZIP);
|
||||
>= UNIV_FORMAT_B);
|
||||
|
||||
node->index = dict_index_get_if_in_cache_low(index_id);
|
||||
ut_a(!node->index == (err != DB_SUCCESS));
|
||||
|
@ -1163,7 +1197,7 @@ dict_create_index_step(
|
|||
}
|
||||
|
||||
function_exit:
|
||||
trx->error_state = err;
|
||||
trx->error_state = static_cast<enum db_err>(err);
|
||||
|
||||
if (err == DB_SUCCESS) {
|
||||
/* Ok: do nothing */
|
||||
|
@ -1182,6 +1216,46 @@ function_exit:
|
|||
return(thr);
|
||||
}
|
||||
|
||||
/****************************************************************//**
|
||||
Check whether the system foreign key tables exist. Additionally, If
|
||||
they exist then move them to non-LRU end of the table LRU list.
|
||||
@return TRUE if they exist. */
|
||||
static
|
||||
ibool
|
||||
dict_check_sys_foreign_tables_exist(void)
|
||||
/*=====================================*/
|
||||
{
|
||||
dict_table_t* sys_foreign;
|
||||
ibool exists = FALSE;
|
||||
dict_table_t* sys_foreign_cols;
|
||||
|
||||
ut_a(srv_get_active_thread_type() == SRV_NONE);
|
||||
|
||||
mutex_enter(&dict_sys->mutex);
|
||||
|
||||
sys_foreign = dict_table_get_low("SYS_FOREIGN");
|
||||
sys_foreign_cols = dict_table_get_low("SYS_FOREIGN_COLS");
|
||||
|
||||
if (sys_foreign != NULL
|
||||
&& sys_foreign_cols != NULL
|
||||
&& UT_LIST_GET_LEN(sys_foreign->indexes) == 3
|
||||
&& UT_LIST_GET_LEN(sys_foreign_cols->indexes) == 1) {
|
||||
|
||||
/* Foreign constraint system tables have already been
|
||||
created, and they are ok. Ensure that they can't be
|
||||
evicted from the table LRU cache. */
|
||||
|
||||
dict_table_move_from_lru_to_non_lru(sys_foreign);
|
||||
dict_table_move_from_lru_to_non_lru(sys_foreign_cols);
|
||||
|
||||
exists = TRUE;
|
||||
}
|
||||
|
||||
mutex_exit(&dict_sys->mutex);
|
||||
|
||||
return(exists);
|
||||
}
|
||||
|
||||
/****************************************************************//**
|
||||
Creates the foreign key constraints system tables inside InnoDB
|
||||
at database creation or database start if they are not found or are
|
||||
|
@ -1192,47 +1266,39 @@ ulint
|
|||
dict_create_or_check_foreign_constraint_tables(void)
|
||||
/*================================================*/
|
||||
{
|
||||
dict_table_t* table1;
|
||||
dict_table_t* table2;
|
||||
ulint error;
|
||||
trx_t* trx;
|
||||
ulint error;
|
||||
ibool success;
|
||||
ibool srv_file_per_table_backup;
|
||||
|
||||
mutex_enter(&(dict_sys->mutex));
|
||||
ut_a(srv_get_active_thread_type() == SRV_NONE);
|
||||
|
||||
table1 = dict_table_get_low("SYS_FOREIGN");
|
||||
table2 = dict_table_get_low("SYS_FOREIGN_COLS");
|
||||
|
||||
if (table1 && table2
|
||||
&& UT_LIST_GET_LEN(table1->indexes) == 3
|
||||
&& UT_LIST_GET_LEN(table2->indexes) == 1) {
|
||||
|
||||
/* Foreign constraint system tables have already been
|
||||
created, and they are ok */
|
||||
|
||||
mutex_exit(&(dict_sys->mutex));
|
||||
/* Note: The master thread has not been started at this point. */
|
||||
|
||||
if (dict_check_sys_foreign_tables_exist()) {
|
||||
return(DB_SUCCESS);
|
||||
}
|
||||
|
||||
mutex_exit(&(dict_sys->mutex));
|
||||
|
||||
trx = trx_allocate_for_mysql();
|
||||
|
||||
trx->op_info = "creating foreign key sys tables";
|
||||
|
||||
row_mysql_lock_data_dictionary(trx);
|
||||
|
||||
if (table1) {
|
||||
/* Check which incomplete table definition to drop. */
|
||||
|
||||
if (dict_table_get_low("SYS_FOREIGN") != NULL) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: dropping incompletely created"
|
||||
" SYS_FOREIGN table\n");
|
||||
row_drop_table_for_mysql("SYS_FOREIGN", trx, TRUE);
|
||||
}
|
||||
|
||||
if (table2) {
|
||||
if (dict_table_get_low("SYS_FOREIGN_COLS") != NULL) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: dropping incompletely created"
|
||||
" SYS_FOREIGN_COLS table\n");
|
||||
|
||||
row_drop_table_for_mysql("SYS_FOREIGN_COLS", trx, TRUE);
|
||||
}
|
||||
|
||||
|
@ -1249,6 +1315,13 @@ dict_create_or_check_foreign_constraint_tables(void)
|
|||
VARBINARY, like in other InnoDB system tables, to get a clean
|
||||
design. */
|
||||
|
||||
srv_file_per_table_backup = (ibool) srv_file_per_table;
|
||||
|
||||
/* We always want SYSTEM tables to be created inside the system
|
||||
tablespace. */
|
||||
|
||||
srv_file_per_table = 0;
|
||||
|
||||
error = que_eval_sql(NULL,
|
||||
"PROCEDURE CREATE_FOREIGN_SYS_TABLES_PROC () IS\n"
|
||||
"BEGIN\n"
|
||||
|
@ -1300,6 +1373,14 @@ dict_create_or_check_foreign_constraint_tables(void)
|
|||
" created\n");
|
||||
}
|
||||
|
||||
/* Note: The master thread has not been started at this point. */
|
||||
/* Confirm and move to the non-LRU part of the table LRU list. */
|
||||
|
||||
success = dict_check_sys_foreign_tables_exist();
|
||||
ut_a(success);
|
||||
|
||||
srv_file_per_table = (my_bool) srv_file_per_table_backup;
|
||||
|
||||
return(error);
|
||||
}
|
||||
|
||||
|
@ -1428,8 +1509,12 @@ dict_create_add_foreign_to_dictionary(
|
|||
|
||||
if (foreign->id == NULL) {
|
||||
/* Generate a new constraint id */
|
||||
char* id;
|
||||
ulint namelen = strlen(table->name);
|
||||
char* id = mem_heap_alloc(foreign->heap, namelen + 20);
|
||||
|
||||
id = static_cast<char*>(mem_heap_alloc(
|
||||
foreign->heap, namelen + 20));
|
||||
|
||||
/* no overflow if number < 1e13 */
|
||||
sprintf(id, "%s_ibfk_%lu", table->name, (ulong) (*id_nr)++);
|
||||
foreign->id = id;
|
||||
|
@ -1468,12 +1553,11 @@ dict_create_add_foreign_to_dictionary(
|
|||
}
|
||||
}
|
||||
|
||||
error = dict_foreign_eval_sql(NULL,
|
||||
"PROCEDURE P () IS\n"
|
||||
"BEGIN\n"
|
||||
"COMMIT WORK;\n"
|
||||
"END;\n"
|
||||
, table, foreign, trx);
|
||||
trx->op_info = "committing foreign key definitions";
|
||||
|
||||
trx_commit(trx);
|
||||
|
||||
trx->op_info = "";
|
||||
|
||||
return(error);
|
||||
}
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
|
||||
Copyright (c) 1996, 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
|
||||
|
@ -11,13 +11,13 @@ 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 program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/******************************************************************//**
|
||||
@file dict/dict0mem.c
|
||||
@file dict/dict0mem.cc
|
||||
Data dictionary memory object creation
|
||||
|
||||
Created 1/8/1996 Heikki Tuuri
|
||||
|
@ -33,8 +33,10 @@ Created 1/8/1996 Heikki Tuuri
|
|||
#include "data0type.h"
|
||||
#include "mach0data.h"
|
||||
#include "dict0dict.h"
|
||||
#include "ha_prototypes.h" /* innobase_casedn_str()*/
|
||||
#include "fts0priv.h"
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
#include "ha_prototypes.h" /* innobase_casedn_str(),
|
||||
innobase_get_lower_case_table_names */
|
||||
# include "lock0lock.h"
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
#ifdef UNIV_BLOB_DEBUG
|
||||
|
@ -62,31 +64,40 @@ dict_mem_table_create(
|
|||
ignored if the table is made a member of
|
||||
a cluster */
|
||||
ulint n_cols, /*!< in: number of columns */
|
||||
ulint flags) /*!< in: table flags */
|
||||
ulint flags, /*!< in: table flags */
|
||||
ulint flags2) /*!< in: table flags2 */
|
||||
{
|
||||
dict_table_t* table;
|
||||
mem_heap_t* heap;
|
||||
|
||||
ut_ad(name);
|
||||
ut_a(!(flags & (~0 << DICT_TF2_BITS)));
|
||||
dict_tf_validate(flags);
|
||||
ut_a(!(flags2 & ~DICT_TF2_BIT_MASK));
|
||||
|
||||
heap = mem_heap_create(DICT_HEAP_SIZE);
|
||||
|
||||
table = mem_heap_zalloc(heap, sizeof(dict_table_t));
|
||||
table = static_cast<dict_table_t*>(
|
||||
mem_heap_zalloc(heap, sizeof(dict_table_t)));
|
||||
|
||||
table->heap = heap;
|
||||
|
||||
table->flags = (unsigned int) flags;
|
||||
table->name = ut_malloc(strlen(name) + 1);
|
||||
table->flags2 = (unsigned int) flags2;
|
||||
table->name = static_cast<char*>(ut_malloc(strlen(name) + 1));
|
||||
memcpy(table->name, name, strlen(name) + 1);
|
||||
table->space = (unsigned int) space;
|
||||
table->n_cols = (unsigned int) (n_cols + DATA_N_SYS_COLS);
|
||||
|
||||
table->cols = mem_heap_alloc(heap, (n_cols + DATA_N_SYS_COLS)
|
||||
* sizeof(dict_col_t));
|
||||
table->cols = static_cast<dict_col_t*>(
|
||||
mem_heap_alloc(heap,
|
||||
(n_cols + DATA_N_SYS_COLS)
|
||||
* sizeof(dict_col_t)));
|
||||
|
||||
ut_d(table->magic_n = DICT_TABLE_MAGIC_N);
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
table->autoinc_lock = mem_heap_alloc(heap, lock_get_size());
|
||||
table->autoinc_lock = static_cast<ib_lock_t*>(
|
||||
mem_heap_alloc(heap, lock_get_size()));
|
||||
|
||||
mutex_create(autoinc_mutex_key,
|
||||
&table->autoinc_mutex, SYNC_DICT_AUTOINC_MUTEX);
|
||||
|
@ -96,9 +107,20 @@ dict_mem_table_create(
|
|||
/* The number of transactions that are either waiting on the
|
||||
AUTOINC lock or have been granted the lock. */
|
||||
table->n_waiting_or_granted_auto_inc_locks = 0;
|
||||
|
||||
/* If the table has an FTS index or we are in the process
|
||||
of building one, create the table->fts */
|
||||
if (dict_table_has_fts_index(table)
|
||||
|| DICT_TF2_FLAG_IS_SET(table, DICT_TF2_FTS_HAS_DOC_ID)
|
||||
|| DICT_TF2_FLAG_IS_SET(table, DICT_TF2_FTS_ADD_DOC_ID)) {
|
||||
table->fts = fts_create(table);
|
||||
table->fts->cache = fts_cache_create(table);
|
||||
fts_optimize_add_table(table);
|
||||
} else {
|
||||
table->fts = NULL;
|
||||
}
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
ut_d(table->magic_n = DICT_TABLE_MAGIC_N);
|
||||
return(table);
|
||||
}
|
||||
|
||||
|
@ -114,6 +136,15 @@ dict_mem_table_free(
|
|||
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
|
||||
ut_d(table->cached = FALSE);
|
||||
|
||||
if (dict_table_has_fts_index(table)
|
||||
|| DICT_TF2_FLAG_IS_SET(table, DICT_TF2_FTS_HAS_DOC_ID)
|
||||
|| DICT_TF2_FLAG_IS_SET(table, DICT_TF2_FTS_ADD_DOC_ID)) {
|
||||
if (table->fts) {
|
||||
fts_free(table);
|
||||
}
|
||||
|
||||
fts_optimize_remove_table(table);
|
||||
}
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
mutex_free(&(table->autoinc_mutex));
|
||||
#endif /* UNIV_HOTBACKUP */
|
||||
|
@ -158,7 +189,7 @@ dict_add_col_name(
|
|||
new_len = strlen(name) + 1;
|
||||
total_len = old_len + new_len;
|
||||
|
||||
res = mem_heap_alloc(heap, total_len);
|
||||
res = static_cast<char*>(mem_heap_alloc(heap, total_len));
|
||||
|
||||
if (old_len > 0) {
|
||||
memcpy(res, col_names, old_len);
|
||||
|
@ -197,7 +228,9 @@ dict_mem_table_add_col(
|
|||
}
|
||||
if (UNIV_LIKELY(i) && UNIV_UNLIKELY(!table->col_names)) {
|
||||
/* All preceding column names are empty. */
|
||||
char* s = mem_heap_zalloc(heap, table->n_def);
|
||||
char* s = static_cast<char*>(
|
||||
mem_heap_zalloc(heap, table->n_def));
|
||||
|
||||
table->col_names = s;
|
||||
}
|
||||
|
||||
|
@ -264,7 +297,9 @@ dict_mem_index_create(
|
|||
ut_ad(table_name && index_name);
|
||||
|
||||
heap = mem_heap_create(DICT_HEAP_SIZE);
|
||||
index = mem_heap_zalloc(heap, sizeof(dict_index_t));
|
||||
|
||||
index = static_cast<dict_index_t*>(
|
||||
mem_heap_zalloc(heap, sizeof(*index)));
|
||||
|
||||
dict_mem_fill_index_struct(index, heap, table_name, index_name,
|
||||
space, type, n_fields);
|
||||
|
@ -272,6 +307,7 @@ dict_mem_index_create(
|
|||
return(index);
|
||||
}
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
/**********************************************************************//**
|
||||
Creates and initializes a foreign constraint memory object.
|
||||
@return own: foreign constraint struct */
|
||||
|
@ -285,7 +321,8 @@ dict_mem_foreign_create(void)
|
|||
|
||||
heap = mem_heap_create(100);
|
||||
|
||||
foreign = mem_heap_zalloc(heap, sizeof(dict_foreign_t));
|
||||
foreign = static_cast<dict_foreign_t*>(
|
||||
mem_heap_zalloc(heap, sizeof(dict_foreign_t)));
|
||||
|
||||
foreign->heap = heap;
|
||||
|
||||
|
@ -306,9 +343,13 @@ dict_mem_foreign_table_name_lookup_set(
|
|||
{
|
||||
if (innobase_get_lower_case_table_names() == 2) {
|
||||
if (do_alloc) {
|
||||
foreign->foreign_table_name_lookup = mem_heap_alloc(
|
||||
foreign->heap,
|
||||
strlen(foreign->foreign_table_name) + 1);
|
||||
ulint len;
|
||||
|
||||
len = strlen(foreign->foreign_table_name) + 1;
|
||||
|
||||
foreign->foreign_table_name_lookup =
|
||||
static_cast<char*>(
|
||||
mem_heap_alloc(foreign->heap, len));
|
||||
}
|
||||
strcpy(foreign->foreign_table_name_lookup,
|
||||
foreign->foreign_table_name);
|
||||
|
@ -333,9 +374,13 @@ dict_mem_referenced_table_name_lookup_set(
|
|||
{
|
||||
if (innobase_get_lower_case_table_names() == 2) {
|
||||
if (do_alloc) {
|
||||
foreign->referenced_table_name_lookup = mem_heap_alloc(
|
||||
foreign->heap,
|
||||
strlen(foreign->referenced_table_name) + 1);
|
||||
ulint len;
|
||||
|
||||
len = strlen(foreign->referenced_table_name) + 1;
|
||||
|
||||
foreign->referenced_table_name_lookup =
|
||||
static_cast<char*>(
|
||||
mem_heap_alloc(foreign->heap, len));
|
||||
}
|
||||
strcpy(foreign->referenced_table_name_lookup,
|
||||
foreign->referenced_table_name);
|
||||
|
@ -345,6 +390,7 @@ dict_mem_referenced_table_name_lookup_set(
|
|||
= foreign->referenced_table_name;
|
||||
}
|
||||
}
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
/**********************************************************************//**
|
||||
Adds a field definition to an index. NOTE: does not take a copy
|
3181
storage/innobase/dict/dict0stats.cc
Normal file
3181
storage/innobase/dict/dict0stats.cc
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
|
||||
Copyright (c) 1996, 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
|
||||
|
@ -11,13 +11,13 @@ 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 program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file dyn/dyn0dyn.c
|
||||
@file dyn/dyn0dyn.cc
|
||||
The dynamically allocated array
|
||||
|
||||
Created 2/5/1996 Heikki Tuuri
|
||||
|
@ -55,7 +55,8 @@ dyn_array_add_block(
|
|||
|
||||
heap = arr->heap;
|
||||
|
||||
block = mem_heap_alloc(heap, sizeof(dyn_block_t));
|
||||
block = static_cast<dyn_block_t*>(
|
||||
mem_heap_alloc(heap, sizeof(dyn_block_t)));
|
||||
|
||||
block->used = 0;
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1997, 2009, Innobase Oy. All Rights Reserved.
|
||||
Copyright (c) 1997, 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
|
||||
|
@ -11,13 +11,13 @@ 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 program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file eval/eval0eval.c
|
||||
@file eval/eval0eval.cc
|
||||
SQL evaluator: evaluates simple data structures, like expressions, in
|
||||
a query graph
|
||||
|
||||
|
@ -32,6 +32,7 @@ Created 12/29/1997 Heikki Tuuri
|
|||
|
||||
#include "data0data.h"
|
||||
#include "row0sel.h"
|
||||
#include "rem0cmp.h"
|
||||
|
||||
/** The RND function seed */
|
||||
static ulint eval_rnd = 128367121;
|
||||
|
@ -41,6 +42,18 @@ eval_node_alloc_val_buf */
|
|||
|
||||
static byte eval_dummy;
|
||||
|
||||
/*************************************************************************
|
||||
Gets the like node from the node */
|
||||
UNIV_INLINE
|
||||
que_node_t*
|
||||
que_node_get_like_node(
|
||||
/*===================*/
|
||||
/* out: next node in a list of nodes */
|
||||
que_node_t* node) /* in: node in a list */
|
||||
{
|
||||
return(((sym_node_t*) node)->like_node);
|
||||
}
|
||||
|
||||
/*****************************************************************//**
|
||||
Allocate a buffer from global dynamic memory for a value of a que_node.
|
||||
NOTE that this memory must be explicitly freed when the query graph is
|
||||
|
@ -65,7 +78,7 @@ eval_node_alloc_val_buf(
|
|||
|
||||
dfield = que_node_get_val(node);
|
||||
|
||||
data = dfield_get_data(dfield);
|
||||
data = static_cast<byte*>(dfield_get_data(dfield));
|
||||
|
||||
if (data && data != &eval_dummy) {
|
||||
mem_free(data);
|
||||
|
@ -74,7 +87,7 @@ eval_node_alloc_val_buf(
|
|||
if (size == 0) {
|
||||
data = &eval_dummy;
|
||||
} else {
|
||||
data = mem_alloc(size);
|
||||
data = static_cast<byte*>(mem_alloc(size));
|
||||
}
|
||||
|
||||
que_node_set_val_buf_size(node, size);
|
||||
|
@ -102,7 +115,7 @@ eval_node_free_val_buf(
|
|||
|
||||
dfield = que_node_get_val(node);
|
||||
|
||||
data = dfield_get_data(dfield);
|
||||
data = static_cast<byte*>(dfield_get_data(dfield));
|
||||
|
||||
if (que_node_get_val_buf_size(node) > 0) {
|
||||
ut_a(data);
|
||||
|
@ -111,10 +124,80 @@ eval_node_free_val_buf(
|
|||
}
|
||||
}
|
||||
|
||||
/*****************************************************************//**
|
||||
/*********************************************************************
|
||||
Evaluates a LIKE comparison node.
|
||||
@return the result of the comparison */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
eval_cmp_like(
|
||||
/*==========*/
|
||||
que_node_t* arg1, /* !< in: left operand */
|
||||
que_node_t* arg2) /* !< in: right operand */
|
||||
{
|
||||
ib_like_t op;
|
||||
int res;
|
||||
que_node_t* arg3;
|
||||
que_node_t* arg4;
|
||||
dfield_t* dfield;
|
||||
dtype_t* dtype;
|
||||
ibool val = TRUE;
|
||||
|
||||
arg3 = que_node_get_like_node(arg2);
|
||||
|
||||
/* Get the comparison type operator */
|
||||
ut_a(arg3);
|
||||
|
||||
dfield = que_node_get_val(arg3);
|
||||
dtype = dfield_get_type(dfield);
|
||||
|
||||
ut_a(dtype_get_mtype(dtype) == DATA_INT);
|
||||
op = static_cast<ib_like_t>(mach_read_from_4(static_cast<const unsigned char*>(dfield_get_data(dfield))));
|
||||
|
||||
switch (op) {
|
||||
case IB_LIKE_PREFIX:
|
||||
|
||||
arg4 = que_node_get_next(arg3);
|
||||
res = cmp_dfield_dfield_like_prefix(
|
||||
que_node_get_val(arg1),
|
||||
que_node_get_val(arg4));
|
||||
break;
|
||||
|
||||
case IB_LIKE_SUFFIX:
|
||||
|
||||
arg4 = que_node_get_next(arg3);
|
||||
res = cmp_dfield_dfield_like_suffix(
|
||||
que_node_get_val(arg1),
|
||||
que_node_get_val(arg4));
|
||||
break;
|
||||
|
||||
case IB_LIKE_SUBSTR:
|
||||
|
||||
arg4 = que_node_get_next(arg3);
|
||||
res = cmp_dfield_dfield_like_substr(
|
||||
que_node_get_val(arg1),
|
||||
que_node_get_val(arg4));
|
||||
break;
|
||||
|
||||
case IB_LIKE_EXACT:
|
||||
res = cmp_dfield_dfield(
|
||||
que_node_get_val(arg1),
|
||||
que_node_get_val(arg2));
|
||||
break;
|
||||
|
||||
default:
|
||||
ut_error;
|
||||
}
|
||||
|
||||
if (res != 0) {
|
||||
val = FALSE;
|
||||
}
|
||||
|
||||
return(val);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
Evaluates a comparison node.
|
||||
@return the result of the comparison */
|
||||
UNIV_INTERN
|
||||
@return the result of the comparison */
|
||||
ibool
|
||||
eval_cmp(
|
||||
/*=====*/
|
||||
|
@ -123,45 +206,52 @@ eval_cmp(
|
|||
que_node_t* arg1;
|
||||
que_node_t* arg2;
|
||||
int res;
|
||||
ibool val;
|
||||
int func;
|
||||
ibool val = TRUE;
|
||||
|
||||
ut_ad(que_node_get_type(cmp_node) == QUE_NODE_FUNC);
|
||||
|
||||
arg1 = cmp_node->args;
|
||||
arg2 = que_node_get_next(arg1);
|
||||
|
||||
res = cmp_dfield_dfield(que_node_get_val(arg1),
|
||||
que_node_get_val(arg2));
|
||||
val = TRUE;
|
||||
|
||||
func = cmp_node->func;
|
||||
|
||||
if (func == '=') {
|
||||
if (res != 0) {
|
||||
val = FALSE;
|
||||
}
|
||||
} else if (func == '<') {
|
||||
if (res != -1) {
|
||||
val = FALSE;
|
||||
}
|
||||
} else if (func == PARS_LE_TOKEN) {
|
||||
if (res == 1) {
|
||||
val = FALSE;
|
||||
}
|
||||
} else if (func == PARS_NE_TOKEN) {
|
||||
if (res == 0) {
|
||||
val = FALSE;
|
||||
}
|
||||
} else if (func == PARS_GE_TOKEN) {
|
||||
if (res == -1) {
|
||||
val = FALSE;
|
||||
}
|
||||
} else {
|
||||
ut_ad(func == '>');
|
||||
if (func == PARS_LIKE_TOKEN_EXACT
|
||||
|| func == PARS_LIKE_TOKEN_PREFIX
|
||||
|| func == PARS_LIKE_TOKEN_SUFFIX
|
||||
|| func == PARS_LIKE_TOKEN_SUBSTR) {
|
||||
|
||||
if (res != 1) {
|
||||
val = FALSE;
|
||||
val = eval_cmp_like(arg1, arg2);
|
||||
} else {
|
||||
res = cmp_dfield_dfield(
|
||||
que_node_get_val(arg1), que_node_get_val(arg2));
|
||||
|
||||
if (func == '=') {
|
||||
if (res != 0) {
|
||||
val = FALSE;
|
||||
}
|
||||
} else if (func == '<') {
|
||||
if (res != -1) {
|
||||
val = FALSE;
|
||||
}
|
||||
} else if (func == PARS_LE_TOKEN) {
|
||||
if (res == 1) {
|
||||
val = FALSE;
|
||||
}
|
||||
} else if (func == PARS_NE_TOKEN) {
|
||||
if (res == 0) {
|
||||
val = FALSE;
|
||||
}
|
||||
} else if (func == PARS_GE_TOKEN) {
|
||||
if (res == -1) {
|
||||
val = FALSE;
|
||||
}
|
||||
} else {
|
||||
ut_ad(func == '>');
|
||||
|
||||
if (res != 1) {
|
||||
val = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -344,8 +434,8 @@ eval_predefined_2(
|
|||
|
||||
} else if (func == PARS_RND_TOKEN) {
|
||||
|
||||
len1 = (ulint)eval_node_get_int_val(arg1);
|
||||
len2 = (ulint)eval_node_get_int_val(arg2);
|
||||
len1 = (ulint) eval_node_get_int_val(arg1);
|
||||
len2 = (ulint) eval_node_get_int_val(arg2);
|
||||
|
||||
ut_ad(len2 >= len1);
|
||||
|
||||
|
@ -362,7 +452,7 @@ eval_predefined_2(
|
|||
|
||||
} else if (func == PARS_RND_STR_TOKEN) {
|
||||
|
||||
len1 = (ulint)eval_node_get_int_val(arg1);
|
||||
len1 = (ulint) eval_node_get_int_val(arg1);
|
||||
|
||||
data = eval_node_ensure_val_buf(func_node, len1);
|
||||
|
||||
|
@ -390,7 +480,7 @@ eval_notfound(
|
|||
|
||||
ut_ad(func_node->func == PARS_NOTFOUND_TOKEN);
|
||||
|
||||
cursor = func_node->args;
|
||||
cursor = static_cast<sym_node_t*>(func_node->args);
|
||||
|
||||
ut_ad(que_node_get_type(cursor) == QUE_NODE_SYMBOL);
|
||||
|
||||
|
@ -436,10 +526,10 @@ eval_substr(
|
|||
|
||||
arg3 = que_node_get_next(arg2);
|
||||
|
||||
str1 = dfield_get_data(que_node_get_val(arg1));
|
||||
str1 = static_cast<byte*>(dfield_get_data(que_node_get_val(arg1)));
|
||||
|
||||
len1 = (ulint)eval_node_get_int_val(arg2);
|
||||
len2 = (ulint)eval_node_get_int_val(arg3);
|
||||
len1 = (ulint) eval_node_get_int_val(arg2);
|
||||
len2 = (ulint) eval_node_get_int_val(arg3);
|
||||
|
||||
dfield = que_node_get_val(func_node);
|
||||
|
||||
|
@ -471,11 +561,11 @@ eval_replstr(
|
|||
arg3 = que_node_get_next(arg2);
|
||||
arg4 = que_node_get_next(arg3);
|
||||
|
||||
str1 = dfield_get_data(que_node_get_val(arg1));
|
||||
str2 = dfield_get_data(que_node_get_val(arg2));
|
||||
str1 = static_cast<byte*>(dfield_get_data(que_node_get_val(arg1)));
|
||||
str2 = static_cast<byte*>(dfield_get_data(que_node_get_val(arg2)));
|
||||
|
||||
len1 = (ulint)eval_node_get_int_val(arg3);
|
||||
len2 = (ulint)eval_node_get_int_val(arg4);
|
||||
len1 = (ulint) eval_node_get_int_val(arg3);
|
||||
len2 = (ulint) eval_node_get_int_val(arg4);
|
||||
|
||||
if ((dfield_get_len(que_node_get_val(arg1)) < len1 + len2)
|
||||
|| (dfield_get_len(que_node_get_val(arg2)) < len2)) {
|
||||
|
@ -513,8 +603,8 @@ eval_instr(
|
|||
dfield1 = que_node_get_val(arg1);
|
||||
dfield2 = que_node_get_val(arg2);
|
||||
|
||||
str1 = dfield_get_data(dfield1);
|
||||
str2 = dfield_get_data(dfield2);
|
||||
str1 = static_cast<byte*>(dfield_get_data(dfield1));
|
||||
str2 = static_cast<byte*>(dfield_get_data(dfield2));
|
||||
|
||||
len1 = dfield_get_len(dfield1);
|
||||
len2 = dfield_get_len(dfield2);
|
||||
|
@ -577,7 +667,7 @@ eval_binary_to_number(
|
|||
|
||||
dfield = que_node_get_val(arg1);
|
||||
|
||||
str1 = dfield_get_data(dfield);
|
||||
str1 = static_cast<byte*>(dfield_get_data(dfield));
|
||||
len1 = dfield_get_len(dfield);
|
||||
|
||||
if (len1 > 4) {
|
||||
|
@ -588,7 +678,7 @@ eval_binary_to_number(
|
|||
str2 = str1;
|
||||
} else {
|
||||
int_val = 0;
|
||||
str2 = (byte*)&int_val;
|
||||
str2 = (byte*) &int_val;
|
||||
|
||||
ut_memcpy(str2 + (4 - len1), str1, len1);
|
||||
}
|
||||
|
@ -659,7 +749,7 @@ eval_to_binary(
|
|||
|
||||
arg1 = func_node->args;
|
||||
|
||||
str1 = dfield_get_data(que_node_get_val(arg1));
|
||||
str1 = static_cast<byte*>(dfield_get_data(que_node_get_val(arg1)));
|
||||
|
||||
if (dtype_get_mtype(que_node_get_data_type(arg1)) != DATA_INT) {
|
||||
|
||||
|
@ -674,7 +764,7 @@ eval_to_binary(
|
|||
|
||||
arg2 = que_node_get_next(arg1);
|
||||
|
||||
len1 = (ulint)eval_node_get_int_val(arg2);
|
||||
len1 = (ulint) eval_node_get_int_val(arg2);
|
||||
|
||||
if (len1 > 4) {
|
||||
|
||||
|
@ -705,7 +795,7 @@ eval_predefined(
|
|||
|
||||
if (func == PARS_LENGTH_TOKEN) {
|
||||
|
||||
int_val = (lint)dfield_get_len(que_node_get_val(arg1));
|
||||
int_val = (lint) dfield_get_len(que_node_get_val(arg1));
|
||||
|
||||
} else if (func == PARS_TO_CHAR_TOKEN) {
|
||||
|
||||
|
@ -768,7 +858,7 @@ eval_predefined(
|
|||
dfield_get_data(que_node_get_val(arg1)));
|
||||
|
||||
} else if (func == PARS_SYSDATE_TOKEN) {
|
||||
int_val = (lint)ut_time();
|
||||
int_val = (lint) ut_time();
|
||||
} else {
|
||||
eval_predefined_2(func_node);
|
||||
|
||||
|
@ -787,12 +877,12 @@ eval_func(
|
|||
func_node_t* func_node) /*!< in: function node */
|
||||
{
|
||||
que_node_t* arg;
|
||||
ulint class;
|
||||
ulint fclass;
|
||||
ulint func;
|
||||
|
||||
ut_ad(que_node_get_type(func_node) == QUE_NODE_FUNC);
|
||||
|
||||
class = func_node->class;
|
||||
fclass = func_node->fclass;
|
||||
func = func_node->func;
|
||||
|
||||
arg = func_node->args;
|
||||
|
@ -805,7 +895,7 @@ eval_func(
|
|||
values, except for eval_cmp and notfound */
|
||||
|
||||
if (dfield_is_null(que_node_get_val(arg))
|
||||
&& (class != PARS_FUNC_CMP)
|
||||
&& (fclass != PARS_FUNC_CMP)
|
||||
&& (func != PARS_NOTFOUND_TOKEN)
|
||||
&& (func != PARS_PRINTF_TOKEN)) {
|
||||
ut_error;
|
||||
|
@ -814,34 +904,47 @@ eval_func(
|
|||
arg = que_node_get_next(arg);
|
||||
}
|
||||
|
||||
if (class == PARS_FUNC_CMP) {
|
||||
switch (fclass) {
|
||||
case PARS_FUNC_CMP:
|
||||
eval_cmp(func_node);
|
||||
} else if (class == PARS_FUNC_ARITH) {
|
||||
return;
|
||||
case PARS_FUNC_ARITH:
|
||||
eval_arith(func_node);
|
||||
} else if (class == PARS_FUNC_AGGREGATE) {
|
||||
return;
|
||||
case PARS_FUNC_AGGREGATE:
|
||||
eval_aggregate(func_node);
|
||||
} else if (class == PARS_FUNC_PREDEFINED) {
|
||||
|
||||
if (func == PARS_NOTFOUND_TOKEN) {
|
||||
return;
|
||||
case PARS_FUNC_PREDEFINED:
|
||||
switch (func) {
|
||||
case PARS_NOTFOUND_TOKEN:
|
||||
eval_notfound(func_node);
|
||||
} else if (func == PARS_SUBSTR_TOKEN) {
|
||||
return;
|
||||
case PARS_SUBSTR_TOKEN:
|
||||
eval_substr(func_node);
|
||||
} else if (func == PARS_REPLSTR_TOKEN) {
|
||||
return;
|
||||
case PARS_REPLSTR_TOKEN:
|
||||
eval_replstr(func_node);
|
||||
} else if (func == PARS_INSTR_TOKEN) {
|
||||
return;
|
||||
case PARS_INSTR_TOKEN:
|
||||
eval_instr(func_node);
|
||||
} else if (func == PARS_BINARY_TO_NUMBER_TOKEN) {
|
||||
return;
|
||||
case PARS_BINARY_TO_NUMBER_TOKEN:
|
||||
eval_binary_to_number(func_node);
|
||||
} else if (func == PARS_CONCAT_TOKEN) {
|
||||
return;
|
||||
case PARS_CONCAT_TOKEN:
|
||||
eval_concat(func_node);
|
||||
} else if (func == PARS_TO_BINARY_TOKEN) {
|
||||
return;
|
||||
case PARS_TO_BINARY_TOKEN:
|
||||
eval_to_binary(func_node);
|
||||
} else {
|
||||
return;
|
||||
default:
|
||||
eval_predefined(func_node);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
ut_ad(class == PARS_FUNC_LOGICAL);
|
||||
|
||||
case PARS_FUNC_LOGICAL:
|
||||
eval_logical(func_node);
|
||||
return;
|
||||
}
|
||||
|
||||
ut_error;
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1998, 2009, Innobase Oy. All Rights Reserved.
|
||||
Copyright (c) 1998, 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
|
||||
|
@ -11,13 +11,13 @@ 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 program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file eval/eval0proc.c
|
||||
@file eval/eval0proc.cc
|
||||
Executes SQL stored procedures and their control structures
|
||||
|
||||
Created 1/20/1998 Heikki Tuuri
|
||||
|
@ -43,7 +43,7 @@ if_step(
|
|||
|
||||
ut_ad(thr);
|
||||
|
||||
node = thr->run_node;
|
||||
node = static_cast<if_node_t*>(thr->run_node);
|
||||
ut_ad(que_node_get_type(node) == QUE_NODE_IF);
|
||||
|
||||
if (thr->prev_node == que_node_get_parent(node)) {
|
||||
|
@ -80,7 +80,8 @@ if_step(
|
|||
break;
|
||||
}
|
||||
|
||||
elsif_node = que_node_get_next(elsif_node);
|
||||
elsif_node = static_cast<elsif_node_t*>(
|
||||
que_node_get_next(elsif_node));
|
||||
|
||||
if (elsif_node == NULL) {
|
||||
thr->run_node = NULL;
|
||||
|
@ -118,7 +119,7 @@ while_step(
|
|||
|
||||
ut_ad(thr);
|
||||
|
||||
node = thr->run_node;
|
||||
node = static_cast<while_node_t*>(thr->run_node);
|
||||
ut_ad(que_node_get_type(node) == QUE_NODE_WHILE);
|
||||
|
||||
ut_ad((thr->prev_node == que_node_get_parent(node))
|
||||
|
@ -154,7 +155,7 @@ assign_step(
|
|||
|
||||
ut_ad(thr);
|
||||
|
||||
node = thr->run_node;
|
||||
node = static_cast<assign_node_t*>(thr->run_node);
|
||||
ut_ad(que_node_get_type(node) == QUE_NODE_ASSIGNMENT);
|
||||
|
||||
/* Evaluate the value to assign */
|
||||
|
@ -183,7 +184,7 @@ for_step(
|
|||
|
||||
ut_ad(thr);
|
||||
|
||||
node = thr->run_node;
|
||||
node = static_cast<for_node_t*>(thr->run_node);
|
||||
|
||||
ut_ad(que_node_get_type(node) == QUE_NODE_FOR);
|
||||
|
||||
|
@ -244,7 +245,7 @@ exit_step(
|
|||
|
||||
ut_ad(thr);
|
||||
|
||||
node = thr->run_node;
|
||||
node = static_cast<exit_node_t*>(thr->run_node);
|
||||
|
||||
ut_ad(que_node_get_type(node) == QUE_NODE_EXIT);
|
||||
|
||||
|
@ -276,7 +277,7 @@ return_step(
|
|||
|
||||
ut_ad(thr);
|
||||
|
||||
node = thr->run_node;
|
||||
node = static_cast<return_node_t*>(thr->run_node);
|
||||
|
||||
ut_ad(que_node_get_type(node) == QUE_NODE_RETURN);
|
||||
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
32
storage/innobase/fts/Makefile.query
Normal file
32
storage/innobase/fts/Makefile.query
Normal file
|
@ -0,0 +1,32 @@
|
|||
LEX=flex
|
||||
YACC=bison
|
||||
PREFIX=fts
|
||||
|
||||
all: fts0pars.cc fts0blex.cc fts0tlex.cc
|
||||
|
||||
fts0par.cc: fts0pars.y
|
||||
fts0blex.cc: fts0blex.l
|
||||
fts0tlex.cc: fts0tlex.l
|
||||
|
||||
.l.cc:
|
||||
$(LEX) -P$(subst lex,,$*) -o $*.cc --header-file=../include/$*.h $<
|
||||
|
||||
.y.cc:
|
||||
$(YACC) -p $(PREFIX) -o $*.cc -d $<
|
||||
mv $*.h ../include
|
||||
LEX=flex
|
||||
YACC=bison
|
||||
PREFIX=fts
|
||||
|
||||
all: fts0pars.cc fts0blex.cc fts0tlex.cc
|
||||
|
||||
fts0par.cc: fts0pars.y
|
||||
fts0blex.cc: fts0blex.l
|
||||
fts0tlex.cc: fts0tlex.l
|
||||
|
||||
.l.cc:
|
||||
$(LEX) -P$(subst lex,,$*) -o $*.cc --header-file=../include/$*.h $<
|
||||
|
||||
.y.cc:
|
||||
$(YACC) -p $(PREFIX) -o $*.cc -d $<
|
||||
mv $*.h ../include
|
416
storage/innobase/fts/fts0ast.cc
Normal file
416
storage/innobase/fts/fts0ast.cc
Normal file
|
@ -0,0 +1,416 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2007, 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 Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file fts/fts0ast.cc
|
||||
Full Text Search parser helper file.
|
||||
|
||||
Created 2007/3/16 Sunny Bains.
|
||||
***********************************************************************/
|
||||
|
||||
#include "mem0mem.h"
|
||||
#include "fts0ast.h"
|
||||
#include "fts0pars.h"
|
||||
|
||||
/******************************************************************//**
|
||||
Create an empty fts_ast_node_t.
|
||||
@return Create a new node */
|
||||
static
|
||||
fts_ast_node_t*
|
||||
fts_ast_node_create(void)
|
||||
/*=====================*/
|
||||
{
|
||||
fts_ast_node_t* node;
|
||||
|
||||
node = (fts_ast_node_t*) ut_malloc(sizeof(*node));
|
||||
memset(node, 0x0, sizeof(*node));
|
||||
|
||||
return(node);
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
Create a operator fts_ast_node_t.
|
||||
@return new node */
|
||||
UNIV_INTERN
|
||||
fts_ast_node_t*
|
||||
fts_ast_create_node_oper(
|
||||
/*=====================*/
|
||||
void* arg, /*!< in: ast state instance */
|
||||
fts_ast_oper_t oper) /*!< in: ast operator */
|
||||
{
|
||||
fts_ast_node_t* node = fts_ast_node_create();
|
||||
|
||||
node->type = FTS_AST_OPER;
|
||||
node->oper = oper;
|
||||
|
||||
fts_ast_state_add_node((fts_ast_state_t*) arg, node);
|
||||
|
||||
return(node);
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
This function takes ownership of the ptr and is responsible
|
||||
for free'ing it
|
||||
@return new node */
|
||||
UNIV_INTERN
|
||||
fts_ast_node_t*
|
||||
fts_ast_create_node_term(
|
||||
/*=====================*/
|
||||
void* arg, /*!< in: ast state instance */
|
||||
const char* ptr) /*!< in: ast term string */
|
||||
{
|
||||
ulint len = strlen(ptr);
|
||||
fts_ast_node_t* node = fts_ast_node_create();
|
||||
|
||||
node->type = FTS_AST_TERM;
|
||||
|
||||
node->term.ptr = static_cast<byte*>(ut_malloc(len + 1));
|
||||
memcpy(node->term.ptr, ptr, len + 1);
|
||||
|
||||
fts_ast_state_add_node((fts_ast_state_t*) arg, node);
|
||||
|
||||
return(node);
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
This function takes ownership of the ptr and is responsible
|
||||
for free'ing it.
|
||||
@return new node */
|
||||
UNIV_INTERN
|
||||
fts_ast_node_t*
|
||||
fts_ast_create_node_text(
|
||||
/*=====================*/
|
||||
void* arg, /*!< in: ast state instance */
|
||||
const char* ptr) /*!< in: ast text string */
|
||||
{
|
||||
/*!< We ignore the actual quotes "" */
|
||||
ulint len = strlen(ptr) - 2;
|
||||
fts_ast_node_t* node = fts_ast_node_create();
|
||||
|
||||
node->type = FTS_AST_TEXT;
|
||||
node->text.ptr = static_cast<byte*>(ut_malloc(len + 1));
|
||||
|
||||
/*!< Skip copying the first quote */
|
||||
memcpy(node->text.ptr, ptr + 1, len);
|
||||
node->text.ptr[len] = 0;
|
||||
node->text.distance = ULINT_UNDEFINED;
|
||||
|
||||
fts_ast_state_add_node((fts_ast_state_t*) arg, node);
|
||||
|
||||
return(node);
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
This function takes ownership of the expr and is responsible
|
||||
for free'ing it.
|
||||
@return new node */
|
||||
UNIV_INTERN
|
||||
fts_ast_node_t*
|
||||
fts_ast_create_node_list(
|
||||
/*=====================*/
|
||||
void* arg, /*!< in: ast state instance */
|
||||
fts_ast_node_t* expr) /*!< in: ast expr instance */
|
||||
{
|
||||
fts_ast_node_t* node = fts_ast_node_create();
|
||||
|
||||
node->type = FTS_AST_LIST;
|
||||
node->list.head = node->list.tail = expr;
|
||||
|
||||
fts_ast_state_add_node((fts_ast_state_t*) arg, node);
|
||||
|
||||
return(node);
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
Create a sub-expression list node. This function takes ownership of
|
||||
expr and is responsible for deleting it.
|
||||
@return new node */
|
||||
UNIV_INTERN
|
||||
fts_ast_node_t*
|
||||
fts_ast_create_node_subexp_list(
|
||||
/*============================*/
|
||||
void* arg, /*!< in: ast state instance */
|
||||
fts_ast_node_t* expr) /*!< in: ast expr instance */
|
||||
{
|
||||
fts_ast_node_t* node = fts_ast_node_create();
|
||||
|
||||
node->type = FTS_AST_SUBEXP_LIST;
|
||||
node->list.head = node->list.tail = expr;
|
||||
|
||||
fts_ast_state_add_node((fts_ast_state_t*) arg, node);
|
||||
|
||||
return(node);
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
Free an expr list node elements. */
|
||||
static
|
||||
void
|
||||
fts_ast_free_list(
|
||||
/*==============*/
|
||||
fts_ast_node_t* node) /*!< in: ast node to free */
|
||||
{
|
||||
ut_a(node->type == FTS_AST_LIST
|
||||
|| node->type == FTS_AST_SUBEXP_LIST);
|
||||
|
||||
for (node = node->list.head;
|
||||
node != NULL;
|
||||
node = fts_ast_free_node(node)) {
|
||||
|
||||
/*!< No op */
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************//**
|
||||
Free a fts_ast_node_t instance.
|
||||
@return next node to free */
|
||||
UNIV_INTERN
|
||||
fts_ast_node_t*
|
||||
fts_ast_free_node(
|
||||
/*==============*/
|
||||
fts_ast_node_t* node) /*!< in: the node to free */
|
||||
{
|
||||
fts_ast_node_t* next_node;
|
||||
|
||||
switch (node->type) {
|
||||
case FTS_AST_TEXT:
|
||||
if (node->text.ptr) {
|
||||
ut_free(node->text.ptr);
|
||||
node->text.ptr = NULL;
|
||||
}
|
||||
break;
|
||||
|
||||
case FTS_AST_TERM:
|
||||
if (node->term.ptr) {
|
||||
ut_free(node->term.ptr);
|
||||
node->term.ptr = NULL;
|
||||
}
|
||||
break;
|
||||
|
||||
case FTS_AST_LIST:
|
||||
case FTS_AST_SUBEXP_LIST:
|
||||
fts_ast_free_list(node);
|
||||
node->list.head = node->list.tail = NULL;
|
||||
break;
|
||||
|
||||
case FTS_AST_OPER:
|
||||
break;
|
||||
|
||||
default:
|
||||
ut_error;
|
||||
}
|
||||
|
||||
/*!< Get next node before freeing the node itself */
|
||||
next_node = node->next;
|
||||
|
||||
ut_free(node);
|
||||
|
||||
return(next_node);
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
This AST takes ownership of the expr and is responsible
|
||||
for free'ing it.
|
||||
@return in param "list" */
|
||||
UNIV_INTERN
|
||||
fts_ast_node_t*
|
||||
fts_ast_add_node(
|
||||
/*=============*/
|
||||
fts_ast_node_t* node, /*!< in: list instance */
|
||||
fts_ast_node_t* elem) /*!< in: node to add to list */
|
||||
{
|
||||
if (!elem) {
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
ut_a(!elem->next);
|
||||
ut_a(node->type == FTS_AST_LIST
|
||||
|| node->type == FTS_AST_SUBEXP_LIST);
|
||||
|
||||
if (!node->list.head) {
|
||||
ut_a(!node->list.tail);
|
||||
|
||||
node->list.head = node->list.tail = elem;
|
||||
} else {
|
||||
ut_a(node->list.tail);
|
||||
|
||||
node->list.tail->next = elem;
|
||||
node->list.tail = elem;
|
||||
}
|
||||
|
||||
return(node);
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
For tracking node allocations, in case there is an error during
|
||||
parsing. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
fts_ast_state_add_node(
|
||||
/*===================*/
|
||||
fts_ast_state_t*state, /*!< in: ast instance */
|
||||
fts_ast_node_t* node) /*!< in: node to add to ast */
|
||||
{
|
||||
if (!state->list.head) {
|
||||
ut_a(!state->list.tail);
|
||||
|
||||
state->list.head = state->list.tail = node;
|
||||
} else {
|
||||
state->list.tail->next_alloc = node;
|
||||
state->list.tail = node;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
Set the wildcard attribute of a term. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
fts_ast_term_set_wildcard(
|
||||
/*======================*/
|
||||
fts_ast_node_t* node) /*!< in/out: set attribute of
|
||||
a term node */
|
||||
{
|
||||
ut_a(node->type == FTS_AST_TERM);
|
||||
ut_a(!node->term.wildcard);
|
||||
|
||||
node->term.wildcard = TRUE;
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
Set the proximity attribute of a text node. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
fts_ast_term_set_distance(
|
||||
/*======================*/
|
||||
fts_ast_node_t* node, /*!< in/out: text node */
|
||||
ulint distance) /*!< in: the text proximity
|
||||
distance */
|
||||
{
|
||||
ut_a(node->type == FTS_AST_TEXT);
|
||||
ut_a(node->text.distance == ULINT_UNDEFINED);
|
||||
|
||||
node->text.distance = distance;
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
Free node and expr allocations. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
fts_ast_state_free(
|
||||
/*===============*/
|
||||
fts_ast_state_t*state) /*!< in: ast state to free */
|
||||
{
|
||||
fts_ast_node_t* node = state->list.head;
|
||||
|
||||
/* Free the nodes that were allocated during parsing. */
|
||||
while (node) {
|
||||
fts_ast_node_t* next = node->next_alloc;
|
||||
|
||||
if (node->type == FTS_AST_TEXT && node->text.ptr) {
|
||||
ut_free(node->text.ptr);
|
||||
node->text.ptr = NULL;
|
||||
} else if (node->type == FTS_AST_TERM && node->term.ptr) {
|
||||
ut_free(node->term.ptr);
|
||||
node->term.ptr = NULL;
|
||||
}
|
||||
|
||||
ut_free(node);
|
||||
node = next;
|
||||
}
|
||||
|
||||
state->root = state->list.head = state->list.tail = NULL;
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
Print an ast node. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
fts_ast_node_print(
|
||||
/*===============*/
|
||||
fts_ast_node_t* node) /*!< in: ast node to print */
|
||||
{
|
||||
switch (node->type) {
|
||||
case FTS_AST_TEXT:
|
||||
printf("TEXT: %s\n", node->text.ptr);
|
||||
break;
|
||||
|
||||
case FTS_AST_TERM:
|
||||
printf("TERM: %s\n", node->term.ptr);
|
||||
break;
|
||||
|
||||
case FTS_AST_LIST:
|
||||
printf("LIST: ");
|
||||
node = node->list.head;
|
||||
|
||||
while (node) {
|
||||
fts_ast_node_print(node);
|
||||
node = node->next;
|
||||
}
|
||||
break;
|
||||
|
||||
case FTS_AST_SUBEXP_LIST:
|
||||
printf("SUBEXP_LIST: ");
|
||||
node = node->list.head;
|
||||
|
||||
while (node) {
|
||||
fts_ast_node_print(node);
|
||||
node = node->next;
|
||||
}
|
||||
case FTS_AST_OPER:
|
||||
printf("OPER: %d\n", node->oper);
|
||||
break;
|
||||
|
||||
default:
|
||||
ut_error;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
Traverse the AST - in-order traversal.
|
||||
@return DB_SUCCESS if all went well */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
fts_ast_visit(
|
||||
/*==========*/
|
||||
fts_ast_oper_t oper, /*!< in: current operator */
|
||||
fts_ast_node_t* node, /*!< in: current root node */
|
||||
fts_ast_callback visitor, /*!< in: callback function */
|
||||
void* arg) /*!< in: arg for callback */
|
||||
{
|
||||
ulint error = DB_SUCCESS;
|
||||
|
||||
ut_a(node->type == FTS_AST_LIST
|
||||
|| node->type == FTS_AST_SUBEXP_LIST);
|
||||
|
||||
for (node = node->list.head;
|
||||
node && error == DB_SUCCESS;
|
||||
node = node->next) {
|
||||
|
||||
if (node->type == FTS_AST_LIST) {
|
||||
error = fts_ast_visit(oper, node, visitor, arg);
|
||||
} else if (node->type == FTS_AST_SUBEXP_LIST) {
|
||||
error = fts_ast_visit_sub_exp(node, visitor, arg);
|
||||
} else if (node->type == FTS_AST_OPER) {
|
||||
oper = node->oper;
|
||||
} else {
|
||||
visitor(oper, node, arg);
|
||||
}
|
||||
}
|
||||
|
||||
return(error);
|
||||
}
|
1955
storage/innobase/fts/fts0blex.cc
Normal file
1955
storage/innobase/fts/fts0blex.cc
Normal file
File diff suppressed because it is too large
Load diff
73
storage/innobase/fts/fts0blex.l
Normal file
73
storage/innobase/fts/fts0blex.l
Normal file
|
@ -0,0 +1,73 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2007, 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 Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file fts/fts0blex.l
|
||||
* FTS parser lexical analyzer
|
||||
*
|
||||
* Created 2007/5/9 Sunny Bains
|
||||
*/
|
||||
|
||||
%{
|
||||
|
||||
#include "fts0ast.h"
|
||||
#include "fts0pars.h"
|
||||
|
||||
/* Required for reentrant parser */
|
||||
#define YY_DECL int fts_blexer(YYSTYPE* val, yyscan_t yyscanner)
|
||||
|
||||
%}
|
||||
|
||||
%option noinput
|
||||
%option nounput
|
||||
%option noyywrap
|
||||
%option nostdinit
|
||||
%option reentrant
|
||||
%option never-interactive
|
||||
|
||||
%%
|
||||
|
||||
[\t ]+ /* Ignore whitespace */ ;
|
||||
|
||||
[*()+\-<>~@] {
|
||||
val->oper = fts0bget_text(yyscanner)[0];
|
||||
|
||||
return(val->oper);
|
||||
}
|
||||
|
||||
[0-9]+ {
|
||||
val->token = strdup(fts0bget_text(yyscanner));
|
||||
|
||||
return(FTS_NUMB);
|
||||
}
|
||||
|
||||
[^" \n*()+\-<>~@]* {
|
||||
val->token = strdup(fts0bget_text(yyscanner));
|
||||
|
||||
return(FTS_TERM);
|
||||
}
|
||||
|
||||
\"[^\"\n]*\" {
|
||||
val->token = strdup(fts0bget_text(yyscanner));
|
||||
|
||||
return(FTS_TEXT);
|
||||
}
|
||||
|
||||
\n
|
||||
|
||||
%%
|
562
storage/innobase/fts/fts0config.cc
Normal file
562
storage/innobase/fts/fts0config.cc
Normal file
|
@ -0,0 +1,562 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2007, 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 Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/******************************************************************//**
|
||||
@file fts/fts0config.cc
|
||||
Full Text Search configuration table.
|
||||
|
||||
Created 2007/5/9 Sunny Bains
|
||||
***********************************************************************/
|
||||
|
||||
#include "trx0roll.h"
|
||||
#include "row0sel.h"
|
||||
|
||||
#include "fts0priv.h"
|
||||
|
||||
#ifndef UNIV_NONINL
|
||||
#include "fts0types.ic"
|
||||
#include "fts0vlc.ic"
|
||||
#endif
|
||||
|
||||
/******************************************************************//**
|
||||
Callback function for fetching the config value.
|
||||
@return always returns TRUE */
|
||||
static
|
||||
ibool
|
||||
fts_config_fetch_value(
|
||||
/*===================*/
|
||||
void* row, /*!< in: sel_node_t* */
|
||||
void* user_arg) /*!< in: pointer to
|
||||
ib_vector_t */
|
||||
{
|
||||
sel_node_t* node = static_cast<sel_node_t*>(row);
|
||||
fts_string_t* value = static_cast<fts_string_t*>(user_arg);
|
||||
|
||||
dfield_t* dfield = que_node_get_val(node->select_list);
|
||||
dtype_t* type = dfield_get_type(dfield);
|
||||
ulint len = dfield_get_len(dfield);
|
||||
void* data = dfield_get_data(dfield);
|
||||
|
||||
ut_a(dtype_get_mtype(type) == DATA_VARCHAR);
|
||||
|
||||
if (len != UNIV_SQL_NULL) {
|
||||
ulint max_len = ut_min(value->f_len - 1, len);
|
||||
|
||||
memcpy(value->f_str, data, max_len);
|
||||
value->f_len = max_len;
|
||||
value->f_str[value->f_len] = '\0';
|
||||
}
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
Get value from the config table. The caller must ensure that enough
|
||||
space is allocated for value to hold the column contents.
|
||||
@return DB_SUCCESS or error code */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
fts_config_get_value(
|
||||
/*=================*/
|
||||
trx_t* trx, /*!< transaction */
|
||||
fts_table_t* fts_table, /*!< in: the indexed
|
||||
FTS table */
|
||||
const char* name, /*!< in: get config value for
|
||||
this parameter name */
|
||||
fts_string_t* value) /*!< out: value read from
|
||||
config table */
|
||||
{
|
||||
pars_info_t* info;
|
||||
que_t* graph;
|
||||
ulint error;
|
||||
ulint name_len = strlen(name);
|
||||
|
||||
info = pars_info_create();
|
||||
|
||||
*value->f_str = '\0';
|
||||
ut_a(value->f_len > 0);
|
||||
|
||||
pars_info_bind_function(info, "my_func", fts_config_fetch_value,
|
||||
value);
|
||||
|
||||
/* The len field of value must be set to the max bytes that
|
||||
it can hold. On a successful read, the len field will be set
|
||||
to the actual number of bytes copied to value. */
|
||||
pars_info_bind_varchar_literal(info, "name", (byte*) name, name_len);
|
||||
|
||||
fts_table->suffix = "CONFIG";
|
||||
|
||||
graph = fts_parse_sql(
|
||||
fts_table,
|
||||
info,
|
||||
"DECLARE FUNCTION my_func;\n"
|
||||
"DECLARE CURSOR c IS SELECT value FROM %s"
|
||||
" WHERE key = :name;\n"
|
||||
"BEGIN\n"
|
||||
""
|
||||
"OPEN c;\n"
|
||||
"WHILE 1 = 1 LOOP\n"
|
||||
" FETCH c INTO my_func();\n"
|
||||
" IF c % NOTFOUND THEN\n"
|
||||
" EXIT;\n"
|
||||
" END IF;\n"
|
||||
"END LOOP;\n"
|
||||
"CLOSE c;");
|
||||
|
||||
trx->op_info = "getting FTS config value";
|
||||
|
||||
error = fts_eval_sql(trx, graph);
|
||||
|
||||
mutex_enter(&dict_sys->mutex);
|
||||
que_graph_free(graph);
|
||||
mutex_exit(&dict_sys->mutex);
|
||||
|
||||
return(error);
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Create the config table name for retrieving index specific value.
|
||||
@return index config parameter name */
|
||||
UNIV_INTERN
|
||||
char*
|
||||
fts_config_create_index_param_name(
|
||||
/*===============================*/
|
||||
const char* param, /*!< in: base name of param */
|
||||
const dict_index_t* index) /*!< in: index for config */
|
||||
{
|
||||
ulint len;
|
||||
char* name;
|
||||
|
||||
/* The format of the config name is: name_<index_id>. */
|
||||
len = strlen(param);
|
||||
|
||||
/* Caller is responsible for deleting name. */
|
||||
name = static_cast<char*>(ut_malloc(
|
||||
len + FTS_AUX_MIN_TABLE_ID_LENGTH + 2));
|
||||
strcpy(name, param);
|
||||
name[len] = '_';
|
||||
|
||||
fts_write_object_id(index->id, name + len + 1);
|
||||
|
||||
return(name);
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
Get value specific to an FTS index from the config table. The caller
|
||||
must ensure that enough space is allocated for value to hold the
|
||||
column contents.
|
||||
@return DB_SUCCESS or error code */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
fts_config_get_index_value(
|
||||
/*=======================*/
|
||||
trx_t* trx, /*!< transaction */
|
||||
dict_index_t* index, /*!< in: index */
|
||||
const char* param, /*!< in: get config value for
|
||||
this parameter name */
|
||||
fts_string_t* value) /*!< out: value read from
|
||||
config table */
|
||||
{
|
||||
char* name;
|
||||
ulint error;
|
||||
fts_table_t fts_table;
|
||||
|
||||
FTS_INIT_FTS_TABLE(&fts_table, "CONFIG", FTS_COMMON_TABLE,
|
||||
index->table);
|
||||
|
||||
/* We are responsible for free'ing name. */
|
||||
name = fts_config_create_index_param_name(param, index);
|
||||
|
||||
error = fts_config_get_value(trx, &fts_table, name, value);
|
||||
|
||||
ut_free(name);
|
||||
|
||||
return(error);
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
Set the value in the config table for name.
|
||||
@return DB_SUCCESS or error code */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
fts_config_set_value(
|
||||
/*=================*/
|
||||
trx_t* trx, /*!< transaction */
|
||||
fts_table_t* fts_table, /*!< in: the indexed
|
||||
FTS table */
|
||||
const char* name, /*!< in: get config value for
|
||||
this parameter name */
|
||||
const fts_string_t*
|
||||
value) /*!< in: value to update */
|
||||
{
|
||||
pars_info_t* info;
|
||||
que_t* graph;
|
||||
ulint error;
|
||||
undo_no_t undo_no;
|
||||
undo_no_t n_rows_updated;
|
||||
ulint name_len = strlen(name);
|
||||
|
||||
info = pars_info_create();
|
||||
|
||||
pars_info_bind_varchar_literal(info, "name", (byte*) name, name_len);
|
||||
pars_info_bind_varchar_literal(info, "value",
|
||||
value->f_str, value->f_len);
|
||||
|
||||
fts_table->suffix = "CONFIG";
|
||||
|
||||
graph = fts_parse_sql(
|
||||
fts_table, info,
|
||||
"BEGIN UPDATE %s SET value = :value WHERE key = :name;");
|
||||
|
||||
trx->op_info = "setting FTS config value";
|
||||
|
||||
undo_no = trx->undo_no;
|
||||
|
||||
error = fts_eval_sql(trx, graph);
|
||||
|
||||
fts_que_graph_free_check_lock(fts_table, NULL, graph);
|
||||
|
||||
n_rows_updated = trx->undo_no - undo_no;
|
||||
|
||||
/* Check if we need to do an insert. */
|
||||
if (n_rows_updated == 0) {
|
||||
info = pars_info_create();
|
||||
|
||||
pars_info_bind_varchar_literal(
|
||||
info, "name", (byte*) name, name_len);
|
||||
|
||||
pars_info_bind_varchar_literal(
|
||||
info, "value", value->f_str, value->f_len);
|
||||
|
||||
graph = fts_parse_sql(
|
||||
fts_table, info,
|
||||
"BEGIN\n"
|
||||
"INSERT INTO %s VALUES(:name, :value);");
|
||||
|
||||
trx->op_info = "inserting FTS config value";
|
||||
|
||||
error = fts_eval_sql(trx, graph);
|
||||
|
||||
fts_que_graph_free_check_lock(fts_table, NULL, graph);
|
||||
}
|
||||
|
||||
return(error);
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
Set the value specific to an FTS index in the config table.
|
||||
@return DB_SUCCESS or error code */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
fts_config_set_index_value(
|
||||
/*=======================*/
|
||||
trx_t* trx, /*!< transaction */
|
||||
dict_index_t* index, /*!< in: index */
|
||||
const char* param, /*!< in: get config value for
|
||||
this parameter name */
|
||||
fts_string_t* value) /*!< out: value read from
|
||||
config table */
|
||||
{
|
||||
char* name;
|
||||
ulint error;
|
||||
fts_table_t fts_table;
|
||||
|
||||
FTS_INIT_FTS_TABLE(&fts_table, "CONFIG", FTS_COMMON_TABLE,
|
||||
index->table);
|
||||
|
||||
/* We are responsible for free'ing name. */
|
||||
name = fts_config_create_index_param_name(param, index);
|
||||
|
||||
error = fts_config_set_value(trx, &fts_table, name, value);
|
||||
|
||||
ut_free(name);
|
||||
|
||||
return(error);
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
Get an ulint value from the config table.
|
||||
@return DB_SUCCESS if all OK else error code */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
fts_config_get_index_ulint(
|
||||
/*=======================*/
|
||||
trx_t* trx, /*!< in: transaction */
|
||||
dict_index_t* index, /*!< in: FTS index */
|
||||
const char* name, /*!< in: param name */
|
||||
ulint* int_value) /*!< out: value */
|
||||
{
|
||||
ulint error;
|
||||
fts_string_t value;
|
||||
|
||||
/* We set the length of value to the max bytes it can hold. This
|
||||
information is used by the callback that reads the value.*/
|
||||
value.f_len = FTS_MAX_CONFIG_VALUE_LEN;
|
||||
value.f_str = static_cast<byte*>(ut_malloc(value.f_len + 1));
|
||||
|
||||
error = fts_config_get_index_value(trx, index, name, &value);
|
||||
|
||||
if (UNIV_UNLIKELY(error != DB_SUCCESS)) {
|
||||
ut_print_timestamp(stderr);
|
||||
|
||||
fprintf(stderr, " InnoDB: Error: (%lu) reading `%s'\n",
|
||||
error, name);
|
||||
} else {
|
||||
*int_value = strtoul((char*) value.f_str, NULL, 10);
|
||||
}
|
||||
|
||||
ut_free(value.f_str);
|
||||
|
||||
return(error);
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
Set an ulint value in the config table.
|
||||
@return DB_SUCCESS if all OK else error code */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
fts_config_set_index_ulint(
|
||||
/*=======================*/
|
||||
trx_t* trx, /*!< in: transaction */
|
||||
dict_index_t* index, /*!< in: FTS index */
|
||||
const char* name, /*!< in: param name */
|
||||
ulint int_value) /*!< in: value */
|
||||
{
|
||||
ulint error;
|
||||
fts_string_t value;
|
||||
|
||||
/* We set the length of value to the max bytes it can hold. This
|
||||
information is used by the callback that reads the value.*/
|
||||
value.f_len = FTS_MAX_CONFIG_VALUE_LEN;
|
||||
value.f_str = static_cast<byte*>(ut_malloc(value.f_len + 1));
|
||||
|
||||
// FIXME: Get rid of snprintf
|
||||
ut_a(FTS_MAX_INT_LEN < FTS_MAX_CONFIG_VALUE_LEN);
|
||||
|
||||
value.f_len = ut_snprintf(
|
||||
(char*) value.f_str, FTS_MAX_INT_LEN, "%lu", int_value);
|
||||
|
||||
error = fts_config_set_index_value(trx, index, name, &value);
|
||||
|
||||
if (UNIV_UNLIKELY(error != DB_SUCCESS)) {
|
||||
ut_print_timestamp(stderr);
|
||||
|
||||
fprintf(stderr, " InnoDB: Error: (%lu) writing `%s'\n",
|
||||
error, name);
|
||||
}
|
||||
|
||||
ut_free(value.f_str);
|
||||
|
||||
return(error);
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
Get an ulint value from the config table.
|
||||
@return DB_SUCCESS if all OK else error code */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
fts_config_get_ulint(
|
||||
/*=================*/
|
||||
trx_t* trx, /*!< in: transaction */
|
||||
fts_table_t* fts_table, /*!< in: the indexed
|
||||
FTS table */
|
||||
const char* name, /*!< in: param name */
|
||||
ulint* int_value) /*!< out: value */
|
||||
{
|
||||
ulint error;
|
||||
fts_string_t value;
|
||||
|
||||
/* We set the length of value to the max bytes it can hold. This
|
||||
information is used by the callback that reads the value.*/
|
||||
value.f_len = FTS_MAX_CONFIG_VALUE_LEN;
|
||||
value.f_str = static_cast<byte*>(ut_malloc(value.f_len + 1));
|
||||
|
||||
error = fts_config_get_value(trx, fts_table, name, &value);
|
||||
|
||||
if (UNIV_UNLIKELY(error != DB_SUCCESS)) {
|
||||
ut_print_timestamp(stderr);
|
||||
|
||||
fprintf(stderr, " InnoDB: Error: (%lu) reading `%s'\n",
|
||||
error, name);
|
||||
} else {
|
||||
*int_value = strtoul((char*) value.f_str, NULL, 10);
|
||||
}
|
||||
|
||||
ut_free(value.f_str);
|
||||
|
||||
return(error);
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
Set an ulint value in the config table.
|
||||
@return DB_SUCCESS if all OK else error code */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
fts_config_set_ulint(
|
||||
/*=================*/
|
||||
trx_t* trx, /*!< in: transaction */
|
||||
fts_table_t* fts_table, /*!< in: the indexed
|
||||
FTS table */
|
||||
const char* name, /*!< in: param name */
|
||||
ulint int_value) /*!< in: value */
|
||||
{
|
||||
ulint error;
|
||||
fts_string_t value;
|
||||
|
||||
/* We set the length of value to the max bytes it can hold. This
|
||||
information is used by the callback that reads the value.*/
|
||||
value.f_len = FTS_MAX_CONFIG_VALUE_LEN;
|
||||
value.f_str = static_cast<byte*>(ut_malloc(value.f_len + 1));
|
||||
|
||||
// FIXME: Get rid of snprintf
|
||||
ut_a(FTS_MAX_INT_LEN < FTS_MAX_CONFIG_VALUE_LEN);
|
||||
|
||||
value.f_len = snprintf(
|
||||
(char*) value.f_str, FTS_MAX_INT_LEN, "%lu", int_value);
|
||||
|
||||
error = fts_config_set_value(trx, fts_table, name, &value);
|
||||
|
||||
if (UNIV_UNLIKELY(error != DB_SUCCESS)) {
|
||||
ut_print_timestamp(stderr);
|
||||
|
||||
fprintf(stderr, " InnoDB: Error: (%lu) writing `%s'\n",
|
||||
error, name);
|
||||
}
|
||||
|
||||
ut_free(value.f_str);
|
||||
|
||||
return(error);
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
Increment the value in the config table for column name.
|
||||
@return DB_SUCCESS or error code */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
fts_config_increment_value(
|
||||
/*=======================*/
|
||||
trx_t* trx, /*!< transaction */
|
||||
fts_table_t* fts_table, /*!< in: the indexed
|
||||
FTS table */
|
||||
const char* name, /*!< in: increment config value
|
||||
for this parameter name */
|
||||
ulint delta) /*!< in: increment by this
|
||||
much */
|
||||
{
|
||||
ulint error;
|
||||
fts_string_t value;
|
||||
que_t* graph = NULL;
|
||||
ulint name_len = strlen(name);
|
||||
pars_info_t* info = pars_info_create();
|
||||
|
||||
/* We set the length of value to the max bytes it can hold. This
|
||||
information is used by the callback that reads the value.*/
|
||||
value.f_len = FTS_MAX_CONFIG_VALUE_LEN;
|
||||
value.f_str = static_cast<byte*>(ut_malloc(value.f_len + 1));
|
||||
|
||||
*value.f_str = '\0';
|
||||
|
||||
pars_info_bind_varchar_literal(info, "name", (byte*) name, name_len);
|
||||
|
||||
pars_info_bind_function(
|
||||
info, "my_func", fts_config_fetch_value, &value);
|
||||
|
||||
fts_table->suffix = "CONFIG";
|
||||
|
||||
graph = fts_parse_sql(
|
||||
fts_table, info,
|
||||
"DECLARE FUNCTION my_func;\n"
|
||||
"DECLARE CURSOR c IS SELECT value FROM %s"
|
||||
" WHERE key = :name FOR UPDATE;\n"
|
||||
"BEGIN\n"
|
||||
""
|
||||
"OPEN c;\n"
|
||||
"WHILE 1 = 1 LOOP\n"
|
||||
" FETCH c INTO my_func();\n"
|
||||
" IF c % NOTFOUND THEN\n"
|
||||
" EXIT;\n"
|
||||
" END IF;\n"
|
||||
"END LOOP;\n"
|
||||
"CLOSE c;");
|
||||
|
||||
trx->op_info = "read FTS config value";
|
||||
|
||||
error = fts_eval_sql(trx, graph);
|
||||
|
||||
fts_que_graph_free_check_lock(fts_table, NULL, graph);
|
||||
|
||||
if (UNIV_UNLIKELY(error == DB_SUCCESS)) {
|
||||
ulint int_value;
|
||||
|
||||
int_value = strtoul((char*) value.f_str, NULL, 10);
|
||||
|
||||
int_value += delta;
|
||||
|
||||
ut_a(FTS_MAX_CONFIG_VALUE_LEN > FTS_MAX_INT_LEN);
|
||||
|
||||
// FIXME: Get rid of snprintf
|
||||
value.f_len = snprintf(
|
||||
(char*) value.f_str, FTS_MAX_INT_LEN, "%lu", int_value);
|
||||
|
||||
fts_config_set_value(trx, fts_table, name, &value);
|
||||
}
|
||||
|
||||
if (UNIV_UNLIKELY(error != DB_SUCCESS)) {
|
||||
|
||||
ut_print_timestamp(stderr);
|
||||
|
||||
fprintf(stderr, " InnoDB: Error: (%lu) "
|
||||
"while incrementing %s.\n", error, name);
|
||||
}
|
||||
|
||||
ut_free(value.f_str);
|
||||
|
||||
return(error);
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
Increment the per index value in the config table for column name.
|
||||
@return DB_SUCCESS or error code */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
fts_config_increment_index_value(
|
||||
/*=============================*/
|
||||
trx_t* trx, /*!< transaction */
|
||||
dict_index_t* index, /*!< in: FTS index */
|
||||
const char* param, /*!< in: increment config value
|
||||
for this parameter name */
|
||||
ulint delta) /*!< in: increment by this
|
||||
much */
|
||||
{
|
||||
char* name;
|
||||
ulint error;
|
||||
fts_table_t fts_table;
|
||||
|
||||
FTS_INIT_FTS_TABLE(&fts_table, "CONFIG", FTS_COMMON_TABLE,
|
||||
index->table);
|
||||
|
||||
/* We are responsible for free'ing name. */
|
||||
name = fts_config_create_index_param_name(param, index);
|
||||
|
||||
error = fts_config_increment_value(trx, &fts_table, name, delta);
|
||||
|
||||
ut_free(name);
|
||||
|
||||
return(error);
|
||||
}
|
||||
|
6287
storage/innobase/fts/fts0fts.cc
Normal file
6287
storage/innobase/fts/fts0fts.cc
Normal file
File diff suppressed because it is too large
Load diff
3109
storage/innobase/fts/fts0opt.cc
Normal file
3109
storage/innobase/fts/fts0opt.cc
Normal file
File diff suppressed because it is too large
Load diff
1912
storage/innobase/fts/fts0pars.cc
Normal file
1912
storage/innobase/fts/fts0pars.cc
Normal file
File diff suppressed because it is too large
Load diff
285
storage/innobase/fts/fts0pars.y
Normal file
285
storage/innobase/fts/fts0pars.y
Normal file
|
@ -0,0 +1,285 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2007, 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 Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file fts/fts0pars.y
|
||||
* FTS parser: input file for the GNU Bison parser generator
|
||||
*
|
||||
* Created 2007/5/9 Sunny Bains
|
||||
*/
|
||||
|
||||
%{
|
||||
|
||||
#include "mem0mem.h"
|
||||
#include "fts0ast.h"
|
||||
#include "fts0blex.h"
|
||||
#include "fts0tlex.h"
|
||||
#include "fts0pars.h"
|
||||
|
||||
extern int fts_lexer(YYSTYPE*, fts_lexer_t*);
|
||||
extern int fts_blexer(YYSTYPE*, yyscan_t);
|
||||
extern int fts_tlexer(YYSTYPE*, yyscan_t);
|
||||
|
||||
typedef int (*fts_scan)();
|
||||
|
||||
extern int ftserror(const char* p);
|
||||
|
||||
/* Required for reentrant parser */
|
||||
#define ftslex fts_lexer
|
||||
|
||||
#define YYERROR_VERBOSE
|
||||
|
||||
/* For passing an argument to yyparse() */
|
||||
#define YYPARSE_PARAM state
|
||||
#define YYLEX_PARAM ((fts_ast_state_t*) state)->lexer
|
||||
|
||||
typedef int (*fts_scanner_alt)(YYSTYPE* val, yyscan_t yyscanner);
|
||||
typedef int (*fts_scanner)();
|
||||
|
||||
struct fts_lexer_struct {
|
||||
fts_scanner scanner;
|
||||
void* yyscanner;
|
||||
};
|
||||
|
||||
%}
|
||||
|
||||
%union {
|
||||
int oper;
|
||||
char* token;
|
||||
fts_ast_node_t* node;
|
||||
};
|
||||
|
||||
/* Enable re-entrant parser */
|
||||
%pure_parser
|
||||
|
||||
%token<oper> FTS_OPER
|
||||
%token<token> FTS_TEXT FTS_TERM FTS_NUMB
|
||||
|
||||
%type<node> prefix term text expr sub_expr expr_lst query
|
||||
|
||||
%nonassoc '+' '-' '~' '<' '>'
|
||||
|
||||
%%
|
||||
|
||||
query : expr_lst {
|
||||
$$ = $1;
|
||||
((fts_ast_state_t*) state)->root = $$;
|
||||
}
|
||||
;
|
||||
|
||||
expr_lst: /* Empty */ {
|
||||
$$ = NULL;
|
||||
}
|
||||
|
||||
| expr_lst expr {
|
||||
$$ = $1;
|
||||
|
||||
if (!$$) {
|
||||
$$ = fts_ast_create_node_list(state, $2);
|
||||
} else {
|
||||
fts_ast_add_node($$, $2);
|
||||
}
|
||||
}
|
||||
|
||||
| expr_lst sub_expr {
|
||||
$$ = $1;
|
||||
$$ = fts_ast_create_node_list(state, $1);
|
||||
|
||||
if (!$$) {
|
||||
$$ = fts_ast_create_node_subexp_list(state, $2);
|
||||
} else {
|
||||
fts_ast_add_node($$, $2);
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
sub_expr: '(' expr_lst ')' {
|
||||
$$ = $2;
|
||||
}
|
||||
|
||||
| prefix '(' expr_lst ')' {
|
||||
$$ = fts_ast_create_node_subexp_list(state, $1);
|
||||
|
||||
if ($3) {
|
||||
fts_ast_add_node($$, $3);
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
expr : term {
|
||||
$$ = $1;
|
||||
}
|
||||
|
||||
| text {
|
||||
$$ = $1;
|
||||
}
|
||||
|
||||
| term '*' {
|
||||
fts_ast_term_set_wildcard($1);
|
||||
}
|
||||
|
||||
| text '@' FTS_NUMB {
|
||||
fts_ast_term_set_distance($1, strtoul($3, NULL, 10));
|
||||
free($3);
|
||||
}
|
||||
|
||||
| prefix term '*' {
|
||||
$$ = fts_ast_create_node_list(state, $1);
|
||||
fts_ast_add_node($$, $2);
|
||||
fts_ast_term_set_wildcard($2);
|
||||
}
|
||||
|
||||
| prefix term {
|
||||
$$ = fts_ast_create_node_list(state, $1);
|
||||
fts_ast_add_node($$, $2);
|
||||
}
|
||||
|
||||
| prefix text '@' FTS_NUMB {
|
||||
$$ = fts_ast_create_node_list(state, $1);
|
||||
fts_ast_add_node($$, $2);
|
||||
fts_ast_term_set_distance($2, strtoul($4, NULL, 10));
|
||||
free($4);
|
||||
}
|
||||
|
||||
| prefix text {
|
||||
$$ = fts_ast_create_node_list(state, $1);
|
||||
fts_ast_add_node($$, $2);
|
||||
}
|
||||
;
|
||||
|
||||
prefix : '-' {
|
||||
$$ = fts_ast_create_node_oper(state, FTS_IGNORE);
|
||||
}
|
||||
|
||||
| '+' {
|
||||
$$ = fts_ast_create_node_oper(state, FTS_EXIST);
|
||||
}
|
||||
|
||||
| '~' {
|
||||
$$ = fts_ast_create_node_oper(state, FTS_NEGATE);
|
||||
}
|
||||
|
||||
| '<' {
|
||||
$$ = fts_ast_create_node_oper(state, FTS_DECR_RATING);
|
||||
}
|
||||
|
||||
| '>' {
|
||||
$$ = fts_ast_create_node_oper(state, FTS_INCR_RATING);
|
||||
}
|
||||
;
|
||||
|
||||
term : FTS_TERM {
|
||||
$$ = fts_ast_create_node_term(state, $1);
|
||||
free($1);
|
||||
}
|
||||
|
||||
| FTS_NUMB {
|
||||
$$ = fts_ast_create_node_term(state, $1);
|
||||
free($1);
|
||||
}
|
||||
|
||||
;
|
||||
|
||||
text : FTS_TEXT {
|
||||
$$ = fts_ast_create_node_text(state, $1);
|
||||
free($1);
|
||||
}
|
||||
;
|
||||
%%
|
||||
|
||||
/********************************************************************
|
||||
*/
|
||||
int
|
||||
ftserror(
|
||||
/*=====*/
|
||||
const char* p)
|
||||
{
|
||||
fprintf(stderr, "%s\n", p);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
Create a fts_lexer_t instance.*/
|
||||
|
||||
fts_lexer_t*
|
||||
fts_lexer_create(
|
||||
/*=============*/
|
||||
ibool boolean_mode,
|
||||
const byte* query,
|
||||
ulint query_len)
|
||||
{
|
||||
fts_lexer_t* fts_lexer = static_cast<fts_lexer_t*>(
|
||||
ut_malloc(sizeof(fts_lexer_t)));
|
||||
|
||||
if (boolean_mode) {
|
||||
fts0blex_init(&fts_lexer->yyscanner);
|
||||
fts0b_scan_bytes((char*) query, query_len, fts_lexer->yyscanner);
|
||||
fts_lexer->scanner = (fts_scan) fts_blexer;
|
||||
/* FIXME: Debugging */
|
||||
/* fts0bset_debug(1 , fts_lexer->yyscanner); */
|
||||
} else {
|
||||
fts0tlex_init(&fts_lexer->yyscanner);
|
||||
fts0t_scan_bytes((char*) query, query_len, fts_lexer->yyscanner);
|
||||
fts_lexer->scanner = (fts_scan) fts_tlexer;
|
||||
}
|
||||
|
||||
return(fts_lexer);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
Free an fts_lexer_t instance.*/
|
||||
void
|
||||
|
||||
fts_lexer_free(
|
||||
/*===========*/
|
||||
fts_lexer_t* fts_lexer)
|
||||
{
|
||||
if (fts_lexer->scanner == (fts_scan) fts_blexer) {
|
||||
fts0blex_destroy(fts_lexer->yyscanner);
|
||||
} else {
|
||||
fts0tlex_destroy(fts_lexer->yyscanner);
|
||||
}
|
||||
|
||||
ut_free(fts_lexer);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
Call the appropaiate scanner.*/
|
||||
|
||||
int
|
||||
fts_lexer(
|
||||
/*======*/
|
||||
YYSTYPE* val,
|
||||
fts_lexer_t* fts_lexer)
|
||||
{
|
||||
fts_scanner_alt func_ptr;
|
||||
|
||||
func_ptr = (fts_scanner_alt) fts_lexer->scanner;
|
||||
|
||||
return(func_ptr(val, fts_lexer->yyscanner));
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
Parse the query.*/
|
||||
int
|
||||
fts_parse(
|
||||
/*======*/
|
||||
fts_ast_state_t* state)
|
||||
{
|
||||
return(ftsparse(state));
|
||||
}
|
3760
storage/innobase/fts/fts0que.cc
Normal file
3760
storage/innobase/fts/fts0que.cc
Normal file
File diff suppressed because it is too large
Load diff
355
storage/innobase/fts/fts0sql.cc
Normal file
355
storage/innobase/fts/fts0sql.cc
Normal file
|
@ -0,0 +1,355 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2007, 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 Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file fts/fts0sql.cc
|
||||
Full Text Search functionality.
|
||||
|
||||
Created 2007-03-27 Sunny Bains
|
||||
*******************************************************/
|
||||
|
||||
#include "que0que.h"
|
||||
#include "trx0roll.h"
|
||||
#include "pars0pars.h"
|
||||
#include "dict0dict.h"
|
||||
#include "fts0types.h"
|
||||
#include "fts0priv.h"
|
||||
|
||||
#ifndef UNIV_NONINL
|
||||
#include "fts0types.ic"
|
||||
#include "fts0vlc.ic"
|
||||
#endif
|
||||
|
||||
/** SQL statements for creating the ancillary FTS tables. %s must be replaced
|
||||
with the indexed table's id. */
|
||||
|
||||
/** Preamble to all SQL statements. */
|
||||
static const char* fts_sql_begin=
|
||||
"PROCEDURE P() IS\n";
|
||||
|
||||
/** Postamble to non-committing SQL statements. */
|
||||
static const char* fts_sql_end=
|
||||
"\n"
|
||||
"END;\n";
|
||||
|
||||
/******************************************************************//**
|
||||
Get the table id.
|
||||
@return number of bytes written */
|
||||
UNIV_INTERN
|
||||
int
|
||||
fts_get_table_id(
|
||||
/*=============*/
|
||||
const fts_table_t*
|
||||
fts_table, /*!< in: FTS Auxiliary table */
|
||||
char* table_id) /*!< out: table id, must be at least
|
||||
FTS_AUX_MIN_TABLE_ID_LENGTH bytes
|
||||
long */
|
||||
{
|
||||
int len;
|
||||
|
||||
switch (fts_table->type) {
|
||||
case FTS_COMMON_TABLE:
|
||||
len = fts_write_object_id(fts_table->table_id, table_id);
|
||||
break;
|
||||
|
||||
case FTS_INDEX_TABLE:
|
||||
|
||||
len = fts_write_object_id(fts_table->table_id, table_id);
|
||||
|
||||
table_id[len] = '_';
|
||||
++len;
|
||||
table_id += len;
|
||||
|
||||
len += fts_write_object_id(fts_table->index_id, table_id);
|
||||
break;
|
||||
|
||||
default:
|
||||
ut_error;
|
||||
}
|
||||
|
||||
ut_a(len >= 16);
|
||||
ut_a(len < FTS_AUX_MIN_TABLE_ID_LENGTH);
|
||||
|
||||
return(len);
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
Construct the prefix name of an FTS table.
|
||||
@return own: table name, must be freed with mem_free() */
|
||||
UNIV_INTERN
|
||||
char*
|
||||
fts_get_table_name_prefix(
|
||||
/*======================*/
|
||||
const fts_table_t*
|
||||
fts_table) /*!< in: Auxiliary table type */
|
||||
{
|
||||
int len;
|
||||
const char* slash;
|
||||
char* prefix_name;
|
||||
int dbname_len = 0;
|
||||
int prefix_name_len;
|
||||
char table_id[FTS_AUX_MIN_TABLE_ID_LENGTH];
|
||||
|
||||
slash = static_cast<const char*>(
|
||||
memchr(fts_table->parent, '/', strlen(fts_table->parent)));
|
||||
|
||||
if (slash) {
|
||||
/* Print up to and including the separator. */
|
||||
dbname_len = (slash - fts_table->parent) + 1;
|
||||
}
|
||||
|
||||
len = fts_get_table_id(fts_table, table_id);
|
||||
|
||||
prefix_name_len = dbname_len + 4 + len + 1;
|
||||
|
||||
prefix_name = static_cast<char*>(mem_alloc(prefix_name_len));
|
||||
|
||||
len = sprintf(prefix_name, "%.*sFTS_%s",
|
||||
dbname_len, fts_table->parent, table_id);
|
||||
|
||||
ut_a(len > 0);
|
||||
ut_a(len == prefix_name_len - 1);
|
||||
|
||||
return(prefix_name);
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
Construct the name of an ancillary FTS table.
|
||||
@return own: table name, must be freed with mem_free() */
|
||||
UNIV_INTERN
|
||||
char*
|
||||
fts_get_table_name(
|
||||
/*===============*/
|
||||
const fts_table_t* fts_table)
|
||||
/*!< in: Auxiliary table type */
|
||||
{
|
||||
int len;
|
||||
char* name;
|
||||
int name_len;
|
||||
char* prefix_name;
|
||||
|
||||
prefix_name = fts_get_table_name_prefix(fts_table);
|
||||
|
||||
name_len = strlen(prefix_name) + 1 + strlen(fts_table->suffix) + 1;
|
||||
|
||||
name = static_cast<char*>(mem_alloc(name_len));
|
||||
|
||||
len = sprintf(name, "%s_%s", prefix_name, fts_table->suffix);
|
||||
|
||||
ut_a(len > 0);
|
||||
ut_a(len == name_len - 1);
|
||||
|
||||
mem_free(prefix_name);
|
||||
|
||||
return(name);
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
Parse an SQL string. %s is replaced with the table's id.
|
||||
@return query graph */
|
||||
UNIV_INTERN
|
||||
que_t*
|
||||
fts_parse_sql(
|
||||
/*==========*/
|
||||
fts_table_t* fts_table, /*!< in: FTS auxiliarry table info */
|
||||
pars_info_t* info, /*!< in: info struct, or NULL */
|
||||
const char* sql) /*!< in: SQL string to evaluate */
|
||||
{
|
||||
char* str;
|
||||
que_t* graph;
|
||||
char* str_tmp;
|
||||
ibool dict_locked;
|
||||
|
||||
if (fts_table != NULL) {
|
||||
char* table_name;
|
||||
|
||||
table_name = fts_get_table_name(fts_table);
|
||||
str_tmp = ut_strreplace(sql, "%s", table_name);
|
||||
mem_free(table_name);
|
||||
} else {
|
||||
ulint sql_len = strlen(sql) + 1;
|
||||
|
||||
str_tmp = static_cast<char*>(mem_alloc(sql_len));
|
||||
strcpy(str_tmp, sql);
|
||||
}
|
||||
|
||||
str = ut_str3cat(fts_sql_begin, str_tmp, fts_sql_end);
|
||||
mem_free(str_tmp);
|
||||
|
||||
dict_locked = (fts_table && fts_table->table
|
||||
&& (fts_table->table->fts->fts_status
|
||||
& TABLE_DICT_LOCKED));
|
||||
|
||||
if (!dict_locked) {
|
||||
ut_ad(!mutex_own(&(dict_sys->mutex)));
|
||||
|
||||
/* The InnoDB SQL parser is not re-entrant. */
|
||||
mutex_enter(&dict_sys->mutex);
|
||||
}
|
||||
|
||||
graph = pars_sql(info, str);
|
||||
ut_a(graph);
|
||||
|
||||
if (!dict_locked) {
|
||||
mutex_exit(&dict_sys->mutex);
|
||||
}
|
||||
|
||||
mem_free(str);
|
||||
|
||||
return(graph);
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
Parse an SQL string. %s is replaced with the table's id.
|
||||
@return query graph */
|
||||
UNIV_INTERN
|
||||
que_t*
|
||||
fts_parse_sql_no_dict_lock(
|
||||
/*=======================*/
|
||||
fts_table_t* fts_table, /*!< in: FTS aux table info */
|
||||
pars_info_t* info, /*!< in: info struct, or NULL */
|
||||
const char* sql) /*!< in: SQL string to evaluate */
|
||||
{
|
||||
char* str;
|
||||
que_t* graph;
|
||||
char* str_tmp = NULL;
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
ut_ad(mutex_own(&dict_sys->mutex));
|
||||
#endif
|
||||
|
||||
if (fts_table != NULL) {
|
||||
char* table_name;
|
||||
|
||||
table_name = fts_get_table_name(fts_table);
|
||||
str_tmp = ut_strreplace(sql, "%s", table_name);
|
||||
mem_free(table_name);
|
||||
}
|
||||
|
||||
if (str_tmp != NULL) {
|
||||
str = ut_str3cat(fts_sql_begin, str_tmp, fts_sql_end);
|
||||
mem_free(str_tmp);
|
||||
} else {
|
||||
str = ut_str3cat(fts_sql_begin, sql, fts_sql_end);
|
||||
}
|
||||
|
||||
//fprintf(stderr, "%s\n", str);
|
||||
|
||||
graph = pars_sql(info, str);
|
||||
ut_a(graph);
|
||||
|
||||
mem_free(str);
|
||||
|
||||
return(graph);
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
Evaluate an SQL query graph.
|
||||
@return DB_SUCCESS or error code */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
fts_eval_sql(
|
||||
/*=========*/
|
||||
trx_t* trx, /*!< in: transaction */
|
||||
que_t* graph) /*!< in: Query graph to evaluate */
|
||||
{
|
||||
que_thr_t* thr;
|
||||
|
||||
graph->trx = trx;
|
||||
graph->fork_type = QUE_FORK_MYSQL_INTERFACE;
|
||||
|
||||
ut_a(thr = que_fork_start_command(graph));
|
||||
|
||||
que_run_threads(thr);
|
||||
|
||||
return(trx->error_state);
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
Construct the column specification part of the SQL string for selecting the
|
||||
indexed FTS columns for the given table. Adds the necessary bound
|
||||
ids to the given 'info' and returns the SQL string. Examples:
|
||||
|
||||
One indexed column named "text":
|
||||
|
||||
"$sel0",
|
||||
info/ids: sel0 -> "text"
|
||||
|
||||
Two indexed columns named "subject" and "content":
|
||||
|
||||
"$sel0, $sel1",
|
||||
info/ids: sel0 -> "subject", sel1 -> "content",
|
||||
@return heap-allocated WHERE string */
|
||||
UNIV_INTERN
|
||||
const char*
|
||||
fts_get_select_columns_str(
|
||||
/*=======================*/
|
||||
dict_index_t* index, /*!< in: index */
|
||||
pars_info_t* info, /*!< in/out: parser info */
|
||||
mem_heap_t* heap) /*!< in: memory heap */
|
||||
{
|
||||
ulint i;
|
||||
const char* str = "";
|
||||
|
||||
for (i = 0; i < index->n_user_defined_cols; i++) {
|
||||
char* sel_str;
|
||||
|
||||
dict_field_t* field = dict_index_get_nth_field(index, i);
|
||||
|
||||
sel_str = mem_heap_printf(heap, "sel%lu", (ulong) i);
|
||||
|
||||
/* Set copy_name to TRUE since it's dynamic. */
|
||||
pars_info_bind_id(info, TRUE, sel_str, field->name);
|
||||
|
||||
str = mem_heap_printf(
|
||||
heap, "%s%s$%s", str, (*str) ? ", " : "", sel_str);
|
||||
}
|
||||
|
||||
return(str);
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
Commit a transaction.
|
||||
@return DB_SUCCESS or error code */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
fts_sql_commit(
|
||||
/*===========*/
|
||||
trx_t* trx) /*!< in: transaction */
|
||||
{
|
||||
ulint error;
|
||||
|
||||
error = trx_commit_for_mysql(trx);
|
||||
|
||||
/* Commit above returns 0 on success, it should always succeed */
|
||||
ut_a(error == DB_SUCCESS);
|
||||
|
||||
return(DB_SUCCESS);
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
Rollback a transaction.
|
||||
@return DB_SUCCESS or error code */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
fts_sql_rollback(
|
||||
/*=============*/
|
||||
trx_t* trx) /*!< in: transaction */
|
||||
{
|
||||
return(trx_rollback_to_savepoint(trx, NULL));
|
||||
}
|
1946
storage/innobase/fts/fts0tlex.cc
Normal file
1946
storage/innobase/fts/fts0tlex.cc
Normal file
File diff suppressed because it is too large
Load diff
68
storage/innobase/fts/fts0tlex.l
Normal file
68
storage/innobase/fts/fts0tlex.l
Normal file
|
@ -0,0 +1,68 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2007, 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 Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file fts/fts0tlex.l
|
||||
* FTS parser lexical analyzer
|
||||
*
|
||||
* Created 2007/5/9 Sunny Bains
|
||||
*/
|
||||
|
||||
%{
|
||||
|
||||
#include "fts0ast.h"
|
||||
#include "fts0pars.h"
|
||||
|
||||
/* Required for reentrant parser */
|
||||
#define YY_DECL int fts_tlexer(YYSTYPE* val, yyscan_t yyscanner)
|
||||
|
||||
%}
|
||||
|
||||
%option noinput
|
||||
%option nounput
|
||||
%option noyywrap
|
||||
%option nostdinit
|
||||
%option reentrant
|
||||
%option never-interactive
|
||||
|
||||
|
||||
%%
|
||||
|
||||
[\t ]+ /* Ignore whitespace */ ;
|
||||
|
||||
[*] {
|
||||
val->oper = fts0tget_text(yyscanner)[0];
|
||||
|
||||
return(val->oper);
|
||||
}
|
||||
|
||||
\"[^\"\n]*\" {
|
||||
val->token = strdup(fts0tget_text(yyscanner));
|
||||
|
||||
return(FTS_TEXT);
|
||||
}
|
||||
|
||||
[^" \n]* {
|
||||
val->token = strdup(fts0tget_text(yyscanner));
|
||||
|
||||
return(FTS_TERM);
|
||||
}
|
||||
|
||||
\n
|
||||
|
||||
%%
|
49
storage/innobase/fts/make_parser.sh
Executable file
49
storage/innobase/fts/make_parser.sh
Executable file
|
@ -0,0 +1,49 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) 2007, 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 Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
|
||||
TMPF=t.$$
|
||||
|
||||
make -f Makefile.query
|
||||
|
||||
echo '#include "univ.i"' > $TMPF
|
||||
|
||||
# This is to avoid compiler warning about unused parameters.
|
||||
# FIXME: gcc extension "__attribute__" causing compilation errors on windows
|
||||
# platform. Quote them out for now.
|
||||
sed -e '
|
||||
s/^\(static.*void.*yy_fatal_error.*msg.*,\)\(.*yyscanner\)/\1 \2 __attribute__((unused))/;
|
||||
s/^\(static.*void.*yy_flex_strncpy.*n.*,\)\(.*yyscanner\)/\1 \2 __attribute__((unused))/;
|
||||
s/^\(static.*int.*yy_flex_strlen.*s.*,\)\(.*yyscanner\)/\1 \2 __attribute__((unused))/;
|
||||
s/^\(\(static\|void\).*fts0[bt]alloc.*,\)\(.*yyscanner\)/\1 \3 __attribute__((unused))/;
|
||||
s/^\(\(static\|void\).*fts0[bt]realloc.*,\)\(.*yyscanner\)/\1 \3 __attribute__((unused))/;
|
||||
s/^\(\(static\|void\).*fts0[bt]free.*,\)\(.*yyscanner\)/\1 \3 __attribute__((unused))/;
|
||||
' < fts0blex.cc >> $TMPF
|
||||
|
||||
mv $TMPF fts0blex.cc
|
||||
|
||||
echo '#include "univ.i"' > $TMPF
|
||||
|
||||
sed -e '
|
||||
s/^\(static.*void.*yy_fatal_error.*msg.*,\)\(.*yyscanner\)/\1 \2 __attribute__((unused))/;
|
||||
s/^\(static.*void.*yy_flex_strncpy.*n.*,\)\(.*yyscanner\)/\1 \2 __attribute__((unused))/;
|
||||
s/^\(static.*int.*yy_flex_strlen.*s.*,\)\(.*yyscanner\)/\1 \2 __attribute__((unused))/;
|
||||
s/^\(\(static\|void\).*fts0[bt]alloc.*,\)\(.*yyscanner\)/\1 \3 __attribute__((unused))/;
|
||||
s/^\(\(static\|void\).*fts0[bt]realloc.*,\)\(.*yyscanner\)/\1 \3 __attribute__((unused))/;
|
||||
s/^\(\(static\|void\).*fts0[bt]free.*,\)\(.*yyscanner\)/\1 \3 __attribute__((unused))/;
|
||||
' < fts0tlex.cc >> $TMPF
|
||||
|
||||
mv $TMPF fts0tlex.cc
|
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
|
||||
Copyright (c) 1995, 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
|
||||
|
@ -11,13 +11,13 @@ 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 program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/******************************************************************//**
|
||||
@file fut/fut0fut.c
|
||||
@file fut/fut0fut.cc
|
||||
File-based utilities
|
||||
|
||||
Created 12/13/1995 Heikki Tuuri
|
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
|
||||
Copyright (c) 1995, 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
|
||||
|
@ -11,13 +11,13 @@ 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 program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/******************************************************************//**
|
||||
@file fut/fut0lst.c
|
||||
@file fut/fut0lst.cc
|
||||
File-based list utilities
|
||||
|
||||
Created 11/28/1995 Heikki Tuuri
|
|
@ -11,13 +11,13 @@ 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 program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/********************************************************************//**
|
||||
@file ha/ha0ha.c
|
||||
@file ha/ha0ha.cc
|
||||
The hash table with external chains
|
||||
|
||||
Created 8/22/1994 Heikki Tuuri
|
||||
|
@ -31,7 +31,9 @@ Created 8/22/1994 Heikki Tuuri
|
|||
#ifdef UNIV_DEBUG
|
||||
# include "buf0buf.h"
|
||||
#endif /* UNIV_DEBUG */
|
||||
#include "btr0sea.h"
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
# include "btr0sea.h"
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
#include "page0page.h"
|
||||
|
||||
/*************************************************************//**
|
||||
|
@ -44,43 +46,56 @@ ha_create_func(
|
|||
/*===========*/
|
||||
ulint n, /*!< in: number of array cells */
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
ulint mutex_level, /*!< in: level of the mutexes in the latching
|
||||
order: this is used in the debug version */
|
||||
ulint sync_level, /*!< in: level of the mutexes or rw_locks
|
||||
in the latching order: this is used in the
|
||||
debug version */
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
ulint n_mutexes) /*!< in: number of mutexes to protect the
|
||||
hash table: must be a power of 2, or 0 */
|
||||
ulint n_sync_obj, /*!< in: number of mutexes or rw_locks
|
||||
to protect the hash table: must be a
|
||||
power of 2, or 0 */
|
||||
ulint type) /*!< in: type of datastructure for which
|
||||
the memory heap is going to be used e.g.:
|
||||
MEM_HEAP_FOR_BTR_SEARCH or
|
||||
MEM_HEAP_FOR_PAGE_HASH */
|
||||
{
|
||||
hash_table_t* table;
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
ulint i;
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
ut_ad(ut_is_2pow(n_mutexes));
|
||||
ut_a(type == MEM_HEAP_FOR_BTR_SEARCH
|
||||
|| type == MEM_HEAP_FOR_PAGE_HASH);
|
||||
|
||||
ut_ad(ut_is_2pow(n_sync_obj));
|
||||
table = hash_create(n);
|
||||
|
||||
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
|
||||
# ifndef UNIV_HOTBACKUP
|
||||
table->adaptive = TRUE;
|
||||
# endif /* !UNIV_HOTBACKUP */
|
||||
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
|
||||
/* Creating MEM_HEAP_BTR_SEARCH type heaps can potentially fail,
|
||||
but in practise it never should in this case, hence the asserts. */
|
||||
|
||||
if (n_mutexes == 0) {
|
||||
table->heap = mem_heap_create_in_btr_search(
|
||||
ut_min(4096, MEM_MAX_ALLOC_IN_BUF));
|
||||
if (n_sync_obj == 0) {
|
||||
table->heap = mem_heap_create_typed(
|
||||
ut_min(4096, MEM_MAX_ALLOC_IN_BUF), type);
|
||||
ut_a(table->heap);
|
||||
|
||||
return(table);
|
||||
}
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
hash_create_mutexes(table, n_mutexes, mutex_level);
|
||||
if (type == MEM_HEAP_FOR_PAGE_HASH) {
|
||||
/* We create a hash table protected by rw_locks for
|
||||
buf_pool->page_hash. */
|
||||
hash_create_sync_obj(table, HASH_TABLE_SYNC_RW_LOCK,
|
||||
n_sync_obj, sync_level);
|
||||
} else {
|
||||
hash_create_sync_obj(table, HASH_TABLE_SYNC_MUTEX,
|
||||
n_sync_obj, sync_level);
|
||||
}
|
||||
|
||||
table->heaps = mem_alloc(n_mutexes * sizeof(void*));
|
||||
table->heaps = static_cast<mem_heap_t**>(
|
||||
mem_alloc(n_sync_obj * sizeof(void*)));
|
||||
|
||||
for (i = 0; i < n_mutexes; i++) {
|
||||
table->heaps[i] = mem_heap_create_in_btr_search(4096);
|
||||
for (i = 0; i < n_sync_obj; i++) {
|
||||
table->heaps[i] = mem_heap_create_typed(4096, type);
|
||||
ut_a(table->heaps[i]);
|
||||
}
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
@ -88,6 +103,65 @@ ha_create_func(
|
|||
return(table);
|
||||
}
|
||||
|
||||
/*************************************************************//**
|
||||
Empties a hash table and frees the memory heaps. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
ha_clear(
|
||||
/*=====*/
|
||||
hash_table_t* table) /*!< in, own: hash table */
|
||||
{
|
||||
ulint i;
|
||||
ulint n;
|
||||
|
||||
ut_ad(table);
|
||||
ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
ut_ad(!table->adaptive
|
||||
|| rw_lock_own(&btr_search_latch, RW_LOCK_EXCLUSIVE));
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
/* Free the memory heaps. */
|
||||
n = table->n_sync_obj;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
mem_heap_free(table->heaps[i]);
|
||||
}
|
||||
|
||||
if (table->heaps) {
|
||||
mem_free(table->heaps);
|
||||
}
|
||||
|
||||
switch (table->type) {
|
||||
case HASH_TABLE_SYNC_MUTEX:
|
||||
mem_free(table->sync_obj.mutexes);
|
||||
table->sync_obj.mutexes = NULL;
|
||||
break;
|
||||
|
||||
case HASH_TABLE_SYNC_RW_LOCK:
|
||||
mem_free(table->sync_obj.rw_locks);
|
||||
table->sync_obj.rw_locks = NULL;
|
||||
break;
|
||||
|
||||
case HASH_TABLE_SYNC_NONE:
|
||||
/* do nothing */
|
||||
break;
|
||||
}
|
||||
|
||||
table->n_sync_obj = 0;
|
||||
table->type = HASH_TABLE_SYNC_NONE;
|
||||
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
/* Clear the hash table. */
|
||||
n = hash_get_n_cells(table);
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
hash_get_nth_cell(table, i)->node = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************//**
|
||||
Inserts an entry into a hash table. If an entry with the same fold number
|
||||
is found, its node is updated to point to the new data, and no new node
|
||||
|
@ -106,7 +180,7 @@ ha_insert_for_fold_func(
|
|||
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
|
||||
buf_block_t* block, /*!< in: buffer block containing the data */
|
||||
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
|
||||
rec_t* data) /*!< in: data, must not be NULL */
|
||||
const rec_t* data) /*!< in: data, must not be NULL */
|
||||
{
|
||||
hash_cell_t* cell;
|
||||
ha_node_t* node;
|
||||
|
@ -119,17 +193,14 @@ ha_insert_for_fold_func(
|
|||
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
|
||||
ut_a(block->frame == page_align(data));
|
||||
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
ASSERT_HASH_MUTEX_OWN(table, fold);
|
||||
hash_assert_can_modify(table, fold);
|
||||
ut_ad(btr_search_enabled);
|
||||
|
||||
hash = hash_calc_hash(fold, table);
|
||||
|
||||
cell = hash_get_nth_cell(table, hash);
|
||||
|
||||
prev_node = cell->node;
|
||||
prev_node = static_cast<ha_node_t*>(cell->node);
|
||||
|
||||
while (prev_node != NULL) {
|
||||
if (prev_node->fold == fold) {
|
||||
|
@ -147,7 +218,7 @@ ha_insert_for_fold_func(
|
|||
|
||||
prev_node->block = block;
|
||||
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
|
||||
prev_node->data = data;
|
||||
prev_node->data = (rec_t*) data;
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
@ -157,7 +228,8 @@ ha_insert_for_fold_func(
|
|||
|
||||
/* We have to allocate a new chain node */
|
||||
|
||||
node = mem_heap_alloc(hash_get_heap(table, fold), sizeof(ha_node_t));
|
||||
node = static_cast<ha_node_t*>(
|
||||
mem_heap_alloc(hash_get_heap(table, fold), sizeof(ha_node_t)));
|
||||
|
||||
if (node == NULL) {
|
||||
/* It was a btr search type memory heap and at the moment
|
||||
|
@ -168,7 +240,7 @@ ha_insert_for_fold_func(
|
|||
return(FALSE);
|
||||
}
|
||||
|
||||
ha_node_set_data(node, block, data);
|
||||
ha_node_set_data(node, block, (rec_t*) data);
|
||||
|
||||
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
|
||||
# ifndef UNIV_HOTBACKUP
|
||||
|
@ -182,7 +254,7 @@ ha_insert_for_fold_func(
|
|||
|
||||
node->next = NULL;
|
||||
|
||||
prev_node = cell->node;
|
||||
prev_node = static_cast<ha_node_t*>(cell->node);
|
||||
|
||||
if (prev_node == NULL) {
|
||||
|
||||
|
@ -231,9 +303,10 @@ ha_delete_hash_node(
|
|||
|
||||
/*********************************************************//**
|
||||
Looks for an element when we know the pointer to the data, and updates
|
||||
the pointer to data, if found. */
|
||||
the pointer to data, if found.
|
||||
@return TRUE if found */
|
||||
UNIV_INTERN
|
||||
void
|
||||
ibool
|
||||
ha_search_and_update_if_found_func(
|
||||
/*===============================*/
|
||||
hash_table_t* table, /*!< in/out: hash table */
|
||||
|
@ -248,7 +321,7 @@ ha_search_and_update_if_found_func(
|
|||
|
||||
ut_ad(table);
|
||||
ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
|
||||
ASSERT_HASH_MUTEX_OWN(table, fold);
|
||||
hash_assert_can_modify(table, fold);
|
||||
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
|
||||
ut_a(new_block->frame == page_align(new_data));
|
||||
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
|
||||
|
@ -257,7 +330,7 @@ ha_search_and_update_if_found_func(
|
|||
#endif /* UNIV_SYNC_DEBUG */
|
||||
|
||||
if (!btr_search_enabled) {
|
||||
return;
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
node = ha_search_with_data(table, fold, data);
|
||||
|
@ -275,7 +348,11 @@ ha_search_and_update_if_found_func(
|
|||
node->block = new_block;
|
||||
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
|
||||
node->data = new_data;
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
|
@ -294,10 +371,7 @@ ha_remove_all_nodes_to_page(
|
|||
|
||||
ut_ad(table);
|
||||
ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
|
||||
ASSERT_HASH_MUTEX_OWN(table, fold);
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
hash_assert_can_modify(table, fold);
|
||||
ut_ad(btr_search_enabled);
|
||||
|
||||
node = ha_chain_get_first(table, fold);
|
||||
|
@ -343,8 +417,6 @@ ha_validate(
|
|||
ulint start_index, /*!< in: start index */
|
||||
ulint end_index) /*!< in: end index */
|
||||
{
|
||||
hash_cell_t* cell;
|
||||
ha_node_t* node;
|
||||
ibool ok = TRUE;
|
||||
ulint i;
|
||||
|
||||
|
@ -355,12 +427,15 @@ ha_validate(
|
|||
ut_a(end_index < hash_get_n_cells(table));
|
||||
|
||||
for (i = start_index; i <= end_index; i++) {
|
||||
ha_node_t* node;
|
||||
hash_cell_t* cell;
|
||||
|
||||
cell = hash_get_nth_cell(table, i);
|
||||
|
||||
node = cell->node;
|
||||
for (node = static_cast<ha_node_t*>(cell->node);
|
||||
node != 0;
|
||||
node = node->next) {
|
||||
|
||||
while (node) {
|
||||
if (hash_calc_hash(node->fold, table) != i) {
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr,
|
||||
|
@ -371,8 +446,6 @@ ha_validate(
|
|||
|
||||
ok = FALSE;
|
||||
}
|
||||
|
||||
node = node->next;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2007, 2009, Innobase Oy. All Rights Reserved.
|
||||
Copyright (c) 2007, 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
|
||||
|
@ -11,13 +11,13 @@ 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 program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file ha/ha0storage.c
|
||||
@file ha/ha0storage.cc
|
||||
Hash storage.
|
||||
Provides a data structure that stores chunks of data in
|
||||
its own storage, avoiding duplicates.
|
||||
|
@ -51,7 +51,7 @@ ha_storage_get(
|
|||
|
||||
/* avoid repetitive calls to ut_fold_binary() in the HASH_SEARCH
|
||||
macro */
|
||||
fold = ut_fold_binary(data, data_len);
|
||||
fold = ut_fold_binary(static_cast<const byte*>(data), data_len);
|
||||
|
||||
#define IS_FOUND \
|
||||
node->data_len == data_len && memcmp(node->data, data, data_len) == 0
|
||||
|
@ -128,7 +128,7 @@ ha_storage_put_memlim(
|
|||
|
||||
/* avoid repetitive calls to ut_fold_binary() in the HASH_INSERT
|
||||
macro */
|
||||
fold = ut_fold_binary(data, data_len);
|
||||
fold = ut_fold_binary(static_cast<const byte*>(data), data_len);
|
||||
|
||||
HASH_INSERT(
|
||||
ha_storage_node_t, /* type used in the hash chain */
|
|
@ -1,184 +0,0 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1997, 2009, Innobase Oy. 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., 59 Temple
|
||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file ha/hash0hash.c
|
||||
The simple hash table utility
|
||||
|
||||
Created 5/20/1997 Heikki Tuuri
|
||||
*******************************************************/
|
||||
|
||||
#include "hash0hash.h"
|
||||
#ifdef UNIV_NONINL
|
||||
#include "hash0hash.ic"
|
||||
#endif
|
||||
|
||||
#include "mem0mem.h"
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
|
||||
# ifdef UNIV_PFS_MUTEX
|
||||
UNIV_INTERN mysql_pfs_key_t hash_table_mutex_key;
|
||||
# endif /* UNIV_PFS_MUTEX */
|
||||
|
||||
/************************************************************//**
|
||||
Reserves the mutex for a fold value in a hash table. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
hash_mutex_enter(
|
||||
/*=============*/
|
||||
hash_table_t* table, /*!< in: hash table */
|
||||
ulint fold) /*!< in: fold */
|
||||
{
|
||||
mutex_enter(hash_get_mutex(table, fold));
|
||||
}
|
||||
|
||||
/************************************************************//**
|
||||
Releases the mutex for a fold value in a hash table. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
hash_mutex_exit(
|
||||
/*============*/
|
||||
hash_table_t* table, /*!< in: hash table */
|
||||
ulint fold) /*!< in: fold */
|
||||
{
|
||||
mutex_exit(hash_get_mutex(table, fold));
|
||||
}
|
||||
|
||||
/************************************************************//**
|
||||
Reserves all the mutexes of a hash table, in an ascending order. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
hash_mutex_enter_all(
|
||||
/*=================*/
|
||||
hash_table_t* table) /*!< in: hash table */
|
||||
{
|
||||
ulint i;
|
||||
|
||||
for (i = 0; i < table->n_mutexes; i++) {
|
||||
|
||||
mutex_enter(table->mutexes + i);
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************//**
|
||||
Releases all the mutexes of a hash table. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
hash_mutex_exit_all(
|
||||
/*================*/
|
||||
hash_table_t* table) /*!< in: hash table */
|
||||
{
|
||||
ulint i;
|
||||
|
||||
for (i = 0; i < table->n_mutexes; i++) {
|
||||
|
||||
mutex_exit(table->mutexes + i);
|
||||
}
|
||||
}
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
/*************************************************************//**
|
||||
Creates a hash table with >= n array cells. The actual number of cells is
|
||||
chosen to be a prime number slightly bigger than n.
|
||||
@return own: created table */
|
||||
UNIV_INTERN
|
||||
hash_table_t*
|
||||
hash_create(
|
||||
/*========*/
|
||||
ulint n) /*!< in: number of array cells */
|
||||
{
|
||||
hash_cell_t* array;
|
||||
ulint prime;
|
||||
hash_table_t* table;
|
||||
|
||||
prime = ut_find_prime(n);
|
||||
|
||||
table = mem_alloc(sizeof(hash_table_t));
|
||||
|
||||
array = ut_malloc(sizeof(hash_cell_t) * prime);
|
||||
|
||||
table->array = array;
|
||||
table->n_cells = prime;
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
# if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
|
||||
table->adaptive = FALSE;
|
||||
# endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
|
||||
table->n_mutexes = 0;
|
||||
table->mutexes = NULL;
|
||||
table->heaps = NULL;
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
table->heap = NULL;
|
||||
ut_d(table->magic_n = HASH_TABLE_MAGIC_N);
|
||||
|
||||
/* Initialize the cell array */
|
||||
hash_table_clear(table);
|
||||
|
||||
return(table);
|
||||
}
|
||||
|
||||
/*************************************************************//**
|
||||
Frees a hash table. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
hash_table_free(
|
||||
/*============*/
|
||||
hash_table_t* table) /*!< in, own: hash table */
|
||||
{
|
||||
ut_ad(table);
|
||||
ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
ut_a(table->mutexes == NULL);
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
ut_free(table->array);
|
||||
mem_free(table);
|
||||
}
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
/*************************************************************//**
|
||||
Creates a mutex array to protect a hash table. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
hash_create_mutexes_func(
|
||||
/*=====================*/
|
||||
hash_table_t* table, /*!< in: hash table */
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
ulint sync_level, /*!< in: latching order level of the
|
||||
mutexes: used in the debug version */
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
ulint n_mutexes) /*!< in: number of mutexes, must be a
|
||||
power of 2 */
|
||||
{
|
||||
ulint i;
|
||||
|
||||
ut_ad(table);
|
||||
ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
|
||||
ut_a(n_mutexes > 0);
|
||||
ut_a(ut_is_2pow(n_mutexes));
|
||||
|
||||
table->mutexes = mem_alloc(n_mutexes * sizeof(mutex_t));
|
||||
|
||||
for (i = 0; i < n_mutexes; i++) {
|
||||
mutex_create(hash_table_mutex_key,
|
||||
table->mutexes + i, sync_level);
|
||||
}
|
||||
|
||||
table->n_mutexes = n_mutexes;
|
||||
}
|
||||
#endif /* !UNIV_HOTBACKUP */
|
403
storage/innobase/ha/hash0hash.cc
Normal file
403
storage/innobase/ha/hash0hash.cc
Normal file
|
@ -0,0 +1,403 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1997, 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 Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file ha/hash0hash.cc
|
||||
The simple hash table utility
|
||||
|
||||
Created 5/20/1997 Heikki Tuuri
|
||||
*******************************************************/
|
||||
|
||||
#include "hash0hash.h"
|
||||
#ifdef UNIV_NONINL
|
||||
#include "hash0hash.ic"
|
||||
#endif
|
||||
|
||||
#include "mem0mem.h"
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
|
||||
# ifdef UNIV_PFS_MUTEX
|
||||
UNIV_INTERN mysql_pfs_key_t hash_table_mutex_key;
|
||||
# endif /* UNIV_PFS_MUTEX */
|
||||
|
||||
# ifdef UNIV_PFS_RWLOCK
|
||||
UNIV_INTERN mysql_pfs_key_t hash_table_rw_lock_key;
|
||||
# endif /* UNIV_PFS_RWLOCK */
|
||||
/************************************************************//**
|
||||
Reserves the mutex for a fold value in a hash table. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
hash_mutex_enter(
|
||||
/*=============*/
|
||||
hash_table_t* table, /*!< in: hash table */
|
||||
ulint fold) /*!< in: fold */
|
||||
{
|
||||
ut_ad(table->type == HASH_TABLE_SYNC_MUTEX);
|
||||
mutex_enter(hash_get_mutex(table, fold));
|
||||
}
|
||||
|
||||
/************************************************************//**
|
||||
Releases the mutex for a fold value in a hash table. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
hash_mutex_exit(
|
||||
/*============*/
|
||||
hash_table_t* table, /*!< in: hash table */
|
||||
ulint fold) /*!< in: fold */
|
||||
{
|
||||
ut_ad(table->type == HASH_TABLE_SYNC_MUTEX);
|
||||
mutex_exit(hash_get_mutex(table, fold));
|
||||
}
|
||||
|
||||
/************************************************************//**
|
||||
Reserves all the mutexes of a hash table, in an ascending order. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
hash_mutex_enter_all(
|
||||
/*=================*/
|
||||
hash_table_t* table) /*!< in: hash table */
|
||||
{
|
||||
ulint i;
|
||||
|
||||
ut_ad(table->type == HASH_TABLE_SYNC_MUTEX);
|
||||
for (i = 0; i < table->n_sync_obj; i++) {
|
||||
|
||||
mutex_enter(table->sync_obj.mutexes + i);
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************//**
|
||||
Releases all the mutexes of a hash table. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
hash_mutex_exit_all(
|
||||
/*================*/
|
||||
hash_table_t* table) /*!< in: hash table */
|
||||
{
|
||||
ulint i;
|
||||
|
||||
ut_ad(table->type == HASH_TABLE_SYNC_MUTEX);
|
||||
for (i = 0; i < table->n_sync_obj; i++) {
|
||||
|
||||
mutex_exit(table->sync_obj.mutexes + i);
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************//**
|
||||
Releases all but the passed in mutex of a hash table. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
hash_mutex_exit_all_but(
|
||||
/*====================*/
|
||||
hash_table_t* table, /*!< in: hash table */
|
||||
mutex_t* keep_mutex) /*!< in: mutex to keep */
|
||||
{
|
||||
ulint i;
|
||||
|
||||
ut_ad(table->type == HASH_TABLE_SYNC_MUTEX);
|
||||
for (i = 0; i < table->n_sync_obj; i++) {
|
||||
|
||||
mutex_t* mutex = table->sync_obj.mutexes + i;
|
||||
if (UNIV_LIKELY(keep_mutex != mutex)) {
|
||||
mutex_exit(mutex);
|
||||
}
|
||||
}
|
||||
|
||||
ut_ad(mutex_own(keep_mutex));
|
||||
}
|
||||
|
||||
/************************************************************//**
|
||||
s-lock a lock for a fold value in a hash table. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
hash_lock_s(
|
||||
/*========*/
|
||||
hash_table_t* table, /*!< in: hash table */
|
||||
ulint fold) /*!< in: fold */
|
||||
{
|
||||
|
||||
rw_lock_t* lock = hash_get_lock(table, fold);
|
||||
|
||||
ut_ad(table->type == HASH_TABLE_SYNC_RW_LOCK);
|
||||
ut_ad(lock);
|
||||
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
ut_ad(!rw_lock_own(lock, RW_LOCK_SHARED));
|
||||
ut_ad(!rw_lock_own(lock, RW_LOCK_EX));
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
|
||||
rw_lock_s_lock(lock);
|
||||
}
|
||||
|
||||
/************************************************************//**
|
||||
x-lock a lock for a fold value in a hash table. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
hash_lock_x(
|
||||
/*========*/
|
||||
hash_table_t* table, /*!< in: hash table */
|
||||
ulint fold) /*!< in: fold */
|
||||
{
|
||||
|
||||
rw_lock_t* lock = hash_get_lock(table, fold);
|
||||
|
||||
ut_ad(table->type == HASH_TABLE_SYNC_RW_LOCK);
|
||||
ut_ad(lock);
|
||||
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
ut_ad(!rw_lock_own(lock, RW_LOCK_SHARED));
|
||||
ut_ad(!rw_lock_own(lock, RW_LOCK_EX));
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
|
||||
rw_lock_x_lock(lock);
|
||||
}
|
||||
|
||||
/************************************************************//**
|
||||
unlock an s-lock for a fold value in a hash table. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
hash_unlock_s(
|
||||
/*==========*/
|
||||
|
||||
hash_table_t* table, /*!< in: hash table */
|
||||
ulint fold) /*!< in: fold */
|
||||
{
|
||||
|
||||
rw_lock_t* lock = hash_get_lock(table, fold);
|
||||
|
||||
ut_ad(table->type == HASH_TABLE_SYNC_RW_LOCK);
|
||||
ut_ad(lock);
|
||||
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
ut_ad(rw_lock_own(lock, RW_LOCK_SHARED));
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
|
||||
rw_lock_s_unlock(lock);
|
||||
}
|
||||
|
||||
/************************************************************//**
|
||||
unlock x-lock for a fold value in a hash table. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
hash_unlock_x(
|
||||
/*==========*/
|
||||
hash_table_t* table, /*!< in: hash table */
|
||||
ulint fold) /*!< in: fold */
|
||||
{
|
||||
rw_lock_t* lock = hash_get_lock(table, fold);
|
||||
|
||||
ut_ad(table->type == HASH_TABLE_SYNC_RW_LOCK);
|
||||
ut_ad(lock);
|
||||
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
ut_ad(rw_lock_own(lock, RW_LOCK_EX));
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
|
||||
rw_lock_x_unlock(lock);
|
||||
}
|
||||
|
||||
/************************************************************//**
|
||||
Reserves all the locks of a hash table, in an ascending order. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
hash_lock_x_all(
|
||||
/*============*/
|
||||
hash_table_t* table) /*!< in: hash table */
|
||||
{
|
||||
ulint i;
|
||||
|
||||
ut_ad(table->type == HASH_TABLE_SYNC_RW_LOCK);
|
||||
for (i = 0; i < table->n_sync_obj; i++) {
|
||||
|
||||
rw_lock_t* lock = table->sync_obj.rw_locks + i;
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
ut_ad(!rw_lock_own(lock, RW_LOCK_SHARED));
|
||||
ut_ad(!rw_lock_own(lock, RW_LOCK_EX));
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
|
||||
rw_lock_x_lock(lock);
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************//**
|
||||
Releases all the locks of a hash table, in an ascending order. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
hash_unlock_x_all(
|
||||
/*==============*/
|
||||
hash_table_t* table) /*!< in: hash table */
|
||||
{
|
||||
ulint i;
|
||||
|
||||
ut_ad(table->type == HASH_TABLE_SYNC_RW_LOCK);
|
||||
for (i = 0; i < table->n_sync_obj; i++) {
|
||||
|
||||
rw_lock_t* lock = table->sync_obj.rw_locks + i;
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
ut_ad(rw_lock_own(lock, RW_LOCK_EX));
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
|
||||
rw_lock_x_unlock(lock);
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************//**
|
||||
Releases all but passed in lock of a hash table, */
|
||||
UNIV_INTERN
|
||||
void
|
||||
hash_unlock_x_all_but(
|
||||
/*==================*/
|
||||
hash_table_t* table, /*!< in: hash table */
|
||||
rw_lock_t* keep_lock) /*!< in: lock to keep */
|
||||
{
|
||||
ulint i;
|
||||
|
||||
ut_ad(table->type == HASH_TABLE_SYNC_RW_LOCK);
|
||||
for (i = 0; i < table->n_sync_obj; i++) {
|
||||
|
||||
rw_lock_t* lock = table->sync_obj.rw_locks + i;
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
ut_ad(rw_lock_own(lock, RW_LOCK_EX));
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
|
||||
if (UNIV_LIKELY(keep_lock != lock)) {
|
||||
rw_lock_x_unlock(lock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
/*************************************************************//**
|
||||
Creates a hash table with >= n array cells. The actual number of cells is
|
||||
chosen to be a prime number slightly bigger than n.
|
||||
@return own: created table */
|
||||
UNIV_INTERN
|
||||
hash_table_t*
|
||||
hash_create(
|
||||
/*========*/
|
||||
ulint n) /*!< in: number of array cells */
|
||||
{
|
||||
hash_cell_t* array;
|
||||
ulint prime;
|
||||
hash_table_t* table;
|
||||
|
||||
prime = ut_find_prime(n);
|
||||
|
||||
table = static_cast<hash_table_t*>(mem_alloc(sizeof(hash_table_t)));
|
||||
|
||||
array = static_cast<hash_cell_t*>(
|
||||
ut_malloc(sizeof(hash_cell_t) * prime));
|
||||
|
||||
/* The default type of hash_table is HASH_TABLE_SYNC_NONE i.e.:
|
||||
the caller is responsible for access control to the table. */
|
||||
table->type = HASH_TABLE_SYNC_NONE;
|
||||
table->array = array;
|
||||
table->n_cells = prime;
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
# if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
|
||||
table->adaptive = FALSE;
|
||||
# endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
|
||||
table->n_sync_obj = 0;
|
||||
table->sync_obj.mutexes = NULL;
|
||||
table->heaps = NULL;
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
table->heap = NULL;
|
||||
ut_d(table->magic_n = HASH_TABLE_MAGIC_N);
|
||||
|
||||
/* Initialize the cell array */
|
||||
hash_table_clear(table);
|
||||
|
||||
return(table);
|
||||
}
|
||||
|
||||
/*************************************************************//**
|
||||
Frees a hash table. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
hash_table_free(
|
||||
/*============*/
|
||||
hash_table_t* table) /*!< in, own: hash table */
|
||||
{
|
||||
ut_ad(table);
|
||||
ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
|
||||
|
||||
ut_free(table->array);
|
||||
mem_free(table);
|
||||
}
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
/*************************************************************//**
|
||||
Creates a sync object array to protect a hash table.
|
||||
::sync_obj can be mutexes or rw_locks depening on the type of
|
||||
hash table. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
hash_create_sync_obj_func(
|
||||
/*======================*/
|
||||
hash_table_t* table, /*!< in: hash table */
|
||||
enum hash_table_sync_t type, /*!< in: HASH_TABLE_SYNC_MUTEX
|
||||
or HASH_TABLE_SYNC_RW_LOCK */
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
ulint sync_level,/*!< in: latching order level
|
||||
of the mutexes: used in the
|
||||
debug version */
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
ulint n_sync_obj)/*!< in: number of sync objects,
|
||||
must be a power of 2 */
|
||||
{
|
||||
ulint i;
|
||||
|
||||
ut_ad(table);
|
||||
ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
|
||||
ut_a(n_sync_obj > 0);
|
||||
ut_a(ut_is_2pow(n_sync_obj));
|
||||
|
||||
table->type = type;
|
||||
|
||||
switch (type) {
|
||||
case HASH_TABLE_SYNC_MUTEX:
|
||||
table->sync_obj.mutexes = static_cast<mutex_t*>(
|
||||
mem_alloc(n_sync_obj * sizeof(mutex_t)));
|
||||
|
||||
for (i = 0; i < n_sync_obj; i++) {
|
||||
mutex_create(hash_table_mutex_key,
|
||||
table->sync_obj.mutexes + i, sync_level);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case HASH_TABLE_SYNC_RW_LOCK:
|
||||
table->sync_obj.rw_locks = static_cast<rw_lock_t*>(
|
||||
mem_alloc(n_sync_obj * sizeof(rw_lock_t)));
|
||||
|
||||
for (i = 0; i < n_sync_obj; i++) {
|
||||
rw_lock_create(hash_table_rw_lock_key,
|
||||
table->sync_obj.rw_locks + i, sync_level);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case HASH_TABLE_SYNC_NONE:
|
||||
ut_error;
|
||||
}
|
||||
|
||||
table->n_sync_obj = n_sync_obj;
|
||||
}
|
||||
#endif /* !UNIV_HOTBACKUP */
|
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2000, 2010, MySQL AB & Innobase Oy. All Rights Reserved.
|
||||
Copyright (c) 2000, 2012, 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
|
||||
|
@ -11,8 +11,8 @@ 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 program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
|
@ -23,9 +23,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA
|
|||
Innodb
|
||||
*/
|
||||
|
||||
#ifdef USE_PRAGMA_INTERFACE
|
||||
#pragma interface /* gcc class implementation */
|
||||
#endif
|
||||
#include "dict0stats.h"
|
||||
|
||||
/* Structure defines translation table between mysql index and innodb
|
||||
index structures */
|
||||
|
@ -110,7 +108,7 @@ class ha_innobase: public handler
|
|||
ulint innobase_update_autoinc(ulonglong auto_inc);
|
||||
void innobase_initialize_autoinc();
|
||||
dict_index_t* innobase_get_index(uint keynr);
|
||||
int info_low(uint flag, bool called_from_analyze);
|
||||
int info_low(uint flag, dict_stats_upd_option_t stats_upd_option);
|
||||
|
||||
/* Init values for the class: */
|
||||
public:
|
||||
|
@ -133,7 +131,6 @@ class ha_innobase: public handler
|
|||
const key_map* keys_to_use_for_scanning();
|
||||
|
||||
int open(const char *name, int mode, uint test_if_locked);
|
||||
handler* clone(const char *name, MEM_ROOT *mem_root);
|
||||
int close(void);
|
||||
double scan_time();
|
||||
double read_time(uint index, uint ranges, ha_rows rows);
|
||||
|
@ -163,13 +160,18 @@ class ha_innobase: public handler
|
|||
int rnd_next(uchar *buf);
|
||||
int rnd_pos(uchar * buf, uchar *pos);
|
||||
|
||||
int ft_init();
|
||||
void ft_end();
|
||||
FT_INFO *ft_init_ext(uint flags, uint inx, String* key);
|
||||
int ft_read(uchar* buf);
|
||||
|
||||
void position(const uchar *record);
|
||||
int info(uint);
|
||||
int analyze(THD* thd,HA_CHECK_OPT* check_opt);
|
||||
int optimize(THD* thd,HA_CHECK_OPT* check_opt);
|
||||
int discard_or_import_tablespace(my_bool discard);
|
||||
int extra(enum ha_extra_function operation);
|
||||
int reset();
|
||||
int reset();
|
||||
int external_lock(THD *thd, int lock_type);
|
||||
int transactional_table_lock(THD *thd, int lock_type);
|
||||
int start_stmt(THD *thd, thr_lock_type lock_type);
|
||||
|
@ -203,7 +205,7 @@ class ha_innobase: public handler
|
|||
int reset_auto_increment(ulonglong value);
|
||||
|
||||
virtual bool get_error_message(int error, String *buf);
|
||||
|
||||
virtual bool get_foreign_dup_key(char*, uint, char*, uint);
|
||||
uint8 table_cache_type();
|
||||
/*
|
||||
ask handler about permission to cache table during query registration
|
||||
|
@ -212,7 +214,7 @@ class ha_innobase: public handler
|
|||
uint key_length,
|
||||
qc_engine_callback *call_back,
|
||||
ulonglong *engine_data);
|
||||
static char *get_mysql_bin_log_name();
|
||||
static const char *get_mysql_bin_log_name();
|
||||
static ulonglong get_mysql_bin_log_pos();
|
||||
bool primary_key_is_clustered();
|
||||
int cmp_ref(const uchar *ref1, const uchar *ref2);
|
||||
|
@ -226,6 +228,77 @@ class ha_innobase: public handler
|
|||
/** @} */
|
||||
bool check_if_incompatible_data(HA_CREATE_INFO *info,
|
||||
uint table_changes);
|
||||
private:
|
||||
/** Builds a 'template' to the prebuilt struct.
|
||||
|
||||
The template is used in fast retrieval of just those column
|
||||
values MySQL needs in its processing.
|
||||
@param whole_row true if access is needed to a whole row,
|
||||
false if accessing individual fields is enough */
|
||||
void build_template(bool whole_row);
|
||||
/** Resets a query execution 'template'.
|
||||
@see build_template() */
|
||||
inline void reset_template();
|
||||
|
||||
public:
|
||||
/** @name Multi Range Read interface @{ */
|
||||
/** Initialize multi range read @see DsMrr_impl::dsmrr_init
|
||||
* @param seq
|
||||
* @param seq_init_param
|
||||
* @param n_ranges
|
||||
* @param mode
|
||||
* @param buf
|
||||
*/
|
||||
int multi_range_read_init(RANGE_SEQ_IF* seq,
|
||||
void* seq_init_param,
|
||||
uint n_ranges, uint mode,
|
||||
HANDLER_BUFFER* buf);
|
||||
/** Process next multi range read @see DsMrr_impl::dsmrr_next
|
||||
* @param range_info
|
||||
*/
|
||||
int multi_range_read_next(range_id_t *range_info);
|
||||
/** Initialize multi range read and get information.
|
||||
* @see ha_myisam::multi_range_read_info_const
|
||||
* @see DsMrr_impl::dsmrr_info_const
|
||||
* @param keyno
|
||||
* @param seq
|
||||
* @param seq_init_param
|
||||
* @param n_ranges
|
||||
* @param bufsz
|
||||
* @param flags
|
||||
* @param cost
|
||||
*/
|
||||
ha_rows multi_range_read_info_const(uint keyno, RANGE_SEQ_IF* seq,
|
||||
void* seq_init_param,
|
||||
uint n_ranges, uint* bufsz,
|
||||
uint* flags, Cost_estimate* cost);
|
||||
/** Initialize multi range read and get information.
|
||||
* @see DsMrr_impl::dsmrr_info
|
||||
* @param keyno
|
||||
* @param seq
|
||||
* @param seq_init_param
|
||||
* @param n_ranges
|
||||
* @param bufsz
|
||||
* @param flags
|
||||
* @param cost
|
||||
*/
|
||||
ha_rows multi_range_read_info(uint keyno,
|
||||
uint n_ranges, uint keys,
|
||||
uint key_parts,
|
||||
uint* bufsz, uint* mrr_mode,
|
||||
Cost_estimate* cost);
|
||||
|
||||
/** Attempt to push down an index condition.
|
||||
* @param[in] keyno MySQL key number
|
||||
* @param[in] idx_cond Index condition to be checked
|
||||
* @return idx_cond if pushed; NULL if not pushed
|
||||
*/
|
||||
class Item* idx_cond_push(uint keyno, class Item* idx_cond);
|
||||
|
||||
private:
|
||||
/** The multi range read session object */
|
||||
DsMrr_impl ds_mrr;
|
||||
/* @} */
|
||||
};
|
||||
|
||||
/* Some accessor functions which the InnoDB plugin needs, but which
|
||||
|
@ -236,9 +309,11 @@ the definitions are bracketed with #ifdef INNODB_COMPATIBILITY_HOOKS */
|
|||
#error InnoDB needs MySQL to be built with #define INNODB_COMPATIBILITY_HOOKS
|
||||
#endif
|
||||
|
||||
LEX_STRING* thd_query_string(MYSQL_THD thd);
|
||||
|
||||
extern "C" {
|
||||
|
||||
struct charset_info_st *thd_charset(MYSQL_THD thd);
|
||||
LEX_STRING *thd_query_string(MYSQL_THD thd);
|
||||
|
||||
/**
|
||||
Check if a user thread is a replication slave thread
|
||||
|
@ -284,7 +359,8 @@ bool thd_binlog_filter_ok(const MYSQL_THD thd);
|
|||
@return 1 the query may generate row changes, 0 otherwise.
|
||||
*/
|
||||
bool thd_sqlcom_can_generate_row_events(const MYSQL_THD thd);
|
||||
}
|
||||
|
||||
} /* extern "C" */
|
||||
|
||||
/** Get the file name and position of the MySQL binlog corresponding to the
|
||||
* current commit.
|
||||
|
@ -292,13 +368,23 @@ bool thd_sqlcom_can_generate_row_events(const MYSQL_THD thd);
|
|||
extern void mysql_bin_log_commit_pos(THD *thd, ulonglong *out_pos, const char **out_file);
|
||||
|
||||
typedef struct trx_struct trx_t;
|
||||
|
||||
extern const struct _ft_vft ft_vft_result;
|
||||
|
||||
/* Structure Returned by ha_innobase::ft_init_ext() */
|
||||
typedef struct new_ft_info
|
||||
{
|
||||
struct _ft_vft *please;
|
||||
row_prebuilt_t* ft_prebuilt;
|
||||
fts_result_t* ft_result;
|
||||
} NEW_FT_INFO;
|
||||
|
||||
/********************************************************************//**
|
||||
@file handler/ha_innodb.h
|
||||
Converts an InnoDB error code to a MySQL error code and also tells to MySQL
|
||||
about a possible transaction rollback inside InnoDB caused by a lock wait
|
||||
timeout or a deadlock.
|
||||
@return MySQL error code */
|
||||
extern "C"
|
||||
int
|
||||
convert_error_code_to_mysql(
|
||||
/*========================*/
|
||||
|
@ -309,20 +395,17 @@ convert_error_code_to_mysql(
|
|||
/*********************************************************************//**
|
||||
Allocates an InnoDB transaction for a MySQL handler object.
|
||||
@return InnoDB transaction handle */
|
||||
extern "C"
|
||||
trx_t*
|
||||
innobase_trx_allocate(
|
||||
/*==================*/
|
||||
MYSQL_THD thd); /*!< in: user thread handle */
|
||||
|
||||
|
||||
/*********************************************************************//**
|
||||
This function checks each index name for a table against reserved
|
||||
system default primary index name 'GEN_CLUST_INDEX'. If a name
|
||||
matches, this function pushes an warning message to the client,
|
||||
and returns true.
|
||||
@return true if the index name matches the reserved name */
|
||||
extern "C"
|
||||
bool
|
||||
innobase_index_name_is_reserved(
|
||||
/*============================*/
|
||||
|
@ -330,4 +413,79 @@ innobase_index_name_is_reserved(
|
|||
const KEY* key_info, /*!< in: Indexes to be created */
|
||||
ulint num_of_keys); /*!< in: Number of indexes to
|
||||
be created. */
|
||||
/*********************************************************************//**
|
||||
Retrieve the FTS Relevance Ranking result for doc with doc_id
|
||||
of prebuilt->fts_doc_id
|
||||
@return the relevance ranking value */
|
||||
UNIV_INTERN
|
||||
float
|
||||
innobase_fts_retrieve_ranking(
|
||||
/*==========================*/
|
||||
FT_INFO* fts_hdl); /*!< in: FTS handler */
|
||||
|
||||
/*********************************************************************//**
|
||||
Find and Retrieve the FTS Relevance Ranking result for doc with doc_id
|
||||
of prebuilt->fts_doc_id
|
||||
@return the relevance ranking value */
|
||||
UNIV_INTERN
|
||||
float
|
||||
innobase_fts_find_ranking(
|
||||
/*==========================*/
|
||||
FT_INFO* fts_hdl, /*!< in: FTS handler */
|
||||
uchar* record, /*!< in: Unused */
|
||||
uint len); /*!< in: Unused */
|
||||
/*********************************************************************//**
|
||||
Free the memory for the FTS handler */
|
||||
UNIV_INTERN
|
||||
void
|
||||
innobase_fts_close_ranking(
|
||||
/*==========================*/
|
||||
FT_INFO* fts_hdl); /*!< in: FTS handler */
|
||||
/*********************************************************************//**
|
||||
Free the memory for the FTS handler */
|
||||
void
|
||||
innobase_fts_close_ranking(
|
||||
/*==========================*/
|
||||
FT_INFO* fts_hdl); /*!< in: FTS handler */
|
||||
/*****************************************************************//**
|
||||
Initialize the table FTS stopword list
|
||||
@return TRUE is succeed */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
innobase_fts_load_stopword(
|
||||
/*=======================*/
|
||||
dict_table_t* table, /*!< in: Table has the FTS */
|
||||
trx_t* trx, /*!< in: transaction */
|
||||
THD* thd); /*!< in: current thread */
|
||||
|
||||
/** Some defines for innobase_fts_check_doc_id_index() return value */
|
||||
enum fts_doc_id_index_enum {
|
||||
FTS_INCORRECT_DOC_ID_INDEX,
|
||||
FTS_EXIST_DOC_ID_INDEX,
|
||||
FTS_NOT_EXIST_DOC_ID_INDEX
|
||||
};
|
||||
|
||||
/*******************************************************************//**
|
||||
Check whether the table has a unique index with FTS_DOC_ID_INDEX_NAME
|
||||
on the Doc ID column.
|
||||
@return FTS_EXIST_DOC_ID_INDEX if there exists the FTS_DOC_ID index,
|
||||
FTS_INCORRECT_DOC_ID_INDEX if the FTS_DOC_ID index is of wrong format */
|
||||
UNIV_INTERN
|
||||
enum fts_doc_id_index_enum
|
||||
innobase_fts_check_doc_id_index(
|
||||
/*============================*/
|
||||
dict_table_t* table, /*!< in: table definition */
|
||||
ulint* fts_doc_col_no);/*!< out: The column number for
|
||||
Doc ID */
|
||||
|
||||
/*******************************************************************//**
|
||||
Check whether the table has a unique index with FTS_DOC_ID_INDEX_NAME
|
||||
on the Doc ID column in MySQL create index definition.
|
||||
@return FTS_EXIST_DOC_ID_INDEX if there exists the FTS_DOC_ID index,
|
||||
FTS_INCORRECT_DOC_ID_INDEX if the FTS_DOC_ID index is of wrong format */
|
||||
UNIV_INTERN
|
||||
enum fts_doc_id_index_enum
|
||||
innobase_fts_check_doc_id_index_in_def(
|
||||
/*===================================*/
|
||||
ulint n_key, /*!< in: Number of keys */
|
||||
KEY* key_info); /*!< in: Key definition */
|
||||
|
|
|
@ -26,7 +26,7 @@ Smart ALTER TABLE
|
|||
#include <sql_lex.h> // SQLCOM_CREATE_INDEX
|
||||
#include <innodb_priv.h>
|
||||
|
||||
extern "C" {
|
||||
#include "dict0stats.h"
|
||||
#include "log0log.h"
|
||||
#include "row0merge.h"
|
||||
#include "srv0srv.h"
|
||||
|
@ -34,7 +34,8 @@ extern "C" {
|
|||
#include "trx0roll.h"
|
||||
#include "ha_prototypes.h"
|
||||
#include "handler0alter.h"
|
||||
}
|
||||
#include "srv0mon.h"
|
||||
#include "fts0priv.h"
|
||||
|
||||
#include "ha_innodb.h"
|
||||
|
||||
|
@ -128,7 +129,7 @@ innobase_col_to_mysql(
|
|||
|
||||
/*************************************************************//**
|
||||
Copies an InnoDB record to table->record[0]. */
|
||||
extern "C" UNIV_INTERN
|
||||
UNIV_INTERN
|
||||
void
|
||||
innobase_rec_to_mysql(
|
||||
/*==================*/
|
||||
|
@ -141,7 +142,9 @@ innobase_rec_to_mysql(
|
|||
uint n_fields = table->s->fields;
|
||||
uint i;
|
||||
|
||||
ut_ad(n_fields == dict_table_get_n_user_cols(index->table));
|
||||
ut_ad(n_fields == dict_table_get_n_user_cols(index->table)
|
||||
|| (DICT_TF2_FLAG_IS_SET(index->table, DICT_TF2_FTS_HAS_DOC_ID)
|
||||
&& n_fields + 1 == dict_table_get_n_user_cols(index->table)));
|
||||
|
||||
for (i = 0; i < n_fields; i++) {
|
||||
Field* field = table->field[i];
|
||||
|
@ -178,7 +181,7 @@ null_field:
|
|||
|
||||
/*************************************************************//**
|
||||
Resets table->record[0]. */
|
||||
extern "C" UNIV_INTERN
|
||||
UNIV_INTERN
|
||||
void
|
||||
innobase_rec_reset(
|
||||
/*===============*/
|
||||
|
@ -362,7 +365,7 @@ innobase_create_index_field_def(
|
|||
&& field->type() != MYSQL_TYPE_VARCHAR)
|
||||
|| (field->type() == MYSQL_TYPE_VARCHAR
|
||||
&& key_part->length < field->pack_length()
|
||||
- ((Field_varstring*)field)->length_bytes)) {
|
||||
- ((Field_varstring*) field)->length_bytes)) {
|
||||
|
||||
index_field->prefix_len = key_part->length;
|
||||
} else {
|
||||
|
@ -416,6 +419,10 @@ innobase_create_index_def(
|
|||
index->ind_type |= DICT_UNIQUE;
|
||||
}
|
||||
|
||||
if (key->flags & HA_FULLTEXT) {
|
||||
index->ind_type |= DICT_FTS;
|
||||
}
|
||||
|
||||
if (key_primary) {
|
||||
index->ind_type |= DICT_CLUSTERED;
|
||||
}
|
||||
|
@ -485,6 +492,143 @@ innobase_copy_index_def(
|
|||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
/*******************************************************************//**
|
||||
Check whether the table has the FTS_DOC_ID column
|
||||
@return TRUE if there exists the FTS_DOC_ID column, if TRUE but fts_doc_col_no
|
||||
equal to ULINT_UNDEFINED then that means the column exists but is not
|
||||
of the right type. */
|
||||
static
|
||||
ibool
|
||||
innobase_fts_check_doc_id_col(
|
||||
/*==========================*/
|
||||
dict_table_t* table, /*!< in: table with FTS index */
|
||||
ulint* fts_doc_col_no) /*!< out: The column number for
|
||||
Doc ID */
|
||||
{
|
||||
*fts_doc_col_no = ULINT_UNDEFINED;
|
||||
|
||||
for (ulint i = 0; i + DATA_N_SYS_COLS < (ulint) table->n_cols; i++) {
|
||||
const char* name = dict_table_get_col_name(table, i);
|
||||
|
||||
if (strcmp(name, FTS_DOC_ID_COL_NAME) == 0) {
|
||||
const dict_col_t* col;
|
||||
|
||||
col = dict_table_get_nth_col(table, i);
|
||||
|
||||
if (col->mtype != DATA_INT || col->len != 8) {
|
||||
fprintf(stderr,
|
||||
" InnoDB: %s column in table %s"
|
||||
" must be of the BIGINT datatype\n",
|
||||
FTS_DOC_ID_COL_NAME, table->name);
|
||||
} else if (!(col->prtype & DATA_NOT_NULL)) {
|
||||
fprintf(stderr,
|
||||
" InnoDB: %s column in table %s"
|
||||
" must be NOT NULL\n",
|
||||
FTS_DOC_ID_COL_NAME, table->name);
|
||||
|
||||
} else if (!(col->prtype & DATA_UNSIGNED)) {
|
||||
fprintf(stderr,
|
||||
" InnoDB: %s column in table %s"
|
||||
" must be UNSIGNED\n",
|
||||
FTS_DOC_ID_COL_NAME, table->name);
|
||||
} else {
|
||||
*fts_doc_col_no = i;
|
||||
}
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
/*******************************************************************//**
|
||||
Check whether the table has a unique index with FTS_DOC_ID_INDEX_NAME
|
||||
on the Doc ID column.
|
||||
@return FTS_EXIST_DOC_ID_INDEX if there exists the FTS_DOC_ID index,
|
||||
FTS_INCORRECT_DOC_ID_INDEX if the FTS_DOC_ID index is of wrong format */
|
||||
UNIV_INTERN
|
||||
enum fts_doc_id_index_enum
|
||||
innobase_fts_check_doc_id_index(
|
||||
/*============================*/
|
||||
dict_table_t* table, /*!< in: table definition */
|
||||
ulint* fts_doc_col_no) /*!< out: The column number for
|
||||
Doc ID */
|
||||
{
|
||||
dict_index_t* index;
|
||||
dict_field_t* field;
|
||||
|
||||
for (index = dict_table_get_first_index(table);
|
||||
index; index = dict_table_get_next_index(index)) {
|
||||
|
||||
/* Check if there exists a unique index with the name of
|
||||
FTS_DOC_ID_INDEX_NAME */
|
||||
if (innobase_strcasecmp(index->name, FTS_DOC_ID_INDEX_NAME)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!dict_index_is_unique(index)
|
||||
|| strcmp(index->name, FTS_DOC_ID_INDEX_NAME)) {
|
||||
return(FTS_INCORRECT_DOC_ID_INDEX);
|
||||
}
|
||||
|
||||
/* Check whether the index has FTS_DOC_ID as its
|
||||
first column */
|
||||
field = dict_index_get_nth_field(index, 0);
|
||||
|
||||
/* The column would be of a BIGINT data type */
|
||||
if (strcmp(field->name, FTS_DOC_ID_COL_NAME) == 0
|
||||
&& field->col->mtype == DATA_INT
|
||||
&& field->col->len == 8
|
||||
&& field->col->prtype & DATA_NOT_NULL) {
|
||||
if (fts_doc_col_no) {
|
||||
*fts_doc_col_no = dict_col_get_no(field->col);
|
||||
}
|
||||
return(FTS_EXIST_DOC_ID_INDEX);
|
||||
} else {
|
||||
return(FTS_INCORRECT_DOC_ID_INDEX);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Not found */
|
||||
return(FTS_NOT_EXIST_DOC_ID_INDEX);
|
||||
}
|
||||
/*******************************************************************//**
|
||||
Check whether the table has a unique index with FTS_DOC_ID_INDEX_NAME
|
||||
on the Doc ID column in MySQL create index definition.
|
||||
@return FTS_EXIST_DOC_ID_INDEX if there exists the FTS_DOC_ID index,
|
||||
FTS_INCORRECT_DOC_ID_INDEX if the FTS_DOC_ID index is of wrong format */
|
||||
UNIV_INTERN
|
||||
enum fts_doc_id_index_enum
|
||||
innobase_fts_check_doc_id_index_in_def(
|
||||
/*===================================*/
|
||||
ulint n_key, /*!< in: Number of keys */
|
||||
KEY * key_info) /*!< in: Key definition */
|
||||
{
|
||||
/* Check whether there is a "FTS_DOC_ID_INDEX" in the to be built index
|
||||
list */
|
||||
for (ulint j = 0; j < n_key; j++) {
|
||||
KEY* key = &key_info[j];
|
||||
|
||||
if (innobase_strcasecmp(key->name, FTS_DOC_ID_INDEX_NAME)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Do a check on FTS DOC ID_INDEX, it must be unique,
|
||||
named as "FTS_DOC_ID_INDEX" and on column "FTS_DOC_ID" */
|
||||
if (!(key->flags & HA_NOSAME)
|
||||
|| strcmp(key->name, FTS_DOC_ID_INDEX_NAME)
|
||||
|| strcmp(key->key_part[0].field->field_name,
|
||||
FTS_DOC_ID_COL_NAME)) {
|
||||
return(FTS_INCORRECT_DOC_ID_INDEX);
|
||||
}
|
||||
|
||||
return(FTS_EXIST_DOC_ID_INDEX);
|
||||
}
|
||||
|
||||
return(FTS_NOT_EXIST_DOC_ID_INDEX);
|
||||
}
|
||||
/*******************************************************************//**
|
||||
Create an index table where indexes are ordered as follows:
|
||||
|
||||
|
@ -507,12 +651,17 @@ merge_index_def_t*
|
|||
innobase_create_key_def(
|
||||
/*====================*/
|
||||
trx_t* trx, /*!< in: trx */
|
||||
const dict_table_t*table, /*!< in: table definition */
|
||||
dict_table_t* table, /*!< in: table definition */
|
||||
mem_heap_t* heap, /*!< in: heap where space for key
|
||||
definitions are allocated */
|
||||
KEY* key_info, /*!< in: Indexes to be created */
|
||||
ulint& n_keys) /*!< in/out: Number of indexes to
|
||||
ulint& n_keys, /*!< in/out: Number of indexes to
|
||||
be created */
|
||||
ulint* num_fts_index, /*!< out: Number of FTS indexes */
|
||||
ibool* add_fts_doc_id, /*!< out: Whether we need to add
|
||||
new DOC ID column for FTS index */
|
||||
ibool* add_fts_doc_id_idx)/*!< out: Whether we need to add
|
||||
new index on DOC ID column */
|
||||
{
|
||||
ulint i = 0;
|
||||
merge_index_def_t* indexdef;
|
||||
|
@ -525,6 +674,9 @@ innobase_create_key_def(
|
|||
mem_heap_alloc(heap, sizeof *indexdef
|
||||
* (n_keys + UT_LIST_GET_LEN(table->indexes)));
|
||||
|
||||
*add_fts_doc_id = FALSE;
|
||||
*add_fts_doc_id_idx = FALSE;
|
||||
|
||||
/* If there is a primary key, it is always the first index
|
||||
defined for the table. */
|
||||
|
||||
|
@ -552,12 +704,111 @@ innobase_create_key_def(
|
|||
}
|
||||
}
|
||||
|
||||
if (new_primary) {
|
||||
/* Check whether any indexes in the create list are Full
|
||||
Text Indexes*/
|
||||
for (ulint j = 0; j < n_keys; j++) {
|
||||
if (key_info[j].flags & HA_FULLTEXT) {
|
||||
(*num_fts_index)++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check whether there is a "FTS_DOC_ID_INDEX" in the to be built index
|
||||
list */
|
||||
if (innobase_fts_check_doc_id_index_in_def(n_keys, key_info)
|
||||
== FTS_INCORRECT_DOC_ID_INDEX) {
|
||||
push_warning_printf((THD*) trx->mysql_thd,
|
||||
Sql_condition::WARN_LEVEL_WARN,
|
||||
ER_WRONG_NAME_FOR_INDEX,
|
||||
" InnoDB: Index name %s is reserved"
|
||||
" for the unique index on"
|
||||
" FTS_DOC_ID column for FTS"
|
||||
" document ID indexing"
|
||||
" on table %s. Please check"
|
||||
" the index definition to"
|
||||
" make sure it is of correct"
|
||||
" type\n",
|
||||
FTS_DOC_ID_INDEX_NAME,
|
||||
table->name);
|
||||
DBUG_RETURN(NULL);
|
||||
}
|
||||
|
||||
/* If we are to build an FTS index, check whether the table
|
||||
already has a DOC ID column, if not, we will need to add a
|
||||
Doc ID hidden column and rebuild the primary index */
|
||||
if (*num_fts_index) {
|
||||
enum fts_doc_id_index_enum ret;
|
||||
ibool exists;
|
||||
ulint doc_col_no;
|
||||
ulint fts_doc_col_no;
|
||||
|
||||
exists = innobase_fts_check_doc_id_col(table, &fts_doc_col_no);
|
||||
|
||||
if (exists) {
|
||||
|
||||
if (fts_doc_col_no == ULINT_UNDEFINED) {
|
||||
|
||||
push_warning_printf(
|
||||
(THD*) trx->mysql_thd,
|
||||
Sql_condition::WARN_LEVEL_WARN,
|
||||
ER_WRONG_COLUMN_NAME,
|
||||
" InnoDB: There exists a column %s "
|
||||
"in table %s, but it is the wrong "
|
||||
"type. Create of FTS index failed.\n",
|
||||
FTS_DOC_ID_COL_NAME, table->name);
|
||||
|
||||
DBUG_RETURN(NULL);
|
||||
|
||||
} else if (!table->fts) {
|
||||
table->fts = fts_create(table);
|
||||
}
|
||||
|
||||
table->fts->doc_col = fts_doc_col_no;
|
||||
|
||||
} else {
|
||||
*add_fts_doc_id = TRUE;
|
||||
*add_fts_doc_id_idx = TRUE;
|
||||
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr, " InnoDB: Rebuild table %s to add "
|
||||
"DOC_ID column\n", table->name);
|
||||
}
|
||||
|
||||
ret = innobase_fts_check_doc_id_index(table, &doc_col_no);
|
||||
|
||||
switch (ret) {
|
||||
case FTS_NOT_EXIST_DOC_ID_INDEX:
|
||||
*add_fts_doc_id_idx = TRUE;
|
||||
break;
|
||||
case FTS_INCORRECT_DOC_ID_INDEX:
|
||||
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr, " InnoDB: Index %s is used for FTS"
|
||||
" Doc ID indexing on table %s, it is"
|
||||
" now on the wrong column or of"
|
||||
" wrong format. Please drop it.\n",
|
||||
FTS_DOC_ID_INDEX_NAME, table->name);
|
||||
DBUG_RETURN(NULL);
|
||||
|
||||
default:
|
||||
ut_ad(ret == FTS_EXIST_DOC_ID_INDEX);
|
||||
|
||||
ut_ad(doc_col_no == fts_doc_col_no);
|
||||
}
|
||||
}
|
||||
|
||||
/* If DICT_TF2_FTS_ADD_DOC_ID is set, we will need to rebuild
|
||||
the table to add the unique Doc ID column for FTS index. And
|
||||
thus the primary index would required to be rebuilt. Copy all
|
||||
the index definitions */
|
||||
if (new_primary || *add_fts_doc_id) {
|
||||
const dict_index_t* index;
|
||||
|
||||
/* Create the PRIMARY key index definition */
|
||||
innobase_create_index_def(&key_info[i++], TRUE, TRUE,
|
||||
indexdef++, heap);
|
||||
if (new_primary) {
|
||||
/* Create the PRIMARY key index definition */
|
||||
innobase_create_index_def(&key_info[i++],
|
||||
TRUE, TRUE,
|
||||
indexdef++, heap);
|
||||
}
|
||||
|
||||
row_mysql_lock_data_dictionary(trx);
|
||||
|
||||
|
@ -568,17 +819,32 @@ innobase_create_key_def(
|
|||
index or a PRIMARY KEY. If the clustered index is a
|
||||
UNIQUE INDEX, it must be converted to a secondary index. */
|
||||
|
||||
if (dict_index_get_nth_col(index, 0)->mtype == DATA_SYS
|
||||
|| !my_strcasecmp(system_charset_info,
|
||||
index->name, "PRIMARY")) {
|
||||
if (new_primary
|
||||
&& (dict_index_get_nth_col(index, 0)->mtype
|
||||
== DATA_SYS
|
||||
|| !my_strcasecmp(system_charset_info,
|
||||
index->name, "PRIMARY"))) {
|
||||
index = dict_table_get_next_index(index);
|
||||
}
|
||||
|
||||
while (index) {
|
||||
innobase_copy_index_def(index, indexdef++, heap);
|
||||
|
||||
if (new_primary && index->type & DICT_FTS) {
|
||||
(*num_fts_index)++;
|
||||
}
|
||||
|
||||
index = dict_table_get_next_index(index);
|
||||
}
|
||||
|
||||
/* The primary index would be rebuilt if a FTS Doc ID
|
||||
column is to be added, and the primary index definition
|
||||
is just copied from old table and stored in indexdefs[0] */
|
||||
if (*add_fts_doc_id) {
|
||||
indexdefs[0].ind_type |= DICT_CLUSTERED;
|
||||
DICT_TF2_FLAG_SET(table, DICT_TF2_FTS_ADD_DOC_ID);
|
||||
}
|
||||
|
||||
row_mysql_unlock_data_dictionary(trx);
|
||||
}
|
||||
|
||||
|
@ -652,6 +918,88 @@ public:
|
|||
~ha_innobase_add_index() {}
|
||||
};
|
||||
|
||||
/*******************************************************************//**
|
||||
This is to create FTS_DOC_ID_INDEX definition on the newly added Doc ID for
|
||||
the FTS indexes table
|
||||
@return dict_index_t for the FTS_DOC_ID_INDEX */
|
||||
dict_index_t*
|
||||
innobase_create_fts_doc_id_idx(
|
||||
/*===========================*/
|
||||
dict_table_t* indexed_table, /*!< in: Table where indexes are
|
||||
created */
|
||||
trx_t* trx, /*!< in: Transaction */
|
||||
mem_heap_t* heap) /*!< Heap for index definitions */
|
||||
{
|
||||
dict_index_t* index;
|
||||
merge_index_def_t fts_index_def;
|
||||
char* index_name;
|
||||
|
||||
/* Create the temp index name for FTS_DOC_ID_INDEX */
|
||||
fts_index_def.name = index_name = (char*) mem_heap_alloc(
|
||||
heap, FTS_DOC_ID_INDEX_NAME_LEN + 2);
|
||||
*index_name++ = TEMP_INDEX_PREFIX;
|
||||
memcpy(index_name, FTS_DOC_ID_INDEX_NAME,
|
||||
FTS_DOC_ID_INDEX_NAME_LEN);
|
||||
index_name[FTS_DOC_ID_INDEX_NAME_LEN] = 0;
|
||||
|
||||
/* Only the Doc ID will be indexed */
|
||||
fts_index_def.n_fields = 1;
|
||||
fts_index_def.ind_type = DICT_UNIQUE;
|
||||
fts_index_def.fields = (merge_index_field_t*) mem_heap_alloc(
|
||||
heap, sizeof *fts_index_def.fields);
|
||||
fts_index_def.fields[0].prefix_len = 0;
|
||||
fts_index_def.fields[0].field_name = mem_heap_strdup(
|
||||
heap, FTS_DOC_ID_COL_NAME);
|
||||
|
||||
index = row_merge_create_index(trx, indexed_table, &fts_index_def);
|
||||
return(index);
|
||||
}
|
||||
|
||||
/*******************************************************************//**
|
||||
Clean up on ha_innobase::add_index error. */
|
||||
static
|
||||
void
|
||||
innobase_add_index_cleanup(
|
||||
/*=======================*/
|
||||
row_prebuilt_t* prebuilt, /*!< in/out: prebuilt */
|
||||
trx_t* trx, /*!< in/out: transaction */
|
||||
dict_table_t* table) /*!< in/out: table on which
|
||||
the indexes were going to be
|
||||
created */
|
||||
{
|
||||
trx_rollback_to_savepoint(trx, NULL);
|
||||
|
||||
ut_a(trx != prebuilt->trx);
|
||||
|
||||
trx_free_for_mysql(trx);
|
||||
|
||||
trx_commit_for_mysql(prebuilt->trx);
|
||||
|
||||
if (table != NULL) {
|
||||
|
||||
rw_lock_x_lock(&dict_operation_lock);
|
||||
|
||||
dict_mutex_enter_for_mysql();
|
||||
|
||||
/* Note: This check excludes the system tables. However, we
|
||||
should be safe because users cannot add indexes to system
|
||||
tables. */
|
||||
|
||||
if (UT_LIST_GET_LEN(table->foreign_list) == 0
|
||||
&& UT_LIST_GET_LEN(table->referenced_list) == 0
|
||||
&& !table->can_be_evicted) {
|
||||
|
||||
dict_table_move_from_non_lru_to_lru(table);
|
||||
}
|
||||
|
||||
dict_table_close(table, TRUE);
|
||||
|
||||
dict_mutex_exit_for_mysql();
|
||||
|
||||
rw_lock_x_unlock(&dict_operation_lock);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************//**
|
||||
Create indexes.
|
||||
@return 0 or error number */
|
||||
|
@ -659,7 +1007,7 @@ UNIV_INTERN
|
|||
int
|
||||
ha_innobase::add_index(
|
||||
/*===================*/
|
||||
TABLE* table, /*!< in: Table where indexes
|
||||
TABLE* in_table, /*!< in: Table where indexes
|
||||
are created */
|
||||
KEY* key_info, /*!< in: Indexes
|
||||
to be created */
|
||||
|
@ -667,16 +1015,21 @@ ha_innobase::add_index(
|
|||
to be created */
|
||||
handler_add_index** add) /*!< out: context */
|
||||
{
|
||||
dict_index_t** index; /*!< Index to be created */
|
||||
dict_index_t** index = NULL; /*!< Index to be created */
|
||||
dict_index_t* fts_index = NULL;/*!< FTS Index to be created */
|
||||
dict_table_t* indexed_table; /*!< Table where indexes are created */
|
||||
merge_index_def_t* index_defs; /*!< Index definitions */
|
||||
mem_heap_t* heap; /*!< Heap for index definitions */
|
||||
mem_heap_t* heap = NULL; /*!< Heap for index definitions */
|
||||
trx_t* trx; /*!< Transaction */
|
||||
ulint num_of_idx;
|
||||
ulint num_created = 0;
|
||||
ibool dict_locked = FALSE;
|
||||
ulint new_primary;
|
||||
ulint new_primary = 0;
|
||||
int error;
|
||||
ulint num_fts_index = 0;
|
||||
ulint num_idx_create = 0;
|
||||
ibool fts_add_doc_id = FALSE;
|
||||
ibool fts_add_doc_idx = FALSE;
|
||||
|
||||
DBUG_ENTER("ha_innobase::add_index");
|
||||
ut_a(table);
|
||||
|
@ -700,7 +1053,7 @@ ha_innobase::add_index(
|
|||
DBUG_RETURN(-1);
|
||||
}
|
||||
|
||||
indexed_table = dict_table_get(prebuilt->table->name, FALSE);
|
||||
indexed_table = dict_table_open_on_name(prebuilt->table->name, FALSE);
|
||||
|
||||
if (UNIV_UNLIKELY(!indexed_table)) {
|
||||
DBUG_RETURN(HA_ERR_NO_SUCH_TABLE);
|
||||
|
@ -712,16 +1065,22 @@ ha_innobase::add_index(
|
|||
error = innobase_check_index_keys(key_info, num_of_keys, prebuilt->table);
|
||||
|
||||
if (UNIV_UNLIKELY(error)) {
|
||||
dict_table_close(prebuilt->table, FALSE);
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
/* Check each index's column length to make sure they do not
|
||||
exceed limit */
|
||||
for (ulint i = 0; i < num_of_keys; i++) {
|
||||
if (key_info[i].flags & HA_FULLTEXT) {
|
||||
continue;
|
||||
}
|
||||
|
||||
error = innobase_check_column_length(prebuilt->table,
|
||||
&key_info[i]);
|
||||
|
||||
if (error) {
|
||||
dict_table_close(prebuilt->table, FALSE);
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
}
|
||||
|
@ -734,6 +1093,20 @@ ha_innobase::add_index(
|
|||
trx = innobase_trx_allocate(user_thd);
|
||||
trx_start_if_not_started(trx);
|
||||
|
||||
/* We don't want this table to be evicted from the cache while we
|
||||
are building an index on it. Another issue is that while we are
|
||||
building the index this table could be referred to in a foreign
|
||||
key relationship. In innobase_add_index_cleanup() we check for
|
||||
that condition before moving it back to the LRU list. */
|
||||
|
||||
row_mysql_lock_data_dictionary(trx);
|
||||
|
||||
if (prebuilt->table->can_be_evicted) {
|
||||
dict_table_move_from_lru_to_non_lru(prebuilt->table);
|
||||
}
|
||||
|
||||
row_mysql_unlock_data_dictionary(trx);
|
||||
|
||||
/* Create table containing all indexes to be built in this
|
||||
alter table add index so that they are in the correct order
|
||||
in the table. */
|
||||
|
@ -741,14 +1114,34 @@ ha_innobase::add_index(
|
|||
num_of_idx = num_of_keys;
|
||||
|
||||
index_defs = innobase_create_key_def(
|
||||
trx, prebuilt->table, heap, key_info, num_of_idx);
|
||||
trx, prebuilt->table, heap, key_info, num_of_idx,
|
||||
&num_fts_index, &fts_add_doc_id, &fts_add_doc_idx);
|
||||
|
||||
if (!index_defs) {
|
||||
error = DB_UNSUPPORTED;
|
||||
goto error_handling;
|
||||
}
|
||||
|
||||
/* Currently, support create one single FULLTEXT index in parallel at
|
||||
a time */
|
||||
if (num_fts_index > 1) {
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr,
|
||||
" InnoDB: Only support create ONE Fulltext index"
|
||||
" at a time\n");
|
||||
error = DB_UNSUPPORTED;
|
||||
goto error_handling;
|
||||
}
|
||||
|
||||
new_primary = DICT_CLUSTERED & index_defs[0].ind_type;
|
||||
|
||||
/* Allocate memory for dictionary index definitions */
|
||||
/* If a new FTS Doc ID column is to be added, there will be
|
||||
one additional index to be built on the Doc ID column itself. */
|
||||
num_idx_create = (fts_add_doc_idx) ? num_of_idx + 1 : num_of_idx;
|
||||
|
||||
/* Allocate memory for dictionary index definitions */
|
||||
index = (dict_index_t**) mem_heap_alloc(
|
||||
heap, num_of_idx * sizeof *index);
|
||||
heap, num_idx_create * sizeof *index);
|
||||
|
||||
/* Flag this transaction as a dictionary operation, so that
|
||||
the data dictionary will be locked in crash recovery. */
|
||||
|
@ -776,8 +1169,9 @@ ha_innobase::add_index(
|
|||
|
||||
if (UNIV_UNLIKELY(new_primary)) {
|
||||
/* This transaction should be the only one
|
||||
operating on the table. */
|
||||
ut_a(prebuilt->table->n_mysql_handles_opened == 1);
|
||||
operating on the table. The table get above
|
||||
would have incremented the ref count to 2. */
|
||||
ut_a(prebuilt->table->n_ref_count == 2);
|
||||
|
||||
char* new_table_name = innobase_create_temporary_tablename(
|
||||
heap, '1', prebuilt->table->name);
|
||||
|
@ -806,11 +1200,12 @@ ha_innobase::add_index(
|
|||
|
||||
ut_d(dict_table_check_for_dup_indexes(prebuilt->table,
|
||||
FALSE));
|
||||
mem_heap_free(heap);
|
||||
trx_general_rollback_for_mysql(trx, NULL);
|
||||
row_mysql_unlock_data_dictionary(trx);
|
||||
trx_free_for_mysql(trx);
|
||||
trx_commit_for_mysql(prebuilt->trx);
|
||||
mem_heap_free(heap);
|
||||
|
||||
innobase_add_index_cleanup(
|
||||
prebuilt, trx, prebuilt->table);
|
||||
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
|
@ -828,6 +1223,40 @@ ha_innobase::add_index(
|
|||
error = trx->error_state;
|
||||
goto error_handling;
|
||||
}
|
||||
|
||||
if (index[num_created]->type & DICT_FTS) {
|
||||
fts_index = index[num_created];
|
||||
fts_create_index_tables(trx, fts_index);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* create FTS_DOC_ID_INDEX on the Doc ID column on the table */
|
||||
if (fts_add_doc_idx) {
|
||||
index[num_of_idx] = innobase_create_fts_doc_id_idx(
|
||||
indexed_table, trx, heap);
|
||||
/* FTS_DOC_ID_INDEX is internal defined new index */
|
||||
num_of_idx++;
|
||||
num_created++;
|
||||
}
|
||||
|
||||
if (num_fts_index) {
|
||||
DICT_TF2_FLAG_SET(indexed_table, DICT_TF2_FTS);
|
||||
|
||||
if (!indexed_table->fts
|
||||
|| ib_vector_size(indexed_table->fts->indexes) == 0) {
|
||||
fts_create_common_tables(trx, indexed_table,
|
||||
prebuilt->table->name, TRUE);
|
||||
|
||||
indexed_table->fts->fts_status |= TABLE_DICT_LOCKED;
|
||||
innobase_fts_load_stopword(
|
||||
indexed_table, trx, ha_thd());
|
||||
indexed_table->fts->fts_status &= ~TABLE_DICT_LOCKED;
|
||||
}
|
||||
|
||||
if (new_primary && prebuilt->table->fts) {
|
||||
indexed_table->fts->doc_col = prebuilt->table->fts->doc_col;
|
||||
}
|
||||
}
|
||||
|
||||
ut_ad(error == DB_SUCCESS);
|
||||
|
@ -843,8 +1272,7 @@ ha_innobase::add_index(
|
|||
row_mysql_unlock_data_dictionary(trx);
|
||||
dict_locked = FALSE;
|
||||
|
||||
ut_a(trx->n_active_thrs == 0);
|
||||
ut_a(UT_LIST_GET_LEN(trx->signals) == 0);
|
||||
ut_a(trx->lock.n_active_thrs == 0);
|
||||
|
||||
if (UNIV_UNLIKELY(new_primary)) {
|
||||
/* A primary key is to be built. Acquire an exclusive
|
||||
|
@ -867,60 +1295,66 @@ ha_innobase::add_index(
|
|||
index, num_of_idx, table);
|
||||
|
||||
error_handling:
|
||||
|
||||
/* After an error, remove all those index definitions from the
|
||||
dictionary which were defined. */
|
||||
|
||||
if (!dict_locked) {
|
||||
row_mysql_lock_data_dictionary(trx);
|
||||
dict_locked = TRUE;
|
||||
}
|
||||
|
||||
switch (error) {
|
||||
case DB_SUCCESS:
|
||||
ut_a(!dict_locked);
|
||||
|
||||
ut_d(mutex_enter(&dict_sys->mutex));
|
||||
ut_d(dict_table_check_for_dup_indexes(prebuilt->table, TRUE));
|
||||
ut_d(mutex_exit(&dict_sys->mutex));
|
||||
*add = new ha_innobase_add_index(table, key_info, num_of_keys,
|
||||
indexed_table);
|
||||
|
||||
*add = new ha_innobase_add_index(
|
||||
table, key_info, num_of_keys, indexed_table);
|
||||
|
||||
dict_table_close(prebuilt->table, dict_locked);
|
||||
break;
|
||||
|
||||
case DB_TOO_BIG_RECORD:
|
||||
my_error(HA_ERR_TO_BIG_ROW, MYF(0));
|
||||
goto error;
|
||||
goto error_exit;
|
||||
case DB_PRIMARY_KEY_IS_NULL:
|
||||
my_error(ER_PRIMARY_CANT_HAVE_NULL, MYF(0));
|
||||
/* fall through */
|
||||
case DB_DUPLICATE_KEY:
|
||||
error:
|
||||
if (fts_add_doc_idx
|
||||
&& prebuilt->trx->error_key_num == num_of_idx - 1) {
|
||||
prebuilt->trx->error_key_num = ULINT_UNDEFINED;
|
||||
}
|
||||
error_exit:
|
||||
prebuilt->trx->error_info = NULL;
|
||||
/* fall through */
|
||||
default:
|
||||
dict_table_close(prebuilt->table, dict_locked);
|
||||
|
||||
trx->error_state = DB_SUCCESS;
|
||||
|
||||
if (new_primary) {
|
||||
if (indexed_table != prebuilt->table) {
|
||||
dict_table_close(indexed_table, dict_locked);
|
||||
row_merge_drop_table(trx, indexed_table);
|
||||
}
|
||||
} else {
|
||||
if (!dict_locked) {
|
||||
row_mysql_lock_data_dictionary(trx);
|
||||
dict_locked = TRUE;
|
||||
}
|
||||
|
||||
row_merge_drop_indexes(trx, indexed_table,
|
||||
index, num_created);
|
||||
}
|
||||
}
|
||||
|
||||
ut_ad(!new_primary || prebuilt->table->n_ref_count == 1);
|
||||
trx_commit_for_mysql(trx);
|
||||
ut_ad(dict_locked);
|
||||
row_mysql_unlock_data_dictionary(trx);
|
||||
trx_free_for_mysql(trx);
|
||||
mem_heap_free(heap);
|
||||
|
||||
if (prebuilt->trx) {
|
||||
trx_commit_for_mysql(prebuilt->trx);
|
||||
}
|
||||
|
||||
if (dict_locked) {
|
||||
row_mysql_unlock_data_dictionary(trx);
|
||||
}
|
||||
|
||||
trx_free_for_mysql(trx);
|
||||
mem_heap_free(heap);
|
||||
|
||||
/* There might be work for utility threads.*/
|
||||
srv_active_wake_master_thread();
|
||||
|
||||
|
@ -982,9 +1416,12 @@ ha_innobase::final_add_index(
|
|||
prebuilt->table, add->indexed_table,
|
||||
tmp_name, trx);
|
||||
|
||||
ut_a(prebuilt->table->n_ref_count == 1);
|
||||
|
||||
switch (error) {
|
||||
case DB_TABLESPACE_ALREADY_EXISTS:
|
||||
case DB_DUPLICATE_KEY:
|
||||
ut_a(add->indexed_table->n_ref_count == 0);
|
||||
innobase_convert_tablename(tmp_name);
|
||||
my_error(HA_ERR_TABLE_EXIST, MYF(0), tmp_name);
|
||||
err = HA_ERR_TABLE_EXIST;
|
||||
|
@ -1000,6 +1437,7 @@ ha_innobase::final_add_index(
|
|||
}
|
||||
|
||||
if (!commit || err) {
|
||||
dict_table_close(add->indexed_table, TRUE);
|
||||
error = row_merge_drop_table(trx, add->indexed_table);
|
||||
trx_commit_for_mysql(prebuilt->trx);
|
||||
} else {
|
||||
|
@ -1007,7 +1445,6 @@ ha_innobase::final_add_index(
|
|||
trx_commit_for_mysql(prebuilt->trx);
|
||||
row_prebuilt_free(prebuilt, TRUE);
|
||||
error = row_merge_drop_table(trx, old_table);
|
||||
add->indexed_table->n_mysql_handles_opened++;
|
||||
prebuilt = row_create_prebuilt(add->indexed_table,
|
||||
0 /* XXX Do we know the mysql_row_len here?
|
||||
Before the addition of this parameter to
|
||||
|
@ -1018,8 +1455,14 @@ ha_innobase::final_add_index(
|
|||
|
||||
err = convert_error_code_to_mysql(
|
||||
error, prebuilt->table->flags, user_thd);
|
||||
} else {
|
||||
/* We created secondary indexes (!new_primary). */
|
||||
}
|
||||
|
||||
if (add->indexed_table == prebuilt->table
|
||||
|| DICT_TF2_FLAG_IS_SET(prebuilt->table, DICT_TF2_FTS_ADD_DOC_ID)) {
|
||||
/* We created secondary indexes (!new_primary) or create full
|
||||
text index and added a new Doc ID column, we will need to
|
||||
rename the secondary index on the Doc ID column to its
|
||||
official index name.. */
|
||||
|
||||
if (commit) {
|
||||
err = convert_error_code_to_mysql(
|
||||
|
@ -1043,13 +1486,66 @@ ha_innobase::final_add_index(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
DICT_TF2_FLAG_UNSET(prebuilt->table, DICT_TF2_FTS_ADD_DOC_ID);
|
||||
}
|
||||
|
||||
/* If index is successfully built, we will need to rebuild index
|
||||
translation table. Set valid index entry count in the translation
|
||||
table to zero. */
|
||||
if (err == 0 && commit) {
|
||||
ibool new_primary;
|
||||
dict_index_t* index;
|
||||
dict_index_t* next_index;
|
||||
ibool new_fts = FALSE;
|
||||
dict_index_t* primary;
|
||||
|
||||
new_primary = !my_strcasecmp(
|
||||
system_charset_info, add->key_info[0].name, "PRIMARY");
|
||||
|
||||
primary = dict_table_get_first_index(add->indexed_table);
|
||||
|
||||
if (!new_primary) {
|
||||
new_primary = !my_strcasecmp(
|
||||
system_charset_info, add->key_info[0].name,
|
||||
primary->name);
|
||||
}
|
||||
|
||||
share->idx_trans_tbl.index_count = 0;
|
||||
|
||||
if (new_primary) {
|
||||
for (index = primary; index; index = next_index) {
|
||||
|
||||
next_index = dict_table_get_next_index(index);
|
||||
|
||||
if (index->type & DICT_FTS) {
|
||||
fts_add_index(index,
|
||||
add->indexed_table);
|
||||
new_fts = TRUE;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ulint i;
|
||||
for (i = 0; i < add->num_of_keys; i++) {
|
||||
if (add->key_info[i].flags & HA_FULLTEXT) {
|
||||
dict_index_t* fts_index;
|
||||
|
||||
fts_index =
|
||||
dict_table_get_index_on_name(
|
||||
prebuilt->table,
|
||||
add->key_info[i].name);
|
||||
|
||||
ut_ad(fts_index);
|
||||
fts_add_index(fts_index,
|
||||
prebuilt->table);
|
||||
new_fts = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (new_fts) {
|
||||
fts_optimize_add_table(prebuilt->table);
|
||||
}
|
||||
}
|
||||
|
||||
trx_commit_for_mysql(trx);
|
||||
|
@ -1058,6 +1554,9 @@ ha_innobase::final_add_index(
|
|||
}
|
||||
|
||||
ut_d(dict_table_check_for_dup_indexes(prebuilt->table, FALSE));
|
||||
|
||||
ut_a(fts_check_cached_index(prebuilt->table));
|
||||
|
||||
row_mysql_unlock_data_dictionary(trx);
|
||||
|
||||
trx_free_for_mysql(trx);
|
||||
|
@ -1068,7 +1567,6 @@ ha_innobase::final_add_index(
|
|||
delete add;
|
||||
DBUG_RETURN(err);
|
||||
}
|
||||
|
||||
/*******************************************************************//**
|
||||
Prepare to drop some indexes of a table.
|
||||
@return 0 or error number */
|
||||
|
@ -1076,13 +1574,13 @@ UNIV_INTERN
|
|||
int
|
||||
ha_innobase::prepare_drop_index(
|
||||
/*============================*/
|
||||
TABLE* table, /*!< in: Table where indexes are dropped */
|
||||
TABLE* in_table, /*!< in: Table where indexes are dropped */
|
||||
uint* key_num, /*!< in: Key nums to be dropped */
|
||||
uint num_of_keys) /*!< in: Number of keys to be dropped */
|
||||
{
|
||||
trx_t* trx;
|
||||
int err = 0;
|
||||
uint n_key;
|
||||
uint n_key;
|
||||
|
||||
DBUG_ENTER("ha_innobase::prepare_drop_index");
|
||||
ut_ad(table);
|
||||
|
@ -1284,7 +1782,8 @@ UNIV_INTERN
|
|||
int
|
||||
ha_innobase::final_drop_index(
|
||||
/*==========================*/
|
||||
TABLE* table) /*!< in: Table where indexes are dropped */
|
||||
TABLE* iin_table) /*!< in: Table where indexes
|
||||
are dropped */
|
||||
{
|
||||
dict_index_t* index; /*!< Index to be dropped */
|
||||
trx_t* trx; /*!< Transaction */
|
||||
|
@ -1300,12 +1799,12 @@ ha_innobase::final_drop_index(
|
|||
update_thd();
|
||||
|
||||
trx_search_latch_release_if_reserved(prebuilt->trx);
|
||||
trx_start_if_not_started(prebuilt->trx);
|
||||
trx_start_if_not_started_xa(prebuilt->trx);
|
||||
|
||||
/* Create a background transaction for the operations on
|
||||
the data dictionary tables. */
|
||||
trx = innobase_trx_allocate(user_thd);
|
||||
trx_start_if_not_started(trx);
|
||||
trx_start_if_not_started_xa(trx);
|
||||
|
||||
/* Flag this transaction as a dictionary operation, so that
|
||||
the data dictionary will be locked in crash recovery. */
|
||||
|
@ -1317,6 +1816,36 @@ ha_innobase::final_drop_index(
|
|||
row_merge_lock_table(prebuilt->trx, prebuilt->table, LOCK_X),
|
||||
prebuilt->table->flags, user_thd);
|
||||
|
||||
/* Delete corresponding rows from the stats table.
|
||||
Marko advises not to edit both user tables and SYS_* tables in one
|
||||
trx, thus we use prebuilt->trx instead of trx. Because of this the
|
||||
drop from SYS_* and from the stats table cannot happen in one
|
||||
transaction and eventually if a crash occurs below, between
|
||||
trx_commit_for_mysql(trx); which drops the indexes from SYS_* and
|
||||
trx_commit_for_mysql(prebuilt->trx);
|
||||
then an orphaned rows will be left in the stats table. */
|
||||
for (index = dict_table_get_first_index(prebuilt->table);
|
||||
index != NULL;
|
||||
index = dict_table_get_next_index(index)) {
|
||||
|
||||
if (index->to_be_dropped) {
|
||||
|
||||
enum db_err ret;
|
||||
char errstr[1024];
|
||||
|
||||
ret = dict_stats_delete_index_stats(
|
||||
index, prebuilt->trx,
|
||||
errstr, sizeof(errstr));
|
||||
|
||||
if (ret != DB_SUCCESS) {
|
||||
push_warning(user_thd,
|
||||
Sql_condition::WARN_LEVEL_WARN,
|
||||
ER_LOCK_WAIT_TIMEOUT,
|
||||
errstr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
row_mysql_lock_data_dictionary(trx);
|
||||
ut_d(dict_table_check_for_dup_indexes(prebuilt->table, FALSE));
|
||||
|
||||
|
@ -1344,7 +1873,6 @@ ha_innobase::final_drop_index(
|
|||
next_index = dict_table_get_next_index(index);
|
||||
|
||||
if (index->to_be_dropped) {
|
||||
|
||||
row_merge_drop_index(index, prebuilt->table, trx);
|
||||
}
|
||||
|
||||
|
@ -1363,6 +1891,9 @@ ha_innobase::final_drop_index(
|
|||
|
||||
func_exit:
|
||||
ut_d(dict_table_check_for_dup_indexes(prebuilt->table, FALSE));
|
||||
|
||||
ut_a(fts_check_cached_index(prebuilt->table));
|
||||
|
||||
trx_commit_for_mysql(trx);
|
||||
trx_commit_for_mysql(prebuilt->trx);
|
||||
row_mysql_unlock_data_dictionary(trx);
|
||||
|
|
File diff suppressed because it is too large
Load diff
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue