Commit 0a780db9 authored by marko's avatar marko

branches/zip: Merge 1575:1664 from trunk.

parent d3255c0b
......@@ -16,6 +16,9 @@
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
ADD_DEFINITIONS(-DMYSQL_SERVER -D_WIN32 -DWIN32 -D_LIB)
IF(EMBEDDED_ONLY)
ADD_DEFINITIONS(-DUSE_TLS)
ENDIF(EMBEDDED_ONLY)
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/zlib
include
......
......@@ -56,7 +56,9 @@ noinst_HEADERS = include/btr0btr.h include/btr0btr.ic \
include/ha0ha.ic include/hash0hash.h \
include/hash0hash.ic include/ibuf0ibuf.h \
include/ibuf0ibuf.ic include/ibuf0types.h \
include/lock0iter.h \
include/lock0lock.h include/lock0lock.ic \
include/lock0priv.h include/lock0priv.ic \
include/lock0types.h include/log0log.h \
include/log0log.ic include/log0recv.h \
include/log0recv.ic include/mach0data.h \
......@@ -134,7 +136,8 @@ libinnobase_a_SOURCES = btr/btr0btr.c btr/btr0cur.c btr/btr0pcur.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 \
ibuf/ibuf0ibuf.c lock/lock0lock.c \
ibuf/ibuf0ibuf.c lock/lock0iter.c \
lock/lock0lock.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 \
......@@ -158,8 +161,8 @@ libinnobase_a_SOURCES = btr/btr0btr.c btr/btr0cur.c btr/btr0pcur.c \
ut/ut0ut.c ut/ut0vec.c ut/ut0wqueue.c \
handler/ha_innodb.cc
libinnobase_a_CXXFLAGS= $(AM_CFLAGS) -DMYSQL_SERVER
libinnobase_a_CFLAGS = $(AM_CFLAGS) -DMYSQL_SERVER
libinnobase_a_CXXFLAGS= $(AM_CFLAGS)
libinnobase_a_CFLAGS = $(AM_CFLAGS)
EXTRA_LTLIBRARIES = ha_innodb.la
pkglib_LTLIBRARIES = @plugin_innobase_shared_target@
......
......@@ -895,7 +895,7 @@ btr_search_guess_on_hash(
btr_search_n_succ++;
#endif
if (UNIV_LIKELY(!has_search_latch)
&& buf_block_peek_if_too_old(block)) {
&& buf_page_peek_if_too_old(&block->page)) {
buf_page_make_young(&block->page);
}
......
......@@ -1329,9 +1329,7 @@ buf_block_make_young(
/* Note that we read freed_page_clock's without holding any mutex:
this is allowed since the result is used only in heuristics */
if (buf_pool->freed_page_clock
>= buf_page_get_freed_page_clock(bpage)
+ 1 + (buf_pool->curr_size / 4)) {
if (buf_page_peek_if_too_old(bpage)) {
mutex_enter(&buf_pool->mutex);
/* There has been freeing activity in the LRU list:
......
......@@ -350,6 +350,18 @@ dict_table_get_col_name(
return(s);
}
/************************************************************************
Acquire the autoinc lock.*/
void
dict_table_autoinc_lock(
/*====================*/
dict_table_t* table)
{
mutex_enter(&table->autoinc_mutex);
}
/************************************************************************
Initializes the autoinc counter. It is not an error to initialize an already
initialized counter. */
......@@ -360,54 +372,8 @@ dict_table_autoinc_initialize(
dict_table_t* table, /* in: table */
ib_longlong value) /* in: next value to assign to a row */
{
mutex_enter(&(table->autoinc_mutex));
table->autoinc_inited = TRUE;
table->autoinc = value;
mutex_exit(&(table->autoinc_mutex));
}
/************************************************************************
Gets the next autoinc value (== autoinc counter value), 0 if not yet
initialized. If initialized, increments the counter by 1. */
ib_longlong
dict_table_autoinc_get(
/*===================*/
/* out: value for a new row, or 0 */
dict_table_t* table) /* in: table */
{
ib_longlong value;
mutex_enter(&(table->autoinc_mutex));
if (!table->autoinc_inited) {
value = 0;
} else {
value = table->autoinc;
table->autoinc = table->autoinc + 1;
}
mutex_exit(&(table->autoinc_mutex));
return(value);
}
/************************************************************************
Decrements the autoinc counter value by 1. */
void
dict_table_autoinc_decrement(
/*=========================*/
dict_table_t* table) /* in: table */
{
mutex_enter(&(table->autoinc_mutex));
table->autoinc = table->autoinc - 1;
mutex_exit(&(table->autoinc_mutex));
}
/************************************************************************
......@@ -422,32 +388,6 @@ dict_table_autoinc_read(
{
ib_longlong value;
mutex_enter(&(table->autoinc_mutex));
if (!table->autoinc_inited) {
value = 0;
} else {
value = table->autoinc;
}
mutex_exit(&(table->autoinc_mutex));
return(value);
}
/************************************************************************
Peeks the autoinc counter value, 0 if not yet initialized. Does not
increment the counter. The read not protected by any mutex! */
ib_longlong
dict_table_autoinc_peek(
/*====================*/
/* out: value of the counter */
dict_table_t* table) /* in: table */
{
ib_longlong value;
if (!table->autoinc_inited) {
value = 0;
......@@ -459,7 +399,7 @@ dict_table_autoinc_peek(
}
/************************************************************************
Updates the autoinc counter if the value supplied is equal or bigger than the
Updates the autoinc counter if the value supplied is greater than the
current value. If not inited, does nothing. */
void
......@@ -469,15 +409,21 @@ dict_table_autoinc_update(
dict_table_t* table, /* in: table */
ib_longlong value) /* in: value which was assigned to a row */
{
mutex_enter(&(table->autoinc_mutex));
if (table->autoinc_inited && value > table->autoinc) {
if (table->autoinc_inited) {
if (value >= table->autoinc) {
table->autoinc = value + 1;
}
table->autoinc = value;
}
}
/************************************************************************
Release the autoinc lock.*/
mutex_exit(&(table->autoinc_mutex));
void
dict_table_autoinc_unlock(
/*======================*/
dict_table_t* table) /* in: release autoinc lock for this table */
{
mutex_exit(&table->autoinc_mutex);
}
/**************************************************************************
......
......@@ -92,6 +92,11 @@ dict_mem_table_create(
mutex_create(&table->autoinc_mutex, SYNC_DICT_AUTOINC_MUTEX);
table->autoinc_inited = FALSE;
/* The actual increment value will be set by MySQL, we simply
default to 1 here.*/
table->autoinc_increment = 1;
#ifdef UNIV_DEBUG
table->magic_n = DICT_TABLE_MAGIC_N;
#endif /* UNIV_DEBUG */
......
......@@ -14,6 +14,9 @@ if [ $# -ne 2 ] ; then
die "Usage: export.sh revision-number-of-last-snapshot current-revision-number"
fi
START_REV=$(($1 + 1))
END_REV=$2
set +u
if test -z $EDITOR; then
die "\$EDITOR is not set"
......@@ -22,10 +25,11 @@ set -u
rm -rf to-mysql
mkdir to-mysql{,/storage,/patches,/mysql-test{,/t,/r,/include}}
svn log -v -r "$(($1 + 1)):BASE" > to-mysql/log
svn log -v -r "$START_REV:BASE" > to-mysql/log
svn export -q . to-mysql/storage/innobase
seq $(($1+1)) $2|while read REV
REV=$START_REV
while [ $REV -le $END_REV ]
do
PATCH=to-mysql/patches/r$REV.patch
svn log -v -r$REV > $PATCH
......@@ -35,6 +39,7 @@ do
else
rm $PATCH
fi
REV=$(($REV + 1))
done
cd to-mysql/storage/innobase
......
......@@ -2983,7 +2983,7 @@ will be able to insert new data to the database without running out the
tablespace. Only free extents are taken into account and we also subtract
the safety margin required by the above function fsp_reserve_free_extents. */
ulint
ullint
fsp_get_available_space_in_free_extents(
/*====================================*/
/* out: available space in kB */
......@@ -3056,10 +3056,12 @@ fsp_get_available_space_in_free_extents(
}
if (!zip_size) {
return(((n_free - reserve) * FSP_EXTENT_SIZE)
return((ullint) (n_free - reserve)
* FSP_EXTENT_SIZE
* (UNIV_PAGE_SIZE / 1024));
} else {
return(((n_free - reserve) * FSP_EXTENT_SIZE)
return((ullint) (n_free - reserve)
* FSP_EXTENT_SIZE
* (zip_size / 1024));
}
}
......
This diff is collapsed.
......@@ -32,7 +32,10 @@ typedef struct st_innobase_share {
} INNOBASE_SHARE;
struct dict_index_struct;
struct row_prebuilt_struct;
typedef struct dict_index_struct dict_index_t;
typedef struct row_prebuilt_struct row_prebuilt_t;
/* The class defining a handle to an Innodb table */
......@@ -54,7 +57,7 @@ class ha_innobase: public handler
ulong upd_and_key_val_buff_len;
/* the length of each of the previous
two buffers */
ulong int_table_flags;
Table_flags int_table_flags;
uint primary_key;
ulong start_of_scan; /* this is set to 1 when we are
starting a table scan but have not
......@@ -70,6 +73,11 @@ class ha_innobase: public handler
int change_active_index(uint keynr);
int general_fetch(uchar* buf, uint direction, uint match_mode);
int innobase_read_and_init_auto_inc(longlong* ret);
ulong innobase_autoinc_lock();
ulong innobase_set_max_autoinc(ulonglong auto_inc);
ulong innobase_reset_autoinc(ulonglong auto_inc);
ulong innobase_get_auto_increment(ulonglong* value);
dict_index_t* innobase_get_index(uint keynr);
/* Init values for the class: */
public:
......@@ -84,7 +92,7 @@ class ha_innobase: public handler
const char* table_type() const { return("InnoDB");}
const char *index_type(uint key_number) { return "BTREE"; }
const char** bas_ext() const;
ulonglong table_flags() const { return int_table_flags; }
Table_flags table_flags() const;
ulong index_flags(uint idx, uint part, bool all_parts) const {
return(HA_READ_NEXT | HA_READ_PREV | HA_READ_ORDER
| HA_READ_RANGE | HA_KEYREAD_ONLY);
......@@ -191,6 +199,52 @@ class ha_innobase: public handler
uint table_changes);
};
/* Some accessor functions which the InnoDB plugin needs, but which
can not be added to mysql/plugin.h as part of the public interface;
the definitions are bracketed with #ifdef INNODB_COMPATIBILITY_HOOKS */
#ifndef INNODB_COMPATIBILITY_HOOKS
#error InnoDB needs MySQL to be built with #define INNODB_COMPATIBILITY_HOOKS
#endif
extern "C" {
struct charset_info_st *thd_charset(MYSQL_THD thd);
char **thd_query(MYSQL_THD thd);
/** Get the file name of the MySQL binlog.
* @return the name of the binlog file
*/
const char* mysql_bin_log_file_name(void);
/** Get the current position of the MySQL binlog.
* @return byte offset from the beginning of the binlog
*/
ulonglong mysql_bin_log_file_pos(void);
/**
Check if a user thread is a replication slave thread
@param thd user thread
@retval 0 the user thread is not a replication slave thread
@retval 1 the user thread is a replication slave thread
*/
int thd_slave_thread(const MYSQL_THD thd);
/**
Check if a user thread is running a non-transactional update
@param thd user thread
@retval 0 the user thread is not running a non-transactional update
@retval 1 the user thread is running a non-transactional update
*/
int thd_non_transactional_update(const MYSQL_THD thd);
/**
Get the user thread's binary logging format
@param thd user thread
@return Value to be used as index into the binlog_format_names array
*/
int thd_binlog_format(const MYSQL_THD thd);
}
/*
don't delete it - it may be re-enabled later
as an optimization for the most common case InnoDB+binlog
......
......@@ -382,11 +382,11 @@ of dropping from the buffer pool. NOTE: does not reserve the buffer pool
mutex. */
UNIV_INLINE
ibool
buf_block_peek_if_too_old(
/*======================*/
buf_page_peek_if_too_old(
/*=====================*/
/* out: TRUE if should be made
younger */
const buf_block_t* block); /* in: block to make younger */
const buf_page_t* bpage); /* in: block to make younger */
/************************************************************************
Returns the current state of is_hashed of a page. FALSE if the page is
not in the pool. NOTE that this operation does not fix the page in the
......
......@@ -41,15 +41,15 @@ of dropping from the buffer pool. NOTE: does not reserve the buffer pool
mutex. */
UNIV_INLINE
ibool
buf_block_peek_if_too_old(
/*======================*/
buf_page_peek_if_too_old(
/*=====================*/
/* out: TRUE if should be made
younger */
const buf_block_t* block) /* in: block to make younger */
const buf_page_t* bpage) /* in: block to make younger */
{
return(buf_pool->freed_page_clock
>= buf_block_get_freed_page_clock(block)
+ 1 + (buf_pool->curr_size / 1024));
>= buf_page_get_freed_page_clock(bpage)
+ 1 + (buf_pool->curr_size / 4));
}
/*************************************************************************
......
......@@ -164,6 +164,13 @@ dict_col_name_is_reserved(
/* out: TRUE if name is reserved */
const char* name); /* in: column name */
/************************************************************************
Acquire the autoinc lock.*/
void
dict_table_autoinc_lock(
/*====================*/
dict_table_t* table); /* in: table */
/************************************************************************
Initializes the autoinc counter. It is not an error to initialize an already
initialized counter. */
......@@ -173,22 +180,6 @@ dict_table_autoinc_initialize(
dict_table_t* table, /* in: table */
ib_longlong value); /* in: next value to assign to a row */
/************************************************************************
Gets the next autoinc value (== autoinc counter value), 0 if not yet
initialized. If initialized, increments the counter by 1. */
ib_longlong
dict_table_autoinc_get(
/*===================*/
/* out: value for a new row, or 0 */
dict_table_t* table); /* in: table */
/************************************************************************
Decrements the autoinc counter value by 1. */
void
dict_table_autoinc_decrement(
/*=========================*/
dict_table_t* table); /* in: table */
/************************************************************************
Reads the next autoinc value (== autoinc counter value), 0 if not yet
initialized. */
......@@ -198,15 +189,6 @@ dict_table_autoinc_read(
/* out: value for a new row, or 0 */
dict_table_t* table); /* in: table */
/************************************************************************
Peeks the autoinc counter value, 0 if not yet initialized. Does not
increment the counter. The read not protected by any mutex! */
ib_longlong
dict_table_autoinc_peek(
/*====================*/
/* out: value of the counter */
dict_table_t* table); /* in: table */
/************************************************************************
Updates the autoinc counter if the value supplied is equal or bigger than the
current value. If not inited, does nothing. */
......@@ -216,6 +198,13 @@ dict_table_autoinc_update(
dict_table_t* table, /* in: table */
ib_longlong value); /* in: value which was assigned to a row */
/************************************************************************
Release the autoinc lock.*/
void
dict_table_autoinc_unlock(
/*======================*/
dict_table_t* table); /* in: table */
/**************************************************************************
Adds system columns to a table object. */
......
......@@ -433,6 +433,10 @@ struct dict_table_struct{
SELECT MAX(auto inc column) */
ib_longlong autoinc;/* autoinc counter value to give to the
next inserted row */
ib_longlong autoinc_increment;
/* The increment step of the auto increment
column. Value must be greater than or equal
to 1 */
/*----------------------*/
UT_LIST_BASE_NODE_T(row_prebuilt_t) prebuilts;
/* base node for the prebuilts defined
......
......@@ -257,7 +257,7 @@ will be able to insert new data to the database without running out the
tablespace. Only free extents are taken into account and we also subtract
the safety margin required by the above function fsp_reserve_free_extents. */
ulint
ullint
fsp_get_available_space_in_free_extents(
/*====================================*/
/* out: available space in kB */
......
/******************************************************
Lock queue iterator type and function prototypes.
(c) 2007 Innobase Oy
Created July 16, 2007 Vasil Dimov
*******************************************************/
#ifndef lock0iter_h
#define lock0iter_h
#include "univ.i"
#include "lock0types.h"
typedef struct lock_queue_iterator_struct {
const lock_t* current_lock;
/* In case this is a record lock queue (not table lock queue)
then bit_no is the record number within the heap in which the
record is stored. */
ulint bit_no;
} lock_queue_iterator_t;
/***********************************************************************
Initialize lock queue iterator so that it starts to iterate from
"lock". bit_no specifies the record number within the heap where the
record is stored. It can be undefined (ULINT_UNDEFINED) in two cases:
1. If the lock is a table lock, thus we have a table lock queue;
2. If the lock is a record lock and it is a wait lock. In this case
bit_no is calculated in this function by using
lock_rec_find_set_bit(). There is exactly one bit set in the bitmap
of a wait lock. */
void
lock_queue_iterator_reset(
/*======================*/
lock_queue_iterator_t* iter, /* out: iterator */
const lock_t* lock, /* in: lock to start from */
ulint bit_no);/* in: record number in the
heap */
/***********************************************************************
Gets the previous lock in the lock queue, returns NULL if there are no
more locks (i.e. the current lock is the first one). The iterator is
receded (if not-NULL is returned). */
const lock_t*
lock_queue_iterator_get_prev(
/*=========================*/
/* out: previous lock or NULL */
lock_queue_iterator_t* iter); /* in/out: iterator */
#endif /* lock0iter_h */
......@@ -597,6 +597,19 @@ lock_is_table_exclusive(
dict_table_t* table, /* in: table */
trx_t* trx); /* in: transaction */
/*************************************************************************
Checks if a lock request lock1 has to wait for request lock2. */
ibool
lock_has_to_wait(
/*=============*/
/* out: TRUE if lock1 has to wait for
lock2 to be removed */
const lock_t* lock1, /* in: waiting lock */
const lock_t* lock2); /* in: another lock; NOTE that it is
assumed that this has a lock bit set
on the same record as in lock1 if the
locks are record locks */
/*************************************************************************
Checks that a transaction id is sensible, i.e., not in the future. */
ibool
......@@ -641,7 +654,7 @@ lock_print_info_all_transactions(
FILE* file); /* in: file where to print */
/*************************************************************************
Return approximate number or record locks (bits set in the bitmap) for
this transaction. Since delete-marked records ma ybe removed, the
this transaction. Since delete-marked records may be removed, the
record count will not be precise. */
ulint
......
/******************************************************
Lock module internal structures and methods.
(c) 2007 Innobase Oy
Created July 12, 2007 Vasil Dimov
*******************************************************/
#ifndef lock0priv_h
#define lock0priv_h
#ifndef LOCK_MODULE_IMPLEMENTATION
/* If you need to access members of the structures defined in this
file, please write appropriate functions that retrieve them and put
those functions in lock/ */
#error Do not include lock0priv.h outside of the lock/ module
#endif
#include "univ.i"
#include "dict0types.h"
#include "hash0hash.h"
#include "trx0types.h"
#include "ut0lst.h"
/* A table lock */
typedef struct lock_table_struct lock_table_t;
struct lock_table_struct {
dict_table_t* table; /* database table in dictionary
cache */
UT_LIST_NODE_T(lock_t)
locks; /* list of locks on the same
table */
};
/* Record lock for a page */
typedef struct lock_rec_struct lock_rec_t;
struct lock_rec_struct {
ulint space; /* space id */
ulint page_no; /* page number */
ulint n_bits; /* number of bits in the lock
bitmap; NOTE: the lock bitmap is
placed immediately after the
lock struct */
};
/* Lock struct */
struct lock_struct {
trx_t* trx; /* transaction owning the
lock */
UT_LIST_NODE_T(lock_t)
trx_locks; /* list of the locks of the
transaction */
ulint type_mode; /* lock type, mode, LOCK_GAP or
LOCK_REC_NOT_GAP,
LOCK_INSERT_INTENTION,
wait flag, ORed */
hash_node_t hash; /* hash chain node for a record
lock */
dict_index_t* index; /* index for a record lock */
union {
lock_table_t tab_lock;/* table lock */
lock_rec_t rec_lock;/* record lock */
} un_member;
};
/*************************************************************************
Gets the type of a lock. */
UNIV_INLINE
ulint
lock_get_type(
/*==========*/
/* out: LOCK_TABLE or LOCK_REC */
const lock_t* lock); /* in: lock */
/**************************************************************************
Looks for a set bit in a record lock bitmap. Returns ULINT_UNDEFINED,
if none found. */
ulint
lock_rec_find_set_bit(
/*==================*/
/* out: bit index == heap number of
the record, or ULINT_UNDEFINED if none found */
const lock_t* lock); /* in: record lock with at least one bit set */
/*************************************************************************
Gets the previous record lock set on a record. */
const lock_t*
lock_rec_get_prev(
/*==============*/
/* out: previous lock on the same
record, NULL if none exists */
const lock_t* in_lock,/* in: record lock */
ulint heap_no);/* in: heap number of the record */
#ifndef UNIV_NONINL
#include "lock0priv.ic"
#endif
#endif /* lock0priv_h */
/******************************************************
Lock module internal inline methods.
(c) 2007 Innobase Oy
Created July 16, 2007 Vasil Dimov
*******************************************************/
/* This file contains only methods which are used in
lock/lock0* files, other than lock/lock0lock.c.
I.e. lock/lock0lock.c contains more internal inline
methods but they are used only in that file. */
#ifndef LOCK_MODULE_IMPLEMENTATION
#error Do not include lock0priv.ic outside of the lock/ module
#endif
/*************************************************************************
Gets the type of a lock. */
UNIV_INLINE
ulint
lock_get_type(
/*==========*/
/* out: LOCK_TABLE or LOCK_REC */
const lock_t* lock) /* in: lock */
{
ut_ad(lock);
return(lock->type_mode & LOCK_TYPE_MASK);
}
/* vim: set filetype=c: */
......@@ -766,6 +766,7 @@ struct row_prebuilt_struct {
to this heap */
mem_heap_t* old_vers_heap; /* memory heap where a previous
version is built in consistent read */
ulonglong last_value; /* last value of AUTO-INC interval */
UT_LIST_NODE_T(row_prebuilt_t) prebuilts;
/* list node of table->prebuilts */
ulint magic_n2; /* this should be the same as
......
......@@ -171,7 +171,17 @@ row_search_check_if_query_cache_permitted(
trx_t* trx, /* in: transaction object */
const char* norm_name); /* in: concatenation of database name,
'/' char, table name */
/***********************************************************************
Read the max AUTOINC value from an index. */
ulint
row_search_max_autoinc(
/*===================*/
/* out: DB_SUCCESS if all OK else
error code */
dict_index_t* index, /* in: index to search */
const char* col_name, /* in: autoinc column name */
ib_longlong* value); /* out: AUTOINC value read */
/* A structure for caching column values for prefetched rows */
struct sel_buf_struct{
......
......@@ -694,6 +694,9 @@ struct trx_struct{
trx_undo_arr_t* undo_no_arr; /* array of undo numbers of undo log
records which are currently processed
by a rollback operation */
ulint n_autoinc_rows; /* no. of AUTO-INC rows required for
an SQL statement. This is useful for
multi-row INSERTs */
/*------------------------------*/
char detailed_error[256]; /* detailed error message for last
error, or empty. */
......
......@@ -231,6 +231,8 @@ typedef longlong ib_longlong;
typedef ulonglong ib_uint64_t;
#endif
typedef unsigned long long int ullint;
#ifndef __WIN__
#if SIZEOF_LONG != SIZEOF_VOIDP
#error "Error: InnoDB's ulint must be of the same size as void*"
......
/******************************************************
Lock queue iterator. Can iterate over table and record
lock queues.
(c) 2007 Innobase Oy
Created July 16, 2007 Vasil Dimov
*******************************************************/
#define LOCK_MODULE_IMPLEMENTATION
#include "univ.i"
#include "lock0iter.h"
#include "lock0lock.h"
#include "lock0priv.h"
#include "ut0dbg.h"
#include "ut0lst.h"
/***********************************************************************
Initialize lock queue iterator so that it starts to iterate from
"lock". bit_no specifies the record number within the heap where the
record is stored. It can be undefined (ULINT_UNDEFINED) in two cases:
1. If the lock is a table lock, thus we have a table lock queue;
2. If the lock is a record lock and it is a wait lock. In this case
bit_no is calculated in this function by using
lock_rec_find_set_bit(). There is exactly one bit set in the bitmap
of a wait lock. */
void
lock_queue_iterator_reset(
/*======================*/
lock_queue_iterator_t* iter, /* out: iterator */
const lock_t* lock, /* in: lock to start from */
ulint bit_no) /* in: record number in the
heap */
{
iter->current_lock = lock;
if (bit_no != ULINT_UNDEFINED) {
iter->bit_no = bit_no;
} else {
switch (lock_get_type(lock)) {
case LOCK_TABLE:
iter->bit_no = ULINT_UNDEFINED;
break;
case LOCK_REC:
iter->bit_no = lock_rec_find_set_bit(lock);
ut_a(iter->bit_no != ULINT_UNDEFINED);
break;
default:
ut_error;
}
}
}
/***********************************************************************
Gets the previous lock in the lock queue, returns NULL if there are no
more locks (i.e. the current lock is the first one). The iterator is
receded (if not-NULL is returned). */
const lock_t*
lock_queue_iterator_get_prev(
/*=========================*/
/* out: previous lock or NULL */
lock_queue_iterator_t* iter) /* in/out: iterator */
{
const lock_t* prev_lock;
switch (lock_get_type(iter->current_lock)) {
case LOCK_REC:
prev_lock = lock_rec_get_prev(
iter->current_lock, iter->bit_no);
break;
case LOCK_TABLE:
prev_lock = UT_LIST_GET_PREV(
un_member.tab_lock.locks, iter->current_lock);
break;
default:
ut_error;
}
if (prev_lock != NULL) {
iter->current_lock = prev_lock;
}
return(prev_lock);
}
......@@ -6,10 +6,14 @@ The transaction lock system
Created 5/7/1996 Heikki Tuuri
*******************************************************/
#define LOCK_MODULE_IMPLEMENTATION
#include "lock0lock.h"
#include "lock0priv.h"
#ifdef UNIV_NONINL
#include "lock0lock.ic"
#include "lock0priv.ic"
#endif
#include "usr0sess.h"
......@@ -373,42 +377,6 @@ lock_rec_validate_page(
/* The lock system */
lock_sys_t* lock_sys = NULL;
/* A table lock */
typedef struct lock_table_struct lock_table_t;
struct lock_table_struct{
dict_table_t* table; /* database table in dictionary cache */
UT_LIST_NODE_T(lock_t)
locks; /* list of locks on the same table */
};
/* Record lock for a page */
typedef struct lock_rec_struct lock_rec_t;
struct lock_rec_struct{
ulint space; /* space id */
ulint page_no; /* page number */
ulint n_bits; /* number of bits in the lock bitmap */
/* NOTE: the lock bitmap is placed immediately
after the lock struct */
};
/* Lock struct */
struct lock_struct{
trx_t* trx; /* transaction owning the lock */
UT_LIST_NODE_T(lock_t)
trx_locks; /* list of the locks of the
transaction */
ulint type_mode; /* lock type, mode, LOCK_GAP or
LOCK_REC_NOT_GAP,
LOCK_INSERT_INTENTION,
wait flag, ORed */
hash_node_t hash; /* hash chain node for a record lock */
dict_index_t* index; /* index for a record lock */
union {
lock_table_t tab_lock;/* table lock */
lock_rec_t rec_lock;/* record lock */
} un_member;
};
/* We store info on the latest deadlock error to this buffer. InnoDB
Monitor will then fetch it and print */
ibool lock_deadlock_found = FALSE;
......@@ -454,20 +422,6 @@ lock_deadlock_recursive(
LOCK_MAX_DEPTH_IN_DEADLOCK_CHECK, we
return LOCK_VICTIM_IS_START */
/*************************************************************************
Gets the type of a lock. */
UNIV_INLINE
ulint
lock_get_type(
/*==========*/
/* out: LOCK_TABLE or LOCK_REC */
const lock_t* lock) /* in: lock */
{
ut_ad(lock);
return(lock->type_mode & LOCK_TYPE_MASK);
}
/*************************************************************************
Gets the nth bit of a record lock. */
UNIV_INLINE
......@@ -1021,7 +975,7 @@ lock_rec_has_to_wait(
/*************************************************************************
Checks if a lock request lock1 has to wait for request lock2. */
static
ibool
lock_has_to_wait(
/*=============*/
......@@ -1095,7 +1049,7 @@ lock_rec_set_nth_bit(
/**************************************************************************
Looks for a set bit in a record lock bitmap. Returns ULINT_UNDEFINED,
if none found. */
static
ulint
lock_rec_find_set_bit(
/*==================*/
......@@ -1359,7 +1313,7 @@ lock_rec_copy(
/*************************************************************************
Gets the previous record lock set on a record. */
static
const lock_t*
lock_rec_get_prev(
/*==============*/
......
......@@ -58,6 +58,16 @@ ibool recv_needed_recovery = FALSE;
ibool recv_lsn_checks_on = FALSE;
/* There are two conditions under which we scan the logs, the first
is normal startup and the second is when we do a recovery from an
archive.
This flag is set if we are doing a scan from the last checkpoint during
startup. If we find log entries that were written after the last checkpoint
we know that the server was not cleanly shutdown. We must then initialize
the crash recovery environment before attempting to store these entries in
the log hash table. */
ibool recv_log_scan_is_startup_type = FALSE;
/* If the following is TRUE, the buffer pool file pages must be invalidated
after recovery and no ibuf operations are allowed; this becomes TRUE if
the log record hash table becomes too full, and log records must be merged
......@@ -100,6 +110,16 @@ the recovery failed and the database may be corrupt. */
ib_uint64_t recv_max_page_lsn;
/* prototypes */
/***********************************************************
Initialize crash recovery environment. Can be called iff
recv_needed_recovery == FALSE. */
static
void
recv_init_crash_recovery(void);
/*===========================*/
/************************************************************
Creates the recovery system. */
......@@ -2339,6 +2359,20 @@ recv_scan_log_recs(
if (scanned_lsn > recv_sys->scanned_lsn) {
/* We have found more entries. If this scan is
of startup type, we must initiate crash recovery
environment before parsing these log records. */
if (recv_log_scan_is_startup_type
&& !recv_needed_recovery) {
fprintf(stderr,
"InnoDB: Log scan progressed"
" past the checkpoint lsn %llu\n",
recv_sys->scanned_lsn);
recv_init_crash_recovery();
}
/* We were able to find more log data: add it to the
parsing buffer if parse_start_lsn is already
non-zero */
......@@ -2460,6 +2494,47 @@ recv_group_scan_log_recs(
#endif /* UNIV_DEBUG */
}
/***********************************************************
Initialize crash recovery environment. Can be called iff
recv_needed_recovery == FALSE. */
static
void
recv_init_crash_recovery(void)
/*==========================*/
{
ut_a(!recv_needed_recovery);
recv_needed_recovery = TRUE;
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: Database was not"
" shut down normally!\n"
"InnoDB: Starting crash recovery.\n");
fprintf(stderr,
"InnoDB: Reading tablespace information"
" from the .ibd files...\n");
fil_load_single_table_tablespaces();
/* If we are using the doublewrite method, we will
check if there are half-written pages in data files,
and restore them from the doublewrite buffer if
possible */
if (srv_force_recovery < SRV_FORCE_NO_LOG_REDO) {
fprintf(stderr,
"InnoDB: Restoring possible"
" half-written data pages from"
" the doublewrite\n"
"InnoDB: buffer...\n");
trx_sys_doublewrite_init_or_restore_pages(TRUE);
}
}
/************************************************************
Recovers from a checkpoint. When this function returns, the database is able
to start processing of new user transactions, but the function
......@@ -2589,81 +2664,6 @@ recv_recovery_from_checkpoint_start(
recv_sys->recovered_lsn = checkpoint_lsn;
srv_start_lsn = checkpoint_lsn;
/* NOTE: we always do a 'recovery' at startup, but only if
there is something wrong we will print a message to the
user about recovery: */
if (checkpoint_lsn != max_flushed_lsn
|| checkpoint_lsn != min_flushed_lsn) {
if (checkpoint_lsn < max_flushed_lsn) {
fprintf(stderr,
"InnoDB: #########################"
"#################################\n"
"InnoDB: "
"WARNING!\n"
"InnoDB: The log sequence number"
" in ibdata files is higher\n"
"InnoDB: than the log sequence number"
" in the ib_logfiles! Are you sure\n"
"InnoDB: you are using the right"
" ib_logfiles to start up"
" the database?\n"
"InnoDB: Log sequence number in"
" ib_logfiles is %llu, log\n"
"InnoDB: sequence numbers stamped"
" to ibdata file headers are between\n"
"InnoDB: %llu and %llu.\n"
"InnoDB: #########################"
"#################################\n",
checkpoint_lsn,
min_flushed_lsn,
max_flushed_lsn);
}
recv_needed_recovery = TRUE;
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: Database was not"
" shut down normally!\n"
"InnoDB: Starting crash recovery.\n");
fprintf(stderr,
"InnoDB: Reading tablespace information"
" from the .ibd files...\n");
fil_load_single_table_tablespaces();
/* If we are using the doublewrite method, we will
check if there are half-written pages in data files,
and restore them from the doublewrite buffer if
possible */
if (srv_force_recovery < SRV_FORCE_NO_LOG_REDO) {
fprintf(stderr,
"InnoDB: Restoring possible"
" half-written data pages from"
" the doublewrite\n"
"InnoDB: buffer...\n");
trx_sys_doublewrite_init_or_restore_pages(
TRUE);
}
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: Starting log scan"
" based on checkpoint at\n"
"InnoDB: log sequence number %llu.\n",
checkpoint_lsn);
} else {
/* Init the doublewrite buffer memory structure */
trx_sys_doublewrite_init_or_restore_pages(FALSE);
}
}
contiguous_lsn = ut_uint64_align_down(recv_sys->scanned_lsn,
......@@ -2713,6 +2713,8 @@ recv_recovery_from_checkpoint_start(
group = UT_LIST_GET_NEXT(log_groups, group);
}
/* Set the flag to publish that we are doing startup scan. */
recv_log_scan_is_startup_type = (type == LOG_CHECKPOINT);
while (group) {
old_scanned_lsn = recv_sys->scanned_lsn;
......@@ -2734,6 +2736,57 @@ recv_recovery_from_checkpoint_start(
group = UT_LIST_GET_NEXT(log_groups, group);
}
/* Done with startup scan. Clear the flag. */
recv_log_scan_is_startup_type = FALSE;
if (type == LOG_CHECKPOINT) {
/* NOTE: we always do a 'recovery' at startup, but only if
there is something wrong we will print a message to the
user about recovery: */
if (checkpoint_lsn != max_flushed_lsn
|| checkpoint_lsn != min_flushed_lsn) {
if (checkpoint_lsn < max_flushed_lsn) {
fprintf(stderr,
"InnoDB: #########################"
"#################################\n"
"InnoDB: "
"WARNING!\n"
"InnoDB: The log sequence number"
" in ibdata files is higher\n"
"InnoDB: than the log sequence number"
" in the ib_logfiles! Are you sure\n"
"InnoDB: you are using the right"
" ib_logfiles to start up"
" the database?\n"
"InnoDB: Log sequence number in"
" ib_logfiles is %llu, log\n"
"InnoDB: sequence numbers stamped"
" to ibdata file headers are between\n"
"InnoDB: %llu and %llu.\n"
"InnoDB: #########################"
"#################################\n",
checkpoint_lsn,
min_flushed_lsn,
max_flushed_lsn);
}
if (!recv_needed_recovery) {
fprintf(stderr,
"InnoDB: The log sequence number"
" in ibdata files does not match\n"
"InnoDB: the log sequence number"
" in the ib_logfiles!\n");
recv_init_crash_recovery();
}
}
if (!recv_needed_recovery) {
/* Init the doublewrite buffer memory structure */
trx_sys_doublewrite_init_or_restore_pages(FALSE);
}
}
/* We currently have only one log group */
if (group_scanned_lsn < checkpoint_lsn) {
ut_print_timestamp(stderr);
......@@ -2786,15 +2839,7 @@ recv_recovery_from_checkpoint_start(
recv_synchronize_groups(up_to_date_group);
if (!recv_needed_recovery) {
if (checkpoint_lsn != recv_sys->recovered_lsn) {
fprintf(stderr,
"InnoDB: Warning: we did not need to do"
" crash recovery, but log scan\n"
"InnoDB: progressed past the checkpoint"
" lsn %llu up to lsn %llu\n",
checkpoint_lsn,
recv_sys->recovered_lsn);
}
ut_a(checkpoint_lsn == recv_sys->recovered_lsn);
} else {
srv_start_lsn = recv_sys->recovered_lsn;
}
......
disable_query_log;
--require r/true.require
select support = 'Enabled' as `TRUE` from information_schema.engines where engine = 'innodb';
select (support = 'YES' or support = 'DEFAULT') as `TRUE` from information_schema.engines where engine = 'innodb';
enable_query_log;
......@@ -501,7 +501,7 @@ ERROR 23000: Duplicate entry 'test2' for key 'ggid'
select * from t1;
id ggid email passwd
1 this will work
3 test2 this will work
4 test2 this will work
select * from t1 where id=1;
id ggid email passwd
1 this will work
......@@ -1086,6 +1086,39 @@ n d
1 30
2 20
drop table t1,t2;
CREATE TABLE `t1` (
`a` int(11) NOT NULL auto_increment,
`b` int(11) default NULL,
PRIMARY KEY (`a`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 ;
CREATE TABLE `t2` (
`a` int(11) NOT NULL auto_increment,
`b` int(11) default NULL,
PRIMARY KEY (`a`)
) ENGINE=INNODB DEFAULT CHARSET=latin1 ;
insert into t1 values (1,1),(2,2);
insert into t2 values (1,1),(4,4);
reset master;
UPDATE t2,t1 SET t2.a=t1.a+2;
ERROR 23000: Duplicate entry '3' for key 'PRIMARY'
select * from t2 /* must be (3,1), (4,4) */;
a b
1 1
4 4
show master status /* there must no UPDATE in binlog */;
File Position Binlog_Do_DB Binlog_Ignore_DB
master-bin.000001 106
delete from t1;
delete from t2;
insert into t1 values (1,2),(3,4),(4,4);
insert into t2 values (1,2),(3,4),(4,4);
reset master;
UPDATE t2,t1 SET t2.a=t2.b where t2.a=t1.a;
ERROR 23000: Duplicate entry '4' for key 'PRIMARY'
show master status /* there must be no UPDATE query event */;
File Position Binlog_Do_DB Binlog_Ignore_DB
master-bin.000001 106
drop table t1, t2;
create table t1 (a int, b int) engine=innodb;
insert into t1 values(20,null);
select t2.b, ifnull(t2.b,"this is null") from t1 as t2 left join t1 as t3 on
......@@ -1607,7 +1640,7 @@ t2 CREATE TABLE `t2` (
) ENGINE=InnoDB DEFAULT CHARSET=latin1
drop table t2;
create table t2 (id int(11) not null, id2 int(11) not null, constraint t1_id_fk foreign key (id2,id) references t1 (id)) engine = innodb;
ERROR HY000: Can't create table 'test.t2' (errno: 150)
ERROR 42000: Incorrect foreign key definition for 't1_id_fk': Key reference and table reference don't match
create table t2 (a int auto_increment primary key, b int, index(b), foreign key (b) references t1(id), unique(b)) engine=innodb;
show create table t2;
Table Create Table
......@@ -1632,30 +1665,6 @@ t2 CREATE TABLE `t2` (
CONSTRAINT `t2_ibfk_2` FOREIGN KEY (`b`) REFERENCES `t1` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
drop table t2, t1;
flush status;
show status like "binlog_cache_use";
Variable_name Value
Binlog_cache_use 0
show status like "binlog_cache_disk_use";
Variable_name Value
Binlog_cache_disk_use 0
create table t1 (a int) engine=innodb;
show status like "binlog_cache_use";
Variable_name Value
Binlog_cache_use 1
show status like "binlog_cache_disk_use";
Variable_name Value
Binlog_cache_disk_use 1
begin;
delete from t1;
commit;
show status like "binlog_cache_use";
Variable_name Value
Binlog_cache_use 2
show status like "binlog_cache_disk_use";
Variable_name Value
Binlog_cache_disk_use 1
drop table t1;
create table t1 (c char(10), index (c,c)) engine=innodb;
ERROR 42S21: Duplicate column name 'c'
create table t1 (c1 char(10), c2 char(10), index (c1,c2,c1)) engine=innodb;
......@@ -1775,13 +1784,13 @@ Variable_name Value
Innodb_page_size 16384
show status like "Innodb_rows_deleted";
Variable_name Value
Innodb_rows_deleted 2070
Innodb_rows_deleted 72
show status like "Innodb_rows_inserted";
Variable_name Value
Innodb_rows_inserted 3083
Innodb_rows_inserted 1088
show status like "Innodb_rows_updated";
Variable_name Value
Innodb_rows_updated 886
Innodb_rows_updated 888
show status like "Innodb_row_lock_waits";
Variable_name Value
Innodb_row_lock_waits 0
......
......@@ -13,6 +13,11 @@
-- source include/not_embedded.inc
-- source include/have_innodb.inc
-- source include/have_log_bin.inc
# Disabling it temporarily for statement-based logging since some
# tests are not safe while binlog is on.
-- source include/have_binlog_format_mixed_or_row.inc
#
# Small basic test with ignore
......@@ -53,7 +58,7 @@ INSERT INTO t1 VALUES (1,0,0),(3,1,1),(4,1,1),(8,2,2),(9,2,2),(17,3,2),(22,4,2),
update t1 set parent_id=parent_id+100;
select * from t1 where parent_id=102;
update t1 set id=id+1000;
-- error ER_DUP_ENTRY_WITH_KEY_NAME,1022
-- error ER_DUP_ENTRY,1022
update t1 set id=1024 where id=1009;
select * from t1;
update ignore t1 set id=id+1; # This will change all rows
......@@ -134,13 +139,13 @@ commit;
select n, "after commit" from t1;
commit;
insert into t1 values (5);
-- error ER_DUP_ENTRY_WITH_KEY_NAME
-- error ER_DUP_ENTRY
insert into t1 values (4);
commit;
select n, "after commit" from t1;
set autocommit=1;
insert into t1 values (6);
-- error ER_DUP_ENTRY_WITH_KEY_NAME
-- error ER_DUP_ENTRY
insert into t1 values (4);
select n from t1;
set autocommit=0;
......@@ -214,7 +219,7 @@ drop table t1;
CREATE TABLE t1 (id char(8) not null primary key, val int not null) engine=innodb;
insert into t1 values ('pippo', 12);
-- error ER_DUP_ENTRY_WITH_KEY_NAME
-- error ER_DUP_ENTRY
insert into t1 values ('pippo', 12); # Gives error
delete from t1;
delete from t1 where id = 'pippo';
......@@ -342,9 +347,9 @@ CREATE TABLE t1 (
insert into t1 (ggid,passwd) values ('test1','xxx');
insert into t1 (ggid,passwd) values ('test2','yyy');
-- error ER_DUP_ENTRY_WITH_KEY_NAME
-- error ER_DUP_ENTRY
insert into t1 (ggid,passwd) values ('test2','this will fail');
-- error ER_DUP_ENTRY_WITH_KEY_NAME
-- error ER_DUP_ENTRY
insert into t1 (ggid,id) values ('this will fail',1);
select * from t1 where ggid='test1';
......@@ -353,7 +358,7 @@ select * from t1 where id=2;
replace into t1 (ggid,id) values ('this will work',1);
replace into t1 (ggid,passwd) values ('test2','this will work');
-- error ER_DUP_ENTRY_WITH_KEY_NAME
-- error ER_DUP_ENTRY
update t1 set id=100,ggid='test2' where id=1;
select * from t1;
select * from t1 where id=1;
......@@ -524,7 +529,7 @@ drop table t1;
create table t1 (id int NOT NULL,id2 int NOT NULL,id3 int NOT NULL,dummy1 char(30),primary key (id,id2),index index_id3 (id3)) engine=innodb;
insert into t1 values (0,0,0,'ABCDEFGHIJ'),(2,2,2,'BCDEFGHIJK'),(1,1,1,'CDEFGHIJKL');
LOCK TABLES t1 WRITE;
--error ER_DUP_ENTRY_WITH_KEY_NAME
--error ER_DUP_ENTRY
insert into t1 values (99,1,2,'D'),(1,1,2,'D');
select id from t1;
select id from t1;
......@@ -535,7 +540,7 @@ create table t1 (id int NOT NULL,id2 int NOT NULL,id3 int NOT NULL,dummy1 char(3
insert into t1 values (0,0,0,'ABCDEFGHIJ'),(2,2,2,'BCDEFGHIJK'),(1,1,1,'CDEFGHIJKL');
LOCK TABLES t1 WRITE;
begin;
--error ER_DUP_ENTRY_WITH_KEY_NAME
--error ER_DUP_ENTRY
insert into t1 values (99,1,2,'D'),(1,1,2,'D');
select id from t1;
insert ignore into t1 values (100,1,2,'D'),(1,1,99,'D');
......@@ -754,6 +759,45 @@ select * from t1;
select * from t2;
drop table t1,t2;
#
# Bug#27716 multi-update did partially and has not binlogged
#
CREATE TABLE `t1` (
`a` int(11) NOT NULL auto_increment,
`b` int(11) default NULL,
PRIMARY KEY (`a`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 ;
CREATE TABLE `t2` (
`a` int(11) NOT NULL auto_increment,
`b` int(11) default NULL,
PRIMARY KEY (`a`)
) ENGINE=INNODB DEFAULT CHARSET=latin1 ;
# A. testing multi_update::send_eof() execution branch
insert into t1 values (1,1),(2,2);
insert into t2 values (1,1),(4,4);
reset master;
--error ER_DUP_ENTRY
UPDATE t2,t1 SET t2.a=t1.a+2;
# check
select * from t2 /* must be (3,1), (4,4) */;
show master status /* there must no UPDATE in binlog */;
# B. testing multi_update::send_error() execution branch
delete from t1;
delete from t2;
insert into t1 values (1,2),(3,4),(4,4);
insert into t2 values (1,2),(3,4),(4,4);
reset master;
--error ER_DUP_ENTRY
UPDATE t2,t1 SET t2.a=t2.b where t2.a=t1.a;
show master status /* there must be no UPDATE query event */;
# cleanup bug#27716
drop table t1, t2;
#
# Testing of IFNULL
#
......@@ -1134,7 +1178,7 @@ drop table t2;
# Clean up filename -- embedded server reports whole path without .frm,
# regular server reports relative path with .frm (argh!)
--replace_result \\ / $MYSQL_TEST_DIR . /var/master-data/ / t2.frm t2
--error 1005
--error ER_WRONG_FK_DEF
create table t2 (id int(11) not null, id2 int(11) not null, constraint t1_id_fk foreign key (id2,id) references t1 (id)) engine = innodb;
# bug#3749
......@@ -1147,41 +1191,6 @@ show create table t2;
drop table t2, t1;
#
# Let us test binlog_cache_use and binlog_cache_disk_use status vars.
# Actually this test has nothing to do with innodb per se, it just requires
# transactional table.
#
flush status;
show status like "binlog_cache_use";
show status like "binlog_cache_disk_use";
create table t1 (a int) engine=innodb;
# Now we are going to create transaction which is long enough so its
# transaction binlog will be flushed to disk...
let $1=2000;
disable_query_log;
begin;
while ($1)
{
eval insert into t1 values( $1 );
dec $1;
}
commit;
enable_query_log;
show status like "binlog_cache_use";
show status like "binlog_cache_disk_use";
# Transaction which should not be flushed to disk and so should not
# increase binlog_cache_disk_use.
begin;
delete from t1;
commit;
show status like "binlog_cache_use";
show status like "binlog_cache_disk_use";
drop table t1;
#
# Bug #6126: Duplicate columns in keys gives misleading error message
#
......@@ -1408,7 +1417,7 @@ create table t1 (rowid int not null auto_increment, val int not null,primary
key (rowid), unique(val)) engine=innodb;
replace into t1 (val) values ('1'),('2');
replace into t1 (val) values ('1'),('2');
--error ER_DUP_ENTRY_WITH_KEY_NAME
--error ER_DUP_ENTRY
insert into t1 (val) values ('1'),('2');
select * from t1;
drop table t1;
......@@ -1421,7 +1430,7 @@ create table t1 (a int not null auto_increment primary key, val int) engine=Inno
insert into t1 (val) values (1);
update t1 set a=2 where a=1;
# We should get the following error because InnoDB does not update the counter
--error ER_DUP_ENTRY_WITH_KEY_NAME
--error ER_DUP_ENTRY
insert into t1 (val) values (1);
select * from t1;
drop table t1;
......@@ -1744,13 +1753,13 @@ create table t3 (s1 varchar(2) binary,primary key (s1)) engine=innodb;
create table t4 (s1 char(2) binary,primary key (s1)) engine=innodb;
insert into t1 values (0x41),(0x4120),(0x4100);
-- error ER_DUP_ENTRY_WITH_KEY_NAME
-- error ER_DUP_ENTRY
insert into t2 values (0x41),(0x4120),(0x4100);
insert into t2 values (0x41),(0x4120);
-- error ER_DUP_ENTRY_WITH_KEY_NAME
-- error ER_DUP_ENTRY
insert into t3 values (0x41),(0x4120),(0x4100);
insert into t3 values (0x41),(0x4100);
-- error ER_DUP_ENTRY_WITH_KEY_NAME
-- error ER_DUP_ENTRY
insert into t4 values (0x41),(0x4120),(0x4100);
insert into t4 values (0x41),(0x4100);
select hex(s1) from t1;
......
......@@ -10,12 +10,18 @@
SET storage_engine=InnoDB;
# we do not really care about what gets output-ed, we are only
# we do not really care about what gets printed, we are only
# interested in getting the deadlock resolved according to our
# expectations
-- disable_query_log
-- disable_result_log
# we want to use "-- eval statement1; statement2" which does not work with
# prepared statements. Because this test should not behave differently with
# or without prepared statements we disable them so the test does not fail
# if someone runs ./mysql-test-run.pl --ps-protocol
-- disable_ps_protocol
-- disable_warnings
DROP TABLE IF EXISTS t1, t2, t3, t4, t5_nontrans;
-- enable_warnings
......
......@@ -456,10 +456,9 @@ os_file_handle_error_no_exit(
#undef USE_FILE_LOCK
#define USE_FILE_LOCK
#if defined(UNIV_HOTBACKUP) || defined(__WIN__) || defined(__FreeBSD__) || defined(__NETWARE__)
#if defined(UNIV_HOTBACKUP) || defined(__WIN__) || defined(__NETWARE__)
/* InnoDB Hot Backup does not lock the data files.
* On Windows, mandatory locking is used.
* On FreeBSD with LinuxThreads, advisory locking does not work properly.
*/
# undef USE_FILE_LOCK
#endif
......
......@@ -3,7 +3,6 @@ MYSQL_STORAGE_ENGINE(innobase, innodb, [InnoDB Storage Engine],
MYSQL_PLUGIN_DIRECTORY(innobase, [storage/innobase])
MYSQL_PLUGIN_STATIC(innobase, [libinnobase.a])
MYSQL_PLUGIN_DYNAMIC(innobase, [ha_innodb.la])
MYSQL_PLUGIN_DEPENDS_ON_MYSQL_INTERNALS(innobase, [handler/ha_innodb.cc])
MYSQL_PLUGIN_ACTIONS(innobase, [
AC_CHECK_LIB(rt, aio_read, [innodb_system_libs="-lrt"])
AC_SUBST(innodb_system_libs)
......@@ -41,5 +40,4 @@ MYSQL_PLUGIN_ACTIONS(innobase, [
CFLAGS="$CFLAGS -DUNIV_MUST_NOT_INLINE";;
esac
])
MYSQL_PLUGIN_DEPENDS_ON_MYSQL_INTERNALS(innobase, [handler/ha_innodb.cc])
......@@ -3143,6 +3143,8 @@ next_rec:
dict_table_change_id_in_cache(table, new_id);
}
/* MySQL calls ha_innobase::reset_auto_increment() which does
the same thing. */
dict_table_autoinc_initialize(table, 0);
dict_update_statistics(table);
......
......@@ -4577,3 +4577,169 @@ row_search_check_if_query_cache_permitted(
return(ret);
}
/***********************************************************************
Read the AUTOINC column from the current row. */
static
ib_longlong
row_search_autoinc_read_column(
/*===========================*/
/* out: value read from the column */
dict_index_t* index, /* in: index to read from */
const rec_t* rec, /* in: current rec */
ulint col_no, /* in: column number */
ibool unsigned_type) /* in: signed or unsigned flag */
{
ulint len;
byte* ptr;
const byte* data;
ib_longlong value;
mem_heap_t* heap = NULL;
byte dest[sizeof(value)];
ulint offsets_[REC_OFFS_NORMAL_SIZE];
ulint* offsets = offsets_;
*offsets_ = sizeof offsets_ / sizeof *offsets_;
/* TODO: We have to cast away the const of rec for now. This needs
to be fixed later.*/
offsets = rec_get_offsets(
(rec_t*) rec, index, offsets, ULINT_UNDEFINED, &heap);
/* TODO: We have to cast away the const of rec for now. This needs
to be fixed later.*/
data = rec_get_nth_field((rec_t*)rec, offsets, col_no, &len);
ut_a(len != UNIV_SQL_NULL);
ut_a(len <= sizeof value);
/* Convert integer data from Innobase to a little-endian format,
sign bit restored to normal */
for (ptr = dest + len; ptr != dest; ++data) {
--ptr;
*ptr = *data;
}
if (!unsigned_type) {
dest[len - 1] ^= 128;
}
/* The assumption here is that the AUTOINC value can't be negative.*/
switch (len) {
case 8:
value = *(ib_longlong*) ptr;
break;
case 4:
value = *(ib_uint32_t*) ptr;
break;
case 2:
value = *(uint16 *) ptr;
break;
case 1:
value = *ptr;
break;
default:
ut_error;
}
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
ut_a(value >= 0);
return(value);
}
/***********************************************************************
Get the last row. */
static
const rec_t*
row_search_autoinc_get_rec(
/*=======================*/
/* out: current rec or NULL */
btr_pcur_t* pcur, /* in: the current cursor */
mtr_t* mtr) /* in: mini transaction */
{
do {
const rec_t* rec = btr_pcur_get_rec(pcur);
if (page_rec_is_user_rec(rec)) {
return(rec);
}
} while (btr_pcur_move_to_prev(pcur, mtr));
return(NULL);
}
/***********************************************************************
Read the max AUTOINC value from an index. */
ulint
row_search_max_autoinc(
/*===================*/
/* out: DB_SUCCESS if all OK else
error code, DB_RECORD_NOT_FOUND if
column name can't be found in index */
dict_index_t* index, /* in: index to search */
const char* col_name, /* in: name of autoinc column */
ib_longlong* value) /* out: AUTOINC value read */
{
ulint i;
ulint n_cols;
dict_field_t* dfield = NULL;
ulint error = DB_SUCCESS;
n_cols = dict_index_get_n_ordering_defined_by_user(index);
/* Search the index for the AUTOINC column name */
for (i = 0; i < n_cols; ++i) {
dfield = dict_index_get_nth_field(index, i);
if (strcmp(col_name, dfield->name) == 0) {
break;
}
}
*value = 0;
/* Must find the AUTOINC column name */
if (i < n_cols && dfield) {
mtr_t mtr;
btr_pcur_t pcur;
mtr_start(&mtr);
/* Open at the high/right end (FALSE), and INIT
cursor (TRUE) */
btr_pcur_open_at_index_side(
FALSE, index, BTR_SEARCH_LEAF, &pcur, TRUE, &mtr);
if (page_get_n_recs(btr_pcur_get_page(&pcur)) > 0) {
const rec_t* rec;
rec = row_search_autoinc_get_rec(&pcur, &mtr);
if (rec != NULL) {
ibool unsigned_type = (
dfield->col->prtype & DATA_UNSIGNED);
*value = row_search_autoinc_read_column(
index, rec, i, unsigned_type);
}
}
btr_pcur_close(&pcur);
mtr_commit(&mtr);
} else {
error = DB_RECORD_NOT_FOUND;
}
return(error);
}
......@@ -15,16 +15,34 @@ Created 9/11/1995 Heikki Tuuri
#include "mem0mem.h"
#include "srv0srv.h"
/* number of system calls made during shared latching */
ulint rw_s_system_call_count = 0;
/* number of spin waits on rw-latches,
resulted during shared (read) locks */
ulint rw_s_spin_wait_count = 0;
/* number of OS waits on rw-latches,
resulted during shared (read) locks */
ulint rw_s_os_wait_count = 0;
/* number of unlocks (that unlock shared locks),
set only when UNIV_SYNC_PERF_STAT is defined */
ulint rw_s_exit_count = 0;
/* number of system calls made during exclusive latching */
ulint rw_x_system_call_count = 0;
/* number of spin waits on rw-latches,
resulted during exclusive (write) locks */
ulint rw_x_spin_wait_count = 0;
/* number of OS waits on rw-latches,
resulted during exclusive (write) locks */
ulint rw_x_os_wait_count = 0;
/* number of unlocks (that unlock exclusive locks),
set only when UNIV_SYNC_PERF_STAT is defined */
ulint rw_x_exit_count = 0;
/* The global list of rw-locks */
......
......@@ -115,6 +115,7 @@ ulint mutex_system_call_count = 0;
/* Number of spin waits on mutexes: for performance monitoring */
/* round=one iteration of a spin loop */
ulint mutex_spin_round_count = 0;
ulint mutex_spin_wait_count = 0;
ulint mutex_os_wait_count = 0;
......
......@@ -182,6 +182,8 @@ trx_create(
memset(&trx->xid, 0, sizeof(trx->xid));
trx->xid.formatID = -1;
trx->n_autoinc_rows = 0;
trx_reset_new_rec_lock_info(trx);
return(trx);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment