Merge abotchkov@work.mysql.com:/home/bk/mysql-4.1

into bisonxp.(none):/home/hf/work/mysql-4.1


BitKeeper/etc/logging_ok:
  auto-union
sql/mysql_priv.h:
  Auto merged
sql/sql_base.cc:
  Auto merged
sql/sql_class.cc:
  Auto merged
sql/sql_class.h:
  Auto merged
sql/sql_handler.cc:
  Auto merged
sql/sql_parse.cc:
  Auto merged
sql/sql_select.cc:
  Auto merged
sql/sql_show.cc:
  Auto merged
sql/sql_table.cc:
  Auto merged
This commit is contained in:
unknown 2002-07-09 10:42:24 +05:00
commit 2da868d45c
43 changed files with 2488 additions and 436 deletions

View File

@ -478,3 +478,4 @@ vio/test-ssl
vio/test-sslclient vio/test-sslclient
vio/test-sslserver vio/test-sslserver
vio/viotest-ssl vio/viotest-ssl
tests/client_test

View File

@ -14,6 +14,7 @@ davida@isil.mysql.com
heikki@donna.mysql.fi heikki@donna.mysql.fi
heikki@hundin.mysql.fi heikki@hundin.mysql.fi
hf@bison.(none) hf@bison.(none)
hf@bisonxp.(none)
jani@dsl-jkl1657.dial.inet.fi jani@dsl-jkl1657.dial.inet.fi
jani@hynda.(none) jani@hynda.(none)
jani@hynda.mysql.fi jani@hynda.mysql.fi
@ -66,7 +67,7 @@ tonu@x153.internalnet
tonu@x3.internalnet tonu@x3.internalnet
venu@myvenu.com venu@myvenu.com
venu@work.mysql.com venu@work.mysql.com
walrus@mysql.com
worm@altair.is.lan worm@altair.is.lan
zak@balfor.local zak@balfor.local
zak@linux.local zak@linux.local
hf@bisonxp.(none)

View File

@ -98,6 +98,14 @@ ha_checksum mi_unique_hash(MI_UNIQUEDEF *def, const byte *record)
} }
end= pos+length; end= pos+length;
if (type == HA_KEYTYPE_TEXT || type == HA_KEYTYPE_VARTEXT) if (type == HA_KEYTYPE_TEXT || type == HA_KEYTYPE_VARTEXT)
{
if (keyseg->charset->hash_sort)
{
ulong nr=1, nr2=4;
keyseg->charset->hash_sort(keyseg->charset,(const uchar*)pos,length,&nr, &nr2);
crc=nr;
}
else
{ {
uchar *sort_order=keyseg->charset->sort_order; uchar *sort_order=keyseg->charset->sort_order;
while (pos != end) while (pos != end)
@ -105,6 +113,7 @@ ha_checksum mi_unique_hash(MI_UNIQUEDEF *def, const byte *record)
(((uchar) sort_order[*(uchar*) pos++]))) + (((uchar) sort_order[*(uchar*) pos++]))) +
(crc >> (8*sizeof(ha_checksum)-8)); (crc >> (8*sizeof(ha_checksum)-8));
} }
}
else else
while (pos != end) while (pos != end)
crc=((crc << 8) + crc=((crc << 8) +
@ -172,6 +181,13 @@ int mi_unique_comp(MI_UNIQUEDEF *def, const byte *a, const byte *b,
} }
end= pos_a+length; end= pos_a+length;
if (type == HA_KEYTYPE_TEXT || type == HA_KEYTYPE_VARTEXT) if (type == HA_KEYTYPE_TEXT || type == HA_KEYTYPE_VARTEXT)
{
if (use_strcoll(keyseg->charset))
{
if (my_strnncoll(keyseg->charset,pos_a,length,pos_b,length))
return 1;
}
else
{ {
uchar *sort_order=keyseg->charset->sort_order; uchar *sort_order=keyseg->charset->sort_order;
while (pos_a != end) while (pos_a != end)
@ -179,6 +195,7 @@ int mi_unique_comp(MI_UNIQUEDEF *def, const byte *a, const byte *b,
sort_order[*(uchar*) pos_b++]) sort_order[*(uchar*) pos_b++])
return 1; return 1;
} }
}
else else
while (pos_a != end) while (pos_a != end)
if (*pos_a++ != *pos_b++) if (*pos_a++ != *pos_b++)

View File

@ -32,7 +32,7 @@ result_file=$RESULT_DIR/$test_name.result
touch $result_file touch $result_file
echo "Running the test case against empty file, will fail, but don't worry" echo "Running the test case against empty file, will fail, but don't worry"
./mysql-test-run --do-test=$test_name ./mysql-test-run --local $test_name
reject_file=$result_file.reject reject_file=$result_file.reject

File diff suppressed because it is too large Load Diff

View File

@ -65,6 +65,21 @@ a
select b,(select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2) from t4; select b,(select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2) from t4;
b (select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2) b (select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2)
8 7.5000 8 7.5000
8 6.0000 8 4.5000
9 5.5000 9 7.5000
select * from t3 where exists (select * from t2 where t2.b=t3.a);
a
7
select * from t3 where not exists (select * from t2 where t2.b=t3.a);
a
6
3
insert into t4 values (12,7),(1,7),(10,9),(9,6),(7,6),(3,9);
select b,max(a) as ma from t4 group by b having b < (select max(t2.a)
from t2 where t2.b=t4.b);
b ma
select b,max(a) as ma from t4 group by b having b >= (select max(t2.a)
from t2 where t2.b=t4.b);
b ma
7 12
drop table t1,t2,t3,t4; drop table t1,t2,t3,t4;

View File

@ -0,0 +1,189 @@
DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (
comment CHAR(32) CHARACTER SET latin1 NOT NULL,
koi8_ru_f CHAR(32) CHARACTER SET koi8_ru NOT NULL
) CHARSET=latin5;
SHOW CREATE TABLE t1;
ALTER TABLE t1 CHANGE comment comment CHAR(32) CHARACTER SET latin2 NOT NULL;
SHOW CREATE TABLE t1;
ALTER TABLE t1 ADD latin5_f CHAR(32) NOT NULL;
SHOW CREATE TABLE t1;
ALTER TABLE t1 CHARSET=latin2;
ALTER TABLE t1 ADD latin2_f CHAR(32) NOT NULL;
SHOW CREATE TABLE t1;
ALTER TABLE t1 DROP latin2_f, DROP latin5_f;
SHOW CREATE TABLE t1;
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('a','LAT SMALL A');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('b','LAT SMALL B');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('c','LAT SMALL C');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('d','LAT SMALL D');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('e','LAT SMALL E');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('f','LAT SMALL F');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('g','LAT SMALL G');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('h','LAT SMALL H');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('i','LAT SMALL I');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('j','LAT SMALL J');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('k','LAT SMALL K');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('l','LAT SMALL L');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('m','LAT SMALL M');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('n','LAT SMALL N');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('o','LAT SMALL O');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('p','LAT SMALL P');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('q','LAT SMALL Q');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('r','LAT SMALL R');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('s','LAT SMALL S');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('t','LAT SMALL T');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('u','LAT SMALL U');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('v','LAT SMALL V');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('w','LAT SMALL W');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('x','LAT SMALL X');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('y','LAT SMALL Y');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('z','LAT SMALL Z');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('A','LAT CAPIT A');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('B','LAT CAPIT B');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('C','LAT CAPIT C');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('D','LAT CAPIT D');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('E','LAT CAPIT E');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('F','LAT CAPIT F');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('G','LAT CAPIT G');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('H','LAT CAPIT H');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('I','LAT CAPIT I');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('J','LAT CAPIT J');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('K','LAT CAPIT K');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('L','LAT CAPIT L');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('M','LAT CAPIT M');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('N','LAT CAPIT N');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('O','LAT CAPIT O');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('P','LAT CAPIT P');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Q','LAT CAPIT Q');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('R','LAT CAPIT R');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('S','LAT CAPIT S');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('T','LAT CAPIT T');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('U','LAT CAPIT U');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('V','LAT CAPIT V');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('W','LAT CAPIT W');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('X','LAT CAPIT X');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Y','LAT CAPIT Y');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Z','LAT CAPIT Z');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Á','CYR SMALL A');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Â','CYR SMALL BE');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('×','CYR SMALL VE');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ç','CYR SMALL GE');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ä','CYR SMALL DE');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Å','CYR SMALL IE');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('£','CYR SMALL IO');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ö','CYR SMALL ZHE');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ú','CYR SMALL ZE');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('É','CYR SMALL I');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ë','CYR SMALL KA');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ì','CYR SMALL EL');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Í','CYR SMALL EM');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Î','CYR SMALL EN');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ï','CYR SMALL O');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ð','CYR SMALL PE');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ò','CYR SMALL ER');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ó','CYR SMALL ES');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ô','CYR SMALL TE');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Õ','CYR SMALL U');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Æ','CYR SMALL EF');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('È','CYR SMALL HA');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ã','CYR SMALL TSE');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Þ','CYR SMALL CHE');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Û','CYR SMALL SHA');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ý','CYR SMALL SCHA');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ß','CYR SMALL HARD SIGN');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ù','CYR SMALL YERU');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ø','CYR SMALL SOFT SIGN');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ü','CYR SMALL E');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('À','CYR SMALL YU');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ñ','CYR SMALL YA');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('á','CYR CAPIT A');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('â','CYR CAPIT BE');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('÷','CYR CAPIT VE');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ç','CYR CAPIT GE');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ä','CYR CAPIT DE');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('å','CYR CAPIT IE');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('³','CYR CAPIT IO');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ö','CYR CAPIT ZHE');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ú','CYR CAPIT ZE');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('é','CYR CAPIT I');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ë','CYR CAPIT KA');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ì','CYR CAPIT EL');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('í','CYR CAPIT EM');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('î','CYR CAPIT EN');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ï','CYR CAPIT O');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ð','CYR CAPIT PE');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ò','CYR CAPIT ER');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ó','CYR CAPIT ES');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ô','CYR CAPIT TE');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('õ','CYR CAPIT U');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('æ','CYR CAPIT EF');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('è','CYR CAPIT HA');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ã','CYR CAPIT TSE');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('þ','CYR CAPIT CHE');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('û','CYR CAPIT SHA');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ý','CYR CAPIT SCHA');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ÿ','CYR CAPIT HARD SIGN');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ù','CYR CAPIT YERU');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ø','CYR CAPIT SOFT SIGN');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ü','CYR CAPIT E');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('à','CYR CAPIT YU');
INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ñ','CYR CAPIT YA');
ALTER TABLE t1 ADD utf8_f CHAR(32) CHARACTER SET utf8 NOT NULL;
UPDATE t1 SET utf8_f=CONVERT(koi8_ru_f USING utf8);
SELECT * FROM t1;
SELECT koi8_ru_f,MIN(comment) FROM t1 GROUP BY 1;
SELECT utf8_f,MIN(comment) FROM t1 GROUP BY 1;
SELECT DISTINCT koi8_ru_f FROM t1;
SELECT DISTINCT utf8_f FROM t1;
SELECT lower(koi8_ru_f) FROM t1 ORDER BY 1 DESC;
SELECT lower(utf8_f) FROM t1 ORDER BY 1 DESC;
SELECT t11.comment,t12.comment
FROM t1 t11,t1 t12 WHERE CONVERT(t11.koi8_ru_f USING utf8)=t12.utf8_f
ORDER BY t11.koi8_ru_f;
SELECT t11.comment,t12.comment
FROM t1 t11,t1 t12
WHERE t11.koi8_ru_f=CONVERT(t12.utf8_f USING koi8_ru)
ORDER BY t12.utf8_f;
ALTER TABLE t1 ADD ucs2_f CHAR(32) CHARACTER SET ucs2 NOT NULL;
INSERT INTO t1 (ucs2_f,comment) VALUES (0x0391,'GREEK CAPIT ALPHA');
INSERT INTO t1 (ucs2_f,comment) VALUES (0x0392,'GREEK CAPIT BETA');
INSERT INTO t1 (ucs2_f,comment) VALUES (0x0393,'GREEK CAPIT GAMMA');
INSERT INTO t1 (ucs2_f,comment) VALUES (0x0394,'GREEK CAPIT DELTA');
INSERT INTO t1 (ucs2_f,comment) VALUES (0x0395,'GREEK CAPIT EPSILON');
INSERT INTO t1 (ucs2_f,comment) VALUES (0x03B1,'GREEK SMALL ALPHA');
INSERT INTO t1 (ucs2_f,comment) VALUES (0x03B2,'GREEK SMALL BETA');
INSERT INTO t1 (ucs2_f,comment) VALUES (0x03B3,'GREEK SMALL GAMMA');
INSERT INTO t1 (ucs2_f,comment) VALUES (0x03B4,'GREEK SMALL DELTA');
INSERT INTO t1 (ucs2_f,comment) VALUES (0x03B5,'GREEK SMALL EPSILON');
INSERT INTO t1 (ucs2_f,comment) VALUES (0x0531,'ARMENIAN CAPIT AYB');
INSERT INTO t1 (ucs2_f,comment) VALUES (0x0532,'ARMENIAN CAPIT BEN');
INSERT INTO t1 (ucs2_f,comment) VALUES (0x0533,'ARMENIAN CAPIT GIM');
INSERT INTO t1 (ucs2_f,comment) VALUES (0x0534,'ARMENIAN CAPIT DA');
INSERT INTO t1 (ucs2_f,comment) VALUES (0x0535,'ARMENIAN CAPIT ECH');
INSERT INTO t1 (ucs2_f,comment) VALUES (0x0536,'ARMENIAN CAPIT ZA');
INSERT INTO t1 (ucs2_f,comment) VALUES (0x0561,'ARMENIAN SMALL YAB');
INSERT INTO t1 (ucs2_f,comment) VALUES (0x0562,'ARMENIAN SMALL BEN');
INSERT INTO t1 (ucs2_f,comment) VALUES (0x0563,'ARMENIAN SMALL GIM');
INSERT INTO t1 (ucs2_f,comment) VALUES (0x0564,'ARMENIAN SMALL DA');
INSERT INTO t1 (ucs2_f,comment) VALUES (0x0565,'ARMENIAN SMALL ECH');
INSERT INTO t1 (ucs2_f,comment) VALUES (0x0566,'ARMENIAN SMALL ZA');
ALTER TABLE t1 ADD armscii8_f CHAR(32) CHARACTER SET armscii8 NOT NULL;
ALTER TABLE t1 ADD greek_f CHAR(32) CHARACTER SET greek NOT NULL;
UPDATE t1 SET greek_f=CONVERT(ucs2_f USING greek) WHERE comment LIKE 'GRE%';
UPDATE t1 SET armscii8_f=CONVERT(ucs2_f USING armscii8) WHERE comment LIKE 'ARM%';
UPDATE t1 SET utf8_f=CONVERT(ucs2_f USING utf8) WHERE utf8_f='';
UPDATE t1 SET ucs2_f=CONVERT(utf8_f USING ucs2) WHERE ucs2_f='';
SELECT min(comment),count(*) FROM t1 GROUP BY ucs2_f;
DROP TABLE t1;

View File

@ -26,4 +26,11 @@ select * from t1 where t1.a=(select t2.a from t2 where t2.b=(select max(a) from
select * from t1 where t1.a=(select t2.a from t2 where t2.b=(select max(a) from t3 where t3.a > t1.a) order by 1 desc limit 1); select * from t1 where t1.a=(select t2.a from t2 where t2.b=(select max(a) from t3 where t3.a > t1.a) order by 1 desc limit 1);
select * from t1 where t1.a=(select t2.a from t2 where t2.b=(select max(a) from t3 where t3.a < t1.a) order by 1 desc limit 1); select * from t1 where t1.a=(select t2.a from t2 where t2.b=(select max(a) from t3 where t3.a < t1.a) order by 1 desc limit 1);
select b,(select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2) from t4; select b,(select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2) from t4;
select * from t3 where exists (select * from t2 where t2.b=t3.a);
select * from t3 where not exists (select * from t2 where t2.b=t3.a);
insert into t4 values (12,7),(1,7),(10,9),(9,6),(7,6),(3,9);
select b,max(a) as ma from t4 group by b having b < (select max(t2.a)
from t2 where t2.b=t4.b);
select b,max(a) as ma from t4 group by b having b >= (select max(t2.a)
from t2 where t2.b=t4.b);
drop table t1,t2,t3,t4; drop table t1,t2,t3,t4;

View File

@ -115,7 +115,6 @@ sub new
$self->{'data_source'} = "DBI:mysql:database=$database;host=$host"; $self->{'data_source'} = "DBI:mysql:database=$database;host=$host";
$self->{'data_source'} .= ";mysql_socket=$socket" if($socket); $self->{'data_source'} .= ";mysql_socket=$socket" if($socket);
$self->{'limits'} = \%limits; $self->{'limits'} = \%limits;
$self->{'smds'} = \%smds;
$self->{'blob'} = "blob"; $self->{'blob'} = "blob";
$self->{'text'} = "text"; $self->{'text'} = "text";
$self->{'double_quotes'} = 1; # Can handle: 'Walker''s' $self->{'double_quotes'} = 1; # Can handle: 'Walker''s'
@ -168,25 +167,6 @@ sub new
$limits{'working_all_fields'} = 1; $limits{'working_all_fields'} = 1;
$limits{'working_blobs'} = 1; # If big varchar/blobs works $limits{'working_blobs'} = 1; # If big varchar/blobs works
$smds{'time'} = 1;
$smds{'q1'} = 'b'; # with time not supp by mysql ('')
$smds{'q2'} = 'b';
$smds{'q3'} = 'b'; # with time ('')
$smds{'q4'} = 'c'; # with time not supp by mysql (d)
$smds{'q5'} = 'b'; # with time not supp by mysql ('')
$smds{'q6'} = 'c'; # with time not supp by mysql ('')
$smds{'q7'} = 'c';
$smds{'q8'} = 'f';
$smds{'q9'} = 'c';
$smds{'q10'} = 'b';
$smds{'q11'} = 'b';
$smds{'q12'} = 'd';
$smds{'q13'} = 'c';
$smds{'q14'} = 'd';
$smds{'q15'} = 'd';
$smds{'q16'} = 'a';
$smds{'q17'} = 'c';
# Some fixes that depends on the environment # Some fixes that depends on the environment
if (defined($main::opt_create_options) && if (defined($main::opt_create_options) &&
$main::opt_create_options =~ /type=heap/i) $main::opt_create_options =~ /type=heap/i)
@ -199,6 +179,11 @@ sub new
$limits{'max_text_size'} = 8000; # Limit in Innobase $limits{'max_text_size'} = 8000; # Limit in Innobase
$self->{'transactions'} = 1; # Transactions enabled $self->{'transactions'} = 1; # Transactions enabled
} }
if (defined($main::opt_create_options) &&
$main::opt_create_options =~ /type=bdb/i)
{
$self->{'transactions'} = 1; # Transactions enabled
}
if (defined($main::opt_create_options) && if (defined($main::opt_create_options) &&
$main::opt_create_options =~ /type=gemini/i) $main::opt_create_options =~ /type=gemini/i)
{ {
@ -266,7 +251,6 @@ sub create
{ {
$field =~ s/ decimal/ double(10,2)/i; $field =~ s/ decimal/ double(10,2)/i;
$field =~ s/ big_decimal/ double(10,2)/i; $field =~ s/ big_decimal/ double(10,2)/i;
$field =~ s/ date/ int/i; # Because of tcp ?
$query.= $field . ','; $query.= $field . ',';
} }
foreach $index (@$index) foreach $index (@$index)
@ -575,7 +559,6 @@ sub new
$self->{'cmp_name'} = "pg"; $self->{'cmp_name'} = "pg";
$self->{'data_source'} = "DBI:Pg:dbname=$database"; $self->{'data_source'} = "DBI:Pg:dbname=$database";
$self->{'limits'} = \%limits; $self->{'limits'} = \%limits;
$self->{'smds'} = \%smds;
$self->{'blob'} = "text"; $self->{'blob'} = "text";
$self->{'text'} = "text"; $self->{'text'} = "text";
$self->{'double_quotes'} = 1; $self->{'double_quotes'} = 1;
@ -626,27 +609,6 @@ sub new
$limits{'working_all_fields'} = 1; $limits{'working_all_fields'} = 1;
$limits{'working_blobs'} = 1; # If big varchar/blobs works $limits{'working_blobs'} = 1; # If big varchar/blobs works
# the different cases per query ...
$smds{'q1'} = 'b'; # with time
$smds{'q2'} = 'b';
$smds{'q3'} = 'b'; # with time
$smds{'q4'} = 'c'; # with time
$smds{'q5'} = 'b'; # with time
$smds{'q6'} = 'c'; # strange error ....
$smds{'q7'} = 'c';
$smds{'q8'} = 'f'; # needs 128M to execute - can't do insert ...group by
$smds{'q9'} = 'c';
$smds{'q10'} = 'b';
$smds{'q11'} = 'b'; # can't do float8 * int4 - create operator
$smds{'q12'} = 'd'; # strange error???
$smds{'q13'} = 'c';
$smds{'q14'} = 'd'; # strange error???
$smds{'q15'} = 'd'; # strange error???
$smds{'q16'} = 'a';
$smds{'q17'} = 'c';
$smds{'time'} = 1; # the use of the time table -> 1 is on.
# when 0 then the date field must be a
# date field not a int field!!!
return $self; return $self;
} }
@ -871,7 +833,6 @@ sub new
$self->{'cmp_name'} = "solid"; $self->{'cmp_name'} = "solid";
$self->{'data_source'} = "DBI:Solid:"; $self->{'data_source'} = "DBI:Solid:";
$self->{'limits'} = \%limits; $self->{'limits'} = \%limits;
$self->{'smds'} = \%smds;
$self->{'blob'} = "long varchar"; $self->{'blob'} = "long varchar";
$self->{'text'} = "long varchar"; $self->{'text'} = "long varchar";
$self->{'double_quotes'} = 1; $self->{'double_quotes'} = 1;
@ -922,28 +883,6 @@ sub new
$limits{'order_by_unused'} = 1; $limits{'order_by_unused'} = 1;
$limits{'working_all_fields'} = 1; $limits{'working_all_fields'} = 1;
# for the smds small benchmark test ....
# the different cases per query ...
$smds{'q1'} = 'a';
$smds{'q2'} = '';
$smds{'q3'} = 'b'; #doesn't work -> strange error about column -fixed
$smds{'q4'} = 'a';
$smds{'q5'} = 'b';
$smds{'q6'} = 'c';
$smds{'q7'} = 'b';
$smds{'q8'} = 'f';
$smds{'q9'} = 'b';
$smds{'q10'} = 'b';
$smds{'q11'} = '';
$smds{'q12'} = 'd';
$smds{'q13'} = 'b';
$smds{'q14'} = 'd';
$smds{'q15'} = 'd';
$smds{'q16'} = '';
$smds{'q17'} = '';
$smds{'time'} = 1; # the use of the time table -> 1 is on.
# when 0 then the date field must be a
# date field not a int field!!!
return $self; return $self;
} }
@ -1119,7 +1058,6 @@ sub new
$self->{'cmp_name'} = "empress"; $self->{'cmp_name'} = "empress";
$self->{'data_source'} = "DBI:EmpressNet:SERVER=$host;Database=/usr/local/empress/rdbms/bin/$database"; $self->{'data_source'} = "DBI:EmpressNet:SERVER=$host;Database=/usr/local/empress/rdbms/bin/$database";
$self->{'limits'} = \%limits; $self->{'limits'} = \%limits;
$self->{'smds'} = \%smds;
$self->{'blob'} = "text"; $self->{'blob'} = "text";
$self->{'text'} = "text"; $self->{'text'} = "text";
$self->{'double_quotes'} = 1; # Can handle: 'Walker''s' $self->{'double_quotes'} = 1; # Can handle: 'Walker''s'
@ -1172,28 +1110,6 @@ sub new
$limits{'order_by_unused'} = 1; $limits{'order_by_unused'} = 1;
$limits{'working_all_fields'} = 1; $limits{'working_all_fields'} = 1;
# for the smds small benchmark test ....
# the different cases per query ... EMPRESS
$smds{'q1'} = 'a';
$smds{'q2'} = '';
$smds{'q3'} = 'a';
$smds{'q4'} = 'a';
$smds{'q5'} = 'a';
$smds{'q6'} = 'a';
$smds{'q7'} = 'b';
$smds{'q8'} = 'd';
$smds{'q9'} = 'b';
$smds{'q10'} = 'a';
$smds{'q11'} = '';
$smds{'q12'} = 'd';
$smds{'q13'} = 'b';
$smds{'q14'} = 'b';
$smds{'q15'} = 'a';
$smds{'q16'} = '';
$smds{'q17'} = '';
$smds{'time'} = 1; # the use of the time table -> 1 is on.
# when 0 then the date field must be a
# date field not a int field!!!
return $self; return $self;
} }
@ -1410,7 +1326,6 @@ sub new
$self->{'cmp_name'} = "Oracle"; $self->{'cmp_name'} = "Oracle";
$self->{'data_source'} = "DBI:Oracle:$database"; $self->{'data_source'} = "DBI:Oracle:$database";
$self->{'limits'} = \%limits; $self->{'limits'} = \%limits;
$self->{'smds'} = \%smds;
$self->{'blob'} = "long"; $self->{'blob'} = "long";
$self->{'text'} = "long"; $self->{'text'} = "long";
$self->{'double_quotes'} = 1; # Can handle: 'Walker''s' $self->{'double_quotes'} = 1; # Can handle: 'Walker''s'
@ -1464,24 +1379,6 @@ sub new
$limits{'order_by_unused'} = 1; $limits{'order_by_unused'} = 1;
$limits{'working_all_fields'} = 1; $limits{'working_all_fields'} = 1;
$smds{'time'} = 1;
$smds{'q1'} = 'b'; # with time not supp by mysql ('')
$smds{'q2'} = 'b';
$smds{'q3'} = 'b'; # with time ('')
$smds{'q4'} = 'c'; # with time not supp by mysql (d)
$smds{'q5'} = 'b'; # with time not supp by mysql ('')
$smds{'q6'} = 'c'; # with time not supp by mysql ('')
$smds{'q7'} = 'c';
$smds{'q8'} = 'f';
$smds{'q9'} = 'c';
$smds{'q10'} = 'b';
$smds{'q11'} = 'b';
$smds{'q12'} = 'd';
$smds{'q13'} = 'c';
$smds{'q14'} = 'd';
$smds{'q15'} = 'd';
$smds{'q16'} = 'a';
$smds{'q17'} = 'c';
return $self; return $self;
} }
@ -1675,7 +1572,6 @@ sub new
$self->{'cmp_name'} = "Informix"; $self->{'cmp_name'} = "Informix";
$self->{'data_source'} = "DBI:Informix:$database"; $self->{'data_source'} = "DBI:Informix:$database";
$self->{'limits'} = \%limits; $self->{'limits'} = \%limits;
$self->{'smds'} = \%smds;
$self->{'blob'} = "byte in table"; $self->{'blob'} = "byte in table";
$self->{'text'} = "byte in table"; $self->{'text'} = "byte in table";
$self->{'double_quotes'} = 0; # Can handle: 'Walker''s' $self->{'double_quotes'} = 0; # Can handle: 'Walker''s'
@ -1888,7 +1784,6 @@ sub new
$self->{'data_source'} .= ":$host"; $self->{'data_source'} .= ":$host";
} }
$self->{'limits'} = \%limits; $self->{'limits'} = \%limits;
$self->{'smds'} = \%smds;
$self->{'blob'} = "blob"; $self->{'blob'} = "blob";
$self->{'text'} = "blob"; # text ? $self->{'text'} = "blob"; # text ?
$self->{'double_quotes'} = 1; # Can handle: 'Walker''s' $self->{'double_quotes'} = 1; # Can handle: 'Walker''s'
@ -2071,7 +1966,6 @@ sub new
$self->{'data_source'} .= ":$host"; $self->{'data_source'} .= ":$host";
} }
$self->{'limits'} = \%limits; $self->{'limits'} = \%limits;
$self->{'smds'} = \%smds;
$self->{'blob'} = "text"; $self->{'blob'} = "text";
$self->{'text'} = "text"; $self->{'text'} = "text";
$self->{'double_quotes'} = 1; # Can handle: 'Walker''s' $self->{'double_quotes'} = 1; # Can handle: 'Walker''s'
@ -2264,7 +2158,6 @@ sub new
$self->{'data_source'} .= ";hostname=$host"; $self->{'data_source'} .= ";hostname=$host";
} }
$self->{'limits'} = \%limits; $self->{'limits'} = \%limits;
$self->{'smds'} = \%smds;
$self->{'blob'} = "text"; $self->{'blob'} = "text";
$self->{'text'} = "text"; $self->{'text'} = "text";
$self->{'double_quotes'} = 1; # Can handle: 'Walker''s' $self->{'double_quotes'} = 1; # Can handle: 'Walker''s'
@ -2497,7 +2390,6 @@ sub new
$self->{'cmp_name'} = "Adabas"; $self->{'cmp_name'} = "Adabas";
$self->{'data_source'} = "DBI:Adabas:$database"; $self->{'data_source'} = "DBI:Adabas:$database";
$self->{'limits'} = \%limits; $self->{'limits'} = \%limits;
$self->{'smds'} = \%smds;
$self->{'blob'} = "long"; $self->{'blob'} = "long";
$self->{'text'} = "long"; $self->{'text'} = "long";
$self->{'double_quotes'} = 1; # Can handle: 'Walker''s' $self->{'double_quotes'} = 1; # Can handle: 'Walker''s'
@ -2549,24 +2441,6 @@ sub new
$limits{'order_by_unused'} = 1; $limits{'order_by_unused'} = 1;
$limits{'working_all_fields'} = 1; $limits{'working_all_fields'} = 1;
$smds{'time'} = 1;
$smds{'q1'} = 'b'; # with time not supp by mysql ('')
$smds{'q2'} = 'b';
$smds{'q3'} = 'b'; # with time ('')
$smds{'q4'} = 'c'; # with time not supp by mysql (d)
$smds{'q5'} = 'b'; # with time not supp by mysql ('')
$smds{'q6'} = 'c'; # with time not supp by mysql ('')
$smds{'q7'} = 'c';
$smds{'q8'} = 'f';
$smds{'q9'} = 'c';
$smds{'q10'} = 'b';
$smds{'q11'} = 'b';
$smds{'q12'} = 'd';
$smds{'q13'} = 'c';
$smds{'q14'} = 'd';
$smds{'q15'} = 'd';
$smds{'q16'} = 'a';
$smds{'q17'} = 'c';
return $self; return $self;
} }
@ -2718,7 +2592,6 @@ sub new
$self->{'data_source'} .= ":$host"; $self->{'data_source'} .= ":$host";
} }
$self->{'limits'} = \%limits; $self->{'limits'} = \%limits;
$self->{'smds'} = \%smds;
$self->{'blob'} = "varchar(255)"; $self->{'blob'} = "varchar(255)";
$self->{'text'} = "varchar(255)"; $self->{'text'} = "varchar(255)";
$self->{'double_quotes'} = 1; # Can handle: 'Walker''s' $self->{'double_quotes'} = 1; # Can handle: 'Walker''s'
@ -2894,7 +2767,6 @@ sub new
$self->{'cmp_name'} = "mimer"; $self->{'cmp_name'} = "mimer";
$self->{'data_source'} = "DBI:mimer:$database:$host"; $self->{'data_source'} = "DBI:mimer:$database:$host";
$self->{'limits'} = \%limits; $self->{'limits'} = \%limits;
$self->{'smds'} = \%smds;
$self->{'blob'} = "binary varying(15000)"; $self->{'blob'} = "binary varying(15000)";
$self->{'text'} = "character varying(15000)"; $self->{'text'} = "character varying(15000)";
$self->{'double_quotes'} = 1; # Can handle: 'Walker''s' $self->{'double_quotes'} = 1; # Can handle: 'Walker''s'
@ -2950,24 +2822,6 @@ sub new
$limits{'order_by_unused'} = 1; $limits{'order_by_unused'} = 1;
$limits{'working_all_fields'} = 1; $limits{'working_all_fields'} = 1;
$smds{'time'} = 1;
$smds{'q1'} = 'b'; # with time not supp by mysql ('')
$smds{'q2'} = 'b';
$smds{'q3'} = 'b'; # with time ('')
$smds{'q4'} = 'c'; # with time not supp by mysql (d)
$smds{'q5'} = 'b'; # with time not supp by mysql ('')
$smds{'q6'} = 'c'; # with time not supp by mysql ('')
$smds{'q7'} = 'c';
$smds{'q8'} = 'f';
$smds{'q9'} = 'c';
$smds{'q10'} = 'b';
$smds{'q11'} = 'b';
$smds{'q12'} = 'd';
$smds{'q13'} = 'c';
$smds{'q14'} = 'd';
$smds{'q15'} = 'd';
$smds{'q16'} = 'a';
$smds{'q17'} = 'c';
return $self; return $self;
} }
@ -3112,7 +2966,6 @@ sub new
$self->{'cmp_name'} = "interbase"; $self->{'cmp_name'} = "interbase";
$self->{'data_source'} = "DBI:InterBase:database=$database:ib_dialect=3"; $self->{'data_source'} = "DBI:InterBase:database=$database:ib_dialect=3";
$self->{'limits'} = \%limits; $self->{'limits'} = \%limits;
$self->{'smds'} = \%smds;
$self->{'blob'} = "blob"; $self->{'blob'} = "blob";
$self->{'text'} = ""; $self->{'text'} = "";
$self->{'double_quotes'} = 1; # Can handle: 'Walker''s' $self->{'double_quotes'} = 1; # Can handle: 'Walker''s'
@ -3166,24 +3019,6 @@ sub new
$limits{'order_by_unused'} = 1; $limits{'order_by_unused'} = 1;
$limits{'working_all_fields'} = 1; $limits{'working_all_fields'} = 1;
$smds{'time'} = 1;
$smds{'q1'} = 'b'; # with time not supp by mysql ('')
$smds{'q2'} = 'b';
$smds{'q3'} = 'b'; # with time ('')
$smds{'q4'} = 'c'; # with time not supp by mysql (d)
$smds{'q5'} = 'b'; # with time not supp by mysql ('')
$smds{'q6'} = 'c'; # with time not supp by mysql ('')
$smds{'q7'} = 'c';
$smds{'q8'} = 'f';
$smds{'q9'} = 'c';
$smds{'q10'} = 'b';
$smds{'q11'} = 'b';
$smds{'q12'} = 'd';
$smds{'q13'} = 'c';
$smds{'q14'} = 'd';
$smds{'q15'} = 'd';
$smds{'q16'} = 'a';
$smds{'q17'} = 'c';
return $self; return $self;
} }
@ -3331,7 +3166,6 @@ sub new
$self->{'cmp_name'} = "FrontBase"; $self->{'cmp_name'} = "FrontBase";
$self->{'data_source'} = "DBI:FB:dbname=$database;host=$host"; $self->{'data_source'} = "DBI:FB:dbname=$database;host=$host";
$self->{'limits'} = \%limits; $self->{'limits'} = \%limits;
$self->{'smds'} = \%smds;
$self->{'blob'} = "varchar(8000000)"; $self->{'blob'} = "varchar(8000000)";
$self->{'text'} = "varchar(8000000)"; $self->{'text'} = "varchar(8000000)";
$self->{'double_quotes'} = 1; # Can handle: 'Walker''s' $self->{'double_quotes'} = 1; # Can handle: 'Walker''s'

