Commit 7d3cb1a4 authored by unknown's avatar unknown

Merge mskold@bk-internal.mysql.com:/home/bk/mysql-5.0

into  mysql.com:/windows/Linux_space/MySQL/mysql-5.0-ndb


ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp:
  Auto merged
ndb/tools/ndb_config.cpp:
  Auto merged
sql/ha_ndbcluster.cc:
  Auto merged
parents 4ec84721 d9540e74
...@@ -140,7 +140,40 @@ b int unsigned not null, ...@@ -140,7 +140,40 @@ b int unsigned not null,
c int unsigned, c int unsigned,
UNIQUE USING HASH (b, c) UNIQUE USING HASH (b, c)
) engine=ndbcluster; ) engine=ndbcluster;
ERROR 42000: Column 'c' is used with UNIQUE or INDEX but is not defined as NOT NULL Warnings:
Warning 1121 Ndb does not support unique index on NULL valued attributes, index access with NULL value will become full table scan
insert t2 values(1,1,NULL),(2,2,2),(3,3,NULL),(4,4,4),(5,5,NULL),(6,6,6),(7,7,NULL),(8,3,NULL),(9,3,NULL);
select * from t2 where c IS NULL order by a;
a b c
1 1 NULL
3 3 NULL
5 5 NULL
7 7 NULL
8 3 NULL
9 3 NULL
select * from t2 where b = 3 AND c IS NULL order by a;
a b c
3 3 NULL
8 3 NULL
9 3 NULL
select * from t2 where (b = 3 OR b = 5) AND c IS NULL order by a;
a b c
3 3 NULL
5 5 NULL
8 3 NULL
9 3 NULL
set @old_ecpd = @@session.engine_condition_pushdown;
set engine_condition_pushdown = true;
explain select * from t2 where (b = 3 OR b = 5) AND c IS NULL AND a < 9 order by a;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 range PRIMARY,b PRIMARY 4 NULL 1 Using where with pushed condition
select * from t2 where (b = 3 OR b = 5) AND c IS NULL AND a < 9 order by a;
a b c
3 3 NULL
5 5 NULL
8 3 NULL
set engine_condition_pushdown = @old_ecpd;
drop table t2;
CREATE TABLE t3 ( CREATE TABLE t3 (
a int unsigned NOT NULL, a int unsigned NOT NULL,
b int unsigned not null, b int unsigned not null,
......
...@@ -17,8 +17,17 @@ pk1 b c ...@@ -17,8 +17,17 @@ pk1 b c
0 0 0 0 0 0
2 2 2 2 2 2
4 1 1 4 1 1
UPDATE t1 set pk1 = 4 where pk1 = 2;
ERROR 23000: Duplicate entry '4' for key 1
UPDATE IGNORE t1 set pk1 = 4 where pk1 = 2;
select * from t1 order by pk1;
pk1 b c
0 0 0
2 2 2
4 1 1
UPDATE t1 set pk1 = 1, c = 2 where pk1 = 4; UPDATE t1 set pk1 = 1, c = 2 where pk1 = 4;
ERROR 23000: Duplicate entry '' for key 0 ERROR 23000: Duplicate entry '' for key 0
UPDATE IGNORE t1 set pk1 = 1, c = 2 where pk1 = 4;
select * from t1 order by pk1; select * from t1 order by pk1;
pk1 b c pk1 b c
0 0 0 0 0 0
......
...@@ -85,7 +85,6 @@ select * from t2 order by a; ...@@ -85,7 +85,6 @@ select * from t2 order by a;
drop table t2; drop table t2;
-- error 1121
CREATE TABLE t2 ( CREATE TABLE t2 (
a int unsigned NOT NULL PRIMARY KEY, a int unsigned NOT NULL PRIMARY KEY,
b int unsigned not null, b int unsigned not null,
...@@ -93,6 +92,20 @@ CREATE TABLE t2 ( ...@@ -93,6 +92,20 @@ CREATE TABLE t2 (
UNIQUE USING HASH (b, c) UNIQUE USING HASH (b, c)
) engine=ndbcluster; ) engine=ndbcluster;
insert t2 values(1,1,NULL),(2,2,2),(3,3,NULL),(4,4,4),(5,5,NULL),(6,6,6),(7,7,NULL),(8,3,NULL),(9,3,NULL);
select * from t2 where c IS NULL order by a;
select * from t2 where b = 3 AND c IS NULL order by a;
select * from t2 where (b = 3 OR b = 5) AND c IS NULL order by a;
set @old_ecpd = @@session.engine_condition_pushdown;
set engine_condition_pushdown = true;
explain select * from t2 where (b = 3 OR b = 5) AND c IS NULL AND a < 9 order by a;
select * from t2 where (b = 3 OR b = 5) AND c IS NULL AND a < 9 order by a;
set engine_condition_pushdown = @old_ecpd;
drop table t2;
# #
# Show use of PRIMARY KEY USING HASH indexes # Show use of PRIMARY KEY USING HASH indexes
# #
......
...@@ -23,8 +23,13 @@ UPDATE t1 set b = c; ...@@ -23,8 +23,13 @@ UPDATE t1 set b = c;
select * from t1 order by pk1; select * from t1 order by pk1;
UPDATE t1 set pk1 = 4 where pk1 = 1; UPDATE t1 set pk1 = 4 where pk1 = 1;
select * from t1 order by pk1; select * from t1 order by pk1;
--error 1062
UPDATE t1 set pk1 = 4 where pk1 = 2;
UPDATE IGNORE t1 set pk1 = 4 where pk1 = 2;
select * from t1 order by pk1;
-- error 1062 -- error 1062
UPDATE t1 set pk1 = 1, c = 2 where pk1 = 4; UPDATE t1 set pk1 = 1, c = 2 where pk1 = 4;
UPDATE IGNORE t1 set pk1 = 1, c = 2 where pk1 = 4;
select * from t1 order by pk1; select * from t1 order by pk1;
UPDATE t1 set pk1 = pk1 + 10; UPDATE t1 set pk1 = pk1 + 10;
select * from t1 order by pk1; select * from t1 order by pk1;
......
...@@ -65,6 +65,5 @@ SocketInputStream::gets(char * buf, int bufLen) { ...@@ -65,6 +65,5 @@ SocketInputStream::gets(char * buf, int bufLen) {
if(res == -1) if(res == -1)
return 0; return 0;
return buf; return buf;
} }
...@@ -53,10 +53,6 @@ readln_socket(NDB_SOCKET_TYPE socket, int timeout_millis, ...@@ -53,10 +53,6 @@ readln_socket(NDB_SOCKET_TYPE socket, int timeout_millis,
if(buflen <= 1) if(buflen <= 1)
return 0; return 0;
int sock_flags= fcntl(socket, F_GETFL);
if(fcntl(socket, F_SETFL, sock_flags | O_NONBLOCK) == -1)
return -1;
fd_set readset; fd_set readset;
FD_ZERO(&readset); FD_ZERO(&readset);
FD_SET(socket, &readset); FD_SET(socket, &readset);
...@@ -71,43 +67,70 @@ readln_socket(NDB_SOCKET_TYPE socket, int timeout_millis, ...@@ -71,43 +67,70 @@ readln_socket(NDB_SOCKET_TYPE socket, int timeout_millis,
} }
if(selectRes == -1){ if(selectRes == -1){
fcntl(socket, F_SETFL, sock_flags);
return -1; return -1;
} }
const int t = recv(socket, buf, buflen, MSG_PEEK); char* ptr = buf;
int len = buflen;
if(t < 1) do
{ {
fcntl(socket, F_SETFL, sock_flags); int t;
return -1; while((t = recv(socket, ptr, len, MSG_PEEK)) == -1 && errno == EINTR);
}
if(t < 1)
{
return -1;
}
for(int i=0; i< t;i++)
{ for(int i = 0; i<t; i++)
if(buf[i] == '\n'){ {
int r= recv(socket, buf, i+1, 0); if(ptr[i] == '\n')
buf[i+1]= 0; {
if(r < 1) { /**
fcntl(socket, F_SETFL, sock_flags); * Now consume
return -1; */
for (len = 1 + i; len; )
{
while ((t = recv(socket, ptr, len, 0)) == -1 && errno == EINTR);
if (t < 1)
return -1;
ptr += t;
len -= t;
}
if (i > 0 && buf[i-1] == '\r')
{
buf[i-1] = '\n';
ptr--;
}
ptr[0]= 0;
return ptr - buf;
} }
}
if(i > 0 && buf[i-1] == '\r'){
buf[i-1] = '\n'; for (int tmp = t; tmp; )
buf[i]= '\0'; {
while ((t = recv(socket, ptr, tmp, 0)) == -1 && errno == EINTR);
if (t < 1)
{
return -1;
} }
ptr += t;
fcntl(socket, F_SETFL, sock_flags); len -= t;
return r; tmp -= t;
} }
}
int r= recv(socket, buf, t, 0); FD_ZERO(&readset);
if(r>=0) FD_SET(socket, &readset);
buf[r] = 0; timeout.tv_sec = (timeout_millis / 1000);
fcntl(socket, F_SETFL, sock_flags); timeout.tv_usec = (timeout_millis % 1000) * 1000;
return r; const int selectRes = select(socket + 1, &readset, 0, 0, &timeout);
if(selectRes != 1){
return -1;
}
} while (len > 0);
return -1;
} }
extern "C" extern "C"
......
...@@ -697,6 +697,7 @@ Cmvmi::execTEST_ORD(Signal * signal){ ...@@ -697,6 +697,7 @@ Cmvmi::execTEST_ORD(Signal * signal){
// Do nothing // Do nothing
break; break;
} }
globalSignalLoggers.flushSignalLog();
} }
#endif #endif
......
...@@ -1893,7 +1893,7 @@ runDictOps(NDBT_Context* ctx, NDBT_Step* step) ...@@ -1893,7 +1893,7 @@ runDictOps(NDBT_Context* ctx, NDBT_Step* step)
// create indexes // create indexes
const char** indlist = NDBT_Tables::getIndexes(tabName); const char** indlist = NDBT_Tables::getIndexes(tabName);
uint indnum = 0; uint indnum = 0;
while (*indlist != 0) { while (indlist != 0 && *indlist != 0) {
uint count = 0; uint count = 0;
try_create_index: try_create_index:
count++; count++;
......
...@@ -510,7 +510,7 @@ args: -n TemporaryTables T1 T6 T7 T8 ...@@ -510,7 +510,7 @@ args: -n TemporaryTables T1 T6 T7 T8
max-time: 1500 max-time: 1500
cmd: testDict cmd: testDict
args: -n Restart_NR2 T1 args: -n Restart_NR2 T1 I3
# #
# TEST NDBAPI # TEST NDBAPI
......
...@@ -37,7 +37,6 @@ static int g_verbose = 0; ...@@ -37,7 +37,6 @@ static int g_verbose = 0;
static int try_reconnect = 3; static int try_reconnect = 3;
static int g_nodes, g_connections, g_section; static int g_nodes, g_connections, g_section;
static const char * g_connectstring = 0;
static const char * g_query = 0; static const char * g_query = 0;
static int g_nodeid = 0; static int g_nodeid = 0;
...@@ -486,7 +485,7 @@ fetch_configuration() ...@@ -486,7 +485,7 @@ fetch_configuration()
ndb_mgm_set_error_stream(mgm, stderr); ndb_mgm_set_error_stream(mgm, stderr);
if (ndb_mgm_set_connectstring(mgm, g_connectstring)) if (ndb_mgm_set_connectstring(mgm, opt_connect_str))
{ {
fprintf(stderr, "* %5d: %s\n", fprintf(stderr, "* %5d: %s\n",
ndb_mgm_get_latest_error(mgm), ndb_mgm_get_latest_error(mgm),
......
...@@ -1059,6 +1059,7 @@ int ha_ndbcluster::build_index_list(Ndb *ndb, TABLE *tab, enum ILBP phase) ...@@ -1059,6 +1059,7 @@ int ha_ndbcluster::build_index_list(Ndb *ndb, TABLE *tab, enum ILBP phase)
int error= 0; int error= 0;
const char *index_name; const char *index_name;
char unique_index_name[FN_LEN]; char unique_index_name[FN_LEN];
bool null_in_unique_index= false;
static const char* unique_suffix= "$unique"; static const char* unique_suffix= "$unique";
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;
...@@ -1096,8 +1097,14 @@ int ha_ndbcluster::build_index_list(Ndb *ndb, TABLE *tab, enum ILBP phase) ...@@ -1096,8 +1097,14 @@ int ha_ndbcluster::build_index_list(Ndb *ndb, TABLE *tab, enum ILBP phase)
error= create_unique_index(unique_index_name, key_info); error= create_unique_index(unique_index_name, key_info);
break; break;
case UNIQUE_INDEX: case UNIQUE_INDEX:
if (!(error= check_index_fields_not_null(i))) if (check_index_fields_not_null(i))
error= create_unique_index(unique_index_name, key_info); {
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_NULL_COLUMN_IN_INDEX,
"Ndb does not support unique index on NULL valued attributes, index access with NULL value will become full table scan");
null_in_unique_index= true;
}
error= create_unique_index(unique_index_name, key_info);
break; break;
case ORDERED_INDEX: case ORDERED_INDEX:
error= create_ordered_index(index_name, key_info); error= create_ordered_index(index_name, key_info);
...@@ -1129,6 +1136,11 @@ int ha_ndbcluster::build_index_list(Ndb *ndb, TABLE *tab, enum ILBP phase) ...@@ -1129,6 +1136,11 @@ int ha_ndbcluster::build_index_list(Ndb *ndb, TABLE *tab, enum ILBP phase)
m_index[i].unique_index= (void *) index; m_index[i].unique_index= (void *) index;
error= fix_unique_index_attr_order(m_index[i], index, key_info); error= fix_unique_index_attr_order(m_index[i], index, key_info);
} }
if (idx_type == UNIQUE_INDEX &&
phase != ILBP_CREATE &&
check_index_fields_not_null(i))
null_in_unique_index= true;
m_index[i].null_in_unique_index= null_in_unique_index;
} }
DBUG_RETURN(error); DBUG_RETURN(error);
...@@ -1150,7 +1162,7 @@ NDB_INDEX_TYPE ha_ndbcluster::get_index_type_from_table(uint inx) const ...@@ -1150,7 +1162,7 @@ NDB_INDEX_TYPE ha_ndbcluster::get_index_type_from_table(uint inx) const
ORDERED_INDEX); ORDERED_INDEX);
} }
int ha_ndbcluster::check_index_fields_not_null(uint inx) bool ha_ndbcluster::check_index_fields_not_null(uint inx)
{ {
KEY* key_info= table->key_info + inx; KEY* key_info= table->key_info + inx;
KEY_PART_INFO* key_part= key_info->key_part; KEY_PART_INFO* key_part= key_info->key_part;
...@@ -1161,14 +1173,10 @@ int ha_ndbcluster::check_index_fields_not_null(uint inx) ...@@ -1161,14 +1173,10 @@ int ha_ndbcluster::check_index_fields_not_null(uint inx)
{ {
Field* field= key_part->field; Field* field= key_part->field;
if (field->maybe_null()) if (field->maybe_null())
{ DBUG_RETURN(true);
my_printf_error(ER_NULL_COLUMN_IN_INDEX,ER(ER_NULL_COLUMN_IN_INDEX),
MYF(0),field->field_name);
DBUG_RETURN(ER_NULL_COLUMN_IN_INDEX);
}
} }
DBUG_RETURN(0); DBUG_RETURN(false);
} }
void ha_ndbcluster::release_metadata() void ha_ndbcluster::release_metadata()
...@@ -1261,6 +1269,12 @@ inline NDB_INDEX_TYPE ha_ndbcluster::get_index_type(uint idx_no) const ...@@ -1261,6 +1269,12 @@ inline NDB_INDEX_TYPE ha_ndbcluster::get_index_type(uint idx_no) const
return m_index[idx_no].type; return m_index[idx_no].type;
} }
inline bool ha_ndbcluster::has_null_in_unique_index(uint idx_no) const
{
DBUG_ASSERT(idx_no < MAX_KEY);
return m_index[idx_no].null_in_unique_index;
}
/* /*
Get the flags for an index Get the flags for an index
...@@ -2089,6 +2103,42 @@ int ha_ndbcluster::ordered_index_scan(const key_range *start_key, ...@@ -2089,6 +2103,42 @@ int ha_ndbcluster::ordered_index_scan(const key_range *start_key,
DBUG_RETURN(next_result(buf)); DBUG_RETURN(next_result(buf));
} }
/*
Unique index scan in NDB (full table scan with scan filter)
*/
int ha_ndbcluster::unique_index_scan(const KEY* key_info,
const byte *key,
uint key_len,
byte *buf)
{
int res;
NdbScanOperation *op;
NdbTransaction *trans= m_active_trans;
DBUG_ENTER("unique_index_scan");
DBUG_PRINT("enter", ("Starting new scan on %s", m_tabname));
NdbOperation::LockMode lm=
(NdbOperation::LockMode)get_ndb_lock_type(m_lock.type);
bool need_pk = (lm == NdbOperation::LM_Read);
if (!(op=trans->getNdbScanOperation((const NDBTAB *) m_table)) ||
op->readTuples(lm,
(need_pk)?NdbScanOperation::SF_KeyInfo:0,
parallelism))
ERR_RETURN(trans->getNdbError());
m_active_cursor= op;
if (generate_scan_filter_from_key(op, key_info, key, key_len, buf))
DBUG_RETURN(ndb_err(trans));
if ((res= define_read_attrs(buf, op)))
DBUG_RETURN(res);
if (execute_no_commit(this,trans,false) != 0)
DBUG_RETURN(ndb_err(trans));
DBUG_PRINT("exit", ("Scan started successfully"));
DBUG_RETURN(next_result(buf));
}
/* /*
Start full table scan in NDB Start full table scan in NDB
*/ */
...@@ -2337,6 +2387,21 @@ int ha_ndbcluster::update_row(const byte *old_data, byte *new_data) ...@@ -2337,6 +2387,21 @@ int ha_ndbcluster::update_row(const byte *old_data, byte *new_data)
uint i; uint i;
DBUG_ENTER("update_row"); DBUG_ENTER("update_row");
/*
* If IGNORE the ignore constraint violations on primary and unique keys
*/
if (m_ignore_dup_key)
{
int peek_res= peek_indexed_rows(new_data);
if (!peek_res)
{
DBUG_RETURN(HA_ERR_FOUND_DUPP_KEY);
}
if (peek_res != HA_ERR_KEY_NOT_FOUND)
DBUG_RETURN(peek_res);
}
statistic_increment(thd->status_var.ha_update_count, &LOCK_status); statistic_increment(thd->status_var.ha_update_count, &LOCK_status);
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE) if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
{ {
...@@ -2763,7 +2828,7 @@ int ha_ndbcluster::index_read(byte *buf, ...@@ -2763,7 +2828,7 @@ int ha_ndbcluster::index_read(byte *buf,
} }
else if (type == UNIQUE_INDEX) else if (type == UNIQUE_INDEX)
{ {
DBUG_RETURN(1); DBUG_RETURN(unique_index_scan(key_info, key, key_len, buf));
} }
break; break;
case ORDERED_INDEX: case ORDERED_INDEX:
...@@ -2856,12 +2921,13 @@ int ha_ndbcluster::read_range_first_to_buf(const key_range *start_key, ...@@ -2856,12 +2921,13 @@ int ha_ndbcluster::read_range_first_to_buf(const key_range *start_key,
bool eq_r, bool sorted, bool eq_r, bool sorted,
byte* buf) byte* buf)
{ {
KEY* key_info; ndb_index_type type= get_index_type(active_index);
KEY* key_info;
int error= 1; int error= 1;
DBUG_ENTER("ha_ndbcluster::read_range_first_to_buf"); DBUG_ENTER("ha_ndbcluster::read_range_first_to_buf");
DBUG_PRINT("info", ("eq_r: %d, sorted: %d", eq_r, sorted)); DBUG_PRINT("info", ("eq_r: %d, sorted: %d", eq_r, sorted));
switch (get_index_type(active_index)){ switch (type){
case PRIMARY_KEY_ORDERED_INDEX: case PRIMARY_KEY_ORDERED_INDEX:
case PRIMARY_KEY_INDEX: case PRIMARY_KEY_INDEX:
key_info= table->key_info + active_index; key_info= table->key_info + active_index;
...@@ -2887,6 +2953,14 @@ int ha_ndbcluster::read_range_first_to_buf(const key_range *start_key, ...@@ -2887,6 +2953,14 @@ int ha_ndbcluster::read_range_first_to_buf(const key_range *start_key,
error= unique_index_read(start_key->key, start_key->length, buf); error= unique_index_read(start_key->key, start_key->length, buf);
DBUG_RETURN(error == HA_ERR_KEY_NOT_FOUND ? HA_ERR_END_OF_FILE : error); DBUG_RETURN(error == HA_ERR_KEY_NOT_FOUND ? HA_ERR_END_OF_FILE : error);
} }
else if (type == UNIQUE_INDEX)
{
error= unique_index_scan(key_info,
start_key->key,
start_key->length,
buf);
DBUG_RETURN(error == HA_ERR_KEY_NOT_FOUND ? HA_ERR_END_OF_FILE : error);
}
break; break;
default: default:
break; break;
...@@ -6117,6 +6191,30 @@ ha_ndbcluster::release_completed_operations(NdbTransaction *trans, ...@@ -6117,6 +6191,30 @@ ha_ndbcluster::release_completed_operations(NdbTransaction *trans,
trans->releaseCompletedOperations(); trans->releaseCompletedOperations();
} }
bool
ha_ndbcluster::null_value_index_search(KEY_MULTI_RANGE *ranges,
KEY_MULTI_RANGE *end_range,
HANDLER_BUFFER *buffer)
{
DBUG_ENTER("null_value_index_search");
KEY* key_info= table->key_info + active_index;
KEY_MULTI_RANGE *range= ranges;
ulong reclength= table->s->reclength;
byte *curr= (byte*)buffer->buffer;
byte *end_of_buffer= (byte*)buffer->buffer_end;
for (; range<end_range && curr+reclength <= end_of_buffer;
range++)
{
const byte *key= range->start_key.key;
uint key_len= range->start_key.length;
if (check_null_in_key(key_info, key, key_len))
DBUG_RETURN(true);
curr += reclength;
}
DBUG_RETURN(false);
}
int int
ha_ndbcluster::read_multi_range_first(KEY_MULTI_RANGE **found_range_p, ha_ndbcluster::read_multi_range_first(KEY_MULTI_RANGE **found_range_p,
KEY_MULTI_RANGE *ranges, KEY_MULTI_RANGE *ranges,
...@@ -6133,11 +6231,14 @@ ha_ndbcluster::read_multi_range_first(KEY_MULTI_RANGE **found_range_p, ...@@ -6133,11 +6231,14 @@ ha_ndbcluster::read_multi_range_first(KEY_MULTI_RANGE **found_range_p,
NdbOperation* op; NdbOperation* op;
Thd_ndb *thd_ndb= get_thd_ndb(current_thd); Thd_ndb *thd_ndb= get_thd_ndb(current_thd);
if (uses_blob_value(m_retrieve_all_fields)) /**
* blobs and unique hash index with NULL can't be batched currently
*/
if (uses_blob_value(m_retrieve_all_fields) ||
(index_type == UNIQUE_INDEX &&
has_null_in_unique_index(active_index) &&
null_value_index_search(ranges, ranges+range_count, buffer)))
{ {
/**
* blobs can't be batched currently
*/
m_disable_multi_read= TRUE; m_disable_multi_read= TRUE;
DBUG_RETURN(handler::read_multi_range_first(found_range_p, DBUG_RETURN(handler::read_multi_range_first(found_range_p,
ranges, ranges,
...@@ -6193,7 +6294,6 @@ ha_ndbcluster::read_multi_range_first(KEY_MULTI_RANGE **found_range_p, ...@@ -6193,7 +6294,6 @@ ha_ndbcluster::read_multi_range_first(KEY_MULTI_RANGE **found_range_p,
goto range; goto range;
/* fall through */ /* fall through */
case PRIMARY_KEY_INDEX: case PRIMARY_KEY_INDEX:
{
multi_range_curr->range_flag |= UNIQUE_RANGE; multi_range_curr->range_flag |= UNIQUE_RANGE;
if ((op= m_active_trans->getNdbOperation(tab)) && if ((op= m_active_trans->getNdbOperation(tab)) &&
!op->readTuple(lm) && !op->readTuple(lm) &&
...@@ -6204,8 +6304,6 @@ ha_ndbcluster::read_multi_range_first(KEY_MULTI_RANGE **found_range_p, ...@@ -6204,8 +6304,6 @@ ha_ndbcluster::read_multi_range_first(KEY_MULTI_RANGE **found_range_p,
else else
ERR_RETURN(op ? op->getNdbError() : m_active_trans->getNdbError()); ERR_RETURN(op ? op->getNdbError() : m_active_trans->getNdbError());
break; break;
}
break;
case UNIQUE_ORDERED_INDEX: case UNIQUE_ORDERED_INDEX:
if (!(multi_range_curr->start_key.length == key_info->key_length && if (!(multi_range_curr->start_key.length == key_info->key_length &&
multi_range_curr->start_key.flag == HA_READ_KEY_EXACT && multi_range_curr->start_key.flag == HA_READ_KEY_EXACT &&
...@@ -6214,18 +6312,16 @@ ha_ndbcluster::read_multi_range_first(KEY_MULTI_RANGE **found_range_p, ...@@ -6214,18 +6312,16 @@ ha_ndbcluster::read_multi_range_first(KEY_MULTI_RANGE **found_range_p,
goto range; goto range;
/* fall through */ /* fall through */
case UNIQUE_INDEX: case UNIQUE_INDEX:
{
multi_range_curr->range_flag |= UNIQUE_RANGE; multi_range_curr->range_flag |= UNIQUE_RANGE;
if ((op= m_active_trans->getNdbIndexOperation(unique_idx, tab)) && if ((op= m_active_trans->getNdbIndexOperation(unique_idx, tab)) &&
!op->readTuple(lm) && !op->readTuple(lm) &&
!set_index_key(op, key_info, multi_range_curr->start_key.key) && !set_index_key(op, key_info, multi_range_curr->start_key.key) &&
!define_read_attrs(curr, op) && !define_read_attrs(curr, op) &&
(op->setAbortOption(AO_IgnoreError), TRUE)) (op->setAbortOption(AO_IgnoreError), TRUE))
curr += reclength; curr += reclength;
else else
ERR_RETURN(op ? op->getNdbError() : m_active_trans->getNdbError()); ERR_RETURN(op ? op->getNdbError() : m_active_trans->getNdbError());
break; break;
}
case ORDERED_INDEX: case ORDERED_INDEX:
{ {
range: range:
...@@ -7968,31 +8064,12 @@ ha_ndbcluster::generate_scan_filter(Ndb_cond_stack *ndb_cond_stack, ...@@ -7968,31 +8064,12 @@ ha_ndbcluster::generate_scan_filter(Ndb_cond_stack *ndb_cond_stack,
NdbScanOperation *op) NdbScanOperation *op)
{ {
DBUG_ENTER("generate_scan_filter"); DBUG_ENTER("generate_scan_filter");
if (ndb_cond_stack) if (ndb_cond_stack)
{ {
DBUG_PRINT("info", ("Generating scan filter"));
NdbScanFilter filter(op); NdbScanFilter filter(op);
bool multiple_cond= FALSE;
// Wrap an AND group around multiple conditions DBUG_RETURN(generate_scan_filter_from_cond(ndb_cond_stack, filter));
if (ndb_cond_stack->next) {
multiple_cond= TRUE;
if (filter.begin() == -1)
DBUG_RETURN(1);
}
for (Ndb_cond_stack *stack= ndb_cond_stack;
(stack);
stack= stack->next)
{
Ndb_cond *cond= stack->ndb_cond;
if (build_scan_filter(cond, &filter))
{
DBUG_PRINT("info", ("build_scan_filter failed"));
DBUG_RETURN(1);
}
}
if (multiple_cond && filter.end() == -1)
DBUG_RETURN(1);
} }
else else
{ {
...@@ -8002,6 +8079,88 @@ ha_ndbcluster::generate_scan_filter(Ndb_cond_stack *ndb_cond_stack, ...@@ -8002,6 +8079,88 @@ ha_ndbcluster::generate_scan_filter(Ndb_cond_stack *ndb_cond_stack,
DBUG_RETURN(0); DBUG_RETURN(0);
} }
int
ha_ndbcluster::generate_scan_filter_from_cond(Ndb_cond_stack *ndb_cond_stack,
NdbScanFilter& filter)
{
DBUG_ENTER("generate_scan_filter_from_cond");
bool multiple_cond= FALSE;
DBUG_PRINT("info", ("Generating scan filter"));
// Wrap an AND group around multiple conditions
if (ndb_cond_stack->next)
{
multiple_cond= TRUE;
if (filter.begin() == -1)
DBUG_RETURN(1);
}
for (Ndb_cond_stack *stack= ndb_cond_stack;
(stack);
stack= stack->next)
{
Ndb_cond *cond= stack->ndb_cond;
if (build_scan_filter(cond, &filter))
{
DBUG_PRINT("info", ("build_scan_filter failed"));
DBUG_RETURN(1);
}
}
if (multiple_cond && filter.end() == -1)
DBUG_RETURN(1);
DBUG_RETURN(0);
}
int ha_ndbcluster::generate_scan_filter_from_key(NdbScanOperation *op,
const KEY* key_info,
const byte *key,
uint key_len,
byte *buf)
{
KEY_PART_INFO* key_part= key_info->key_part;
KEY_PART_INFO* end= key_part+key_info->key_parts;
NdbScanFilter filter(op);
int res;
DBUG_ENTER("generate_scan_filter_from_key");
filter.begin(NdbScanFilter::AND);
for (; key_part != end; key_part++)
{
Field* field= key_part->field;
uint32 pack_len= field->pack_length();
const byte* ptr= key;
char buf[256];
DBUG_PRINT("info", ("Filtering value for %s", field->field_name));
DBUG_DUMP("key", (char*)ptr, pack_len);
if (key_part->null_bit)
{
DBUG_PRINT("info", ("Generating ISNULL filter"));
if (filter.isnull(key_part->fieldnr-1) == -1)
DBUG_RETURN(1);
}
else
{
DBUG_PRINT("info", ("Generating EQ filter"));
if (filter.cmp(NdbScanFilter::COND_EQ,
key_part->fieldnr-1,
ptr,
pack_len) == -1)
DBUG_RETURN(1);
}
key += key_part->store_length;
}
// Add any pushed condition
if (m_cond_stack &&
(res= generate_scan_filter_from_cond(m_cond_stack, filter)))
DBUG_RETURN(res);
if (filter.end() == -1)
DBUG_RETURN(1);
DBUG_RETURN(0);
}
int int
ndbcluster_show_status(THD* thd) ndbcluster_show_status(THD* thd)
{ {
......
...@@ -56,6 +56,7 @@ typedef struct ndb_index_data { ...@@ -56,6 +56,7 @@ typedef struct ndb_index_data {
void *index; void *index;
void *unique_index; void *unique_index;
unsigned char *unique_index_attrid_map; unsigned char *unique_index_attrid_map;
bool null_in_unique_index;
} NDB_INDEX_DATA; } NDB_INDEX_DATA;
typedef struct st_ndbcluster_share { typedef struct st_ndbcluster_share {
...@@ -546,7 +547,9 @@ class ha_ndbcluster: public handler ...@@ -546,7 +547,9 @@ class ha_ndbcluster: public handler
KEY_MULTI_RANGE*ranges, uint range_count, KEY_MULTI_RANGE*ranges, uint range_count,
bool sorted, HANDLER_BUFFER *buffer); bool sorted, HANDLER_BUFFER *buffer);
int read_multi_range_next(KEY_MULTI_RANGE **found_range_p); int read_multi_range_next(KEY_MULTI_RANGE **found_range_p);
bool null_value_index_search(KEY_MULTI_RANGE *ranges,
KEY_MULTI_RANGE *end_range,
HANDLER_BUFFER *buffer);
bool get_error_message(int error, String *buf); bool get_error_message(int error, String *buf);
int info(uint); int info(uint);
int extra(enum ha_extra_function operation); int extra(enum ha_extra_function operation);
...@@ -649,7 +652,8 @@ private: ...@@ -649,7 +652,8 @@ private:
void release_metadata(); void release_metadata();
NDB_INDEX_TYPE get_index_type(uint idx_no) const; NDB_INDEX_TYPE get_index_type(uint idx_no) const;
NDB_INDEX_TYPE get_index_type_from_table(uint index_no) const; NDB_INDEX_TYPE get_index_type_from_table(uint index_no) const;
int check_index_fields_not_null(uint index_no); bool has_null_in_unique_index(uint idx_no) const;
bool check_index_fields_not_null(uint index_no);
int pk_read(const byte *key, uint key_len, byte *buf); int pk_read(const byte *key, uint key_len, byte *buf);
int complemented_pk_read(const byte *old_data, byte *new_data); int complemented_pk_read(const byte *old_data, byte *new_data);
...@@ -663,6 +667,11 @@ private: ...@@ -663,6 +667,11 @@ private:
int ordered_index_scan(const key_range *start_key, int ordered_index_scan(const key_range *start_key,
const key_range *end_key, const key_range *end_key,
bool sorted, bool descending, byte* buf); bool sorted, bool descending, byte* buf);
int unique_index_scan(const KEY* key_info,
const byte *key,
uint key_len,
byte *buf);
int full_table_scan(byte * buf); int full_table_scan(byte * buf);
int fetch_next(NdbScanOperation* op); int fetch_next(NdbScanOperation* op);
int next_result(byte *buf); int next_result(byte *buf);
...@@ -725,6 +734,13 @@ bool uses_blob_value(bool all_fields); ...@@ -725,6 +734,13 @@ bool uses_blob_value(bool all_fields);
int build_scan_filter(Ndb_cond* &cond, NdbScanFilter* filter); int build_scan_filter(Ndb_cond* &cond, NdbScanFilter* filter);
int generate_scan_filter(Ndb_cond_stack* cond_stack, int generate_scan_filter(Ndb_cond_stack* cond_stack,
NdbScanOperation* op); NdbScanOperation* op);
int generate_scan_filter_from_cond(Ndb_cond_stack* cond_stack,
NdbScanFilter& filter);
int generate_scan_filter_from_key(NdbScanOperation* op,
const KEY* key_info,
const byte *key,
uint key_len,
byte *buf);
friend int execute_commit(ha_ndbcluster*, NdbTransaction*); friend int execute_commit(ha_ndbcluster*, NdbTransaction*);
friend int execute_no_commit(ha_ndbcluster*, NdbTransaction*, bool); friend int execute_no_commit(ha_ndbcluster*, NdbTransaction*, bool);
......
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