summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <mskold/marty@mysql.com/linux.site>2007-05-02 10:02:27 +0200
committerunknown <mskold/marty@mysql.com/linux.site>2007-05-02 10:02:27 +0200
commit4a3d208c6b09ae0d90cf67327a3f053c0e6a5ea8 (patch)
tree6e5b9179d6c138d67c3ca9c613d8db0766cb85b9
parentd903636afa6983577f76a85f8a0a168764772c39 (diff)
downloadmariadb-git-4a3d208c6b09ae0d90cf67327a3f053c0e6a5ea8.tar.gz
ndb_insert.test, ndb_insert.result, ha_ndbcluster.cc:
Bug#27980 INSERT IGNORE wrongly ignores NULLs in unique index: added check for null values mysql-test/t/ndb_insert.test: Bug#27980 INSERT IGNORE wrongly ignores NULLs in unique index: added check for null values sql/ha_ndbcluster.cc: Bug#27980 INSERT IGNORE wrongly ignores NULLs in unique index: added check for null values mysql-test/r/ndb_insert.result: Bug#27980 INSERT IGNORE wrongly ignores NULLs in unique index: added check for null values
-rw-r--r--mysql-test/r/ndb_insert.result8
-rw-r--r--mysql-test/t/ndb_insert.test9
-rw-r--r--sql/ha_ndbcluster.cc42
3 files changed, 57 insertions, 2 deletions
diff --git a/mysql-test/r/ndb_insert.result b/mysql-test/r/ndb_insert.result
index 0818f9ce9ac..e7275bde2b8 100644
--- a/mysql-test/r/ndb_insert.result
+++ b/mysql-test/r/ndb_insert.result
@@ -649,3 +649,11 @@ pk a
6 NULL
7 4
DROP TABLE t1;
+create table t1(a int primary key, b int, unique key(b)) engine=ndb;
+insert ignore into t1 values (1,0), (2,0), (2,null), (3,null);
+select * from t1 order by a;
+a b
+1 0
+2 NULL
+3 NULL
+drop table t1;
diff --git a/mysql-test/t/ndb_insert.test b/mysql-test/t/ndb_insert.test
index bf25ca9a133..f346b7dc4ab 100644
--- a/mysql-test/t/ndb_insert.test
+++ b/mysql-test/t/ndb_insert.test
@@ -630,4 +630,13 @@ INSERT IGNORE INTO t1 VALUES (4,NULL),(5,NULL),(6,NULL),(7,4);
SELECT * FROM t1 ORDER BY pk;
DROP TABLE t1;
+#
+# Bug #27980 INSERT IGNORE wrongly ignores NULLs in unique index
+#
+
+create table t1(a int primary key, b int, unique key(b)) engine=ndb;
+insert ignore into t1 values (1,0), (2,0), (2,null), (3,null);
+select * from t1 order by a;
+drop table t1;
+
# End of 4.1 tests
diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc
index 8701a216b8e..9b48e0d4f38 100644
--- a/sql/ha_ndbcluster.cc
+++ b/sql/ha_ndbcluster.cc
@@ -1630,6 +1630,34 @@ bool ha_ndbcluster::check_all_operations_for_error(NdbTransaction *trans,
DBUG_RETURN(true);
}
+
+/**
+ * Check if record contains any null valued columns that are part of a key
+ */
+static
+int
+check_null_in_record(const KEY* key_info, const byte *record)
+{
+ KEY_PART_INFO *curr_part, *end_part;
+ curr_part= key_info->key_part;
+ end_part= curr_part + key_info->key_parts;
+
+ while (curr_part != end_part)
+ {
+ if (curr_part->null_bit &&
+ (record[curr_part->null_offset] & curr_part->null_bit))
+ return 1;
+ curr_part++;
+ }
+ return 0;
+ /*
+ We could instead pre-compute a bitmask in table_share with one bit for
+ every null-bit in the key, and so check this just by OR'ing the bitmask
+ with the null bitmap in the record.
+ But not sure it's worth it.
+ */
+}
+
/*
* Peek to check if any rows already exist with conflicting
* primary key or unique index values
@@ -1671,7 +1699,17 @@ int ha_ndbcluster::peek_indexed_rows(const byte *record, bool check_pk)
if (i != table->s->primary_key &&
key_info->flags & HA_NOSAME)
{
- // A unique index is defined on table
+ /*
+ A unique index is defined on table.
+ We cannot look up a NULL field value in a unique index. But since
+ keys with NULLs are not indexed, such rows cannot conflict anyway, so
+ we just skip the index in this case.
+ */
+ if (check_null_in_record(key_info, record))
+ {
+ DBUG_PRINT("info", ("skipping check for key with NULL"));
+ continue;
+ }
NdbIndexOperation *iop;
NDBINDEX *unique_index = (NDBINDEX *) m_index[i].unique_index;
key_part= key_info->key_part;
@@ -2816,7 +2854,7 @@ int ha_ndbcluster::index_end()
}
/**
- * Check if key contains null
+ * Check if key contains nullable columns
*/
static
int