View File

@ -3782,10 +3782,10 @@ uint Field_varstring::max_packed_col_length(uint max_length)
Field_blob::Field_blob(char *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, Field_blob::Field_blob(char *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg, enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg,uint blob_pack_length, struct st_table *table_arg,uint blob_pack_length,
bool binary_arg) bool binary_arg, CHARSET_INFO *cs)
:Field_str(ptr_arg, (1L << min(blob_pack_length,3)*8)-1L, :Field_str(ptr_arg, (1L << min(blob_pack_length,3)*8)-1L,
null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg,
table_arg, default_charset_info), table_arg, cs),
packlength(blob_pack_length),binary_flag(binary_arg), geom_flag(true) packlength(blob_pack_length),binary_flag(binary_arg), geom_flag(true)
{ {
flags|= BLOB_FLAG; flags|= BLOB_FLAG;
@ -3967,9 +3967,9 @@ String *Field_blob::val_str(String *val_buffer __attribute__((unused)),
char *blob; char *blob;
memcpy_fixed(&blob,ptr+packlength,sizeof(char*)); memcpy_fixed(&blob,ptr+packlength,sizeof(char*));
if (!blob) if (!blob)
val_ptr->set("",0,default_charset_info); // A bit safer than ->length(0) val_ptr->set("",0,field_charset); // A bit safer than ->length(0)
else else
val_ptr->set((const char*) blob,get_length(ptr),default_charset_info); val_ptr->set((const char*) blob,get_length(ptr),field_charset);
return val_ptr; return val_ptr;
} }
@ -4782,7 +4782,8 @@ Field *make_field(char *ptr, uint32 field_length,
if (f_is_blob(pack_flag)) if (f_is_blob(pack_flag))
return new Field_blob(ptr,null_pos,null_bit, return new Field_blob(ptr,null_pos,null_bit,
unireg_check, field_name, table, unireg_check, field_name, table,
pack_length,f_is_binary(pack_flag) != 0); pack_length,f_is_binary(pack_flag) != 0,
default_charset_info);
if (f_is_geom(pack_flag)) if (f_is_geom(pack_flag))
return new Field_geom(ptr,null_pos,null_bit, return new Field_geom(ptr,null_pos,null_bit,
unireg_check, field_name, table, unireg_check, field_name, table,

View File

@ -842,11 +842,11 @@ public:
Field_blob(char *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, Field_blob(char *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg, enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg,uint blob_pack_length, struct st_table *table_arg,uint blob_pack_length,
bool binary_arg); bool binary_arg, CHARSET_INFO *cs);
Field_blob(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg, Field_blob(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg,
struct st_table *table_arg, bool binary_arg) struct st_table *table_arg, bool binary_arg, CHARSET_INFO *cs)
:Field_str((char*) 0,len_arg, maybe_null_arg ? (uchar*) "": 0,0, :Field_str((char*) 0,len_arg, maybe_null_arg ? (uchar*) "": 0,0,
NONE, field_name_arg, table_arg, default_charset_info), NONE, field_name_arg, table_arg, cs),
packlength(3),binary_flag(binary_arg), geom_flag(true) packlength(3),binary_flag(binary_arg), geom_flag(true)
{ {
flags|= BLOB_FLAG; flags|= BLOB_FLAG;
@ -930,11 +930,12 @@ public:
struct st_table *table_arg,uint blob_pack_length, struct st_table *table_arg,uint blob_pack_length,
bool binary_arg) bool binary_arg)
:Field_blob(ptr_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, :Field_blob(ptr_arg, null_ptr_arg, null_bit_arg, unireg_check_arg,
field_name_arg, table_arg, blob_pack_length,binary_arg) {} field_name_arg, table_arg, blob_pack_length,binary_arg,
default_charset_info) {}
Field_geom(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg, Field_geom(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg,
struct st_table *table_arg, bool binary_arg) struct st_table *table_arg, bool binary_arg)
:Field_blob(len_arg, maybe_null_arg, field_name_arg, :Field_blob(len_arg, maybe_null_arg, field_name_arg,
table_arg, binary_arg) {} table_arg, binary_arg, default_charset_info) {}
enum ha_base_keytype key_type() const { return HA_KEYTYPE_VARBINARY; } enum ha_base_keytype key_type() const { return HA_KEYTYPE_VARBINARY; }
void get_key_image(char *buff,uint length, imagetype type); void get_key_image(char *buff,uint length, imagetype type);

View File

@ -508,7 +508,8 @@ void field_conv(Field *to,Field *from)
if (!blob->value.is_alloced() && if (!blob->value.is_alloced() &&
from->real_type() != FIELD_TYPE_STRING) from->real_type() != FIELD_TYPE_STRING)
blob->value.copy(); blob->value.copy();
blob->store(blob->value.ptr(),blob->value.length(),default_charset_info); blob->store(blob->value.ptr(),blob->value.length(),
to->binary()?default_charset_info:((Field_str*)to)->charset());
return; return;
} }
if ((from->result_type() == STRING_RESULT && if ((from->result_type() == STRING_RESULT &&
@ -520,7 +521,9 @@ void field_conv(Field *to,Field *from)
char buff[MAX_FIELD_WIDTH]; char buff[MAX_FIELD_WIDTH];
String result(buff,sizeof(buff),default_charset_info); String result(buff,sizeof(buff),default_charset_info);
from->val_str(&result,&result); from->val_str(&result,&result);
to->store(result.c_ptr_quick(),result.length(),default_charset_info); to->store(result.c_ptr_quick(),result.length(),
to->binary()?default_charset_info:((Field_str*)to)->charset());
// QQ: what to do if "from" and "to" are of dirrent charsets?
} }
else if (from->result_type() == REAL_RESULT) else if (from->result_type() == REAL_RESULT)
to->store(from->val_real()); to->store(from->val_real());

View File

@ -137,6 +137,7 @@ enum row_type { ROW_TYPE_NOT_USED=-1, ROW_TYPE_DEFAULT, ROW_TYPE_FIXED,
#define HA_CREATE_USED_MAX_ROWS 32 #define HA_CREATE_USED_MAX_ROWS 32
#define HA_CREATE_USED_AVG_ROW_LENGTH 64 #define HA_CREATE_USED_AVG_ROW_LENGTH 64
#define HA_CREATE_USED_PACK_KEYS 128 #define HA_CREATE_USED_PACK_KEYS 128
#define HA_CREATE_USED_CHARSET 256
typedef struct st_thd_trans { typedef struct st_thd_trans {
void *bdb_tid; void *bdb_tid;

View File

@ -133,6 +133,9 @@ void Item_field::set_field(Field *field_par)
field_name=field_par->field_name; field_name=field_par->field_name;
binary=field_par->binary(); binary=field_par->binary();
unsigned_flag=test(field_par->flags & UNSIGNED_FLAG); unsigned_flag=test(field_par->flags & UNSIGNED_FLAG);
/* For string fields copy character set from original field */
if (!field_par->binary())
str_value.set_charset(((Field_str*)field_par)->charset());
} }
const char *Item_ident::full_name() const const char *Item_ident::full_name() const
@ -443,12 +446,13 @@ String *Item_copy_string::val_str(String *str)
/* ARGSUSED */ /* ARGSUSED */
bool Item::fix_fields(THD *thd, bool Item::fix_fields(THD *thd,
struct st_table_list *list) struct st_table_list *list,
Item ** ref)
{ {
return 0; return 0;
} }
bool Item_field::fix_fields(THD *thd,TABLE_LIST *tables) bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{ {
if (!field) // If field is not checked if (!field) // If field is not checked
{ {
@ -464,7 +468,7 @@ bool Item_field::fix_fields(THD *thd,TABLE_LIST *tables)
mention of table name, but if we join tables in one list it will mention of table name, but if we join tables in one list it will
cause error ER_NON_UNIQ_ERROR in find_field_in_tables. cause error ER_NON_UNIQ_ERROR in find_field_in_tables.
*/ */
SELECT_LEX *last; SELECT_LEX *last= 0;
for (SELECT_LEX *sl= thd->lex.select->outer_select(); for (SELECT_LEX *sl= thd->lex.select->outer_select();
sl && !tmp; sl && !tmp;
sl= sl->outer_select()) sl= sl->outer_select())
@ -473,6 +477,8 @@ bool Item_field::fix_fields(THD *thd,TABLE_LIST *tables)
if (!tmp) if (!tmp)
return 1; return 1;
else else
{
depended_from= last;
/* /*
Mark all selects from resolved to 1 before select where was Mark all selects from resolved to 1 before select where was
found table as depended (of select where was found table) found table as depended (of select where was found table)
@ -491,6 +497,7 @@ bool Item_field::fix_fields(THD *thd,TABLE_LIST *tables)
tbl->shared= 1; tbl->shared= 1;
} }
} }
}
set_field(tmp); set_field(tmp);
} }
else if (thd && thd->set_query_id && field->query_id != thd->query_id) else if (thd && thd->set_query_id && field->query_id != thd->query_id)
@ -501,6 +508,14 @@ bool Item_field::fix_fields(THD *thd,TABLE_LIST *tables)
table->used_fields++; table->used_fields++;
table->used_keys&=field->part_of_key; table->used_keys&=field->part_of_key;
} }
if (depended_from != 0 && depended_from->having_fix_field)
{
*ref= new Item_ref((char *)db_name, (char *)table_name,
(char *)field_name);
if (!*ref)
return 1;
return (*ref)->fix_fields(thd, tables, ref);
}
return 0; return 0;
} }
@ -784,12 +799,50 @@ bool Item_null::send(THD *thd, String *packet)
Find field in select list having the same name Find field in select list having the same name
*/ */
bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables) bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
{ {
if (!ref) if (!ref)
{ {
if (!(ref=find_item_in_list(this,thd->lex.select->item_list))) if (!(ref= find_item_in_list(this,thd->lex.select->item_list)))
{
/*
We can't find table field in table list of current select,
consequently we have to find it in outer subselect(s).
We can't join lists of outer & current select, because of scope
of view rules. For example if both tables (outer & current) have
field 'field' it is not mistake to refer to this field without
mention of table name, but if we join tables in one list it will
cause error ER_NON_UNIQ_ERROR in find_field_in_tables.
*/
SELECT_LEX *last=0;
for (SELECT_LEX *sl= thd->lex.select->outer_select();
sl && !ref;
sl= sl->outer_select())
ref= find_item_in_list(this, (last= sl)->item_list);
if (!ref)
return 1; return 1;
else
{
depended_from= last;
/*
Mark all selects from resolved to 1 before select where was
found table as depended (of select where was found table)
*/
for (SELECT_LEX *s= thd->lex.select;
s &&s != last;
s= s->outer_select())
if( !s->depended )
{
s->depended= 1; //Select is depended of outer select
//Tables will be reopened many times
for (TABLE_LIST *tbl=
(TABLE_LIST*)s->table_list.first;
tbl;
tbl= tbl->next)
tbl->shared= 1;
}
}
}
max_length= (*ref)->max_length; max_length= (*ref)->max_length;
maybe_null= (*ref)->maybe_null; maybe_null= (*ref)->maybe_null;
decimals= (*ref)->decimals; decimals= (*ref)->decimals;

View File

@ -52,7 +52,7 @@ public:
virtual ~Item() { name=0; } /*lint -e1509 */ virtual ~Item() { name=0; } /*lint -e1509 */
void set_name(char* str,uint length=0); void set_name(char* str,uint length=0);
void init_make_field(Send_field *tmp_field,enum enum_field_types type); void init_make_field(Send_field *tmp_field,enum enum_field_types type);
virtual bool fix_fields(THD *,struct st_table_list *); virtual bool fix_fields(THD *, struct st_table_list *, Item **);
virtual bool save_in_field(Field *field); virtual bool save_in_field(Field *field);
virtual void save_org_in_field(Field *field) virtual void save_org_in_field(Field *field)
{ (void) save_in_field(field); } { (void) save_in_field(field); }
@ -85,15 +85,18 @@ public:
}; };
class st_select_lex;
class Item_ident :public Item class Item_ident :public Item
{ {
public: public:
const char *db_name; const char *db_name;
const char *table_name; const char *table_name;
const char *field_name; const char *field_name;
st_select_lex *depended_from;
Item_ident(const char *db_name_par,const char *table_name_par, Item_ident(const char *db_name_par,const char *table_name_par,
const char *field_name_par) const char *field_name_par)
:db_name(db_name_par),table_name(table_name_par),field_name(field_name_par) :db_name(db_name_par),table_name(table_name_par),
field_name(field_name_par), depended_from(0)
{ name = (char*) field_name_par; } { name = (char*) field_name_par; }
const char *full_name() const; const char *full_name() const;
}; };
@ -120,7 +123,7 @@ public:
String *str_result(String* tmp); String *str_result(String* tmp);
bool send(THD *thd, String *str_arg) { return result_field->send(thd,str_arg); } bool send(THD *thd, String *str_arg) { return result_field->send(thd,str_arg); }
void make_field(Send_field *field); void make_field(Send_field *field);
bool fix_fields(THD *,struct st_table_list *); bool fix_fields(THD *, struct st_table_list *, Item **);
bool save_in_field(Field *field); bool save_in_field(Field *field);
void save_org_in_field(Field *field); void save_org_in_field(Field *field);
table_map used_tables() const; table_map used_tables() const;
@ -390,7 +393,7 @@ public:
} }
bool send(THD *thd, String *tmp) { return (*ref)->send(thd, tmp); } bool send(THD *thd, String *tmp) { return (*ref)->send(thd, tmp); }
void make_field(Send_field *field) { (*ref)->make_field(field); } void make_field(Send_field *field) { (*ref)->make_field(field); }
bool fix_fields(THD *,struct st_table_list *); bool fix_fields(THD *, struct st_table_list *, Item **);
bool save_in_field(Field *field) { return (*ref)->save_in_field(field); } bool save_in_field(Field *field) { return (*ref)->save_in_field(field); }
void save_org_in_field(Field *field) { (*ref)->save_org_in_field(field); } void save_org_in_field(Field *field) { (*ref)->save_org_in_field(field); }
enum Item_result result_type () const { return (*ref)->result_type(); } enum Item_result result_type () const { return (*ref)->result_type(); }

View File

@ -727,12 +727,12 @@ double Item_func_case::val()
bool bool
Item_func_case::fix_fields(THD *thd,TABLE_LIST *tables) Item_func_case::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{ {
if (first_expr && first_expr->fix_fields(thd,tables) || if (first_expr && first_expr->fix_fields(thd, tables, &first_expr) ||
else_expr && else_expr->fix_fields(thd,tables)) else_expr && else_expr->fix_fields(thd, tables, &else_expr))
return 1; return 1;
if (Item_func::fix_fields(thd,tables)) if (Item_func::fix_fields(thd, tables, ref))
return 1; return 1;
if (first_expr) if (first_expr)
{ {
@ -1074,7 +1074,7 @@ longlong Item_func_bit_and::val_int()
bool bool
Item_cond::fix_fields(THD *thd,TABLE_LIST *tables) Item_cond::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{ {
List_iterator<Item> li(list); List_iterator<Item> li(list);
Item *item; Item *item;
@ -1096,7 +1096,7 @@ Item_cond::fix_fields(THD *thd,TABLE_LIST *tables)
#endif #endif
item= *li.ref(); // new current item item= *li.ref(); // new current item
} }
if (item->fix_fields(thd,tables)) if (item->fix_fields(thd, tables, li.ref()))
return 1; /* purecov: inspected */ return 1; /* purecov: inspected */
used_tables_cache|=item->used_tables(); used_tables_cache|=item->used_tables();
with_sum_func= with_sum_func || item->with_sum_func; with_sum_func= with_sum_func || item->with_sum_func;
@ -1272,9 +1272,9 @@ Item_func::optimize_type Item_func_like::select_optimize() const
return OPTIMIZE_NONE; return OPTIMIZE_NONE;
} }
bool Item_func_like::fix_fields(THD *thd,struct st_table_list *tlist) bool Item_func_like::fix_fields(THD *thd, TABLE_LIST *tlist, Item ** ref)
{ {
if (Item_bool_func2::fix_fields(thd, tlist)) if (Item_bool_func2::fix_fields(thd, tlist, ref))
return 1; return 1;
/* /*
@ -1324,9 +1324,10 @@ bool Item_func_like::fix_fields(THD *thd,struct st_table_list *tlist)
#ifdef USE_REGEX #ifdef USE_REGEX
bool bool
Item_func_regex::fix_fields(THD *thd,TABLE_LIST *tables) Item_func_regex::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{ {
if (args[0]->fix_fields(thd,tables) || args[1]->fix_fields(thd,tables)) if (args[0]->fix_fields(thd, tables, args) ||
args[1]->fix_fields(thd,tables, args + 1))
return 1; /* purecov: inspected */ return 1; /* purecov: inspected */
with_sum_func=args[0]->with_sum_func || args[1]->with_sum_func; with_sum_func=args[0]->with_sum_func || args[1]->with_sum_func;
max_length=1; decimals=0; max_length=1; decimals=0;

View File

@ -177,9 +177,10 @@ public:
Item_func_interval(Item *a,List<Item> &list) Item_func_interval(Item *a,List<Item> &list)
:Item_int_func(list),item(a),intervals(0) {} :Item_int_func(list),item(a),intervals(0) {}
longlong val_int(); longlong val_int();
bool fix_fields(THD *thd,struct st_table_list *tlist) bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref)
{ {
return (item->fix_fields(thd,tlist) || Item_func::fix_fields(thd,tlist)); return (item->fix_fields(thd, tlist, &item) ||
Item_func::fix_fields(thd, tlist, ref));
} }
void fix_length_and_dec(); void fix_length_and_dec();
~Item_func_interval() { delete item; } ~Item_func_interval() { delete item; }
@ -259,7 +260,7 @@ public:
enum Item_result result_type () const { return cached_result_type; } enum Item_result result_type () const { return cached_result_type; }
const char *func_name() const { return "case"; } const char *func_name() const { return "case"; }
void print(String *str); void print(String *str);
bool fix_fields(THD *thd,struct st_table_list *tlist); bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref);
Item *find_item(String *str); Item *find_item(String *str);
}; };
@ -409,9 +410,10 @@ class Item_func_in :public Item_int_func
Item_func_in(Item *a,List<Item> &list) Item_func_in(Item *a,List<Item> &list)
:Item_int_func(list),item(a),array(0),in_item(0) {} :Item_int_func(list),item(a),array(0),in_item(0) {}
longlong val_int(); longlong val_int();
bool fix_fields(THD *thd,struct st_table_list *tlist) bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref)
{ {
return (item->fix_fields(thd,tlist) || Item_func::fix_fields(thd,tlist)); return (item->fix_fields(thd, tlist, &item) ||
Item_func::fix_fields(thd, tlist, ref));
} }
void fix_length_and_dec(); void fix_length_and_dec();
~Item_func_in() { delete item; delete array; delete in_item; } ~Item_func_in() { delete item; delete array; delete in_item; }
@ -505,7 +507,7 @@ public:
cond_result eq_cmp_result() const { return COND_TRUE; } cond_result eq_cmp_result() const { return COND_TRUE; }
const char *func_name() const { return "like"; } const char *func_name() const { return "like"; }
void fix_length_and_dec(); void fix_length_and_dec();
bool fix_fields(THD *thd,struct st_table_list *tlist); bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref);
}; };
#ifdef USE_REGEX #ifdef USE_REGEX
@ -523,7 +525,7 @@ public:
regex_compiled(0),regex_is_const(0) {} regex_compiled(0),regex_is_const(0) {}
~Item_func_regex(); ~Item_func_regex();
longlong val_int(); longlong val_int();
bool fix_fields(THD *thd,struct st_table_list *tlist); bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref);
const char *func_name() const { return "regex"; } const char *func_name() const { return "regex"; }
}; };
@ -552,7 +554,7 @@ public:
{ list.push_back(i1); list.push_back(i2); } { list.push_back(i1); list.push_back(i2); }
~Item_cond() { list.delete_elements(); } ~Item_cond() { list.delete_elements(); }
bool add(Item *item) { return list.push_back(item); } bool add(Item *item) { return list.push_back(item); }
bool fix_fields(THD *,struct st_table_list *); bool fix_fields(THD *, struct st_table_list *, Item **ref);
enum Type type() const { return COND_ITEM; } enum Type type() const { return COND_ITEM; }
List<Item>* argument_list() { return &list; } List<Item>* argument_list() { return &list; }

View File

@ -58,7 +58,7 @@ Item_func::Item_func(List<Item> &list)
} }
bool bool
Item_func::fix_fields(THD *thd,TABLE_LIST *tables) Item_func::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{ {
Item **arg,**arg_end; Item **arg,**arg_end;
char buff[STACK_BUFF_ALLOC]; // Max argument in function char buff[STACK_BUFF_ALLOC]; // Max argument in function
@ -72,12 +72,23 @@ Item_func::fix_fields(THD *thd,TABLE_LIST *tables)
{ // Print purify happy { // Print purify happy
for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++) for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++)
{ {
if ((*arg)->fix_fields(thd,tables)) if ((*arg)->fix_fields(thd, tables, arg))
return 1; /* purecov: inspected */ return 1; /* purecov: inspected */
if ((*arg)->maybe_null) if ((*arg)->maybe_null)
maybe_null=1; maybe_null=1;
if ((*arg)->binary) if ((*arg)->binary)
binary=1; binary=1;
/*
Change charset to arg charset if it is not equal to
default_charset_info. This will work for many cases,
but generally this should be done more carefull. Each string
function should have it's own fix_fields() method to correctly
setup it's result's character set taking in account arguments.
For example: left(a,b) should take in account only first argument,
but ignore the second one.
*/
if ((*arg)->str_value.charset() != default_charset_info)
str_value.set_charset((*arg)->str_value.charset());
with_sum_func= with_sum_func || (*arg)->with_sum_func; with_sum_func= with_sum_func || (*arg)->with_sum_func;
used_tables_cache|=(*arg)->used_tables(); used_tables_cache|=(*arg)->used_tables();
const_item_cache&= (*arg)->const_item(); const_item_cache&= (*arg)->const_item();
@ -1091,7 +1102,7 @@ udf_handler::~udf_handler()
bool bool
udf_handler::fix_fields(THD *thd,TABLE_LIST *tables,Item_result_field *func, udf_handler::fix_fields(THD *thd, TABLE_LIST *tables, Item_result_field *func,
uint arg_count, Item **arguments) uint arg_count, Item **arguments)
{ {
char buff[STACK_BUFF_ALLOC]; // Max argument in function char buff[STACK_BUFF_ALLOC]; // Max argument in function
@ -1135,7 +1146,7 @@ udf_handler::fix_fields(THD *thd,TABLE_LIST *tables,Item_result_field *func,
arg != arg_end ; arg != arg_end ;
arg++,i++) arg++,i++)
{ {
if ((*arg)->fix_fields(thd,tables)) if ((*arg)->fix_fields(thd, tables, arg))
return 1; return 1;
if ((*arg)->binary) if ((*arg)->binary)
func->binary=1; func->binary=1;
@ -1754,11 +1765,12 @@ static user_var_entry *get_variable(HASH *hash, LEX_STRING &name,
} }
bool Item_func_set_user_var::fix_fields(THD *thd,TABLE_LIST *tables) bool Item_func_set_user_var::fix_fields(THD *thd, TABLE_LIST *tables,
Item **ref)
{ {
if (!thd) if (!thd)
thd=current_thd; thd=current_thd;
if (Item_func::fix_fields(thd,tables) || if (Item_func::fix_fields(thd, tables, ref) ||
!(entry= get_variable(&thd->user_vars, name, 1))) !(entry= get_variable(&thd->user_vars, name, 1)))
return 1; return 1;
entry->update_query_id=thd->query_id; entry->update_query_id=thd->query_id;
@ -2084,7 +2096,7 @@ void Item_func_match::init_search(bool no_order)
} }
} }
bool Item_func_match::fix_fields(THD *thd,struct st_table_list *tlist) bool Item_func_match::fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref)
{ {
List_iterator<Item> li(fields); List_iterator<Item> li(fields);
Item *item; Item *item;
@ -2097,7 +2109,7 @@ bool Item_func_match::fix_fields(THD *thd,struct st_table_list *tlist)
modifications to find_best and auto_close as complement to auto_init code modifications to find_best and auto_close as complement to auto_init code
above. above.
*/ */
if (Item_func::fix_fields(thd,tlist) || !const_item()) if (Item_func::fix_fields(thd, tlist, ref) || !const_item())
{ {
my_error(ER_WRONG_ARGUMENTS,MYF(0),"AGAINST"); my_error(ER_WRONG_ARGUMENTS,MYF(0),"AGAINST");
return 1; return 1;
@ -2105,7 +2117,7 @@ bool Item_func_match::fix_fields(THD *thd,struct st_table_list *tlist)
while ((item=li++)) while ((item=li++))
{ {
if (item->fix_fields(thd,tlist)) if (item->fix_fields(thd, tlist, li.ref()))
return 1; return 1;
if (item->type() == Item::REF_ITEM) if (item->type() == Item::REF_ITEM)
li.replace(item= *((Item_ref *)item)->ref); li.replace(item= *((Item_ref *)item)->ref);

View File

@ -99,7 +99,7 @@ public:
} }
Item_func(List<Item> &list); Item_func(List<Item> &list);
~Item_func() {} /* Nothing to do; Items are freed automaticly */ ~Item_func() {} /* Nothing to do; Items are freed automaticly */
bool fix_fields(THD *,struct st_table_list *); bool fix_fields(THD *,struct st_table_list *, Item **ref);
void make_field(Send_field *field); void make_field(Send_field *field);
table_map used_tables() const; table_map used_tables() const;
void update_used_tables(); void update_used_tables();
@ -567,9 +567,10 @@ public:
Item_func_field(Item *a,List<Item> &list) :Item_int_func(list),item(a) {} Item_func_field(Item *a,List<Item> &list) :Item_int_func(list),item(a) {}
~Item_func_field() { delete item; } ~Item_func_field() { delete item; }
longlong val_int(); longlong val_int();
bool fix_fields(THD *thd,struct st_table_list *tlist) bool fix_fields(THD *thd,struct st_table_list *tlist, Item **ref)
{ {
return (item->fix_fields(thd,tlist) || Item_func::fix_fields(thd,tlist)); return (item->fix_fields(thd, tlist, &item) ||
Item_func::fix_fields(thd, tlist, ref));
} }
void update_used_tables() void update_used_tables()
{ {
@ -708,11 +709,11 @@ public:
:Item_func(list), udf(udf_arg) {} :Item_func(list), udf(udf_arg) {}
~Item_udf_func() {} ~Item_udf_func() {}
const char *func_name() const { return udf.name(); } const char *func_name() const { return udf.name(); }
bool fix_fields(THD *thd,struct st_table_list *tables) bool fix_fields(THD *thd, struct st_table_list *tables, Item **ref)
{ {
bool res=udf.fix_fields(thd,tables,this,arg_count,args); bool res= udf.fix_fields(thd, tables, this, arg_count, args);
used_tables_cache=udf.used_tables_cache; used_tables_cache= udf.used_tables_cache;
const_item_cache=udf.const_item_cache; const_item_cache= udf.const_item_cache;
return res; return res;
} }
Item_result result_type () const { return udf.result_type(); } Item_result result_type () const { return udf.result_type(); }
@ -867,7 +868,7 @@ public:
void update_hash(void *ptr, uint length, enum Item_result type); void update_hash(void *ptr, uint length, enum Item_result type);
bool update(); bool update();
enum Item_result result_type () const { return cached_result_type; } enum Item_result result_type () const { return cached_result_type; }
bool fix_fields(THD *thd,struct st_table_list *tables); bool fix_fields(THD *thd, struct st_table_list *tables, Item **ref);
void fix_length_and_dec(); void fix_length_and_dec();
void print(String *str); void print(String *str);
const char *func_name() const { return "set_user_var"; } const char *func_name() const { return "set_user_var"; }
@ -941,7 +942,7 @@ public:
} }
enum Functype functype() const { return FT_FUNC; } enum Functype functype() const { return FT_FUNC; }
void update_used_tables() {} void update_used_tables() {}
bool fix_fields(THD *thd,struct st_table_list *tlist); bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref);
bool eq(const Item *, bool binary_cmp) const; bool eq(const Item *, bool binary_cmp) const;
longlong val_int() { return val()!=0.0; } longlong val_int() { return val()!=0.0; }
double val(); double val();

View File

@ -759,6 +759,7 @@ String *Item_func_left::val_str(String *str)
if (!res->alloced_length()) if (!res->alloced_length())
{ // Don't change const str { // Don't change const str
str_value= *res; // Not malloced string str_value= *res; // Not malloced string
str_value.set_charset(res->charset());
res= &str_value; res= &str_value;
} }
res->length((uint) length); res->length((uint) length);
@ -1791,6 +1792,7 @@ String *Item_func_conv_charset::val_str(String *str)
null_value=1; null_value=1;
return 0; return 0;
} }
null_value=0;
from=arg->charset(); from=arg->charset();
to=conv_charset; to=conv_charset;
@ -1798,7 +1800,7 @@ String *Item_func_conv_charset::val_str(String *str)
s=(const uchar*)arg->ptr(); s=(const uchar*)arg->ptr();
se=s+arg->length(); se=s+arg->length();
dmaxlen=arg->length()*(conv_charset->mbmaxlen?conv_charset->mbmaxlen:1)+1; dmaxlen=arg->length()*(to->mbmaxlen?to->mbmaxlen:1)+1;
str->alloc(dmaxlen); str->alloc(dmaxlen);
d0=d=(unsigned char*)str->ptr(); d0=d=(unsigned char*)str->ptr();
de=d+dmaxlen; de=d+dmaxlen;
@ -1840,7 +1842,7 @@ outp:
void Item_func_conv_charset::fix_length_and_dec() void Item_func_conv_charset::fix_length_and_dec()
{ {
/* BAR TODO: What to do here??? */ max_length = args[0]->max_length*(conv_charset->mbmaxlen?conv_charset->mbmaxlen:1);
} }
@ -1910,9 +1912,41 @@ outp:
return str; return str;
} }
bool Item_func_conv_charset::fix_fields(THD *thd,struct st_table_list *tables)
{
char buff[STACK_BUFF_ALLOC]; // Max argument in function
binary=0;
used_tables_cache=0;
const_item_cache=1;
if (thd && check_stack_overrun(thd,buff))
return 0; // Fatal error if flag is set!
if (args[0]->fix_fields(thd, tables, args))
return 1;
maybe_null=args[0]->maybe_null;
binary=args[0]->binary;
const_item_cache=args[0]->const_item();
str_value.set_charset(conv_charset);
fix_length_and_dec();
return 0;
}
void Item_func_conv_charset3::fix_length_and_dec() void Item_func_conv_charset3::fix_length_and_dec()
{ {
/* BAR TODO: What to do here??? */ max_length = args[0]->max_length;
}
String *Item_func_charset::val_str(String *str)
{
String *res = args[0]->val_str(str);
if ((null_value=(args[0]->null_value || !res->charset())))
return 0;
str->copy(res->charset()->name,strlen(res->charset()->name));
return str;
} }

View File

@ -40,9 +40,10 @@ public:
if (!t_arg) if (!t_arg)
return result_field; return result_field;
return (max_length > 255) ? return (max_length > 255) ?
(Field *)new Field_blob(max_length,maybe_null, name,t_arg, binary) : (Field *)new Field_blob(max_length,maybe_null, name,t_arg, binary,
str_value.charset()) :
(Field *) new Field_string(max_length,maybe_null, name,t_arg, binary, (Field *) new Field_string(max_length,maybe_null, name,t_arg, binary,
default_charset_info); str_value.charset());
} }
}; };
@ -79,10 +80,10 @@ public:
String *val_str(String *); String *val_str(String *);
void fix_length_and_dec(); void fix_length_and_dec();
void update_used_tables(); void update_used_tables();
bool fix_fields(THD *thd,struct st_table_list *tlist) bool fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref)
{ {
return (separator->fix_fields(thd,tlist) return (separator->fix_fields(thd, tlist, &separator)
|| Item_func::fix_fields(thd,tlist)); || Item_func::fix_fields(thd, tlist, ref));
} }
const char *func_name() const { return "concat_ws"; } const char *func_name() const { return "concat_ws"; }
}; };
@ -325,9 +326,10 @@ public:
double val(); double val();
longlong val_int(); longlong val_int();
String *val_str(String *str); String *val_str(String *str);
bool fix_fields(THD *thd,struct st_table_list *tlist) bool fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref)
{ {
return (item->fix_fields(thd,tlist) || Item_func::fix_fields(thd,tlist)); return (item->fix_fields(thd, tlist, &item) ||
Item_func::fix_fields(thd, tlist, ref));
} }
void fix_length_and_dec(); void fix_length_and_dec();
void update_used_tables(); void update_used_tables();
@ -344,9 +346,10 @@ public:
Item_func_make_set(Item *a,List<Item> &list) :Item_str_func(list),item(a) {} Item_func_make_set(Item *a,List<Item> &list) :Item_str_func(list),item(a) {}
~Item_func_make_set() { delete item; } ~Item_func_make_set() { delete item; }
String *val_str(String *str); String *val_str(String *str);
bool fix_fields(THD *thd,struct st_table_list *tlist) bool fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref)
{ {
return (item->fix_fields(thd,tlist) || Item_func::fix_fields(thd,tlist)); return (item->fix_fields(thd, tlist, &item) ||
Item_func::fix_fields(thd, tlist, ref));
} }
void fix_length_and_dec(); void fix_length_and_dec();
void update_used_tables(); void update_used_tables();
@ -488,6 +491,7 @@ public:
{ {
conv_charset=cs; conv_charset=cs;
} }
bool fix_fields(THD *thd,struct st_table_list *tables);
String *val_str(String *); String *val_str(String *);
void fix_length_and_dec(); void fix_length_and_dec();
const char *func_name() const { return "conv_charset"; } const char *func_name() const { return "conv_charset"; }
@ -503,6 +507,18 @@ public:
const char *func_name() const { return "conv_charset3"; } const char *func_name() const { return "conv_charset3"; }
}; };
class Item_func_charset :public Item_str_func
{
public:
Item_func_charset(Item *a) :Item_str_func(a) {}
String *val_str(String *);
const char *func_name() const { return "charset"; }
void fix_length_and_dec()
{
max_length=20; // should be enough
};
};
/******************************************************* /*******************************************************
Spatial functions Spatial functions

View File

@ -35,12 +35,13 @@ SUBSELECT TODO:
#include "mysql_priv.h" #include "mysql_priv.h"
#include "sql_select.h" #include "sql_select.h"
Item_subselect::Item_subselect(THD *thd, st_select_lex *select_lex): Item_subselect::Item_subselect(THD *thd, st_select_lex *select_lex,
select_subselect *result):
assigned(0), executed(0), optimized(0), error(0) assigned(0), executed(0), optimized(0), error(0)
{ {
DBUG_ENTER("Item_subselect::Item_subselect"); DBUG_ENTER("Item_subselect::Item_subselect");
DBUG_PRINT("subs", ("select_lex 0x%xl", (long) select_lex)); DBUG_PRINT("subs", ("select_lex 0x%xl", (long) select_lex));
result= new select_subselect(this); this->result= result;
SELECT_LEX_UNIT *unit= select_lex->master_unit(); SELECT_LEX_UNIT *unit= select_lex->master_unit();
unit->offset_limit_cnt= unit->global_parameters->offset_limit; unit->offset_limit_cnt= unit->global_parameters->offset_limit;
unit->select_limit_cnt= unit->global_parameters->select_limit+ unit->select_limit_cnt= unit->global_parameters->select_limit+
@ -51,41 +52,15 @@ Item_subselect::Item_subselect(THD *thd, st_select_lex *select_lex):
select_lex->options&= ~OPTION_FOUND_ROWS; select_lex->options&= ~OPTION_FOUND_ROWS;
join= new JOIN(thd, select_lex->item_list, select_lex->options, result); join= new JOIN(thd, select_lex->item_list, select_lex->options, result);
this->select_lex= select_lex; this->select_lex= select_lex;
maybe_null= 1; assign_null();
/* /*
item value is NULL if select_subselect not changed this value item value is NULL if select_subselect not changed this value
(i.e. some rows will be found returned) (i.e. some rows will be found returned)
*/ */
assign_null(); null_value= 1;
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
Item::Type Item_subselect::type() const
{
return SUBSELECT_ITEM;
}
double Item_subselect::val ()
{
if (exec())
return 0;
return real_value;
}
longlong Item_subselect::val_int ()
{
if (exec())
return 0;
return int_value;
}
String *Item_subselect::val_str (String *str)
{
if (exec() || null_value)
return 0;
return &str_value;
}
void Item_subselect::make_field (Send_field *tmp_field) void Item_subselect::make_field (Send_field *tmp_field)
{ {
if (null_value) if (null_value)
@ -100,17 +75,10 @@ void Item_subselect::make_field (Send_field *tmp_field)
} }
} }
bool Item_subselect::fix_fields(THD *thd,TABLE_LIST *tables) bool Item_subselect::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{ {
if (thd->having_fix_field)
{
//TODO: subselects in having do not suported now
my_printf_error(ER_SYNTAX_ERROR, ER(ER_SYNTAX_ERROR), MYF(0));
return 1;
}
// Is it one field subselect? // Is it one field subselect?
if (select_lex->item_list.elements != 1) if (select_lex->item_list.elements > max_columns)
{ {
my_printf_error(ER_SUBSELECT_NO_1_COL, ER(ER_SUBSELECT_NO_1_COL), MYF(0)); my_printf_error(ER_SUBSELECT_NO_1_COL, ER(ER_SUBSELECT_NO_1_COL), MYF(0));
return 1; return 1;
@ -131,13 +99,14 @@ bool Item_subselect::fix_fields(THD *thd,TABLE_LIST *tables)
int Item_subselect::exec() int Item_subselect::exec()
{ {
DBUG_ENTER("Item_subselect::exec");
if (!optimized) if (!optimized)
{ {
optimized=1; optimized=1;
if (join->optimize()) if (join->optimize())
{ {
executed= 1; executed= 1;
return (join->error?join->error:1); DBUG_RETURN(join->error?join->error:1);
} }
} }
if (join->select_lex->depended && executed) if (join->select_lex->depended && executed)
@ -145,7 +114,7 @@ int Item_subselect::exec()
if (join->reinit()) if (join->reinit())
{ {
error= 1; error= 1;
return 1; DBUG_RETURN(1);
} }
assign_null(); assign_null();
executed= assigned= 0; executed= assigned= 0;
@ -157,7 +126,80 @@ int Item_subselect::exec()
join->exec(); join->exec();
join->thd->lex.select= save_select; join->thd->lex.select= save_select;
executed= 1; executed= 1;
return join->error; DBUG_RETURN(join->error);
} }
return 0; DBUG_RETURN(0);
} }
inline table_map Item_subselect::used_tables() const
{
return (table_map) select_lex->depended ? 1L : 0L;
}
Item_singleval_subselect::Item_singleval_subselect(THD *thd,
st_select_lex *select_lex):
Item_subselect(thd, select_lex, new select_singleval_subselect(this))
{
max_columns= 1;
maybe_null= 1;
}
Item::Type Item_subselect::type() const
{
return SUBSELECT_ITEM;
}
double Item_singleval_subselect::val ()
{
if (exec())
return 0;
return real_value;
}
longlong Item_singleval_subselect::val_int ()
{
if (exec())
return 0;
return int_value;
}
String *Item_singleval_subselect::val_str (String *str)
{
if (exec() || null_value)
return 0;
return &str_value;
}
Item_exists_subselect::Item_exists_subselect(THD *thd,
st_select_lex *select_lex):
Item_subselect(thd, select_lex, new select_singleval_subselect(this))
{
max_columns= UINT_MAX;
null_value= 0; //can't be NULL
maybe_null= 0; //can't be NULL
value= 0;
select_lex->select_limit= 1; // we need only 1 row to determinate existence
}
double Item_exists_subselect::val ()
{
if (exec())
return 0;
return (double) value;
}
longlong Item_exists_subselect::val_int ()
{
if (exec())
return 0;
return value;
}
String *Item_exists_subselect::val_str(String *str)
{
if (exec())
return 0;
str->set(value);
return str;
}

View File

@ -20,46 +20,38 @@
#pragma interface /* gcc class implementation */ #pragma interface /* gcc class implementation */
#endif #endif
struct st_select_lex; class st_select_lex;
class JOIN; class JOIN;
class select_subselect; class select_subselect;
/* simple (not depended of covered select ) subselect */ /* base class for subselects */
class Item_subselect :public Item class Item_subselect :public Item
{ {
protected: protected:
longlong int_value; uint max_columns;
double real_value;
my_bool assigned; /* value already assigned to subselect */ my_bool assigned; /* value already assigned to subselect */
my_bool executed; /* simple subselect is executed */ my_bool executed; /* simple subselect is executed */
my_bool optimized; /* simple subselect is optimized */ my_bool optimized; /* simple subselect is optimized */
my_bool error; /* error in query */ my_bool error; /* error in query */
enum Item_result res_type;
int exec(); int exec();
void assign_null() virtual void assign_null()
{ {
null_value= 1; null_value= 1;
int_value= 0;
real_value= 0;
max_length= 4;
res_type= STRING_RESULT;
} }
public: public:
st_select_lex *select_lex; st_select_lex *select_lex;
JOIN *join; JOIN *join;
select_subselect *result; select_subselect *result;
Item_subselect(THD *thd, st_select_lex *select_lex); Item_subselect(THD *thd, st_select_lex *select_lex,
select_subselect* result);
Item_subselect(Item_subselect *item) Item_subselect(Item_subselect *item)
{ {
null_value= item->null_value; null_value= item->null_value;
int_value= item->int_value;
real_value= item->real_value;
max_length= item->max_length;
decimals= item->decimals; decimals= item->decimals;
res_type= item->res_type; max_columns= item->max_columns;
assigned= item->assigned; assigned= item->assigned;
executed= item->executed; executed= item->executed;
select_lex= item->select_lex; select_lex= item->select_lex;
@ -69,16 +61,75 @@ public:
error= item->error; error= item->error;
} }
enum Type type() const; enum Type type() const;
double val ();
longlong val_int ();
String *val_str (String *);
bool is_null() { return null_value; } bool is_null() { return null_value; }
void make_field (Send_field *); void make_field (Send_field *);
bool fix_fields(THD *thd, TABLE_LIST *tables); bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref);
Item *new_item() { return new Item_subselect(this); } table_map used_tables() const;
enum Item_result result_type() const { return res_type; }
friend class select_subselect; friend class select_subselect;
}; };
/* single value subselect */
class Item_singleval_subselect :public Item_subselect
{
protected:
longlong int_value;
double real_value;
enum Item_result res_type;
virtual void assign_null()
{
null_value= 1;
int_value= 0;
real_value= 0;
max_length= 4;
res_type= STRING_RESULT;
}
public:
Item_singleval_subselect(THD *thd, st_select_lex *select_lex);
Item_singleval_subselect(Item_singleval_subselect *item):
Item_subselect(item)
{
int_value= item->int_value;
real_value= item->real_value;
max_length= item->max_length;
decimals= item->decimals;
res_type= item->res_type;
}
double val ();
longlong val_int ();
String *val_str (String *);
Item *new_item() { return new Item_singleval_subselect(this); }
enum Item_result result_type() const { return res_type; }
friend class select_singleval_subselect;
};
/* exists subselect */
class Item_exists_subselect :public Item_subselect
{
protected:
longlong value;
virtual void assign_null()
{
value= 0;
}
public:
Item_exists_subselect(THD *thd, st_select_lex *select_lex);
Item_exists_subselect(Item_exists_subselect *item):
Item_subselect(item)
{
value= item->value;
}
Item *new_item() { return new Item_exists_subselect(this); }
enum Item_result result_type() const { return INT_RESULT;}
longlong val_int();
double val();
String *val_str(String*);
friend class select_exists_subselect;
};

View File

@ -112,7 +112,7 @@ Item_sum_int::val_str(String *str)
bool bool
Item_sum_num::fix_fields(THD *thd,TABLE_LIST *tables) Item_sum_num::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{ {
if (!thd->allow_sum_func) if (!thd->allow_sum_func)
{ {
@ -124,7 +124,7 @@ Item_sum_num::fix_fields(THD *thd,TABLE_LIST *tables)
maybe_null=0; maybe_null=0;
for (uint i=0 ; i < arg_count ; i++) for (uint i=0 ; i < arg_count ; i++)
{ {
if (args[i]->fix_fields(thd,tables)) if (args[i]->fix_fields(thd, tables, args + i))
return 1; return 1;
if (decimals < args[i]->decimals) if (decimals < args[i]->decimals)
decimals=args[i]->decimals; decimals=args[i]->decimals;
@ -140,7 +140,7 @@ Item_sum_num::fix_fields(THD *thd,TABLE_LIST *tables)
bool bool
Item_sum_hybrid::fix_fields(THD *thd,TABLE_LIST *tables) Item_sum_hybrid::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{ {
Item *item=args[0]; Item *item=args[0];
if (!thd->allow_sum_func) if (!thd->allow_sum_func)
@ -149,7 +149,7 @@ Item_sum_hybrid::fix_fields(THD *thd,TABLE_LIST *tables)
return 1; return 1;
} }
thd->allow_sum_func=0; // No included group funcs thd->allow_sum_func=0; // No included group funcs
if (item->fix_fields(thd,tables)) if (item->fix_fields(thd, tables, args))
return 1; return 1;
hybrid_type=item->result_type(); hybrid_type=item->result_type();
if (hybrid_type == INT_RESULT) if (hybrid_type == INT_RESULT)
@ -930,9 +930,10 @@ Item_sum_count_distinct::~Item_sum_count_distinct()
} }
bool Item_sum_count_distinct::fix_fields(THD *thd,TABLE_LIST *tables) bool Item_sum_count_distinct::fix_fields(THD *thd, TABLE_LIST *tables,
Item **ref)
{ {
if (Item_sum_num::fix_fields(thd,tables) || if (Item_sum_num::fix_fields(thd, tables, ref) ||
!(tmp_table_param= new TMP_TABLE_PARAM)) !(tmp_table_param= new TMP_TABLE_PARAM))
return 1; return 1;
return 0; return 0;

View File

@ -80,7 +80,7 @@ public:
Item_sum_num(Item *item_par) :Item_sum(item_par) {} Item_sum_num(Item *item_par) :Item_sum(item_par) {}
Item_sum_num(Item *a, Item* b) :Item_sum(a,b) {} Item_sum_num(Item *a, Item* b) :Item_sum(a,b) {}
Item_sum_num(List<Item> &list) :Item_sum(list) {} Item_sum_num(List<Item> &list) :Item_sum(list) {}
bool fix_fields(THD *,struct st_table_list *); bool fix_fields(THD *, TABLE_LIST *, Item **);
longlong val_int() { return (longlong) val(); } /* Real as default */ longlong val_int() { return (longlong) val(); } /* Real as default */
String *val_str(String*str); String *val_str(String*str);
void reset_field(); void reset_field();
@ -146,7 +146,7 @@ class Item_sum_count_distinct :public Item_sum_int
{ {
TABLE *table; TABLE *table;
table_map used_table_cache; table_map used_table_cache;
bool fix_fields(THD *thd,TABLE_LIST *tables); bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref);
uint32 *field_lengths; uint32 *field_lengths;
TMP_TABLE_PARAM *tmp_table_param; TMP_TABLE_PARAM *tmp_table_param;
TREE tree; TREE tree;
@ -283,7 +283,7 @@ class Item_sum_hybrid :public Item_sum
Item_sum_hybrid(Item *item_par,int sign) :Item_sum(item_par),cmp_sign(sign), Item_sum_hybrid(Item *item_par,int sign) :Item_sum(item_par),cmp_sign(sign),
used_table_cache(~(table_map) 0) used_table_cache(~(table_map) 0)
{} {}
bool fix_fields(THD *,struct st_table_list *); bool fix_fields(THD *, TABLE_LIST *, Item **);
table_map used_tables() const { return used_table_cache; } table_map used_tables() const { return used_table_cache; }
bool const_item() const { return !used_table_cache; } bool const_item() const { return !used_table_cache; }
@ -382,7 +382,7 @@ public:
{ quick_group=0;} { quick_group=0;}
~Item_udf_sum() {} ~Item_udf_sum() {}
const char *func_name() const { return udf.name(); } const char *func_name() const { return udf.name(); }
bool fix_fields(THD *thd,struct st_table_list *tables) bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{ {
return udf.fix_fields(thd,tables,this,this->arg_count,this->args); return udf.fix_fields(thd,tables,this,this->arg_count,this->args);
} }

View File

@ -42,5 +42,5 @@ public:
bool add() { return 0; } bool add() { return 0; }
void reset_field() {} void reset_field() {}
void update_field(int offset) {} void update_field(int offset) {}
bool fix_fields(THD *thd,struct st_table_list *tlist) { return 0;} bool fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref) { return 0;}
}; };

View File

@ -82,6 +82,7 @@ static SYMBOL symbols[] = {
{ "CASE", SYM(CASE_SYM),0,0}, { "CASE", SYM(CASE_SYM),0,0},
{ "CHAR", SYM(CHAR_SYM),0,0}, { "CHAR", SYM(CHAR_SYM),0,0},
{ "CHARACTER", SYM(CHAR_SYM),0,0}, { "CHARACTER", SYM(CHAR_SYM),0,0},
{ "CHARSET", SYM(CHARSET),0,0},
{ "CHANGE", SYM(CHANGE),0,0}, { "CHANGE", SYM(CHANGE),0,0},
{ "CHANGED", SYM(CHANGED),0,0}, { "CHANGED", SYM(CHANGED),0,0},
{ "CHECK", SYM(CHECK_SYM),0,0}, { "CHECK", SYM(CHECK_SYM),0,0},

View File

@ -289,7 +289,8 @@ inline THD *_current_thd(void)
#define prepare_execute(A) ((A)->command == COM_EXECUTE) #define prepare_execute(A) ((A)->command == COM_EXECUTE)
int mysql_create_db(THD *thd, char *db, uint create_info, bool silent); int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create, bool silent);
int mysql_alter_db(THD *thd, char *db, HA_CREATE_INFO *create, bool silent);
int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent); int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent);
void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags); void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags);
int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists); int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists);
@ -471,6 +472,7 @@ int mysqld_show_logs(THD *thd);
void mysqld_list_fields(THD *thd,TABLE_LIST *table, const char *wild); void mysqld_list_fields(THD *thd,TABLE_LIST *table, const char *wild);
int mysqld_dump_create_info(THD *thd, TABLE *table, int fd = -1); int mysqld_dump_create_info(THD *thd, TABLE *table, int fd = -1);
int mysqld_show_create(THD *thd, TABLE_LIST *table_list); int mysqld_show_create(THD *thd, TABLE_LIST *table_list);
int mysqld_show_create_db(THD *thd, const char *dbname);
void mysqld_list_processes(THD *thd,const char *user,bool verbose); void mysqld_list_processes(THD *thd,const char *user,bool verbose);
int mysqld_show_status(THD *thd); int mysqld_show_status(THD *thd);

