summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <monty@donna.mysql.fi>2001-04-10 11:32:28 +0300
committerunknown <monty@donna.mysql.fi>2001-04-10 11:32:28 +0300
commit92de72694b78d41980c48b8a6fedf10f153bb56e (patch)
tree95bbcccc6e046548f22eead9222fdd1cce980d1e /sql
parentc7105d8008aa42e90e830ede25e7cbf0c22893c0 (diff)
downloadmariadb-git-92de72694b78d41980c48b8a6fedf10f153bb56e.tar.gz
Fixed bug with UPDATE/DELETE on UNIQUE key which could be NULL
Docs/manual.texi: Updated replication section mysql-test/r/null_key.result: Added test UPDATE/DELETE with IS NULL on unique key mysql-test/t/null_key.test: Added test UPDATE/DELETE with IS NULL on unique key mysys/Makefile.am: Removed -f from $CP as this is not portable Fixed rule for testhash sql/field.cc: Safety fix sql/opt_range.cc: Fixed bug with UPDATE/DELETE on UNIQUE key which could be NULL sql/opt_range.h: Fixed bug with UPDATE/DELETE on UNIQUE key which could be NULL
Diffstat (limited to 'sql')
-rw-r--r--sql/field.cc2
-rw-r--r--sql/opt_range.cc32
-rw-r--r--sql/opt_range.h1
3 files changed, 31 insertions, 4 deletions
diff --git a/sql/field.cc b/sql/field.cc
index f2310dd0229..f7dbd3c72f0 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -3891,7 +3891,7 @@ String *Field_blob::val_str(String *val_buffer __attribute__((unused)),
char *blob;
memcpy_fixed(&blob,ptr+packlength,sizeof(char*));
if (!blob)
- val_ptr->length(0);
+ val_ptr->set("",0); // A bit safer than ->length(0)
else
val_ptr->set((const char*) blob,get_length(ptr));
return val_ptr;
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 4c1a0db72b7..eedae87719d 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -321,7 +321,7 @@ static bool get_quick_keys(PARAM *param,QUICK_SELECT *quick,KEY_PART *key,
static bool eq_tree(SEL_ARG* a,SEL_ARG *b);
static SEL_ARG null_element(SEL_ARG::IMPOSSIBLE);
-
+static bool null_part_in_key(KEY_PART *key_part, const char *key, uint length);
/***************************************************************************
** Basic functions for SQL_SELECT and QUICK_SELECT
@@ -2306,7 +2306,15 @@ get_quick_keys(PARAM *param,QUICK_SELECT *quick,KEY_PART *key,
KEY *table_key=quick->head->key_info+quick->index;
flag=EQ_RANGE;
if (table_key->flags & HA_NOSAME && key->part == table_key->key_parts-1)
- flag|= UNIQUE_RANGE;
+ {
+ if (!(table_key->flags & HA_NULL_PART_KEY) ||
+ !null_part_in_key(key,
+ param->min_key,
+ (uint) (tmp_min_key - param->min_key)))
+ flag|= UNIQUE_RANGE;
+ else
+ flag|= NULL_RANGE;
+ }
}
}
@@ -2339,7 +2347,7 @@ bool QUICK_SELECT::unique_key_range()
if (ranges.elements == 1)
{
QUICK_RANGE *tmp;
- if ((tmp=ranges.head())->flag & EQ_RANGE)
+ if (((tmp=ranges.head())->flag & (EQ_RANGE | NULL_RANGE)) == EQ_RANGE)
{
KEY *key=head->key_info+index;
return ((key->flags & HA_NOSAME) &&
@@ -2349,6 +2357,24 @@ bool QUICK_SELECT::unique_key_range()
return 0;
}
+
+/* Returns true if any part of the key is NULL */
+
+static bool null_part_in_key(KEY_PART *key_part, const char *key, uint length)
+{
+ for (const char *end=key+length ;
+ key < end;
+ key+= key_part++->part_length)
+ {
+ if (key_part->null_bit)
+ {
+ if (*key++)
+ return 1;
+ }
+ }
+ return 0;
+}
+
/****************************************************************************
** Create a QUICK RANGE based on a key
****************************************************************************/
diff --git a/sql/opt_range.h b/sql/opt_range.h
index 2005773eca7..247dd260817 100644
--- a/sql/opt_range.h
+++ b/sql/opt_range.h
@@ -30,6 +30,7 @@
#define NEAR_MAX 8
#define UNIQUE_RANGE 16
#define EQ_RANGE 32
+#define NULL_RANGE 64
typedef struct st_key_part {
uint16 key,part,part_length;