Commit 7e7729f6 authored by df@pippilotta.erinye.com's avatar df@pippilotta.erinye.com

Merge pippilotta.erinye.com:/shared/home/df/mysql/build/mysql-4.1-build

into  pippilotta.erinye.com:/shared/home/df/mysql/build/mysql-4.1-build-work
parents d7690722 395d8751
......@@ -803,3 +803,8 @@ ERROR 42000: You have an error in your SQL syntax; check the manual that corresp
alter table table_24562 order by no_such_col;
ERROR 42S22: Unknown column 'no_such_col' in 'order clause'
drop table table_24562;
CREATE TABLE t1 (c1 CHAR(255));
INSERT INTO t1 VALUES (REPEAT("x", 255)), (REPEAT("x", 255));
ALTER TABLE t1 ADD UNIQUE (c1);
ERROR 23000: Duplicate entry 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' for key 1
DROP TABLE t1;
......@@ -294,7 +294,7 @@ drop table t1;
create table t1 (c char(255), primary key(c(90)));
insert into t1 values ("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz");
insert into t1 values ("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz");
ERROR 23000: Duplicate entry 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl' for key 1
ERROR 23000: Duplicate entry 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl' for key 1
drop table t1;
CREATE TABLE t1 (a int, key(a)) engine=heap;
insert into t1 values (0);
......
......@@ -128,4 +128,37 @@ show /*!50002 GLOBAL */ status like 'Handler_rollback';
Variable_name Value
Handler_rollback 0
drop table t1;
CREATE TABLE t1(c1 TEXT, UNIQUE (c1(1)), cnt INT DEFAULT 1)
ENGINE=INNODB CHARACTER SET UTF8;
INSERT INTO t1 (c1) VALUES ('1a');
SELECT * FROM t1;
c1 cnt
1a 1
INSERT INTO t1 (c1) VALUES ('1b') ON DUPLICATE KEY UPDATE cnt=cnt+1;
SELECT * FROM t1;
c1 cnt
1a 2
DROP TABLE t1;
CREATE TABLE t1(c1 VARCHAR(2), UNIQUE (c1(1)), cnt INT DEFAULT 1)
ENGINE=INNODB CHARACTER SET UTF8;
INSERT INTO t1 (c1) VALUES ('1a');
SELECT * FROM t1;
c1 cnt
1a 1
INSERT INTO t1 (c1) VALUES ('1b') ON DUPLICATE KEY UPDATE cnt=cnt+1;
SELECT * FROM t1;
c1 cnt
1a 2
DROP TABLE t1;
CREATE TABLE t1(c1 CHAR(2), UNIQUE (c1(1)), cnt INT DEFAULT 1)
ENGINE=INNODB CHARACTER SET UTF8;
INSERT INTO t1 (c1) VALUES ('1a');
SELECT * FROM t1;
c1 cnt
1a 1
INSERT INTO t1 (c1) VALUES ('1b') ON DUPLICATE KEY UPDATE cnt=cnt+1;
SELECT * FROM t1;
c1 cnt
1a 2
DROP TABLE t1;
End of 4.1 tests
......@@ -556,3 +556,64 @@ x a sum(b)
2006-07-01 NULL 11
NULL NULL 11
drop table t1;
CREATE TABLE t1 (a int, b int);
INSERT INTO t1
VALUES (2,10),(3,30),(2,40),(1,10),(2,30),(1,20),(2,10);
SELECT a, SUM(b) FROM t1 GROUP BY a WITH ROLLUP;
a SUM(b)
1 30
2 90
3 30
NULL 150
SELECT DISTINCT a, SUM(b) FROM t1 GROUP BY a WITH ROLLUP;
a SUM(b)
1 30
2 90
3 30
NULL 150
SELECT a, b, COUNT(*) FROM t1 GROUP BY a,b WITH ROLLUP;
a b COUNT(*)
1 10 1
1 20 1
1 NULL 2
2 10 2
2 30 1
2 40 1
2 NULL 4
3 30 1
3 NULL 1
NULL NULL 7
SELECT DISTINCT a, b, COUNT(*) FROM t1 GROUP BY a,b WITH ROLLUP;
a b COUNT(*)
1 10 1
1 20 1
1 NULL 2
2 10 2
2 30 1
2 40 1
2 NULL 4
3 30 1
3 NULL 1
NULL NULL 7
SELECT 'x', a, SUM(b) FROM t1 GROUP BY 1,2 WITH ROLLUP;
x a SUM(b)
x 1 30
x 2 90
x 3 30
x NULL 150
NULL NULL 150
SELECT DISTINCT 'x', a, SUM(b) FROM t1 GROUP BY 1,2 WITH ROLLUP;
x a SUM(b)
x 1 30
x 2 90
x 3 30
x NULL 150
NULL NULL 150
SELECT DISTINCT 'x', a, SUM(b) FROM t1 GROUP BY 1,2 WITH ROLLUP;
x a SUM(b)
x 1 30
x 2 90
x 3 30
x NULL 150
NULL NULL 150
DROP TABLE t1;
......@@ -583,5 +583,16 @@ alter table table_24562 order by no_such_col;
drop table table_24562;
#
# Bug #20710: adding unique index of column with duplicated
# long values to reproduce error message with truncated key value.
#
CREATE TABLE t1 (c1 CHAR(255));
INSERT INTO t1 VALUES (REPEAT("x", 255)), (REPEAT("x", 255));
--error 1062
ALTER TABLE t1 ADD UNIQUE (c1);
DROP TABLE t1;
# End of 4.1 tests
......@@ -161,4 +161,34 @@ show /*!50002 GLOBAL */ status like 'Handler_rollback';
connection default;
drop table t1;
disconnect con1;
#
# Bug #13191: INSERT...ON DUPLICATE KEY UPDATE of UTF-8 string fields
# used in partial unique indices.
#
CREATE TABLE t1(c1 TEXT, UNIQUE (c1(1)), cnt INT DEFAULT 1)
ENGINE=INNODB CHARACTER SET UTF8;
INSERT INTO t1 (c1) VALUES ('1a');
SELECT * FROM t1;
INSERT INTO t1 (c1) VALUES ('1b') ON DUPLICATE KEY UPDATE cnt=cnt+1;
SELECT * FROM t1;
DROP TABLE t1;
CREATE TABLE t1(c1 VARCHAR(2), UNIQUE (c1(1)), cnt INT DEFAULT 1)
ENGINE=INNODB CHARACTER SET UTF8;
INSERT INTO t1 (c1) VALUES ('1a');
SELECT * FROM t1;
INSERT INTO t1 (c1) VALUES ('1b') ON DUPLICATE KEY UPDATE cnt=cnt+1;
SELECT * FROM t1;
DROP TABLE t1;
CREATE TABLE t1(c1 CHAR(2), UNIQUE (c1(1)), cnt INT DEFAULT 1)
ENGINE=INNODB CHARACTER SET UTF8;
INSERT INTO t1 (c1) VALUES ('1a');
SELECT * FROM t1;
INSERT INTO t1 (c1) VALUES ('1b') ON DUPLICATE KEY UPDATE cnt=cnt+1;
SELECT * FROM t1;
DROP TABLE t1;
--echo End of 4.1 tests
......@@ -281,4 +281,23 @@ select left(a,10), a, sum(b) from t1 group by 1,2 with rollup;
select left(a,10) x, a, sum(b) from t1 group by x,a with rollup;
drop table t1;
#
# Bug #24856: ROLLUP by const item in a query with DISTINCT
#
CREATE TABLE t1 (a int, b int);
INSERT INTO t1
VALUES (2,10),(3,30),(2,40),(1,10),(2,30),(1,20),(2,10);
SELECT a, SUM(b) FROM t1 GROUP BY a WITH ROLLUP;
SELECT DISTINCT a, SUM(b) FROM t1 GROUP BY a WITH ROLLUP;
SELECT a, b, COUNT(*) FROM t1 GROUP BY a,b WITH ROLLUP;
SELECT DISTINCT a, b, COUNT(*) FROM t1 GROUP BY a,b WITH ROLLUP;
SELECT 'x', a, SUM(b) FROM t1 GROUP BY 1,2 WITH ROLLUP;
SELECT DISTINCT 'x', a, SUM(b) FROM t1 GROUP BY 1,2 WITH ROLLUP;
SELECT DISTINCT 'x', a, SUM(b) FROM t1 GROUP BY 1,2 WITH ROLLUP;
DROP TABLE t1;
# End of 4.1 tests
......@@ -82,6 +82,11 @@ int my_error(int nr,myf MyFlags, ...)
If "%.*u" or "%.*d" are encountered, the precision number is read
from the variable argument list but its value is ignored.
*/
if (*tpos == '-')
{
tpos++;
olen--;
}
prec_supplied= 0;
if (*tpos== '.')
{
......@@ -94,6 +99,14 @@ int my_error(int nr,myf MyFlags, ...)
prec_chars= va_arg(ap, int); /* get length parameter */
prec_supplied= 1;
}
else
{
for (prec_chars= 0; my_isdigit(&my_charset_latin1, *tpos); tpos++, olen--)
{
prec_supplied= 1;
prec_chars= prec_chars * 10 + *tpos - '0';
}
}
}
if (!prec_supplied)
......
......@@ -5204,6 +5204,16 @@ uint Field_string::max_packed_col_length(uint max_length)
return (max_length > 255 ? 2 : 1)+max_length;
}
uint Field_string::get_key_image(char *buff, uint length, CHARSET_INFO *cs,
imagetype type_arg)
{
uint bytes = my_charpos(cs, ptr, ptr + field_length,
length / field_charset->mbmaxlen);
memcpy(buff, ptr, bytes);
if (bytes < length)
bzero(buff + bytes, length - bytes);
return bytes;
}
/****************************************************************************
** VARCHAR type (Not available for the end user yet)
......@@ -5414,8 +5424,8 @@ uint Field_varstring::max_packed_col_length(uint max_length)
return (max_length > 255 ? 2 : 1)+max_length;
}
void Field_varstring::get_key_image(char *buff, uint length, CHARSET_INFO *cs,
imagetype type)
uint Field_varstring::get_key_image(char *buff, uint length, CHARSET_INFO *cs,
imagetype type)
{
uint f_length=uint2korr(ptr);
if (f_length > length)
......@@ -5426,6 +5436,7 @@ void Field_varstring::get_key_image(char *buff, uint length, CHARSET_INFO *cs,
if (f_length < length)
bzero(buff+HA_KEY_BLOB_LENGTH+f_length, (length-f_length));
#endif
return HA_KEY_BLOB_LENGTH+f_length;
}
void Field_varstring::set_key_image(char *buff,uint length, CHARSET_INFO *cs)
......@@ -5724,8 +5735,8 @@ int Field_blob::cmp_binary(const char *a_ptr, const char *b_ptr,
/* The following is used only when comparing a key */
void Field_blob::get_key_image(char *buff,uint length,
CHARSET_INFO *cs, imagetype type)
uint Field_blob::get_key_image(char *buff,uint length,
CHARSET_INFO *cs, imagetype type)
{
uint32 blob_length= get_length(ptr);
char *blob;
......@@ -5737,16 +5748,17 @@ void Field_blob::get_key_image(char *buff,uint length,
MBR mbr;
Geometry_buffer buffer;
Geometry *gobj;
const uint image_length= SIZEOF_STORED_DOUBLE*4;
if (blob_length < SRID_SIZE)
{
bzero(buff, SIZEOF_STORED_DOUBLE*4);
return;
bzero(buff, image_length);
return image_length;
}
get_ptr(&blob);
gobj= Geometry::construct(&buffer, blob, blob_length);
if (gobj->get_mbr(&mbr, &dummy))
bzero(buff, SIZEOF_STORED_DOUBLE*4);
bzero(buff, image_length);
else
{
float8store(buff, mbr.xmin);
......@@ -5754,7 +5766,7 @@ void Field_blob::get_key_image(char *buff,uint length,
float8store(buff+16, mbr.ymin);
float8store(buff+24, mbr.ymax);
}
return;
return image_length;
}
#endif /*HAVE_SPATIAL*/
......@@ -5774,6 +5786,7 @@ void Field_blob::get_key_image(char *buff,uint length,
}
int2store(buff,length);
memcpy(buff+HA_KEY_BLOB_LENGTH, blob, length);
return HA_KEY_BLOB_LENGTH+length;
}
void Field_blob::set_key_image(char *buff,uint length, CHARSET_INFO *cs)
......@@ -6021,8 +6034,8 @@ uint Field_blob::max_packed_col_length(uint max_length)
#ifdef HAVE_SPATIAL
void Field_geom::get_key_image(char *buff, uint length, CHARSET_INFO *cs,
imagetype type)
uint Field_geom::get_key_image(char *buff, uint length, CHARSET_INFO *cs,
imagetype type)
{
char *blob;
const char *dummy;
......@@ -6030,16 +6043,17 @@ void Field_geom::get_key_image(char *buff, uint length, CHARSET_INFO *cs,
ulong blob_length= get_length(ptr);
Geometry_buffer buffer;
Geometry *gobj;
const uint image_length= SIZEOF_STORED_DOUBLE*4;
if (blob_length < SRID_SIZE)
{
bzero(buff, SIZEOF_STORED_DOUBLE*4);
return;
bzero(buff, image_length);
return image_length;
}
get_ptr(&blob);
gobj= Geometry::construct(&buffer, blob, blob_length);
if (gobj->get_mbr(&mbr, &dummy))
bzero(buff, SIZEOF_STORED_DOUBLE*4);
bzero(buff, image_length);
else
{
float8store(buff, mbr.xmin);
......@@ -6047,6 +6061,7 @@ void Field_geom::get_key_image(char *buff, uint length, CHARSET_INFO *cs,
float8store(buff + 16, mbr.ymin);
float8store(buff + 24, mbr.ymax);
}
return image_length;
}
......
......@@ -228,9 +228,43 @@ public:
{ memcpy(buff,ptr,length); }
inline void set_image(char *buff,uint length, CHARSET_INFO *cs)
{ memcpy(ptr,buff,length); }
virtual void get_key_image(char *buff,uint length, CHARSET_INFO *cs,
imagetype type)
{ get_image(buff,length,cs); }
/*
Copy a field part into an output buffer.
SYNOPSIS
Field::get_key_image()
buff [out] output buffer
length output buffer size
cs charset, always same as this->charset(),
(to be removed in 5.x)
type itMBR for geometry blobs, otherwise itRAW
DESCRIPTION
This function makes a copy of field part of size equal to or
less than "length" parameter value.
For fields of string types (CHAR, VARCHAR, TEXT) the rest of buffer
is padded by zero byte.
NOTES
For variable length character fields (i.e. UTF-8) the "length"
parameter means a number of output buffer bytes as if all field
characters have maximal possible size (mbmaxlen). In the other words,
"length" parameter is a number of characters multiplied by
field_charset->mbmaxlen.
RETURN
Number of copied bytes (excluding padded zero bytes -- see above).
*/
virtual uint get_key_image(char *buff, uint length,
CHARSET_INFO *cs,
imagetype type)
{
get_image(buff,length,cs);
return length;
}
virtual void set_key_image(char *buff,uint length, CHARSET_INFO *cs)
{ set_image(buff,length,cs); }
inline longlong val_int_offset(uint row_offset)
......@@ -947,6 +981,8 @@ public:
enum_field_types real_type() const { return FIELD_TYPE_STRING; }
bool has_charset(void) const
{ return charset() == &my_charset_bin ? FALSE : TRUE; }
virtual uint get_key_image(char *buff,uint length, CHARSET_INFO *cs,
imagetype type);
};
......@@ -981,7 +1017,7 @@ public:
String *val_str(String*,String *);
int cmp(const char *,const char*);
void sort_string(char *buff,uint length);
void get_key_image(char *buff,uint length, CHARSET_INFO *cs, imagetype type);
uint get_key_image(char *buff,uint length, CHARSET_INFO *cs, imagetype type);
void set_key_image(char *buff,uint length, CHARSET_INFO *cs);
void sql_type(String &str) const;
char *pack(char *to, const char *from, uint max_length=~(uint) 0);
......@@ -1060,7 +1096,7 @@ public:
store_length(length);
memcpy_fixed(ptr+packlength,&data,sizeof(char*));
}
void get_key_image(char *buff,uint length, CHARSET_INFO *cs, imagetype type);
uint get_key_image(char *buff,uint length, CHARSET_INFO *cs, imagetype type);
void set_key_image(char *buff,uint length, CHARSET_INFO *cs);
void sql_type(String &str) const;
inline bool copy()
......@@ -1117,7 +1153,7 @@ public:
int store(longlong nr) { return 1; }
int reset(void) { return !maybe_null() || Field_blob::reset(); }
void get_key_image(char *buff,uint length, CHARSET_INFO *cs,imagetype type);
uint get_key_image(char *buff,uint length, CHARSET_INFO *cs,imagetype type);
void set_key_image(char *buff,uint length, CHARSET_INFO *cs);
};
#endif /*HAVE_SPATIAL*/
......
......@@ -590,6 +590,31 @@ public:
};
/*
Objects of this class are used for ROLLUP queries to wrap up
each constant item referred to in GROUP BY list.
*/
class Item_func_rollup_const :public Item_func
{
public:
Item_func_rollup_const(Item *a) :Item_func(a)
{ name= a->name; }
double val() { return args[0]->val(); }
longlong val_int() { return args[0]->val_int(); }
String *val_str(String *str) { return args[0]->val_str(str); }
const char *func_name() const { return "rollup_const"; }
bool const_item() const { return 0; }
Item_result result_type() const { return args[0]->result_type(); }
void fix_length_and_dec()
{
collation= args[0]->collation;
max_length= args[0]->max_length;
decimals=args[0]->decimals;
}
};
class Item_func_length :public Item_int_func
{
String value;
......
......@@ -89,20 +89,21 @@ void key_copy(byte *key,TABLE *table,uint idx,uint key_length)
}
if (key_part->key_part_flag & HA_BLOB_PART)
{
char *pos;
ulong blob_length=((Field_blob*) key_part->field)->get_length();
key_length-=2;
((Field_blob*) key_part->field)->get_ptr(&pos);
length=min(key_length,key_part->length);
set_if_smaller(blob_length,length);
int2store(key,(uint) blob_length);
key+=2; // Skip length info
memcpy(key,pos,blob_length);
key_length-= HA_KEY_BLOB_LENGTH;
length= min(key_length, key_part->length);
key_part->field->get_key_image((char *) key, length,
key_part->field->charset(),
Field::itRAW);
key+= HA_KEY_BLOB_LENGTH;
}
else
{
length=min(key_length,key_part->length);
memcpy(key,table->record[0]+key_part->offset,(size_t) length);
length= min(key_length, key_part->length);
Field *field= key_part->field;
CHARSET_INFO *cs= field->charset();
uint bytes= field->get_key_image((char *) key, length, cs, Field::itRAW);
if (bytes < length)
cs->cset->fill(cs, (char *) key + bytes, length - bytes, ' ');
}
key+=length;
key_length-=length;
......
......@@ -9754,7 +9754,7 @@ bool JOIN::rollup_init()
for (j=0 ; j < fields_list.elements ; j++)
rollup.fields[i].push_back(rollup.null_items[i]);
}
List_iterator_fast<Item> it(all_fields);
List_iterator<Item> it(all_fields);
Item *item;
while ((item= it++))
{
......@@ -9767,6 +9767,32 @@ bool JOIN::rollup_init()
{
item->maybe_null= 1;
found_in_group= 1;
if (item->const_item())
{
/*
For ROLLUP queries each constant item referenced in GROUP BY list
is wrapped up into an Item_func object yielding the same value
as the constant item. The objects of the wrapper class are never
considered as constant items and besides they inherit all
properties of the Item_result_field class.
This wrapping allows us to ensure writing constant items
into temporary tables whenever the result of the ROLLUP
operation has to be written into a temporary table, e.g. when
ROLLUP is used together with DISTINCT in the SELECT list.
Usually when creating temporary tables for a intermidiate
result we do not include fields for constant expressions.
*/
Item* new_item= new Item_func_rollup_const(item);
if (!new_item)
return 1;
new_item->fix_fields(thd,0, (Item **) 0);
thd->change_item_tree(it.ref(), new_item);
for (ORDER *tmp= group_tmp; tmp; tmp= tmp->next)
{
if (*tmp->item == item)
thd->change_item_tree(tmp->item, new_item);
}
}
}
}
if (item->type() == Item::FUNC_ITEM && !found_in_group)
......
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