View File

@ -1876,7 +1876,7 @@ int setup_fields(THD *thd, TABLE_LIST *tables, List<Item> &fields,
} }
else else
{ {
if (item->fix_fields(thd,tables)) if (item->fix_fields(thd, tables, it.ref()))
DBUG_RETURN(-1); /* purecov: inspected */ DBUG_RETURN(-1); /* purecov: inspected */
if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM && if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM &&
sum_func_list) sum_func_list)
@ -2027,7 +2027,7 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
if (*conds) if (*conds)
{ {
thd->where="where clause"; thd->where="where clause";
if ((*conds)->fix_fields(thd,tables)) if ((*conds)->fix_fields(thd, tables, conds))
DBUG_RETURN(1); DBUG_RETURN(1);
} }
@ -2038,7 +2038,7 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
{ {
/* Make a join an a expression */ /* Make a join an a expression */
thd->where="on clause"; thd->where="on clause";
if (table->on_expr->fix_fields(thd,tables)) if (table->on_expr->fix_fields(thd, tables, &table->on_expr))
DBUG_RETURN(1); DBUG_RETURN(1);
thd->cond_count++; thd->cond_count++;

View File

@ -81,7 +81,7 @@ static void free_var(user_var_entry *entry)
THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0), THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0),
insert_id_used(0), in_lock_tables(0), insert_id_used(0), in_lock_tables(0),
global_read_lock(0), bootstrap(0), having_fix_field(0) global_read_lock(0), bootstrap(0)
{ {
host=user=priv_user=db=query=ip=0; host=user=priv_user=db=query=ip=0;
host_or_ip="unknown ip"; host_or_ip="unknown ip";
@ -103,6 +103,7 @@ THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0),
file_id = 0; file_id = 0;
cond_count=0; cond_count=0;
convert_set=0; convert_set=0;
db_charset=default_charset_info;
mysys_var=0; mysys_var=0;
#ifndef DBUG_OFF #ifndef DBUG_OFF
dbug_sentry=THD_SENTRY_MAGIC; dbug_sentry=THD_SENTRY_MAGIC;
@ -769,7 +770,6 @@ void select_dump::send_error(uint errcode,const char *err)
file= -1; file= -1;
} }
bool select_dump::send_eof() bool select_dump::send_eof()
{ {
int error=test(end_io_cache(&cache)); int error=test(end_io_cache(&cache));
@ -788,10 +788,11 @@ select_subselect::select_subselect(Item_subselect *item)
this->item=item; this->item=item;
} }
bool select_subselect::send_data(List<Item> &items) bool select_singleval_subselect::send_data(List<Item> &items)
{ {
DBUG_ENTER("select_subselect::send_data"); DBUG_ENTER("select_singleval_subselect::send_data");
if (item->assigned){ Item_singleval_subselect *it= (Item_singleval_subselect *)item;
if (it->assigned){
my_printf_error(ER_SUBSELECT_NO_1_ROW, ER(ER_SUBSELECT_NO_1_ROW), MYF(0)); my_printf_error(ER_SUBSELECT_NO_1_ROW, ER(ER_SUBSELECT_NO_1_ROW), MYF(0));
DBUG_RETURN(1); DBUG_RETURN(1);
} }
@ -806,18 +807,33 @@ bool select_subselect::send_data(List<Item> &items)
Following val() call have to be first, because function AVG() & STD() Following val() call have to be first, because function AVG() & STD()
calculate value on it & determinate "is it NULL?". calculate value on it & determinate "is it NULL?".
*/ */
item->real_value= val_item->val(); it->real_value= val_item->val();
if ((item->null_value= val_item->is_null())) if ((it->null_value= val_item->is_null()))
{ {
item->assign_null(); it->assign_null();
} else { } else {
item->max_length= val_item->max_length; it->max_length= val_item->max_length;
item->decimals= val_item->decimals; it->decimals= val_item->decimals;
item->binary= val_item->binary; it->binary= val_item->binary;
val_item->val_str(&item->str_value); val_item->val_str(&it->str_value);
item->int_value= val_item->val_int(); it->int_value= val_item->val_int();
item->res_type= val_item->result_type(); it->res_type= val_item->result_type();
} }
item->assigned= 1; it->assigned= 1;
DBUG_RETURN(0); DBUG_RETURN(0);
} }
bool select_exists_subselect::send_data(List<Item> &items)
{
DBUG_ENTER("select_exists_subselect::send_data");
Item_exists_subselect *it= (Item_exists_subselect *)item;
if (unit->offset_limit_cnt)
{ // Using limit offset,count
unit->offset_limit_cnt--;
DBUG_RETURN(0);
}
it->value= 1;
it->assigned= 1;
DBUG_RETURN(0);
}

