mirror of
https://github.com/MariaDB/server.git
synced 2026-05-10 09:04:29 +02:00
Merge mskold@bk-internal.mysql.com:/home/bk/mysql-5.1-new
into mysql.com:/usr/local/home/marty/MySQL/mysql-5.1-new sql/ha_ndbcluster.cc: Auto merged
This commit is contained in:
commit
7a86236dfd
13 changed files with 315 additions and 57 deletions
|
|
@ -577,6 +577,25 @@ pk1 b c
|
||||||
2 2 17
|
2 2 17
|
||||||
4 4 3
|
4 4 3
|
||||||
6 6 3
|
6 6 3
|
||||||
|
DELETE FROM t1;
|
||||||
|
CREATE UNIQUE INDEX bi ON t1(b);
|
||||||
|
INSERT INTO t1 VALUES
|
||||||
|
(1,1,1),(2,2,2),(3,3,3),(4,4,4),(5,5,5),
|
||||||
|
(6,6,6),(7,7,7),(8,8,8),(9,9,9),(10,10,10);
|
||||||
|
INSERT INTO t1 VALUES(0,1,0),(21,21,21) ON DUPLICATE KEY UPDATE pk1=b+10,b=b+10;
|
||||||
|
select * from t1 order by pk1;
|
||||||
|
pk1 b c
|
||||||
|
2 2 2
|
||||||
|
3 3 3
|
||||||
|
4 4 4
|
||||||
|
5 5 5
|
||||||
|
6 6 6
|
||||||
|
7 7 7
|
||||||
|
8 8 8
|
||||||
|
9 9 9
|
||||||
|
10 10 10
|
||||||
|
11 11 1
|
||||||
|
21 21 21
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
CREATE TABLE t1(a INT) ENGINE=ndb;
|
CREATE TABLE t1(a INT) ENGINE=ndb;
|
||||||
INSERT IGNORE INTO t1 VALUES (1);
|
INSERT IGNORE INTO t1 VALUES (1);
|
||||||
|
|
@ -586,7 +605,7 @@ INSERT IGNORE INTO t1 SELECT a FROM t1;
|
||||||
INSERT IGNORE INTO t1 SELECT a FROM t1;
|
INSERT IGNORE INTO t1 SELECT a FROM t1;
|
||||||
INSERT IGNORE INTO t1 VALUES (1);
|
INSERT IGNORE INTO t1 VALUES (1);
|
||||||
INSERT IGNORE INTO t1 VALUES (1);
|
INSERT IGNORE INTO t1 VALUES (1);
|
||||||
SELECT * FROM t1;
|
SELECT * FROM t1 ORDER BY a;
|
||||||
a
|
a
|
||||||
1
|
1
|
||||||
1
|
1
|
||||||
|
|
@ -606,4 +625,11 @@ a
|
||||||
1
|
1
|
||||||
1
|
1
|
||||||
1
|
1
|
||||||
|
DELETE FROM t1;
|
||||||
|
CREATE UNIQUE INDEX ai ON t1(a);
|
||||||
|
INSERT IGNORE INTO t1 VALUES (1);
|
||||||
|
INSERT IGNORE INTO t1 VALUES (1);
|
||||||
|
SELECT * FROM t1 ORDER BY a;
|
||||||
|
a
|
||||||
|
1
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
|
|
||||||
|
|
@ -19,3 +19,15 @@ gesuchnr benutzer_id
|
||||||
2 1
|
2 1
|
||||||
3 2
|
3 2
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
CREATE TABLE t1(i INT PRIMARY KEY AUTO_INCREMENT,
|
||||||
|
j INT,
|
||||||
|
k INT,
|
||||||
|
UNIQUE INDEX(j)
|
||||||
|
) ENGINE = ndb;
|
||||||
|
INSERT INTO t1 VALUES (1,1,23),(2,2,24);
|
||||||
|
REPLACE INTO t1 (j,k) VALUES (1,42);
|
||||||
|
REPLACE INTO t1 (i,j) VALUES (17,2);
|
||||||
|
SELECT * from t1 ORDER BY i;
|
||||||
|
i j k
|
||||||
|
3 1 42
|
||||||
|
17 2 24
|
||||||
|
|
|
||||||
|
|
@ -591,14 +591,14 @@ DELETE FROM t1 WHERE pk1 = 2 OR pk1 = 4 OR pk1 = 6;
|
||||||
INSERT INTO t1 VALUES(1,1,1),(2,2,17),(3,4,5) ON DUPLICATE KEY UPDATE pk1=b;
|
INSERT INTO t1 VALUES(1,1,1),(2,2,17),(3,4,5) ON DUPLICATE KEY UPDATE pk1=b;
|
||||||
select * from t1 where pk1 = b and b != c order by pk1;
|
select * from t1 where pk1 = b and b != c order by pk1;
|
||||||
|
|
||||||
# The following test case currently does not work
|
# Test handling of duplicate unique
|
||||||
#DELETE FROM t1;
|
DELETE FROM t1;
|
||||||
#CREATE UNIQUE INDEX bi ON t1(b);
|
CREATE UNIQUE INDEX bi ON t1(b);
|
||||||
#INSERT INTO t1 VALUES
|
INSERT INTO t1 VALUES
|
||||||
#(1,1,1),(2,2,2),(3,3,3),(4,4,4),(5,5,5),
|
(1,1,1),(2,2,2),(3,3,3),(4,4,4),(5,5,5),
|
||||||
#(6,6,6),(7,7,7),(8,8,8),(9,9,9),(10,10,10);
|
(6,6,6),(7,7,7),(8,8,8),(9,9,9),(10,10,10);
|
||||||
#INSERT INTO t1 VALUES(0,1,0),(21,21,21) ON DUPLICATE KEY UPDATE pk1=b+10,c=b+10;
|
INSERT INTO t1 VALUES(0,1,0),(21,21,21) ON DUPLICATE KEY UPDATE pk1=b+10,b=b+10;
|
||||||
#select * from t1 order by pk1;
|
select * from t1 order by pk1;
|
||||||
|
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
|
@ -614,7 +614,12 @@ INSERT IGNORE INTO t1 SELECT a FROM t1;
|
||||||
INSERT IGNORE INTO t1 SELECT a FROM t1;
|
INSERT IGNORE INTO t1 SELECT a FROM t1;
|
||||||
INSERT IGNORE INTO t1 VALUES (1);
|
INSERT IGNORE INTO t1 VALUES (1);
|
||||||
INSERT IGNORE INTO t1 VALUES (1);
|
INSERT IGNORE INTO t1 VALUES (1);
|
||||||
SELECT * FROM t1;
|
SELECT * FROM t1 ORDER BY a;
|
||||||
|
DELETE FROM t1;
|
||||||
|
CREATE UNIQUE INDEX ai ON t1(a);
|
||||||
|
INSERT IGNORE INTO t1 VALUES (1);
|
||||||
|
INSERT IGNORE INTO t1 VALUES (1);
|
||||||
|
SELECT * FROM t1 ORDER BY a;
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
|
||||||
# End of 4.1 tests
|
# End of 4.1 tests
|
||||||
|
|
|
||||||
|
|
@ -27,4 +27,15 @@ replace into t1 (gesuchnr,benutzer_id) values (1,1);
|
||||||
select * from t1 order by gesuchnr;
|
select * from t1 order by gesuchnr;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
|
# bug#17431
|
||||||
|
CREATE TABLE t1(i INT PRIMARY KEY AUTO_INCREMENT,
|
||||||
|
j INT,
|
||||||
|
k INT,
|
||||||
|
UNIQUE INDEX(j)
|
||||||
|
) ENGINE = ndb;
|
||||||
|
INSERT INTO t1 VALUES (1,1,23),(2,2,24);
|
||||||
|
REPLACE INTO t1 (j,k) VALUES (1,42);
|
||||||
|
REPLACE INTO t1 (i,j) VALUES (17,2);
|
||||||
|
SELECT * from t1 ORDER BY i;
|
||||||
|
|
||||||
# End of 4.1 tests
|
# End of 4.1 tests
|
||||||
|
|
|
||||||
|
|
@ -1240,6 +1240,7 @@ int ha_ndbcluster::add_index_handle(THD *thd, NDBDICT *dict, KEY *key_info,
|
||||||
{
|
{
|
||||||
char unique_index_name[FN_LEN];
|
char unique_index_name[FN_LEN];
|
||||||
static const char* unique_suffix= "$unique";
|
static const char* unique_suffix= "$unique";
|
||||||
|
m_has_unique_index= TRUE;
|
||||||
strxnmov(unique_index_name, FN_LEN, index_name, unique_suffix, NullS);
|
strxnmov(unique_index_name, FN_LEN, index_name, unique_suffix, NullS);
|
||||||
DBUG_PRINT("info", ("Get handle to unique_index %s", unique_index_name));
|
DBUG_PRINT("info", ("Get handle to unique_index %s", unique_index_name));
|
||||||
const NDBINDEX *index= dict->getIndex(unique_index_name, m_tabname);
|
const NDBINDEX *index= dict->getIndex(unique_index_name, m_tabname);
|
||||||
|
|
@ -1266,7 +1267,7 @@ int ha_ndbcluster::open_indexes(Ndb *ndb, TABLE *tab, bool ignore_error)
|
||||||
KEY* key_info= tab->key_info;
|
KEY* key_info= tab->key_info;
|
||||||
const char **key_name= tab->s->keynames.type_names;
|
const char **key_name= tab->s->keynames.type_names;
|
||||||
DBUG_ENTER("ha_ndbcluster::open_indexes");
|
DBUG_ENTER("ha_ndbcluster::open_indexes");
|
||||||
|
m_has_unique_index= FALSE;
|
||||||
for (i= 0; i < tab->s->keys; i++, key_info++, key_name++)
|
for (i= 0; i < tab->s->keys; i++, key_info++, key_name++)
|
||||||
{
|
{
|
||||||
if ((error= add_index_handle(thd, dict, key_info, *key_name, i)))
|
if ((error= add_index_handle(thd, dict, key_info, *key_name, i)))
|
||||||
|
|
@ -1568,6 +1569,25 @@ int ha_ndbcluster::set_primary_key_from_record(NdbOperation *op, const byte *rec
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ha_ndbcluster::set_index_key_from_record(NdbOperation *op,
|
||||||
|
const byte *record, uint keyno)
|
||||||
|
{
|
||||||
|
KEY* key_info= table->key_info + keyno;
|
||||||
|
KEY_PART_INFO* key_part= key_info->key_part;
|
||||||
|
KEY_PART_INFO* end= key_part+key_info->key_parts;
|
||||||
|
uint i;
|
||||||
|
DBUG_ENTER("set_index_key_from_record");
|
||||||
|
|
||||||
|
for (i= 0; key_part != end; key_part++, i++)
|
||||||
|
{
|
||||||
|
Field* field= key_part->field;
|
||||||
|
if (set_ndb_key(op, field, m_index[keyno].unique_index_attrid_map[i],
|
||||||
|
record+key_part->offset))
|
||||||
|
ERR_RETURN(m_active_trans->getNdbError());
|
||||||
|
}
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
ha_ndbcluster::set_index_key(NdbOperation *op,
|
ha_ndbcluster::set_index_key(NdbOperation *op,
|
||||||
const KEY *key_info,
|
const KEY *key_info,
|
||||||
|
|
@ -1776,46 +1796,154 @@ int ha_ndbcluster::complemented_read(const byte *old_data, byte *new_data,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Peek to check if a particular row already exists
|
* Check that all operations between first and last all
|
||||||
|
* have gotten the errcode
|
||||||
|
* If checking for HA_ERR_KEY_NOT_FOUND then update m_dupkey
|
||||||
|
* for all succeeding operations
|
||||||
|
*/
|
||||||
|
bool ha_ndbcluster::check_all_operations_for_error(NdbTransaction *trans,
|
||||||
|
const NdbOperation *first,
|
||||||
|
const NdbOperation *last,
|
||||||
|
uint errcode)
|
||||||
|
{
|
||||||
|
const NdbOperation *op= first;
|
||||||
|
DBUG_ENTER("ha_ndbcluster::check_all_operations_for_error");
|
||||||
|
|
||||||
|
while(op)
|
||||||
|
{
|
||||||
|
NdbError err= op->getNdbError();
|
||||||
|
if (err.status != NdbError::Success)
|
||||||
|
{
|
||||||
|
if (ndb_to_mysql_error(&err) != (int) errcode)
|
||||||
|
DBUG_RETURN(false);
|
||||||
|
if (op == last) break;
|
||||||
|
op= trans->getNextCompletedOperation(op);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// We found a duplicate
|
||||||
|
if (op->getType() == NdbOperation::UniqueIndexAccess)
|
||||||
|
{
|
||||||
|
if (errcode == HA_ERR_KEY_NOT_FOUND)
|
||||||
|
{
|
||||||
|
NdbIndexOperation *iop= (NdbIndexOperation *) op;
|
||||||
|
const NDBINDEX *index= iop->getIndex();
|
||||||
|
// Find the key_no of the index
|
||||||
|
for(uint i= 0; i<table->s->keys; i++)
|
||||||
|
{
|
||||||
|
if (m_index[i].unique_index == index)
|
||||||
|
{
|
||||||
|
m_dupkey= i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Must have been primary key access
|
||||||
|
DBUG_ASSERT(op->getType() == NdbOperation::PrimaryKeyAccess);
|
||||||
|
if (errcode == HA_ERR_KEY_NOT_FOUND)
|
||||||
|
m_dupkey= table->s->primary_key;
|
||||||
|
}
|
||||||
|
DBUG_RETURN(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DBUG_RETURN(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Peek to check if any rows already exist with conflicting
|
||||||
|
* primary key or unique index values
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int ha_ndbcluster::peek_row(const byte *record)
|
int ha_ndbcluster::peek_indexed_rows(const byte *record)
|
||||||
{
|
{
|
||||||
NdbTransaction *trans= m_active_trans;
|
NdbTransaction *trans= m_active_trans;
|
||||||
NdbOperation *op;
|
NdbOperation *op;
|
||||||
DBUG_ENTER("peek_row");
|
const NdbOperation *first, *last;
|
||||||
|
uint i;
|
||||||
NdbOperation::LockMode lm=
|
|
||||||
(NdbOperation::LockMode)get_ndb_lock_type(m_lock.type);
|
|
||||||
if (!(op= trans->getNdbOperation((const NDBTAB *) m_table)) ||
|
|
||||||
op->readTuple(lm) != 0)
|
|
||||||
ERR_RETURN(trans->getNdbError());
|
|
||||||
|
|
||||||
int res;
|
int res;
|
||||||
if ((res= set_primary_key_from_record(op, record)))
|
DBUG_ENTER("peek_indexed_rows");
|
||||||
ERR_RETURN(trans->getNdbError());
|
|
||||||
|
|
||||||
if (m_use_partition_function)
|
NdbOperation::LockMode lm= NdbOperation::LM_Read;
|
||||||
|
first= NULL;
|
||||||
|
if (table->s->primary_key != MAX_KEY)
|
||||||
{
|
{
|
||||||
uint32 part_id;
|
/*
|
||||||
int error;
|
* Fetch any row with colliding primary key
|
||||||
longlong func_value;
|
*/
|
||||||
if ((error= m_part_info->get_partition_id(m_part_info, &part_id,
|
if (!(op= trans->getNdbOperation((const NDBTAB *) m_table)) ||
|
||||||
&func_value)))
|
op->readTuple(lm) != 0)
|
||||||
{
|
ERR_RETURN(trans->getNdbError());
|
||||||
DBUG_RETURN(error);
|
|
||||||
}
|
first= op;
|
||||||
op->setPartitionId(part_id);
|
if ((res= set_primary_key_from_record(op, record)))
|
||||||
}
|
ERR_RETURN(trans->getNdbError());
|
||||||
|
|
||||||
if (execute_no_commit_ie(this,trans) != 0)
|
if (m_use_partition_function)
|
||||||
|
{
|
||||||
|
uint32 part_id;
|
||||||
|
int error;
|
||||||
|
longlong func_value;
|
||||||
|
if ((error= m_part_info->get_partition_id(m_part_info, &part_id,
|
||||||
|
&func_value)))
|
||||||
|
{
|
||||||
|
DBUG_RETURN(error);
|
||||||
|
}
|
||||||
|
op->setPartitionId(part_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Fetch any rows with colliding unique indexes
|
||||||
|
*/
|
||||||
|
KEY* key_info;
|
||||||
|
KEY_PART_INFO *key_part, *end;
|
||||||
|
for (i= 0, key_info= table->key_info; i < table->s->keys; i++, key_info++)
|
||||||
|
{
|
||||||
|
if (i != table->s->primary_key &&
|
||||||
|
key_info->flags & HA_NOSAME)
|
||||||
|
{
|
||||||
|
// A unique index is defined on table
|
||||||
|
NdbIndexOperation *iop;
|
||||||
|
NDBINDEX *unique_index = (NDBINDEX *) m_index[i].unique_index;
|
||||||
|
key_part= key_info->key_part;
|
||||||
|
end= key_part + key_info->key_parts;
|
||||||
|
if (!(iop= trans->getNdbIndexOperation(unique_index,
|
||||||
|
(const NDBTAB *) m_table)) ||
|
||||||
|
iop->readTuple(lm) != 0)
|
||||||
|
ERR_RETURN(trans->getNdbError());
|
||||||
|
|
||||||
|
if (!first)
|
||||||
|
first= iop;
|
||||||
|
if ((res= set_index_key_from_record(iop, record, i)))
|
||||||
|
ERR_RETURN(trans->getNdbError());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
last= trans->getLastDefinedOperation();
|
||||||
|
if (first)
|
||||||
|
res= execute_no_commit_ie(this,trans);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Table has no keys
|
||||||
|
table->status= STATUS_NOT_FOUND;
|
||||||
|
DBUG_RETURN(HA_ERR_KEY_NOT_FOUND);
|
||||||
|
}
|
||||||
|
if (check_all_operations_for_error(trans, first, last,
|
||||||
|
HA_ERR_KEY_NOT_FOUND))
|
||||||
{
|
{
|
||||||
table->status= STATUS_NOT_FOUND;
|
table->status= STATUS_NOT_FOUND;
|
||||||
DBUG_RETURN(ndb_err(trans));
|
DBUG_RETURN(ndb_err(trans));
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DBUG_PRINT("info", ("m_dupkey %d", m_dupkey));
|
||||||
|
}
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Read one record from NDB using unique secondary index
|
Read one record from NDB using unique secondary index
|
||||||
*/
|
*/
|
||||||
|
|
@ -2310,13 +2438,33 @@ int ha_ndbcluster::write_row(byte *record)
|
||||||
DBUG_ENTER("ha_ndbcluster::write_row");
|
DBUG_ENTER("ha_ndbcluster::write_row");
|
||||||
|
|
||||||
m_write_op= TRUE;
|
m_write_op= TRUE;
|
||||||
if (!m_use_write && m_ignore_dup_key && table_share->primary_key != MAX_KEY)
|
has_auto_increment= (table->next_number_field && record == table->record[0]);
|
||||||
|
if (table_share->primary_key != MAX_KEY)
|
||||||
{
|
{
|
||||||
int peek_res= peek_row(record);
|
/*
|
||||||
|
* Increase any auto_incremented primary key
|
||||||
|
*/
|
||||||
|
if (has_auto_increment)
|
||||||
|
{
|
||||||
|
THD *thd= table->in_use;
|
||||||
|
|
||||||
|
m_skip_auto_increment= FALSE;
|
||||||
|
update_auto_increment();
|
||||||
|
/* Ensure that handler is always called for auto_increment values */
|
||||||
|
thd->next_insert_id= 0;
|
||||||
|
m_skip_auto_increment= !auto_increment_column_changed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If IGNORE the ignore constraint violations on primary and unique keys
|
||||||
|
*/
|
||||||
|
if (!m_use_write && m_ignore_dup_key)
|
||||||
|
{
|
||||||
|
int peek_res= peek_indexed_rows(record);
|
||||||
|
|
||||||
if (!peek_res)
|
if (!peek_res)
|
||||||
{
|
{
|
||||||
m_dupkey= table_share->primary_key;
|
|
||||||
DBUG_RETURN(HA_ERR_FOUND_DUPP_KEY);
|
DBUG_RETURN(HA_ERR_FOUND_DUPP_KEY);
|
||||||
}
|
}
|
||||||
if (peek_res != HA_ERR_KEY_NOT_FOUND)
|
if (peek_res != HA_ERR_KEY_NOT_FOUND)
|
||||||
|
|
@ -2326,7 +2474,6 @@ int ha_ndbcluster::write_row(byte *record)
|
||||||
statistic_increment(thd->status_var.ha_write_count, &LOCK_status);
|
statistic_increment(thd->status_var.ha_write_count, &LOCK_status);
|
||||||
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
|
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
|
||||||
table->timestamp_field->set_time();
|
table->timestamp_field->set_time();
|
||||||
has_auto_increment= (table->next_number_field && record == table->record[0]);
|
|
||||||
|
|
||||||
if (!(op= trans->getNdbOperation((const NDBTAB *) m_table)))
|
if (!(op= trans->getNdbOperation((const NDBTAB *) m_table)))
|
||||||
ERR_RETURN(trans->getNdbError());
|
ERR_RETURN(trans->getNdbError());
|
||||||
|
|
@ -2367,17 +2514,6 @@ int ha_ndbcluster::write_row(byte *record)
|
||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
if (has_auto_increment)
|
|
||||||
{
|
|
||||||
THD *thd= table->in_use;
|
|
||||||
|
|
||||||
m_skip_auto_increment= FALSE;
|
|
||||||
update_auto_increment();
|
|
||||||
/* Ensure that handler is always called for auto_increment values */
|
|
||||||
thd->next_insert_id= 0;
|
|
||||||
m_skip_auto_increment= !auto_increment_column_changed;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((res= set_primary_key_from_record(op, record)))
|
if ((res= set_primary_key_from_record(op, record)))
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
@ -3463,7 +3599,7 @@ int ha_ndbcluster::extra(enum ha_extra_function operation)
|
||||||
break;
|
break;
|
||||||
case HA_EXTRA_IGNORE_DUP_KEY: /* Dup keys don't rollback everything*/
|
case HA_EXTRA_IGNORE_DUP_KEY: /* Dup keys don't rollback everything*/
|
||||||
DBUG_PRINT("info", ("HA_EXTRA_IGNORE_DUP_KEY"));
|
DBUG_PRINT("info", ("HA_EXTRA_IGNORE_DUP_KEY"));
|
||||||
if (current_thd->lex->sql_command == SQLCOM_REPLACE)
|
if (current_thd->lex->sql_command == SQLCOM_REPLACE && !m_has_unique_index)
|
||||||
{
|
{
|
||||||
DBUG_PRINT("info", ("Turning ON use of write instead of insert"));
|
DBUG_PRINT("info", ("Turning ON use of write instead of insert"));
|
||||||
m_use_write= TRUE;
|
m_use_write= TRUE;
|
||||||
|
|
@ -5137,6 +5273,7 @@ ha_ndbcluster::ha_ndbcluster(TABLE_SHARE *table_arg):
|
||||||
m_sorted(FALSE),
|
m_sorted(FALSE),
|
||||||
m_use_write(FALSE),
|
m_use_write(FALSE),
|
||||||
m_ignore_dup_key(FALSE),
|
m_ignore_dup_key(FALSE),
|
||||||
|
m_has_unique_index(FALSE),
|
||||||
m_primary_key_update(FALSE),
|
m_primary_key_update(FALSE),
|
||||||
m_ignore_no_key(FALSE),
|
m_ignore_no_key(FALSE),
|
||||||
m_rows_to_insert((ha_rows) 1),
|
m_rows_to_insert((ha_rows) 1),
|
||||||
|
|
|
||||||
|
|
@ -738,7 +738,11 @@ private:
|
||||||
part_id_range *part_spec);
|
part_id_range *part_spec);
|
||||||
int full_table_scan(byte * buf);
|
int full_table_scan(byte * buf);
|
||||||
|
|
||||||
int peek_row(const byte *record);
|
bool check_all_operations_for_error(NdbTransaction *trans,
|
||||||
|
const NdbOperation *first,
|
||||||
|
const NdbOperation *last,
|
||||||
|
uint errcode);
|
||||||
|
int peek_indexed_rows(const byte *record);
|
||||||
int unique_index_read(const byte *key, uint key_len,
|
int unique_index_read(const byte *key, uint key_len,
|
||||||
byte *buf);
|
byte *buf);
|
||||||
int fetch_next(NdbScanOperation* op);
|
int fetch_next(NdbScanOperation* op);
|
||||||
|
|
@ -766,6 +770,8 @@ private:
|
||||||
int get_ndb_blobs_value(NdbBlob *last_ndb_blob);
|
int get_ndb_blobs_value(NdbBlob *last_ndb_blob);
|
||||||
int set_primary_key(NdbOperation *op, const byte *key);
|
int set_primary_key(NdbOperation *op, const byte *key);
|
||||||
int set_primary_key_from_record(NdbOperation *op, const byte *record);
|
int set_primary_key_from_record(NdbOperation *op, const byte *record);
|
||||||
|
int set_index_key_from_record(NdbOperation *op, const byte *record,
|
||||||
|
uint keyno);
|
||||||
int set_bounds(NdbIndexScanOperation*, uint inx, bool rir,
|
int set_bounds(NdbIndexScanOperation*, uint inx, bool rir,
|
||||||
const key_range *keys[2], uint= 0);
|
const key_range *keys[2], uint= 0);
|
||||||
int key_cmp(uint keynr, const byte * old_row, const byte * new_row);
|
int key_cmp(uint keynr, const byte * old_row, const byte * new_row);
|
||||||
|
|
@ -832,6 +838,7 @@ private:
|
||||||
bool m_sorted;
|
bool m_sorted;
|
||||||
bool m_use_write;
|
bool m_use_write;
|
||||||
bool m_ignore_dup_key;
|
bool m_ignore_dup_key;
|
||||||
|
bool m_has_unique_index;
|
||||||
bool m_primary_key_update;
|
bool m_primary_key_update;
|
||||||
bool m_write_op;
|
bool m_write_op;
|
||||||
bool m_ignore_no_key;
|
bool m_ignore_no_key;
|
||||||
|
|
|
||||||
|
|
@ -129,6 +129,11 @@ public:
|
||||||
*/
|
*/
|
||||||
int deleteTuple();
|
int deleteTuple();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get index object for this operation
|
||||||
|
*/
|
||||||
|
const NdbDictionary::Index * getIndex() const;
|
||||||
|
|
||||||
#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
|
#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
|
||||||
/**
|
/**
|
||||||
* Define the NdbIndexOperation to be a standard operation of type
|
* Define the NdbIndexOperation to be a standard operation of type
|
||||||
|
|
|
||||||
|
|
@ -55,10 +55,33 @@ public:
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Different access types (supported by sub-classes of NdbOperation)
|
||||||
|
*/
|
||||||
|
|
||||||
|
enum Type {
|
||||||
|
PrimaryKeyAccess ///< Read, insert, update, or delete using pk
|
||||||
|
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
|
||||||
|
= 0 // NdbOperation
|
||||||
|
#endif
|
||||||
|
,UniqueIndexAccess ///< Read, update, or delete using unique index
|
||||||
|
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
|
||||||
|
= 1 // NdbIndexOperation
|
||||||
|
#endif
|
||||||
|
,TableScan ///< Full table scan
|
||||||
|
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
|
||||||
|
= 2 // NdbScanOperation
|
||||||
|
#endif
|
||||||
|
,OrderedIndexScan ///< Ordered index scan
|
||||||
|
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
|
||||||
|
= 3 // NdbIndexScanOperation
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lock when performing read
|
* Lock when performing read
|
||||||
*/
|
*/
|
||||||
|
|
||||||
enum LockMode {
|
enum LockMode {
|
||||||
LM_Read ///< Read with shared lock
|
LM_Read ///< Read with shared lock
|
||||||
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
|
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
|
||||||
|
|
@ -720,6 +743,11 @@ public:
|
||||||
*/
|
*/
|
||||||
const NdbDictionary::Table * getTable() const;
|
const NdbDictionary::Table * getTable() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the type of access for this operation
|
||||||
|
*/
|
||||||
|
const Type getType() const;
|
||||||
|
|
||||||
/** @} *********************************************************************/
|
/** @} *********************************************************************/
|
||||||
|
|
||||||
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
|
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
|
||||||
|
|
@ -773,7 +801,7 @@ protected:
|
||||||
int init(const class NdbTableImpl*, NdbTransaction* aCon);
|
int init(const class NdbTableImpl*, NdbTransaction* aCon);
|
||||||
void initInterpreter();
|
void initInterpreter();
|
||||||
|
|
||||||
NdbOperation(Ndb* aNdb);
|
NdbOperation(Ndb* aNdb, Type aType = PrimaryKeyAccess);
|
||||||
virtual ~NdbOperation();
|
virtual ~NdbOperation();
|
||||||
void next(NdbOperation*); // Set next pointer
|
void next(NdbOperation*); // Set next pointer
|
||||||
NdbOperation* next(); // Get next pointer
|
NdbOperation* next(); // Get next pointer
|
||||||
|
|
@ -887,6 +915,8 @@ protected:
|
||||||
* These are the private variables that are defined in the operation objects.
|
* These are the private variables that are defined in the operation objects.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
|
Type m_type;
|
||||||
|
|
||||||
NdbReceiver theReceiver;
|
NdbReceiver theReceiver;
|
||||||
|
|
||||||
NdbError theError; // Errorcode
|
NdbError theError; // Errorcode
|
||||||
|
|
@ -1050,6 +1080,19 @@ NdbOperation::getFirstRecAttr() const
|
||||||
return theReceiver.theFirstRecAttr;
|
return theReceiver.theFirstRecAttr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
Type getType()
|
||||||
|
|
||||||
|
Return Value Return the Type.
|
||||||
|
Remark: Gets type of access.
|
||||||
|
******************************************************************************/
|
||||||
|
inline
|
||||||
|
const NdbOperation::Type
|
||||||
|
NdbOperation::getType() const
|
||||||
|
{
|
||||||
|
return m_type;
|
||||||
|
}
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
OperationStatus Status();
|
OperationStatus Status();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -178,7 +178,8 @@ public:
|
||||||
int restart(bool forceSend = false);
|
int restart(bool forceSend = false);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
NdbScanOperation(Ndb* aNdb);
|
NdbScanOperation(Ndb* aNdb,
|
||||||
|
NdbOperation::Type aType = NdbOperation::TableScan);
|
||||||
virtual ~NdbScanOperation();
|
virtual ~NdbScanOperation();
|
||||||
|
|
||||||
int nextResultImpl(bool fetchAllowed = true, bool forceSend = false);
|
int nextResultImpl(bool fetchAllowed = true, bool forceSend = false);
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@
|
||||||
#include <signaldata/IndxAttrInfo.hpp>
|
#include <signaldata/IndxAttrInfo.hpp>
|
||||||
|
|
||||||
NdbIndexOperation::NdbIndexOperation(Ndb* aNdb) :
|
NdbIndexOperation::NdbIndexOperation(Ndb* aNdb) :
|
||||||
NdbOperation(aNdb),
|
NdbOperation(aNdb, NdbOperation::UniqueIndexAccess),
|
||||||
m_theIndex(NULL)
|
m_theIndex(NULL)
|
||||||
{
|
{
|
||||||
m_tcReqGSN = GSN_TCINDXREQ;
|
m_tcReqGSN = GSN_TCINDXREQ;
|
||||||
|
|
@ -164,6 +164,12 @@ int NdbIndexOperation::interpretedDeleteTuple()
|
||||||
return NdbOperation::interpretedDeleteTuple();
|
return NdbOperation::interpretedDeleteTuple();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const NdbDictionary::Index*
|
||||||
|
NdbIndexOperation::getIndex() const
|
||||||
|
{
|
||||||
|
return m_theIndex;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
NdbIndexOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransactionId)
|
NdbIndexOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransactionId)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,8 @@
|
||||||
* aTable: Pointers to the Table object
|
* aTable: Pointers to the Table object
|
||||||
* Remark: Creat an object of NdbOperation.
|
* Remark: Creat an object of NdbOperation.
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
NdbOperation::NdbOperation(Ndb* aNdb) :
|
NdbOperation::NdbOperation(Ndb* aNdb, NdbOperation::Type aType) :
|
||||||
|
m_type(aType),
|
||||||
theReceiver(aNdb),
|
theReceiver(aNdb),
|
||||||
theErrorLine(0),
|
theErrorLine(0),
|
||||||
theNdb(aNdb),
|
theNdb(aNdb),
|
||||||
|
|
|
||||||
|
|
@ -37,8 +37,8 @@
|
||||||
|
|
||||||
#define DEBUG_NEXT_RESULT 0
|
#define DEBUG_NEXT_RESULT 0
|
||||||
|
|
||||||
NdbScanOperation::NdbScanOperation(Ndb* aNdb) :
|
NdbScanOperation::NdbScanOperation(Ndb* aNdb, NdbOperation::Type aType) :
|
||||||
NdbOperation(aNdb),
|
NdbOperation(aNdb, aType),
|
||||||
m_transConnection(NULL)
|
m_transConnection(NULL)
|
||||||
{
|
{
|
||||||
theParallelism = 0;
|
theParallelism = 0;
|
||||||
|
|
@ -1032,7 +1032,7 @@ NdbScanOperation::getBlobHandle(Uint32 anAttrId)
|
||||||
}
|
}
|
||||||
|
|
||||||
NdbIndexScanOperation::NdbIndexScanOperation(Ndb* aNdb)
|
NdbIndexScanOperation::NdbIndexScanOperation(Ndb* aNdb)
|
||||||
: NdbScanOperation(aNdb)
|
: NdbScanOperation(aNdb, NdbOperation::OrderedIndexScan)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1193,6 +1193,8 @@ NdbTransaction::getNdbIndexScanOperation(const NdbIndexImpl* index,
|
||||||
{
|
{
|
||||||
tOp->m_currentTable = table;
|
tOp->m_currentTable = table;
|
||||||
}
|
}
|
||||||
|
// Mark that this really an NdbIndexScanOperation
|
||||||
|
tOp->m_type = NdbOperation::OrderedIndexScan;
|
||||||
return tOp;
|
return tOp;
|
||||||
} else {
|
} else {
|
||||||
setOperationErrorCodeAbort(4271);
|
setOperationErrorCodeAbort(4271);
|
||||||
|
|
@ -1254,6 +1256,8 @@ NdbTransaction::getNdbScanOperation(const NdbTableImpl * tab)
|
||||||
|
|
||||||
if (tOp->init(tab, this) != -1) {
|
if (tOp->init(tab, this) != -1) {
|
||||||
define_scan_op(tOp);
|
define_scan_op(tOp);
|
||||||
|
// Mark that this NdbIndexScanOperation is used as NdbScanOperation
|
||||||
|
tOp->m_type = NdbOperation::TableScan;
|
||||||
return tOp;
|
return tOp;
|
||||||
} else {
|
} else {
|
||||||
theNdb->releaseScanOperation(tOp);
|
theNdb->releaseScanOperation(tOp);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue