Commit 817debb6 authored by Andrei Elkin's avatar Andrei Elkin

merging from 5.1-bt rep to local branch

parents f16145a5 fe229e33
......@@ -430,4 +430,24 @@ SELECT b, COUNT(DISTINCT a) FROM t1 GROUP BY b HAVING b is NULL;
b COUNT(DISTINCT a)
NULL 1
DROP TABLE t1;
#
# Bug#50995 Having clause on subquery result produces incorrect results.
#
CREATE TABLE t1
(
id1 INT,
id2 INT NOT NULL,
INDEX id1(id2)
);
INSERT INTO t1 SET id1=1, id2=1;
INSERT INTO t1 SET id1=2, id2=1;
INSERT INTO t1 SET id1=3, id2=1;
SELECT t1.id1,
(SELECT 0 FROM DUAL
WHERE t1.id1=t1.id1) AS amount FROM t1
WHERE t1.id2 = 1
HAVING amount > 0
ORDER BY t1.id1;
id1 amount
DROP TABLE t1;
End of 5.0 tests
......@@ -1161,3 +1161,86 @@ t1 CREATE TABLE `t1` (
PRIMARY KEY (`c1`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1
DROP TABLE t1;
DROP TABLE IF EXISTS t1;
Warnings:
Note 1051 Unknown table 't1'
CREATE TABLE t1 (c1 INTEGER AUTO_INCREMENT, PRIMARY KEY (c1)) ENGINE=InnoDB;
INSERT INTO t1 VALUES (-685113344), (1), (NULL), (NULL);
SELECT * FROM t1;
c1
-685113344
1
2
3
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`c1`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE TABLE t1 (c1 INTEGER AUTO_INCREMENT, PRIMARY KEY (c1)) ENGINE=InnoDB;
INSERT INTO t1 VALUES (-685113344), (2), (NULL), (NULL);
SELECT * FROM t1;
c1
-685113344
2
3
4
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`c1`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE TABLE t1 (c1 INTEGER AUTO_INCREMENT, PRIMARY KEY (c1)) ENGINE=InnoDB;
INSERT INTO t1 VALUES (NULL), (2), (-685113344), (NULL);
INSERT INTO t1 VALUES (4), (5), (6), (NULL);
SELECT * FROM t1;
c1
-685113344
1
2
3
4
5
6
7
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`c1`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE TABLE t1 (c1 INTEGER AUTO_INCREMENT, PRIMARY KEY (c1)) ENGINE=InnoDB;
INSERT INTO t1 VALUES (NULL), (2), (-685113344), (5);
SELECT * FROM t1;
c1
-685113344
1
2
5
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`c1`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE TABLE t1 (c1 INTEGER AUTO_INCREMENT, PRIMARY KEY (c1)) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1), (2), (-685113344), (NULL);
SELECT * FROM t1;
c1
-685113344
1
2
3
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`c1`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=latin1
DROP TABLE t1;
......@@ -442,4 +442,30 @@ INSERT INTO t1 VALUES (1, 1), (2,2), (3, NULL);
SELECT b, COUNT(DISTINCT a) FROM t1 GROUP BY b HAVING b is NULL;
DROP TABLE t1;
--echo #
--echo # Bug#50995 Having clause on subquery result produces incorrect results.
--echo #
CREATE TABLE t1
(
id1 INT,
id2 INT NOT NULL,
INDEX id1(id2)
);
INSERT INTO t1 SET id1=1, id2=1;
INSERT INTO t1 SET id1=2, id2=1;
INSERT INTO t1 SET id1=3, id2=1;
SELECT t1.id1,
(SELECT 0 FROM DUAL
WHERE t1.id1=t1.id1) AS amount FROM t1
WHERE t1.id2 = 1
HAVING amount > 0
ORDER BY t1.id1;
DROP TABLE t1;
--echo End of 5.0 tests
......@@ -631,3 +631,34 @@ REPLACE INTO t1 VALUES (-1);
SELECT * FROM t1;
SHOW CREATE TABLE t1;
DROP TABLE t1;
##
# 49497: Error 1467 (ER_AUTOINC_READ_FAILED) on inserting a negative value
#
DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (c1 INTEGER AUTO_INCREMENT, PRIMARY KEY (c1)) ENGINE=InnoDB;
INSERT INTO t1 VALUES (-685113344), (1), (NULL), (NULL);
SELECT * FROM t1;
SHOW CREATE TABLE t1;
DROP TABLE t1;
CREATE TABLE t1 (c1 INTEGER AUTO_INCREMENT, PRIMARY KEY (c1)) ENGINE=InnoDB;
INSERT INTO t1 VALUES (-685113344), (2), (NULL), (NULL);
SELECT * FROM t1;
SHOW CREATE TABLE t1;
DROP TABLE t1;
CREATE TABLE t1 (c1 INTEGER AUTO_INCREMENT, PRIMARY KEY (c1)) ENGINE=InnoDB;
INSERT INTO t1 VALUES (NULL), (2), (-685113344), (NULL);
INSERT INTO t1 VALUES (4), (5), (6), (NULL);
SELECT * FROM t1;
SHOW CREATE TABLE t1;
DROP TABLE t1;
CREATE TABLE t1 (c1 INTEGER AUTO_INCREMENT, PRIMARY KEY (c1)) ENGINE=InnoDB;
INSERT INTO t1 VALUES (NULL), (2), (-685113344), (5);
SELECT * FROM t1;
SHOW CREATE TABLE t1;
DROP TABLE t1;
CREATE TABLE t1 (c1 INTEGER AUTO_INCREMENT, PRIMARY KEY (c1)) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1), (2), (-685113344), (NULL);
SELECT * FROM t1;
SHOW CREATE TABLE t1;
DROP TABLE t1;
......@@ -1474,9 +1474,21 @@ public:
Item_cond(THD *thd, Item_cond *item);
Item_cond(List<Item> &nlist)
:Item_bool_func(), list(nlist), abort_on_null(0) {}
bool add(Item *item) { return list.push_back(item); }
bool add_at_head(Item *item) { return list.push_front(item); }
void add_at_head(List<Item> *nlist) { list.prepand(nlist); }
bool add(Item *item)
{
DBUG_ASSERT(item);
return list.push_back(item);
}
bool add_at_head(Item *item)
{
DBUG_ASSERT(item);
return list.push_front(item);
}
void add_at_head(List<Item> *nlist)
{
DBUG_ASSERT(nlist->elements);
list.prepand(nlist);
}
bool fix_fields(THD *, Item **ref);
enum Type type() const { return COND_ITEM; }
......
......@@ -8200,7 +8200,8 @@ static Item *eliminate_item_equal(COND *cond, COND_EQUAL *upper_levels,
else
{
DBUG_ASSERT(cond->type() == Item::COND_ITEM);
((Item_cond *) cond)->add_at_head(&eq_list);
if (eq_list.elements)
((Item_cond *) cond)->add_at_head(&eq_list);
}
cond->quick_fix_field();
......@@ -15664,7 +15665,7 @@ static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab)
Item_cond_and *cond=new Item_cond_and();
TABLE *table=join_tab->table;
int error;
int error= 0;
if (!cond)
DBUG_RETURN(TRUE);
......@@ -15682,7 +15683,8 @@ static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab)
cond->fix_fields(thd, (Item**)&cond);
if (join_tab->select)
{
error=(int) cond->add(join_tab->select->cond);
if (join_tab->select->cond)
error=(int) cond->add(join_tab->select->cond);
join_tab->select_cond=join_tab->select->cond=cond;
}
else if ((join_tab->select= make_select(join_tab->table, 0, 0, cond, 0,
......
......@@ -224,6 +224,9 @@ in the free list to the frames.
/* Value in microseconds */
static const int WAIT_FOR_READ = 20000;
/* Number of attemtps made to read in a page in the buffer pool */
static const ulint BUF_PAGE_READ_MAX_RETRIES = 100;
buf_pool_t* buf_pool = NULL; /* The buffer buf_pool of the database */
#ifdef UNIV_DEBUG
......@@ -1160,6 +1163,7 @@ buf_page_get_gen(
ulint fix_type;
ibool success;
ibool must_read;
ulint retries = 0;
ut_ad(mtr);
ut_ad((rw_latch == RW_S_LATCH)
......@@ -1200,7 +1204,29 @@ loop:
return(NULL);
}
buf_read_page(space, offset);
if (buf_read_page(space, offset)) {
retries = 0;
} else if (retries < BUF_PAGE_READ_MAX_RETRIES) {
++retries;
} else {
fprintf(stderr, "InnoDB: Error: Unable"
" to read tablespace %lu page no"
" %lu into the buffer pool after"
" %lu attempts\n"
"InnoDB: The most probable cause"
" of this error may be that the"
" table has been corrupted.\n"
"InnoDB: You can try to fix this"
" problem by using"
" innodb_force_recovery.\n"
"InnoDB: Please see reference manual"
" for more details.\n"
"InnoDB: Aborting...\n",
space, offset,
BUF_PAGE_READ_MAX_RETRIES);
ut_error;
}
#ifdef UNIV_DEBUG
buf_dbg_counter++;
......
......@@ -299,30 +299,27 @@ 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. Does a random read-ahead if it seems
sensible. */
ulint
ibool
buf_read_page(
/*==========*/
/* out: number of page read requests issued: this can
be > 1 if read-ahead occurred */
/* out: TRUE if success, FALSE otherwise */
ulint space, /* in: space id */
ulint offset) /* in: page number */
{
ib_longlong tablespace_version;
ulint count;
ulint count2;
ulint err;
tablespace_version = fil_space_get_version(space);
count = buf_read_ahead_random(space, offset);
buf_read_ahead_random(space, offset);
/* We do the i/o in the synchronous aio mode to save thread
switches: hence TRUE */
count2 = buf_read_page_low(&err, TRUE, BUF_READ_ANY_PAGE, space,
count = buf_read_page_low(&err, TRUE, BUF_READ_ANY_PAGE, space,
tablespace_version, offset);
srv_buf_pool_reads+= count2;
srv_buf_pool_reads+= count;
if (err == DB_TABLESPACE_DELETED) {
ut_print_timestamp(stderr);
fprintf(stderr,
......@@ -336,7 +333,7 @@ buf_read_page(
/* Flush pages from the end of the LRU list if necessary */
buf_flush_free_margin();
return(count + count2);
return(count > 0);
}
/************************************************************************
......
......@@ -2652,9 +2652,9 @@ ha_innobase::innobase_initialize_autoinc()
auto_inc = innobase_get_int_col_max_value(field);
} else {
/* We have no idea what's been passed in to us as the
autoinc column. We set it to the MAX_INT of our table
autoinc type. */
auto_inc = 0xFFFFFFFFFFFFFFFFULL;
autoinc column. We set it to the 0, effectively disabling
updates to the table. */
auto_inc = 0;
ut_print_timestamp(stderr);
fprintf(stderr, " InnoDB: Unable to determine the AUTOINC "
......@@ -2663,7 +2663,7 @@ ha_innobase::innobase_initialize_autoinc()
if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
/* If the recovery level is set so high that writes
are disabled we force the AUTOINC counter to the MAX
are disabled we force the AUTOINC counter to 0
value effectively disabling writes to the table.
Secondly, we avoid reading the table in case the read
results in failure due to a corrupted table/index.
......@@ -2672,7 +2672,10 @@ ha_innobase::innobase_initialize_autoinc()
tables can be dumped with minimal hassle. If an error
were returned in this case, the first attempt to read
the table would fail and subsequent SELECTs would succeed. */
auto_inc = 0;
} else if (field == NULL) {
/* This is a far more serious error, best to avoid
opening the table and return failure. */
my_error(ER_AUTOINC_READ_FAILED, MYF(0));
} else {
dict_index_t* index;
......@@ -2701,7 +2704,7 @@ ha_innobase::innobase_initialize_autoinc()
"InnoDB: Unable to find the AUTOINC column "
"%s in the InnoDB table %s.\n"
"InnoDB: We set the next AUTOINC column "
"value to the maximum possible value,\n"
"value to 0,\n"
"InnoDB: in effect disabling the AUTOINC "
"next value generation.\n"
"InnoDB: You can either set the next "
......@@ -2710,7 +2713,13 @@ ha_innobase::innobase_initialize_autoinc()
"recreating the table.\n",
col_name, index->table->name);
my_error(ER_AUTOINC_READ_FAILED, MYF(0));
/* This will disable the AUTOINC generation. */
auto_inc = 0;
/* We want the open to succeed, so that the user can
take corrective action. ie. reads should succeed but
updates should fail. */
err = DB_SUCCESS;
break;
default:
/* row_search_max_autoinc() should only return
......@@ -3968,11 +3977,17 @@ no_commit:
prebuilt->autoinc_error = DB_SUCCESS;
if ((error = update_auto_increment())) {
/* We don't want to mask autoinc overflow errors. */
if (prebuilt->autoinc_error != DB_SUCCESS) {
error = (int) prebuilt->autoinc_error;
/* Handle the case where the AUTOINC sub-system
failed during initialization. */
if (prebuilt->autoinc_error == DB_UNSUPPORTED) {
error_result = ER_AUTOINC_READ_FAILED;
/* Set the error message to report too. */
my_error(ER_AUTOINC_READ_FAILED, MYF(0));
goto func_exit;
} else if (prebuilt->autoinc_error != DB_SUCCESS) {
error = (int) prebuilt->autoinc_error;
goto report_error;
}
......@@ -7883,7 +7898,10 @@ ha_innobase::innobase_get_autoinc(
*value = dict_table_autoinc_read(prebuilt->table);
/* It should have been initialized during open. */
ut_a(*value != 0);
if (*value == 0) {
prebuilt->autoinc_error = DB_UNSUPPORTED;
dict_table_autoinc_unlock(prebuilt->table);
}
}
return(ulong(prebuilt->autoinc_error));
......@@ -7963,6 +7981,11 @@ ha_innobase::get_auto_increment(
invoking this method. So we are not sure if it's guaranteed to
be 0 or not. */
/* We need the upper limit of the col type to check for
whether we update the table autoinc counter or not. */
ulonglong col_max_value = innobase_get_int_col_max_value(
table->next_number_field);
/* Called for the first time ? */
if (trx->n_autoinc_rows == 0) {
......@@ -7979,6 +8002,11 @@ ha_innobase::get_auto_increment(
/* Not in the middle of a mult-row INSERT. */
} else if (prebuilt->autoinc_last_value == 0) {
set_if_bigger(*first_value, autoinc);
/* Check for -ve values. */
} else if (*first_value > col_max_value && trx->n_autoinc_rows > 0) {
/* Set to next logical value. */
ut_a(autoinc > trx->n_autoinc_rows);
*first_value = (autoinc - trx->n_autoinc_rows) - 1;
}
*nb_reserved_values = trx->n_autoinc_rows;
......@@ -7989,12 +8017,6 @@ ha_innobase::get_auto_increment(
ulonglong need;
ulonglong current;
ulonglong next_value;
ulonglong col_max_value;
/* We need the upper limit of the col type to check for
whether we update the table autoinc counter or not. */
col_max_value = innobase_get_int_col_max_value(
table->next_number_field);
current = *first_value > col_max_value ? autoinc : *first_value;
need = *nb_reserved_values * increment;
......
......@@ -18,12 +18,10 @@ 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. Does a random read-ahead if it seems
sensible. */
ulint
ibool
buf_read_page(
/*==========*/
/* out: number of page read requests issued: this can
be > 1 if read-ahead occurred */
/* out: TRUE if success, FALSE otherwise */
ulint space, /* in: space id */
ulint offset);/* in: page number */
/************************************************************************
......
......@@ -306,6 +306,7 @@ FILE* lock_latest_err_file;
/* Flags for recursive deadlock search */
#define LOCK_VICTIM_IS_START 1
#define LOCK_VICTIM_IS_OTHER 2
#define LOCK_EXCEED_MAX_DEPTH 3
/************************************************************************
Checks if a lock request results in a deadlock. */
......@@ -332,16 +333,18 @@ lock_deadlock_recursive(
was found and we chose some other trx as a
victim: we must do the search again in this
last case because there may be another
deadlock! */
deadlock!
LOCK_EXCEED_MAX_DEPTH if the lock search
exceeds max steps and/or max depth. */
trx_t* start, /* in: recursion starting point */
trx_t* trx, /* in: a transaction waiting for a lock */
lock_t* wait_lock, /* in: the lock trx is waiting to be granted */
ulint* cost, /* in/out: number of calculation steps thus
far: if this exceeds LOCK_MAX_N_STEPS_...
we return LOCK_VICTIM_IS_START */
we return LOCK_EXCEED_MAX_DEPTH */
ulint depth); /* in: recursion depth: if this exceeds
LOCK_MAX_DEPTH_IN_DEADLOCK_CHECK, we
return LOCK_VICTIM_IS_START */
return LOCK_EXCEED_MAX_DEPTH */
/*************************************************************************
Gets the nth bit of a record lock. */
......@@ -3084,8 +3087,6 @@ lock_deadlock_occurs(
lock_t* lock, /* in: lock the transaction is requesting */
trx_t* trx) /* in: transaction */
{
dict_table_t* table;
dict_index_t* index;
trx_t* mark_trx;
ulint ret;
ulint cost = 0;
......@@ -3107,31 +3108,50 @@ retry:
ret = lock_deadlock_recursive(trx, trx, lock, &cost, 0);
if (ret == LOCK_VICTIM_IS_OTHER) {
switch (ret) {
case LOCK_VICTIM_IS_OTHER:
/* We chose some other trx as a victim: retry if there still
is a deadlock */
goto retry;
}
if (ret == LOCK_VICTIM_IS_START) {
if (lock_get_type(lock) & LOCK_TABLE) {
table = lock->un_member.tab_lock.table;
index = NULL;
case LOCK_EXCEED_MAX_DEPTH:
/* If the lock search exceeds the max step
or the max depth, the current trx will be
the victim. Print its information. */
rewind(lock_latest_err_file);
ut_print_timestamp(lock_latest_err_file);
fputs("TOO DEEP OR LONG SEARCH IN THE LOCK TABLE"
" WAITS-FOR GRAPH, WE WILL ROLL BACK"
" FOLLOWING TRANSACTION \n",
lock_latest_err_file);
fputs("\n*** TRANSACTION:\n", lock_latest_err_file);
trx_print(lock_latest_err_file, trx, 3000);
fputs("*** WAITING FOR THIS LOCK TO BE GRANTED:\n",
lock_latest_err_file);
if (lock_get_type(lock) == LOCK_REC) {
lock_rec_print(lock_latest_err_file, lock);
} else {
index = lock->index;
table = index->table;
lock_table_print(lock_latest_err_file, lock);
}
break;
lock_deadlock_found = TRUE;
case LOCK_VICTIM_IS_START:
fputs("*** WE ROLL BACK TRANSACTION (2)\n",
lock_latest_err_file);
break;
return(TRUE);
default:
/* No deadlock detected*/
return(FALSE);
}
return(FALSE);
lock_deadlock_found = TRUE;
return(TRUE);
}
/************************************************************************
......@@ -3147,16 +3167,18 @@ lock_deadlock_recursive(
was found and we chose some other trx as a
victim: we must do the search again in this
last case because there may be another
deadlock! */
deadlock!
LOCK_EXCEED_MAX_DEPTH if the lock search
exceeds max steps and/or max depth. */
trx_t* start, /* in: recursion starting point */
trx_t* trx, /* in: a transaction waiting for a lock */
lock_t* wait_lock, /* in: the lock trx is waiting to be granted */
ulint* cost, /* in/out: number of calculation steps thus
far: if this exceeds LOCK_MAX_N_STEPS_...
we return LOCK_VICTIM_IS_START */
we return LOCK_EXCEED_MAX_DEPTH */
ulint depth) /* in: recursion depth: if this exceeds
LOCK_MAX_DEPTH_IN_DEADLOCK_CHECK, we
return LOCK_VICTIM_IS_START */
return LOCK_EXCEED_MAX_DEPTH */
{
lock_t* lock;
ulint bit_no = ULINT_UNDEFINED;
......@@ -3215,7 +3237,7 @@ lock_deadlock_recursive(
lock_trx = lock->trx;
if (lock_trx == start || too_far) {
if (lock_trx == start) {
/* We came back to the recursion starting
point: a deadlock detected; or we have
......@@ -3262,19 +3284,10 @@ lock_deadlock_recursive(
}
#ifdef UNIV_DEBUG
if (lock_print_waits) {
fputs("Deadlock detected"
" or too long search\n",
fputs("Deadlock detected\n",
stderr);
}
#endif /* UNIV_DEBUG */
if (too_far) {
fputs("TOO DEEP OR LONG SEARCH"
" IN THE LOCK TABLE"
" WAITS-FOR GRAPH\n", ef);
return(LOCK_VICTIM_IS_START);
}
if (trx_weight_cmp(wait_lock->trx,
start) >= 0) {
......@@ -3310,6 +3323,21 @@ lock_deadlock_recursive(
return(LOCK_VICTIM_IS_OTHER);
}
if (too_far) {
#ifdef UNIV_DEBUG
if (lock_print_waits) {
fputs("Deadlock search exceeds"
" max steps or depth.\n",
stderr);
}
#endif /* UNIV_DEBUG */
/* The information about transaction/lock
to be rolled back is available in the top
level. Do not print anything here. */
return(LOCK_EXCEED_MAX_DEPTH);
}
if (lock_trx->que_state == TRX_QUE_LOCK_WAIT) {
/* Another trx ahead has requested lock in an
......
......@@ -759,7 +759,15 @@ next_file:
#ifdef HAVE_READDIR_R
ret = readdir_r(dir, (struct dirent*)dirent_buf, &ent);
if (ret != 0) {
if (ret != 0
#ifdef UNIV_AIX
/* On AIX, only if we got non-NULL 'ent' (result) value and
a non-zero 'ret' (return) value, it indicates a failed
readdir_r() call. An NULL 'ent' with an non-zero 'ret'
would indicate the "end of the directory" is reached. */
&& ent != NULL
#endif
) {
fprintf(stderr,
"InnoDB: cannot read directory %s, error %lu\n",
dirname, (ulong)ret);
......
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