View File

@ -460,7 +460,6 @@ public:
bool query_error, bootstrap, cleanup_done; bool query_error, bootstrap, cleanup_done;
bool safe_to_cache_query; bool safe_to_cache_query;
bool volatile killed; bool volatile killed;
bool having_fix_field; //TRUE when having fix field called
bool prepare_command; bool prepare_command;
ulong param_count,current_param_number; ulong param_count,current_param_number;
Error<mysql_st_error> err_list; Error<mysql_st_error> err_list;
@ -480,6 +479,7 @@ public:
ulong slave_proxy_id; ulong slave_proxy_id;
NET* slave_net; // network connection from slave -> m. NET* slave_net; // network connection from slave -> m.
my_off_t log_pos; my_off_t log_pos;
CHARSET_INFO *db_charset;
THD(); THD();
~THD(); ~THD();
@ -749,19 +749,36 @@ class select_union :public select_result {
bool flush(); bool flush();
}; };
/* Single value subselect interface class */ /* Base subselect interface class */
class select_subselect :public select_result class select_subselect :public select_result
{ {
protected:
Item_subselect *item; Item_subselect *item;
public: public:
select_subselect(Item_subselect *item); select_subselect(Item_subselect *item);
bool send_fields(List<Item> &list, uint flag) { return 0; }; bool send_fields(List<Item> &list, uint flag) { return 0; };
bool send_data(List<Item> &items); bool send_data(List<Item> &items)=0;
bool send_eof() { return 0; }; bool send_eof() { return 0; };
friend class Ttem_subselect; friend class Ttem_subselect;
}; };
/* Single value subselect interface class */
class select_singleval_subselect :public select_subselect
{
public:
select_singleval_subselect(Item_subselect *item):select_subselect(item){}
bool send_data(List<Item> &items);
};
/* EXISTS subselect interface class */
class select_exists_subselect :public select_subselect
{
public:
select_exists_subselect(Item_subselect *item):select_subselect(item){}
bool send_data(List<Item> &items);
};
/* Structs used when sorting */ /* Structs used when sorting */
typedef struct st_sort_field { typedef struct st_sort_field {

View File

@ -25,18 +25,112 @@
#include <direct.h> #include <direct.h>
#endif #endif
#define MY_DB_OPT_FILE ".db.opt"
static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, static long mysql_rm_known_files(THD *thd, MY_DIR *dirp,
const char *db, const char *path, const char *db, const char *path,
uint level); uint level);
/*
Create database options file:
Currently databse default charset is only stored there.
*/
static int write_db_opt(THD *thd,const char *db,HA_CREATE_INFO *create,char *fn)
{
register File file;
char buf[256]; // Should be enough
int error=0;
if ((file=my_create(fn,CREATE_MODE,O_RDWR | O_TRUNC,MYF(MY_WME))) >= 0)
{
sprintf(buf,"default-character-set=%s\n",
(create && create->table_charset) ?
create->table_charset->name : "DEFAULT");
if (my_write(file,(byte*)buf,strlen(buf),MYF(MY_NABP+MY_WME)))
{
// QQ : should we send more suitable error message?
my_error(ER_CANT_CREATE_DB,MYF(0),db,my_errno);
error = -1;
goto exit;
}
my_close(file,MYF(0));
}
else
{
// QQ : should we send more suitable error message?
my_error(ER_CANT_CREATE_DB,MYF(0),db,my_errno);
error = -1;
goto exit;
}
exit:
return error;
}
/*
Load database options file:
*/
static int load_db_opt(THD *thd,const char *db,HA_CREATE_INFO *create,char *fn)
{
register File file;
char buf[256]="";
if ((file=my_open(fn,O_RDWR|O_BINARY,MYF(MY_WME))) >= 0)
{
int nbytes=my_read(file,(byte*)buf,sizeof(buf)-1,MYF(0));
if ( nbytes >= 0 )
{
char *ln=buf;
char *pe=buf+nbytes;
buf[nbytes]='\0';
for ( ln=buf; ln<pe; )
{
char *le,*val;
for ( le=ln, val=0 ; le<pe ; le++ )
{
switch(le[0])
{
case '=':
le[0]='\0';
val=le+1;
le++;
break;
case '\r':
case '\n':
le[0]='\0';
le++;
for( ; (le[0]=='\r' || le[0]=='\n') ; le++);
if (!strcmp(ln,"default-character-set") && val && val[0])
{
create->table_charset=get_charset_by_name(val, MYF(0));
}
goto cnt;
break;
}
}
cnt:
ln=le;
}
}
my_close(file,MYF(0));
}
return 0;
}
/* db-name is already validated when we come here */ /* db-name is already validated when we come here */
int mysql_create_db(THD *thd, char *db, uint create_options, bool silent) int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info, bool silent)
{ {
char path[FN_REFLEN+16]; char path[FN_REFLEN+16];
MY_DIR *dirp; MY_DIR *dirp;
long result=1; long result=1;
int error = 0; int error = 0;
uint create_options = create_info ? create_info->options : 0;
DBUG_ENTER("mysql_create_db"); DBUG_ENTER("mysql_create_db");
VOID(pthread_mutex_lock(&LOCK_mysql_create_db)); VOID(pthread_mutex_lock(&LOCK_mysql_create_db));
@ -73,6 +167,12 @@ int mysql_create_db(THD *thd, char *db, uint create_options, bool silent)
} }
} }
strcat(path,"/");
unpack_dirname(path,path);
strcat(path,MY_DB_OPT_FILE);
if ((error=write_db_opt(thd,db,create_info,path)))
goto exit;
if (!silent) if (!silent)
{ {
if (!thd->query) if (!thd->query)
@ -104,7 +204,81 @@ exit2:
DBUG_RETURN(error); DBUG_RETURN(error);
} }
const char *del_exts[]= {".frm", ".BAK", ".TMD", NullS};
/* db-name is already validated when we come here */
int mysql_alter_db(THD *thd, char *db, HA_CREATE_INFO *create_info, bool silent)
{
char path[FN_REFLEN+16];
MY_DIR *dirp;
long result=1;
int error = 0;
DBUG_ENTER("mysql_create_db");
register File file;
uint create_options = create_info ? create_info->options : 0;
VOID(pthread_mutex_lock(&LOCK_mysql_create_db));
// do not alter database if another thread is holding read lock
if (wait_if_global_read_lock(thd,0))
{
error= -1;
goto exit2;
}
/* Check directory */
(void)sprintf(path,"%s/%s", mysql_data_home, db);
strcat(path,"/");
unpack_dirname(path,path); // Convert if not unix
strcat(path,MY_DB_OPT_FILE);
if ((error=write_db_opt(thd,db,create_info,path)))
goto exit;
/*
Change options if current
database is being altered
*/
if (thd->db && !strcmp(thd->db,db))
{
thd->db_charset= create_info ? create_info->table_charset : NULL;
}
if (!silent)
{
if (!thd->query)
{
thd->query = path;
thd->query_length = (uint) (strxmov(path,"alter database ", db, NullS)-
path);
}
{
mysql_update_log.write(thd,thd->query, thd->query_length);
if (mysql_bin_log.is_open())
{
Query_log_event qinfo(thd, thd->query);
mysql_bin_log.write(&qinfo);
}
}
if (thd->query == path)
{
thd->query = 0; // just in case
thd->query_length = 0;
}
send_ok(&thd->net, result);
}
exit:
start_waiting_global_read_lock(thd);
exit2:
VOID(pthread_mutex_unlock(&LOCK_mysql_create_db));
DBUG_RETURN(error);
}
const char *del_exts[]= {".frm", ".BAK", ".TMD",".opt", NullS};
static TYPELIB deletable_extentions= static TYPELIB deletable_extentions=
{array_elements(del_exts)-1,"del_exts", del_exts}; {array_elements(del_exts)-1,"del_exts", del_exts};
@ -332,6 +506,8 @@ bool mysql_change_db(THD *thd,const char *name)
char *dbname=my_strdup((char*) name,MYF(MY_WME)); char *dbname=my_strdup((char*) name,MYF(MY_WME));
char path[FN_REFLEN]; char path[FN_REFLEN];
uint db_access; uint db_access;
HA_CREATE_INFO create;
DBUG_ENTER("mysql_change_db"); DBUG_ENTER("mysql_change_db");
if (!dbname || !(db_length=strip_sp(dbname))) if (!dbname || !(db_length=strip_sp(dbname)))
@ -382,5 +558,102 @@ bool mysql_change_db(THD *thd,const char *name)
thd->db=dbname; thd->db=dbname;
thd->db_length=db_length; thd->db_length=db_length;
thd->db_access=db_access; thd->db_access=db_access;
strcat(path,"/");
unpack_dirname(path,path);
strcat(path,MY_DB_OPT_FILE);
bzero(&create,sizeof(create));
load_db_opt(thd,name,&create,path);
thd->db_charset=create.table_charset;
DBUG_RETURN(0);
}
int mysqld_show_create_db(THD *thd,const char *name)
{
int length, db_length;
char *dbname=my_strdup((char*) name,MYF(MY_WME));
char path[FN_REFLEN];
uint db_access;
HA_CREATE_INFO create;
CONVERT *convert=thd->convert_set;
DBUG_ENTER("mysql_show_create_db");
if (!dbname || !(db_length=strip_sp(dbname)))
{
x_free(dbname); /* purecov: inspected */
send_error(&thd->net,ER_NO_DB_ERROR); /* purecov: inspected */
DBUG_RETURN(1); /* purecov: inspected */
}
if ((db_length > NAME_LEN) || check_db_name(dbname))
{
net_printf(&thd->net,ER_WRONG_DB_NAME, dbname);
x_free(dbname);
DBUG_RETURN(1);
}
if (test_all_bits(thd->master_access,DB_ACLS))
db_access=DB_ACLS;
else
db_access= (acl_get(thd->host,thd->ip,(char*) &thd->remote.sin_addr,
thd->priv_user,dbname) |
thd->master_access);
if (!(db_access & DB_ACLS) && (!grant_option || check_grant_db(thd,dbname)))
{
net_printf(&thd->net,ER_DBACCESS_DENIED_ERROR,
thd->priv_user,
thd->host_or_ip,
dbname);
mysql_log.write(thd,COM_INIT_DB,ER(ER_DBACCESS_DENIED_ERROR),
thd->priv_user,
thd->host_or_ip,
dbname);
my_free(dbname,MYF(0));
DBUG_RETURN(1);
}
(void) sprintf(path,"%s/%s",mysql_data_home,dbname);
length=unpack_dirname(path,path); // Convert if not unix
if (length && path[length-1] == FN_LIBCHAR)
path[length-1]=0; // remove ending '\'
if (access(path,F_OK))
{
net_printf(&thd->net,ER_BAD_DB_ERROR,dbname);
my_free(dbname,MYF(0));
DBUG_RETURN(1);
}
strcat(path,"/");
unpack_dirname(path,path);
strcat(path,MY_DB_OPT_FILE);
bzero(&create,sizeof(create));
load_db_opt(thd,name,&create,path);
List<Item> field_list;
field_list.push_back(new Item_empty_string("Database",NAME_LEN));
field_list.push_back(new Item_empty_string("Create Database",1024));
if (send_fields(thd,field_list,1))
DBUG_RETURN(1);
String *packet = &thd->packet;
packet->length(0);
net_store_data(packet, convert, name);
sprintf(path, "CREATE DATABASE %s", name);
if (create.table_charset)
{
strcat(path," DEFAULT CHARACTER SET ");
strcat(path,create.table_charset->name);
}
net_store_data(packet, convert, path);
if (my_net_write(&thd->net,(char*) packet->ptr(),packet->length()))
DBUG_RETURN(1);
send_eof(&thd->net);
DBUG_RETURN(0); DBUG_RETURN(0);
} }

View File

@ -106,7 +106,7 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
} }
tables->table=table; tables->table=table;
if (cond && cond->fix_fields(thd,tables)) if (cond && cond->fix_fields(thd, tables, &cond))
return -1; return -1;
if (keyname) if (keyname)

View File

