summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormskold/marty@mysql.com/linux.site <>2006-11-30 16:04:12 +0100
committermskold/marty@mysql.com/linux.site <>2006-11-30 16:04:12 +0100
commita172df24a902e586adf62a3258206b60fb1b9cc3 (patch)
tree6ee16833943fcf23eaf62aaf38124f4b125afc0d
parent4d418e6c43d2d17c84965da08a0a22451fbc96fb (diff)
parent638c294b7f0ce9687e73cc5553296f4d50753f25 (diff)
downloadmariadb-git-a172df24a902e586adf62a3258206b60fb1b9cc3.tar.gz
Merge mskold@bk-internal.mysql.com:/home/bk/mysql-5.0
into mysql.com:/windows/Linux_space/MySQL/mysql-5.0-ndb
-rw-r--r--mysql-test/r/ndb_index_unique.result35
-rw-r--r--mysql-test/r/ndb_update.result9
-rw-r--r--mysql-test/t/ndb_index_unique.test15
-rw-r--r--mysql-test/t/ndb_update.test5
-rw-r--r--ndb/src/common/util/InputStream.cpp1
-rw-r--r--ndb/src/common/util/socket_io.cpp87
-rw-r--r--ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp1
-rw-r--r--ndb/test/ndbapi/testDict.cpp2
-rw-r--r--ndb/test/run-test/daily-basic-tests.txt2
-rw-r--r--ndb/tools/ndb_config.cpp3
-rw-r--r--sql/ha_ndbcluster.cc257
-rw-r--r--sql/ha_ndbcluster.h20
12 files changed, 347 insertions, 90 deletions
diff --git a/mysql-test/r/ndb_index_unique.result b/mysql-test/r/ndb_index_unique.result
index ce4759ad553..12ffc8437db 100644
--- a/mysql-test/r/ndb_index_unique.result
+++ b/mysql-test/r/ndb_index_unique.result
@@ -140,7 +140,40 @@ b int unsigned not null,
c int unsigned,
UNIQUE USING HASH (b, c)
) 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 (
a int unsigned NOT NULL,
b int unsigned not null,
diff --git a/mysql-test/r/ndb_update.result b/mysql-test/r/ndb_update.result
index 164d1bd700c..d75f82172ae 100644
--- a/mysql-test/r/ndb_update.result
+++ b/mysql-test/r/ndb_update.result
@@ -17,8 +17,17 @@ pk1 b c
0 0 0
2 2 2
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;
ERROR 23000: Duplicate entry '' for key 0
+UPDATE IGNORE t1 set pk1 = 1, c = 2 where pk1 = 4;
select * from t1 order by pk1;
pk1 b c
0 0 0
diff --git a/mysql-test/t/ndb_index_unique.test b/mysql-test/t/ndb_index_unique.test
index 8561b3794c4..e210491c9d0 100644
--- a/mysql-test/t/ndb_index_unique.test
+++ b/mysql-test/t/ndb_index_unique.test
@@ -85,7 +85,6 @@ select * from t2 order by a;
drop table t2;
--- error 1121
CREATE TABLE t2 (
a int unsigned NOT NULL PRIMARY KEY,
b int unsigned not null,
@@ -93,6 +92,20 @@ CREATE TABLE t2 (
UNIQUE USING HASH (b, c)
) 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
#
diff --git a/mysql-test/t/ndb_update.test b/mysql-test/t/ndb_update.test
index 45e3add4639..ebcc6995d74 100644
--- a/mysql-test/t/ndb_update.test
+++ b/mysql-test/t/ndb_update.test
@@ -23,8 +23,13 @@ UPDATE t1 set b = c;
select * from t1 order by pk1;
UPDATE t1 set pk1 = 4 where pk1 = 1;
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
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;
UPDATE t1 set pk1 = pk1 + 10;
select * from t1 order by pk1;
diff --git a/ndb/src/common/util/InputStream.cpp b/ndb/src/common/util/InputStream.cpp
index 1b0e809a047..adeca127eb5 100644
--- a/ndb/src/common/util/InputStream.cpp
+++ b/ndb/src/common/util/InputStream.cpp
@@ -65,6 +65,5 @@ SocketInputStream::gets(char * buf, int bufLen) {
if(res == -1)
return 0;
-
return buf;
}
diff --git a/ndb/src/common/util/socket_io.cpp b/ndb/src/common/util/socket_io.cpp
index ba2794e4374..9401d1cd6d0 100644
--- a/ndb/src/common/util/socket_io.cpp
+++ b/ndb/src/common/util/socket_io.cpp
@@ -53,10 +53,6 @@ readln_socket(NDB_SOCKET_TYPE socket, int timeout_millis,
if(buflen <= 1)
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_ZERO(&readset);
FD_SET(socket, &readset);
@@ -71,43 +67,70 @@ readln_socket(NDB_SOCKET_TYPE socket, int timeout_millis,
}
if(selectRes == -1){
- fcntl(socket, F_SETFL, sock_flags);
return -1;
}
- const int t = recv(socket, buf, buflen, MSG_PEEK);
-
- if(t < 1)
+ char* ptr = buf;
+ int len = buflen;
+ do
{
- fcntl(socket, F_SETFL, sock_flags);
- return -1;
- }
+ int t;
+ while((t = recv(socket, ptr, len, MSG_PEEK)) == -1 && errno == EINTR);
+
+ if(t < 1)
+ {
+ return -1;
+ }
- for(int i=0; i< t;i++)
- {
- if(buf[i] == '\n'){
- int r= recv(socket, buf, i+1, 0);
- buf[i+1]= 0;
- if(r < 1) {
- fcntl(socket, F_SETFL, sock_flags);
- return -1;
+
+ for(int i = 0; i<t; i++)
+ {
+ if(ptr[i] == '\n')
+ {
+ /**
+ * Now consume
+ */
+ 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';
- buf[i]= '\0';
+ }
+
+ for (int tmp = t; tmp; )
+ {
+ while ((t = recv(socket, ptr, tmp, 0)) == -1 && errno == EINTR);
+ if (t < 1)
+ {
+ return -1;
}
-
- fcntl(socket, F_SETFL, sock_flags);
- return r;
+ ptr += t;
+ len -= t;
+ tmp -= t;
}
- }
- int r= recv(socket, buf, t, 0);
- if(r>=0)
- buf[r] = 0;
- fcntl(socket, F_SETFL, sock_flags);
- return r;
+ FD_ZERO(&readset);
+ FD_SET(socket, &readset);
+ timeout.tv_sec = (timeout_millis / 1000);
+ timeout.tv_usec = (timeout_millis % 1000) * 1000;
+ const int selectRes = select(socket + 1, &readset, 0, 0, &timeout);
+ if(selectRes != 1){
+ return -1;
+ }
+ } while (len > 0);
+
+ return -1;
}
extern "C"
diff --git a/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp b/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp
index 44f9917438f..53beb3a169a 100644
--- a/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp
+++ b/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp
@@ -697,6 +697,7 @@ Cmvmi::execTEST_ORD(Signal * signal){
// Do nothing
break;
}
+ globalSignalLoggers.flushSignalLog();
}
#endif
diff --git a/ndb/test/ndbapi/testDict.cpp b/ndb/test/ndbapi/testDict.cpp
index ba05bbad7bb..a8e28742757 100644
--- a/ndb/test/ndbapi/testDict.cpp
+++ b/ndb/test/ndbapi/testDict.cpp
@@ -1893,7 +1893,7 @@ runDictOps(NDBT_Context* ctx, NDBT_Step* step)
// create indexes
const char** indlist = NDBT_Tables::getIndexes(tabName);
uint indnum = 0;
- while (*indlist != 0) {
+ while (indlist != 0 && *indlist != 0) {
uint count = 0;
try_create_index:
count++;
diff --git a/ndb/test/run-test/daily-basic-tests.txt b/ndb/test/run-test/daily-basic-tests.txt
index a544355abd6..8ee9d6f7310 100644
--- a/ndb/test/run-test/daily-basic-tests.txt
+++ b/ndb/test/run-test/daily-basic-tests.txt
@@ -510,7 +510,7 @@ args: -n TemporaryTables T1 T6 T7 T8
max-time: 1500
cmd: testDict
-args: -n Restart_NR2 T1
+args: -n Restart_NR2 T1 I3
#
# TEST NDBAPI
diff --git a/ndb/tools/ndb_config.cpp b/ndb/tools/ndb_config.cpp
index 049e4599447..c65f7157c15 100644
--- a/ndb/tools/ndb_config.cpp
+++ b/ndb/tools/ndb_config.cpp
@@ -37,7 +37,6 @@ static int g_verbose = 0;
static int try_reconnect = 3;
static int g_nodes, g_connections, g_section;
-static const char * g_connectstring = 0;
static const char * g_query = 0;
static int g_nodeid = 0;
@@ -486,7 +485,7 @@ fetch_configuration()
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",
ndb_mgm_get_latest_error(mgm),
diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc
index 739fae79565..0672299aa71 100644
--- a/sql/ha_ndbcluster.cc
+++ b/sql/ha_ndbcluster.cc
@@ -1059,6 +1059,7 @@ int ha_ndbcluster::build_index_list(Ndb *ndb, TABLE *tab, enum ILBP phase)
int error= 0;
const char *index_name;
char unique_index_name[FN_LEN];
+ bool null_in_unique_index= false;
static const char* unique_suffix= "$unique";
KEY* key_info= tab->key_info;
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)
error= create_unique_index(unique_index_name, key_info);
break;
case UNIQUE_INDEX:
- if (!(error= check_index_fields_not_null(i)))
- error= create_unique_index(unique_index_name, key_info);
+ if (check_index_fields_not_null(i))
+ {
+ 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;
case ORDERED_INDEX:
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)
m_index[i].unique_index= (void *) index;
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);
@@ -1150,7 +1162,7 @@ NDB_INDEX_TYPE ha_ndbcluster::get_index_type_from_table(uint inx) const
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_PART_INFO* key_part= key_info->key_part;
@@ -1161,14 +1173,10 @@ int ha_ndbcluster::check_index_fields_not_null(uint inx)
{
Field* field= key_part->field;
if (field->maybe_null())
- {
- 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(true);
}
- DBUG_RETURN(0);
+ DBUG_RETURN(false);
}
void ha_ndbcluster::release_metadata()
@@ -1261,6 +1269,12 @@ inline NDB_INDEX_TYPE ha_ndbcluster::get_index_type(uint idx_no) const
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
@@ -2090,6 +2104,42 @@ int ha_ndbcluster::ordered_index_scan(const key_range *start_key,
}
/*
+ 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
*/
@@ -2337,6 +2387,21 @@ int ha_ndbcluster::update_row(const byte *old_data, byte *new_data)
uint i;
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);
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
{
@@ -2763,7 +2828,7 @@ int ha_ndbcluster::index_read(byte *buf,
}
else if (type == UNIQUE_INDEX)
{
- DBUG_RETURN(1);
+ DBUG_RETURN(unique_index_scan(key_info, key, key_len, buf));
}
break;
case ORDERED_INDEX:
@@ -2856,12 +2921,13 @@ int ha_ndbcluster::read_range_first_to_buf(const key_range *start_key,
bool eq_r, bool sorted,
byte* buf)
{
- KEY* key_info;
+ ndb_index_type type= get_index_type(active_index);
+KEY* key_info;
int error= 1;
DBUG_ENTER("ha_ndbcluster::read_range_first_to_buf");
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_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,
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);
}
+ 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;
default:
break;
@@ -6117,6 +6191,30 @@ ha_ndbcluster::release_completed_operations(NdbTransaction *trans,
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
ha_ndbcluster::read_multi_range_first(KEY_MULTI_RANGE **found_range_p,
KEY_MULTI_RANGE *ranges,
@@ -6133,11 +6231,14 @@ ha_ndbcluster::read_multi_range_first(KEY_MULTI_RANGE **found_range_p,
NdbOperation* op;
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;
DBUG_RETURN(handler::read_multi_range_first(found_range_p,
ranges,
@@ -6193,7 +6294,6 @@ ha_ndbcluster::read_multi_range_first(KEY_MULTI_RANGE **found_range_p,
goto range;
/* fall through */
case PRIMARY_KEY_INDEX:
- {
multi_range_curr->range_flag |= UNIQUE_RANGE;
if ((op= m_active_trans->getNdbOperation(tab)) &&
!op->readTuple(lm) &&
@@ -6204,8 +6304,6 @@ ha_ndbcluster::read_multi_range_first(KEY_MULTI_RANGE **found_range_p,
else
ERR_RETURN(op ? op->getNdbError() : m_active_trans->getNdbError());
break;
- }
- break;
case UNIQUE_ORDERED_INDEX:
if (!(multi_range_curr->start_key.length == key_info->key_length &&
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,
goto range;
/* fall through */
case UNIQUE_INDEX:
- {
multi_range_curr->range_flag |= UNIQUE_RANGE;
if ((op= m_active_trans->getNdbIndexOperation(unique_idx, tab)) &&
- !op->readTuple(lm) &&
- !set_index_key(op, key_info, multi_range_curr->start_key.key) &&
- !define_read_attrs(curr, op) &&
- (op->setAbortOption(AO_IgnoreError), TRUE))
- curr += reclength;
+ !op->readTuple(lm) &&
+ !set_index_key(op, key_info, multi_range_curr->start_key.key) &&
+ !define_read_attrs(curr, op) &&
+ (op->setAbortOption(AO_IgnoreError), TRUE))
+ curr += reclength;
else
- ERR_RETURN(op ? op->getNdbError() : m_active_trans->getNdbError());
+ ERR_RETURN(op ? op->getNdbError() : m_active_trans->getNdbError());
break;
- }
case ORDERED_INDEX:
{
range:
@@ -7968,31 +8064,12 @@ ha_ndbcluster::generate_scan_filter(Ndb_cond_stack *ndb_cond_stack,
NdbScanOperation *op)
{
DBUG_ENTER("generate_scan_filter");
+
if (ndb_cond_stack)
{
- DBUG_PRINT("info", ("Generating scan filter"));
NdbScanFilter filter(op);
- bool multiple_cond= FALSE;
- // 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(generate_scan_filter_from_cond(ndb_cond_stack, filter));
}
else
{
@@ -8003,6 +8080,88 @@ ha_ndbcluster::generate_scan_filter(Ndb_cond_stack *ndb_cond_stack,
}
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
ndbcluster_show_status(THD* thd)
{
Protocol *protocol= thd->protocol;
diff --git a/sql/ha_ndbcluster.h b/sql/ha_ndbcluster.h
index d0f7c020184..378b50ec85f 100644
--- a/sql/ha_ndbcluster.h
+++ b/sql/ha_ndbcluster.h
@@ -56,6 +56,7 @@ typedef struct ndb_index_data {
void *index;
void *unique_index;
unsigned char *unique_index_attrid_map;
+ bool null_in_unique_index;
} NDB_INDEX_DATA;
typedef struct st_ndbcluster_share {
@@ -546,7 +547,9 @@ class ha_ndbcluster: public handler
KEY_MULTI_RANGE*ranges, uint range_count,
bool sorted, HANDLER_BUFFER *buffer);
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);
int info(uint);
int extra(enum ha_extra_function operation);
@@ -649,7 +652,8 @@ private:
void release_metadata();
NDB_INDEX_TYPE get_index_type(uint idx_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 complemented_pk_read(const byte *old_data, byte *new_data);
@@ -663,6 +667,11 @@ private:
int ordered_index_scan(const key_range *start_key,
const key_range *end_key,
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 fetch_next(NdbScanOperation* op);
int next_result(byte *buf);
@@ -725,6 +734,13 @@ bool uses_blob_value(bool all_fields);
int build_scan_filter(Ndb_cond* &cond, NdbScanFilter* filter);
int generate_scan_filter(Ndb_cond_stack* cond_stack,
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_no_commit(ha_ndbcluster*, NdbTransaction*, bool);