@ -525,6 +525,18 @@ int yylex(void *arg)
yylval->lex_str=get_token(lex,length); yylval->lex_str=get_token(lex,length);
if (lex->convert_set) if (lex->convert_set)
lex->convert_set->convert((char*) yylval->lex_str.str,lex->yytoklen); lex->convert_set->convert((char*) yylval->lex_str.str,lex->yytoklen);
/*
Note: "SELECT _bla AS 'alias'"
_bla should be considered as a IDENT if charset haven't been found.
So we don't use MYF(MY_WME) with get_charset_by_name to avoid
producing an error.
*/
if ((yylval->lex_str.str[0]=='_') &&
(lex->charset=get_charset_by_name(yylval->lex_str.str+1,MYF(0))))
return(UNDERSCORE_CHARSET);
else
return(IDENT); return(IDENT);
case STATE_IDENT_SEP: // Found ident and now '.' case STATE_IDENT_SEP: // Found ident and now '.'
@ -930,8 +942,8 @@ void st_select_lex::init_select()
interval_list.empty(); interval_list.empty();
use_index.empty(); use_index.empty();
ftfunc_list.empty(); ftfunc_list.empty();
linkage=UNSPECIFIED_TYPE; linkage= UNSPECIFIED_TYPE;
depended= 0; depended= having_fix_field= 0;
} }
/* /*

View File

@ -42,9 +42,11 @@ enum enum_sql_command {
SQLCOM_SHOW_KEYS, SQLCOM_SHOW_VARIABLES, SQLCOM_SHOW_LOGS, SQLCOM_SHOW_STATUS, SQLCOM_SHOW_KEYS, SQLCOM_SHOW_VARIABLES, SQLCOM_SHOW_LOGS, SQLCOM_SHOW_STATUS,
SQLCOM_SHOW_PROCESSLIST, SQLCOM_SHOW_MASTER_STAT, SQLCOM_SHOW_SLAVE_STAT, SQLCOM_SHOW_PROCESSLIST, SQLCOM_SHOW_MASTER_STAT, SQLCOM_SHOW_SLAVE_STAT,
SQLCOM_SHOW_GRANTS, SQLCOM_SHOW_CREATE, SQLCOM_SHOW_CHARSETS, SQLCOM_SHOW_GRANTS, SQLCOM_SHOW_CREATE, SQLCOM_SHOW_CHARSETS,
SQLCOM_SHOW_CREATE_DB,
SQLCOM_LOAD,SQLCOM_SET_OPTION,SQLCOM_LOCK_TABLES,SQLCOM_UNLOCK_TABLES, SQLCOM_LOAD,SQLCOM_SET_OPTION,SQLCOM_LOCK_TABLES,SQLCOM_UNLOCK_TABLES,
SQLCOM_GRANT, SQLCOM_CHANGE_DB, SQLCOM_CREATE_DB, SQLCOM_DROP_DB, SQLCOM_GRANT,
SQLCOM_CHANGE_DB, SQLCOM_CREATE_DB, SQLCOM_DROP_DB, SQLCOM_ALTER_DB,
SQLCOM_REPAIR, SQLCOM_REPLACE, SQLCOM_REPLACE_SELECT, SQLCOM_REPAIR, SQLCOM_REPLACE, SQLCOM_REPLACE_SELECT,
SQLCOM_CREATE_FUNCTION, SQLCOM_DROP_FUNCTION, SQLCOM_CREATE_FUNCTION, SQLCOM_DROP_FUNCTION,
SQLCOM_REVOKE,SQLCOM_OPTIMIZE, SQLCOM_CHECK, SQLCOM_REVOKE,SQLCOM_OPTIMIZE, SQLCOM_CHECK,
@ -234,11 +236,12 @@ private:
bool create_total_list_n_last_return(THD *thd, st_lex *lex, bool create_total_list_n_last_return(THD *thd, st_lex *lex,
TABLE_LIST ***result); TABLE_LIST ***result);
}; };
typedef struct st_select_lex_unit SELECT_LEX_UNIT; typedef class st_select_lex_unit SELECT_LEX_UNIT;
/* /*
SELECT_LEX - store information of parsed SELECT_LEX statment SELECT_LEX - store information of parsed SELECT_LEX statment
*/ */
class JOIN;
class st_select_lex: public st_select_lex_node { class st_select_lex: public st_select_lex_node {
public: public:
char *db, *db1, *table1, *db2, *table2; /* For outer join using .. */ char *db, *db1, *table1, *db2, *table2; /* For outer join using .. */
@ -250,10 +253,14 @@ public:
List<String> interval_list, use_index, *use_index_ptr, List<String> interval_list, use_index, *use_index_ptr,
ignore_index, *ignore_index_ptr; ignore_index, *ignore_index_ptr;
List<Item_func_match> ftfunc_list; List<Item_func_match> ftfunc_list;
JOIN *join; /* after JOIN::prepare it is pointer to corresponding JOIN */
uint in_sum_expr; uint in_sum_expr;
bool create_refs, bool create_refs,
braces, /* SELECT ... UNION (SELECT ... ) <- this braces */ braces, /* SELECT ... UNION (SELECT ... ) <- this braces */
depended; /* depended from outer select subselect */ depended, /* depended from outer select subselect */
/* TRUE when having fix field called in processing of this SELECT */
having_fix_field;
void init_query(); void init_query();
void init_select(); void init_select();
st_select_lex_unit* master_unit() { return (st_select_lex_unit*) master; } st_select_lex_unit* master_unit() { return (st_select_lex_unit*) master; }
@ -277,7 +284,7 @@ public:
friend void mysql_init_query(THD *thd); friend void mysql_init_query(THD *thd);
}; };
typedef struct st_select_lex SELECT_LEX; typedef class st_select_lex SELECT_LEX;
class Set_option :public Sql_alloc { class Set_option :public Sql_alloc {
public: public:

View File

@ -2310,7 +2310,7 @@ mysql_execute_command(void)
} }
if (check_access(thd,CREATE_ACL,lex->name,0,1)) if (check_access(thd,CREATE_ACL,lex->name,0,1))
break; break;
res=mysql_create_db(thd,lex->name,lex->create_info.options,0); res=mysql_create_db(thd,lex->name,&lex->create_info,0);
break; break;
} }
case SQLCOM_DROP_DB: case SQLCOM_DROP_DB:
@ -2330,6 +2330,40 @@ mysql_execute_command(void)
res=mysql_rm_db(thd,lex->name,lex->drop_if_exists,0); res=mysql_rm_db(thd,lex->name,lex->drop_if_exists,0);
break; break;
} }
case SQLCOM_ALTER_DB:
{
if (!strip_sp(lex->name) || check_db_name(lex->name))
{
net_printf(&thd->net,ER_WRONG_DB_NAME, lex->name);
break;
}
if (check_access(thd,ALTER_ACL,lex->name,0,1))
break;
if (thd->locked_tables || thd->active_transaction())
{
send_error(&thd->net,ER_LOCK_OR_ACTIVE_TRANSACTION);
goto error;
}
res=mysql_alter_db(thd,lex->name,&lex->create_info,0);
break;
}
case SQLCOM_SHOW_CREATE_DB:
{
if (!strip_sp(lex->name) || check_db_name(lex->name))
{
net_printf(&thd->net,ER_WRONG_DB_NAME, lex->name);
break;
}
if (check_access(thd,DROP_ACL,lex->name,0,1))
break;
if (thd->locked_tables || thd->active_transaction())
{
send_error(&thd->net,ER_LOCK_OR_ACTIVE_TRANSACTION);
goto error;
}
res=mysqld_show_create_db(thd,lex->name);
break;
}
case SQLCOM_CREATE_FUNCTION: case SQLCOM_CREATE_FUNCTION:
if (check_access(thd,INSERT_ACL,"mysql",0,1)) if (check_access(thd,INSERT_ACL,"mysql",0,1))
break; break;

View File

@ -448,7 +448,7 @@ static bool mysql_test_upd_fields(THD *thd, TABLE_LIST *table_list,
static bool mysql_test_select_fields(THD *thd, TABLE_LIST *tables, static bool mysql_test_select_fields(THD *thd, TABLE_LIST *tables,
List<Item> &fields, List<Item> &values, List<Item> &fields, List<Item> &values,
COND *conds, ORDER *order, ORDER *group, COND *conds, ORDER *order, ORDER *group,
Item *having,thr_lock_type lock_type) Item *having, thr_lock_type lock_type)
{ {
TABLE *table; TABLE *table;
bool hidden_group_fields; bool hidden_group_fields;
@ -470,7 +470,7 @@ static bool mysql_test_select_fields(THD *thd, TABLE_LIST *tables,
{ {
thd->where="having clause"; thd->where="having clause";
thd->allow_sum_func=1; thd->allow_sum_func=1;
if (having->fix_fields(thd,tables) || thd->fatal_error) if (having->fix_fields(thd, tables, &having) || thd->fatal_error)
DBUG_RETURN(1); DBUG_RETURN(1);
if (having->with_sum_func) if (having->with_sum_func)
having->split_sum_func(all_fields); having->split_sum_func(all_fields);

View File

@ -211,6 +211,7 @@ JOIN::prepare(TABLE_LIST *tables_init,
proc_param= proc_param_init; proc_param= proc_param_init;
tables_list= tables_init; tables_list= tables_init;
select_lex= select; select_lex= select;
select->join= this;
union_part= (unit->first_select()->next_select() != 0); union_part= (unit->first_select()->next_select() != 0);
/* Check that all tables, fields, conds and order are ok */ /* Check that all tables, fields, conds and order are ok */
@ -227,10 +228,9 @@ JOIN::prepare(TABLE_LIST *tables_init,
{ {
thd->where="having clause"; thd->where="having clause";
thd->allow_sum_func=1; thd->allow_sum_func=1;
bool having_fix_field_store= thd->having_fix_field; select_lex->having_fix_field= 1;
thd->having_fix_field= 1; bool having_fix_rc= having->fix_fields(thd, tables_list, &having);
bool having_fix_rc= having->fix_fields(thd,tables_list); select_lex->having_fix_field= 0;
thd->having_fix_field= having_fix_field_store;
if (having_fix_rc || thd->fatal_error) if (having_fix_rc || thd->fatal_error)
DBUG_RETURN(-1); /* purecov: inspected */ DBUG_RETURN(-1); /* purecov: inspected */
if (having->with_sum_func) if (having->with_sum_func)
@ -349,7 +349,7 @@ JOIN::optimize()
} }
else if ((conds=new Item_cond_and(conds,having))) else if ((conds=new Item_cond_and(conds,having)))
{ {
conds->fix_fields(thd, tables_list); conds->fix_fields(thd, tables_list, &conds);
conds->change_ref_to_fields(thd, tables_list); conds->change_ref_to_fields(thd, tables_list);
having= 0; having= 0;
} }
@ -613,6 +613,15 @@ JOIN::reinit()
if (setup_tables(tables_list)) if (setup_tables(tables_list))
DBUG_RETURN(1); DBUG_RETURN(1);
// Reset of sum functions
first_record= 0;
if (sum_funcs)
{
Item_sum *func, **func_ptr= sum_funcs;
while ((func= *(func_ptr++)))
func->null_value= 1;
}
DBUG_RETURN(0); DBUG_RETURN(0);
} }
@ -966,6 +975,21 @@ JOIN::cleanup(THD *thd)
delete select; delete select;
delete_dynamic(&keyuse); delete_dynamic(&keyuse);
delete procedure; delete procedure;
for (SELECT_LEX_UNIT *unit= select_lex->first_inner_unit();
unit != 0;
unit= unit->next_unit())
for (SELECT_LEX *sl= unit->first_select();
sl != 0;
sl= sl->next_select())
{
if (sl->join)
{
int err= sl->join->cleanup(thd);
if (err)
error= err;
sl->join= 0;
}
}
return error; return error;
} }
@ -3381,7 +3405,7 @@ remove_eq_conds(COND *cond,Item::cond_result *cond_value)
21)))) 21))))
{ {
cond=new_cond; cond=new_cond;
cond->fix_fields(thd,0); cond->fix_fields(thd, 0, &cond);
} }
thd->insert_id(0); // Clear for next request thd->insert_id(0); // Clear for next request
} }
@ -3395,7 +3419,7 @@ remove_eq_conds(COND *cond,Item::cond_result *cond_value)
if ((new_cond= new Item_func_eq(args[0],new Item_int("0", 0, 2)))) if ((new_cond= new Item_func_eq(args[0],new Item_int("0", 0, 2))))
{ {
cond=new_cond; cond=new_cond;
cond->fix_fields(thd,0); cond->fix_fields(thd, 0, &cond);
} }
} }
} }
@ -3523,7 +3547,7 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
case STRING_RESULT: case STRING_RESULT:
if (item_sum->max_length > 255) if (item_sum->max_length > 255)
return new Field_blob(item_sum->max_length,maybe_null, return new Field_blob(item_sum->max_length,maybe_null,
item->name,table,item->binary); item->name,table,item->binary,default_charset_info);
return new Field_string(item_sum->max_length,maybe_null, return new Field_string(item_sum->max_length,maybe_null,
item->name,table,item->binary,default_charset_info); item->name,table,item->binary,default_charset_info);
} }
@ -3576,10 +3600,12 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
case STRING_RESULT: case STRING_RESULT:
if (item->max_length > 255) if (item->max_length > 255)
new_field= new Field_blob(item->max_length,maybe_null, new_field= new Field_blob(item->max_length,maybe_null,
item->name,table,item->binary); item->name,table,item->binary,
item->str_value.charset());
else else
new_field= new Field_string(item->max_length,maybe_null, new_field= new Field_string(item->max_length,maybe_null,
item->name,table,item->binary,default_charset_info); item->name,table,item->binary,
item->str_value.charset());
break; break;
} }
if (copy_func) if (copy_func)
@ -4103,7 +4129,9 @@ static bool create_myisam_tmp_table(TABLE *table,TMP_TABLE_PARAM *param,
{ {
Field *field=keyinfo->key_part[i].field; Field *field=keyinfo->key_part[i].field;
seg->flag= 0; seg->flag= 0;
seg->language= MY_CHARSET_CURRENT; seg->language= field->binary() ? MY_CHARSET_CURRENT :
((Field_str*)field)->charset()->number;
seg->length= keyinfo->key_part[i].length; seg->length= keyinfo->key_part[i].length;
seg->start= keyinfo->key_part[i].offset; seg->start= keyinfo->key_part[i].offset;
if (field->flags & BLOB_FLAG) if (field->flags & BLOB_FLAG)
@ -6428,7 +6456,7 @@ find_order_in_list(THD *thd,TABLE_LIST *tables,ORDER *order,List<Item> &fields,
return 0; return 0;
} }
order->in_field_list=0; order->in_field_list=0;
if ((*order->item)->fix_fields(thd,tables) || thd->fatal_error) if ((*order->item)->fix_fields(thd, tables, order->item) || thd->fatal_error)
return 1; // Wrong field return 1; // Wrong field
all_fields.push_front(*order->item); // Add new field to field list all_fields.push_front(*order->item); // Add new field to field list
order->item=(Item**) all_fields.head_ref(); order->item=(Item**) all_fields.head_ref();
@ -6526,7 +6554,7 @@ setup_new_fields(THD *thd,TABLE_LIST *tables,List<Item> &fields,
else else
{ {
thd->where="procedure list"; thd->where="procedure list";
if ((*new_field->item)->fix_fields(thd,tables)) if ((*new_field->item)->fix_fields(thd, tables, new_field->item))
DBUG_RETURN(1); /* purecov: inspected */ DBUG_RETURN(1); /* purecov: inspected */
thd->where=0; thd->where=0;
all_fields.push_front(*new_field->item); all_fields.push_front(*new_field->item);
@ -7091,7 +7119,7 @@ static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab)
Here we pass 0 as the first argument to fix_fields that don't need Here we pass 0 as the first argument to fix_fields that don't need
to do any stack checking (This is already done in the initial fix_fields). to do any stack checking (This is already done in the initial fix_fields).
*/ */
cond->fix_fields((THD *) 0,(TABLE_LIST *) 0); cond->fix_fields((THD *) 0,(TABLE_LIST *) 0, (Item**)&cond);
if (join_tab->select) if (join_tab->select)
{ {
error=(int) cond->add(join_tab->select->cond); error=(int) cond->add(join_tab->select->cond);

View File

@ -1158,6 +1158,12 @@ store_create_info(THD *thd, TABLE *table, String *packet)
char buff[128]; char buff[128];
char* p; char* p;
if (table->table_charset)
{
packet->append(" CHARSET=");
packet->append(table->table_charset->name);
}
if (table->min_rows) if (table->min_rows)
{ {
packet->append(" MIN_ROWS="); packet->append(" MIN_ROWS=");
@ -1389,7 +1395,7 @@ int mysqld_show_charsets(THD *thd, const char *wild)
net_store_data(&packet2,(uint32) cs->mbmaxlen); net_store_data(&packet2,(uint32) cs->mbmaxlen);
if (my_net_write(&thd->net, (char*) packet2.ptr(),packet2.length())) if (my_net_write(&thd->net, (char*) packet2.ptr(),packet2.length()))
goto err; /* purecov: inspected */ goto err;
} }
} }
send_eof(&thd->net); send_eof(&thd->net);

View File

@ -375,6 +375,11 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
sql_field->offset= pos; sql_field->offset= pos;
if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER) if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
auto_increment++; auto_increment++;
if(!sql_field->charset)
sql_field->charset = create_info->table_charset ?
create_info->table_charset :
thd->db_charset? thd->db_charset :
default_charset_info;
pos+=sql_field->pack_length; pos+=sql_field->pack_length;
} }
if (auto_increment > 1) if (auto_increment > 1)
@ -1648,6 +1653,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
create_info->max_rows=table->max_rows; create_info->max_rows=table->max_rows;
if (!(used_fields & HA_CREATE_USED_AVG_ROW_LENGTH)) if (!(used_fields & HA_CREATE_USED_AVG_ROW_LENGTH))
create_info->avg_row_length=table->avg_row_length; create_info->avg_row_length=table->avg_row_length;
if (!(used_fields & HA_CREATE_USED_CHARSET))
create_info->table_charset=table->table_charset;
table->file->update_create_info(create_info); table->file->update_create_info(create_info);
if ((create_info->table_options & if ((create_info->table_options &

View File

@ -162,6 +162,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token CACHE_SYM %token CACHE_SYM
%token CASCADE %token CASCADE
%token CAST_SYM %token CAST_SYM
%token CHARSET
%token CHECKSUM_SYM %token CHECKSUM_SYM
%token CHECK_SYM %token CHECK_SYM
%token CIPHER %token CIPHER
@ -333,6 +334,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token UDF_SONAME_SYM %token UDF_SONAME_SYM
%token UDF_SYM %token UDF_SYM
%token UNCOMMITTED_SYM %token UNCOMMITTED_SYM
%token UNDERSCORE_CHARSET
%token UNION_SYM %token UNION_SYM
%token UNIQUE_SYM %token UNIQUE_SYM
%token USAGE %token USAGE
@ -524,7 +526,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%type <lex_str> %type <lex_str>
IDENT TEXT_STRING REAL_NUM FLOAT_NUM NUM LONG_NUM HEX_NUM LEX_HOSTNAME IDENT TEXT_STRING REAL_NUM FLOAT_NUM NUM LONG_NUM HEX_NUM LEX_HOSTNAME
ULONGLONG_NUM field_ident select_alias ident ident_or_text ULONGLONG_NUM field_ident select_alias ident ident_or_text UNDERSCORE_CHARSET
%type <lex_str_ptr> %type <lex_str_ptr>
opt_table_alias opt_table_alias
@ -554,7 +556,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
literal text_literal insert_ident order_ident literal text_literal insert_ident order_ident
simple_ident select_item2 expr opt_expr opt_else sum_expr in_sum_expr simple_ident select_item2 expr opt_expr opt_else sum_expr in_sum_expr
table_wild opt_pad no_in_expr expr_expr simple_expr no_and_expr table_wild opt_pad no_in_expr expr_expr simple_expr no_and_expr
using_list param_marker subselect subselect_init using_list param_marker singleval_subselect singleval_subselect_init
exists_subselect exists_subselect_init
%type <item_list> %type <item_list>
expr_list udf_expr_list when_list ident_list ident_list_arg expr_list udf_expr_list when_list ident_list ident_list_arg
@ -767,7 +770,7 @@ create:
bzero((char*) &lex->create_info,sizeof(lex->create_info)); bzero((char*) &lex->create_info,sizeof(lex->create_info));
lex->create_info.options=$2 | $4; lex->create_info.options=$2 | $4;
lex->create_info.db_type= default_table_type; lex->create_info.db_type= default_table_type;
lex->create_info.table_charset=default_charset_info; lex->create_info.table_charset=NULL;
} }
create2 create2
@ -795,6 +798,7 @@ create:
lex->sql_command=SQLCOM_CREATE_DB; lex->sql_command=SQLCOM_CREATE_DB;
lex->name=$4.str; lex->name=$4.str;
lex->create_info.options=$3; lex->create_info.options=$3;
lex->create_info.table_charset=lex->charset;
} }
| CREATE udf_func_type UDF_SYM ident | CREATE udf_func_type UDF_SYM ident
{ {
@ -881,6 +885,11 @@ create_table_option:
table_list->next=0; table_list->next=0;
lex->create_info.used_fields|= HA_CREATE_USED_UNION; lex->create_info.used_fields|= HA_CREATE_USED_UNION;
} }
| CHARSET EQ charset_or_nocharset
{
Lex->create_info.table_charset=Lex->charset;
Lex->create_info.used_fields|= HA_CREATE_USED_CHARSET;
}
| INSERT_METHOD EQ merge_insert_types { Lex->create_info.merge_insert_method= $3; Lex->create_info.used_fields|= HA_CREATE_USED_INSERT_METHOD;} | INSERT_METHOD EQ merge_insert_types { Lex->create_info.merge_insert_method= $3; Lex->create_info.used_fields|= HA_CREATE_USED_INSERT_METHOD;}
| DATA_SYM DIRECTORY_SYM EQ TEXT_STRING { Lex->create_info.data_file_name= $4.str; } | DATA_SYM DIRECTORY_SYM EQ TEXT_STRING { Lex->create_info.data_file_name= $4.str; }
| INDEX DIRECTORY_SYM EQ TEXT_STRING { Lex->create_info.index_file_name= $4.str; }; | INDEX DIRECTORY_SYM EQ TEXT_STRING { Lex->create_info.index_file_name= $4.str; };
@ -965,7 +974,7 @@ field_spec:
LEX *lex=Lex; LEX *lex=Lex;
lex->length=lex->dec=0; lex->type=0; lex->interval=0; lex->length=lex->dec=0; lex->type=0; lex->interval=0;
lex->default_value=lex->comment=0; lex->default_value=lex->comment=0;
lex->charset=default_charset_info; lex->charset=NULL;
} }
type opt_attribute type opt_attribute
{ {
@ -1115,32 +1124,28 @@ attribute:
| UNIQUE_SYM KEY_SYM { Lex->type|= UNIQUE_KEY_FLAG; } | UNIQUE_SYM KEY_SYM { Lex->type|= UNIQUE_KEY_FLAG; }
| COMMENT_SYM text_literal { Lex->comment= $2; }; | COMMENT_SYM text_literal { Lex->comment= $2; };
opt_binary: charset:
/* empty */ { Lex->charset=default_charset_info; } ident
| BINARY { Lex->type|=BINARY_FLAG; Lex->charset=default_charset_info; }
| CHAR_SYM SET ident
{ {
CHARSET_INFO *cs=get_charset_by_name($3.str,MYF(MY_WME)); if (!(Lex->charset=get_charset_by_name($1.str,MYF(0))))
if (!cs)
{ {
net_printf(&current_thd->net,ER_UNKNOWN_CHARACTER_SET,$3); net_printf(&current_thd->net,ER_UNKNOWN_CHARACTER_SET,$1);
YYABORT; YYABORT;
} }
Lex->charset=cs;
}; };
charset_or_nocharset:
charset
| DEFAULT {Lex->charset=NULL; }
opt_binary:
/* empty */ { Lex->charset=NULL; }
| BINARY { Lex->type|=BINARY_FLAG; Lex->charset=NULL; }
| CHAR_SYM SET charset {/* charset is already in Lex->charset */} ;
default_charset: default_charset:
/* empty */ { Lex->charset-default_charset_info; } /* empty */ { Lex->charset=NULL; }
| DEFAULT CHAR_SYM SET ident | DEFAULT CHAR_SYM SET charset_or_nocharset ;
{
CHARSET_INFO *cs=get_charset_by_name($4.str,MYF(MY_WME));
if (!cs)
{
net_printf(&current_thd->net,ER_UNKNOWN_CHARACTER_SET,$4);
YYABORT;
}
Lex->charset=cs;
};
references: references:
REFERENCES table_ident REFERENCES table_ident
@ -1259,12 +1264,21 @@ alter:
bzero((char*) &lex->create_info,sizeof(lex->create_info)); bzero((char*) &lex->create_info,sizeof(lex->create_info));
lex->create_info.db_type= DB_TYPE_DEFAULT; lex->create_info.db_type= DB_TYPE_DEFAULT;
lex->create_info.row_type= ROW_TYPE_NOT_USED; lex->create_info.row_type= ROW_TYPE_NOT_USED;
lex->create_info.table_charset=default_charset_info; lex->create_info.table_charset=NULL;
lex->alter_keys_onoff=LEAVE_AS_IS; lex->alter_keys_onoff=LEAVE_AS_IS;
lex->simple_alter=1; lex->simple_alter=1;
} }
alter_list; alter_list;
| ALTER DATABASE ident default_charset
{
LEX *lex=Lex;
lex->sql_command=SQLCOM_ALTER_DB;
lex->name=$3.str;
lex->create_info.table_charset=lex->charset;
}
alter_list: alter_list:
| alter_list_item | alter_list_item
| alter_list ',' alter_list_item; | alter_list ',' alter_list_item;
@ -1745,7 +1759,8 @@ simple_expr:
| NOT expr %prec NEG { $$= new Item_func_not($2); } | NOT expr %prec NEG { $$= new Item_func_not($2); }
| '!' expr %prec NEG { $$= new Item_func_not($2); } | '!' expr %prec NEG { $$= new Item_func_not($2); }
| '(' expr ')' { $$= $2; } | '(' expr ')' { $$= $2; }
| subselect { $$= $1; } | EXISTS exists_subselect { $$= $2; }
| singleval_subselect { $$= $1; }
| '{' ident expr '}' { $$= $3; } | '{' ident expr '}' { $$= $3; }
| MATCH ident_list_arg AGAINST '(' expr ')' | MATCH ident_list_arg AGAINST '(' expr ')'
{ Select->ftfunc_list.push_back((Item_func_match *) { Select->ftfunc_list.push_back((Item_func_match *)
@ -1758,16 +1773,8 @@ simple_expr:
| CASE_SYM opt_expr WHEN_SYM when_list opt_else END | CASE_SYM opt_expr WHEN_SYM when_list opt_else END
{ $$= new Item_func_case(* $4, $2, $5 ); } { $$= new Item_func_case(* $4, $2, $5 ); }
| CONVERT_SYM '(' expr ',' cast_type ')' { $$= create_func_cast($3, $5); } | CONVERT_SYM '(' expr ',' cast_type ')' { $$= create_func_cast($3, $5); }
| CONVERT_SYM '(' expr USING IDENT ')' | CONVERT_SYM '(' expr USING charset ')'
{ { $$= new Item_func_conv_charset($3,Lex->charset); }
CHARSET_INFO *cs=get_charset_by_name($5.str,MYF(MY_WME));
if (!cs)
{
net_printf(&current_thd->net,ER_UNKNOWN_CHARACTER_SET,$5);
YYABORT;
}
$$= new Item_func_conv_charset($3,cs);
}
| CONVERT_SYM '(' expr ',' expr ',' expr ')' | CONVERT_SYM '(' expr ',' expr ',' expr ')'
{ {
$$= new Item_func_conv_charset3($3,$7,$5); $$= new Item_func_conv_charset3($3,$7,$5);
@ -1786,6 +1793,8 @@ simple_expr:
{ $$= new Item_func_atan($3,$5); } { $$= new Item_func_atan($3,$5); }
| CHAR_SYM '(' expr_list ')' | CHAR_SYM '(' expr_list ')'
{ $$= new Item_func_char(*$3); } { $$= new Item_func_char(*$3); }
| CHARSET '(' expr ')'
{ $$= new Item_func_charset($3); }
| COALESCE '(' expr_list ')' | COALESCE '(' expr_list ')'
{ $$= new Item_func_coalesce(* $3); } { $$= new Item_func_coalesce(* $3); }
| CONCAT '(' expr_list ')' | CONCAT '(' expr_list ')'
@ -2842,6 +2851,11 @@ show_param:
lex->grant_user=$3; lex->grant_user=$3;
lex->grant_user->password.str=NullS; lex->grant_user->password.str=NullS;
} }
| CREATE DATABASE ident
{
Lex->sql_command=SQLCOM_SHOW_CREATE_DB;
Lex->name=$3.str;
}
| CREATE TABLE_SYM table_ident | CREATE TABLE_SYM table_ident
{ {
Lex->sql_command = SQLCOM_SHOW_CREATE; Lex->sql_command = SQLCOM_SHOW_CREATE;
@ -2972,7 +2986,7 @@ kill:
KILL_SYM expr KILL_SYM expr
{ {
LEX *lex=Lex; LEX *lex=Lex;
if ($2->fix_fields(lex->thd,0)) if ($2->fix_fields(lex->thd, 0, &$2))
{ {
send_error(&lex->thd->net, ER_SET_CONSTANTS_ONLY); send_error(&lex->thd->net, ER_SET_CONSTANTS_ONLY);
YYABORT; YYABORT;
@ -3075,6 +3089,7 @@ opt_ignore_lines:
text_literal: text_literal:
TEXT_STRING { $$ = new Item_string($1.str,$1.length,default_charset_info); } TEXT_STRING { $$ = new Item_string($1.str,$1.length,default_charset_info); }
| UNDERSCORE_CHARSET TEXT_STRING { $$ = new Item_string($2.str,$2.length,Lex->charset); }
| text_literal TEXT_STRING | text_literal TEXT_STRING
{ ((Item_string*) $1)->append($2.str,$2.length); }; { ((Item_string*) $1)->append($2.str,$2.length); };
@ -3467,7 +3482,8 @@ option_value:
| '@' ident_or_text equal expr | '@' ident_or_text equal expr
{ {
Item_func_set_user_var *item = new Item_func_set_user_var($2,$4); Item_func_set_user_var *item = new Item_func_set_user_var($2,$4);
if (item->fix_fields(current_thd,0) || item->update()) if (item->fix_fields(current_thd, 0, (Item**) &item) ||
item->update())
{ {
send_error(&current_thd->net, ER_SET_CONSTANTS_ONLY); send_error(&current_thd->net, ER_SET_CONSTANTS_ONLY);
YYABORT; YYABORT;
@ -3499,7 +3515,7 @@ option_value:
{ {
THD *thd=current_thd; THD *thd=current_thd;
Item *item= $3; Item *item= $3;
if (item->fix_fields(current_thd,0)) if (item->fix_fields(current_thd, 0, &item))
{ {
send_error(&thd->net, ER_SET_CONSTANTS_ONLY); send_error(&thd->net, ER_SET_CONSTANTS_ONLY);
YYABORT; YYABORT;
@ -3973,17 +3989,30 @@ union_option:
/* empty */ {} /* empty */ {}
| ALL {Lex->union_option=1;}; | ALL {Lex->union_option=1;};
subselect: singleval_subselect:
subselect_start subselect_init subselect_start singleval_subselect_init
subselect_end subselect_end
{ {
$$= $2; $$= $2;
}; };
subselect_init: singleval_subselect_init:
select_init select_init
{ {
$$= new Item_subselect(current_thd, Lex->select); $$= new Item_singleval_subselect(current_thd, Lex->select);
};
exists_subselect:
subselect_start exists_subselect_init
subselect_end
{
$$= $2;
};
exists_subselect_init:
select_init
{
$$= new Item_exists_subselect(current_thd, Lex->select);
}; };
subselect_start: subselect_start:

View File

@ -118,7 +118,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
outparam->raid_chunks= head[42]; outparam->raid_chunks= head[42];
outparam->raid_chunksize= uint4korr(head+43); outparam->raid_chunksize= uint4korr(head+43);
if (!(outparam->table_charset=get_charset((uint) head[38],MYF(0)))) if (!(outparam->table_charset=get_charset((uint) head[38],MYF(0))))
outparam->table_charset=default_charset_info; outparam->table_charset=NULL; // QQ display error message?
null_field_first=1; null_field_first=1;
} }
outparam->db_record_offset=1; outparam->db_record_offset=1;
@ -358,7 +358,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
uint comment_length=uint2korr(strpos+13); uint comment_length=uint2korr(strpos+13);
field_type=(enum_field_types) (uint) strpos[11]; field_type=(enum_field_types) (uint) strpos[11];
if (!(charset=get_charset((uint) strpos[12], MYF(0)))) if (!(charset=get_charset((uint) strpos[12], MYF(0))))
charset=outparam->table_charset; charset=outparam->table_charset?outparam->table_charset:default_charset_info;
if (!comment_length) if (!comment_length)
{ {
comment.str= (char*) ""; comment.str= (char*) "";
@ -375,7 +375,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
{ {
/* old frm file */ /* old frm file */
field_type= (enum_field_types) f_packtype(pack_flag); field_type= (enum_field_types) f_packtype(pack_flag);
charset=outparam->table_charset; charset=outparam->table_charset?outparam->table_charset:default_charset_info;
bzero((char*) &comment, sizeof(comment)); bzero((char*) &comment, sizeof(comment));
} }
*field_ptr=reg_field= *field_ptr=reg_field=
@ -1041,7 +1041,7 @@ File create_frm(register my_string name, uint reclength, uchar *fileinfo,
int2store(fileinfo+30,create_info->table_options); int2store(fileinfo+30,create_info->table_options);
fileinfo[32]=0; // No filename anymore fileinfo[32]=0; // No filename anymore
int4store(fileinfo+34,create_info->avg_row_length); int4store(fileinfo+34,create_info->avg_row_length);
fileinfo[38]= create_info->table_charset->number; fileinfo[38]= create_info->table_charset?create_info->table_charset->number:0;
fileinfo[40]= (uchar) create_info->row_type; fileinfo[40]= (uchar) create_info->row_type;
fileinfo[41]= (uchar) create_info->raid_type; fileinfo[41]= (uchar) create_info->raid_type;
fileinfo[42]= (uchar) create_info->raid_chunks; fileinfo[42]= (uchar) create_info->raid_chunks;
@ -1072,6 +1072,7 @@ void update_create_info_from_table(HA_CREATE_INFO *create_info, TABLE *table)
create_info->raid_type=table->raid_type; create_info->raid_type=table->raid_type;
create_info->raid_chunks=table->raid_chunks; create_info->raid_chunks=table->raid_chunks;
create_info->raid_chunksize=table->raid_chunksize; create_info->raid_chunksize=table->raid_chunksize;
create_info->table_charset=table->table_charset;
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
@ -1094,7 +1095,7 @@ char *get_field(MEM_ROOT *mem, TABLE *table, uint fieldnr)
{ {
Field *field=table->field[fieldnr]; Field *field=table->field[fieldnr];
char buff[MAX_FIELD_WIDTH]; char buff[MAX_FIELD_WIDTH];
String str(buff,sizeof(buff),table->table_charset); String str(buff,sizeof(buff),default_charset_info);
field->val_str(&str,&str); field->val_str(&str,&str);
uint length=str.length(); uint length=str.length();
if (!length) if (!length)

View File

@ -459,8 +459,7 @@ static bool pack_fields(File file,List<create_field> &create_fields)
int2store(buff+8,field->unireg_check); int2store(buff+8,field->unireg_check);
buff[10]= (uchar) field->interval_id; buff[10]= (uchar) field->interval_id;
buff[11]= (uchar) field->sql_type; buff[11]= (uchar) field->sql_type;
buff[12]= (uchar) (field->charset ? field->charset->number : buff[12]= (uchar) field->charset->number;
default_charset_info->number);
int2store(buff+13, field->comment.length); int2store(buff+13, field->comment.length);
comment_length+= field->comment.length; comment_length+= field->comment.length;
set_if_bigger(int_count,field->interval_id); set_if_bigger(int_count,field->interval_id);