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-sslserver
vio/viotest-ssl
tests/client_test

View File

@ -14,6 +14,7 @@ davida@isil.mysql.com
heikki@donna.mysql.fi
heikki@hundin.mysql.fi
hf@bison.(none)
hf@bisonxp.(none)
jani@dsl-jkl1657.dial.inet.fi
jani@hynda.(none)
jani@hynda.mysql.fi
@ -66,7 +67,7 @@ tonu@x153.internalnet
tonu@x3.internalnet
venu@myvenu.com
venu@work.mysql.com
walrus@mysql.com
worm@altair.is.lan
zak@balfor.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;
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;
while (pos != end)
@ -105,6 +113,7 @@ ha_checksum mi_unique_hash(MI_UNIQUEDEF *def, const byte *record)
(((uchar) sort_order[*(uchar*) pos++]))) +
(crc >> (8*sizeof(ha_checksum)-8));
}
}
else
while (pos != end)
crc=((crc << 8) +
@ -172,6 +181,13 @@ int mi_unique_comp(MI_UNIQUEDEF *def, const byte *a, const byte *b,
}
end= pos_a+length;
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;
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++])
return 1;
}
}
else
while (pos_a != end)
if (*pos_a++ != *pos_b++)

View File

@ -32,7 +32,7 @@ result_file=$RESULT_DIR/$test_name.result
touch $result_file
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

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;
b (select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2)
8 7.5000
8 6.0000
9 5.5000
8 4.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;

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 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;

View File

@ -115,7 +115,6 @@ sub new
$self->{'data_source'} = "DBI:mysql:database=$database;host=$host";
$self->{'data_source'} .= ";mysql_socket=$socket" if($socket);
$self->{'limits'} = \%limits;
$self->{'smds'} = \%smds;
$self->{'blob'} = "blob";
$self->{'text'} = "text";
$self->{'double_quotes'} = 1; # Can handle: 'Walker''s'
@ -168,25 +167,6 @@ sub new
$limits{'working_all_fields'} = 1;
$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
if (defined($main::opt_create_options) &&
$main::opt_create_options =~ /type=heap/i)
@ -199,6 +179,11 @@ sub new
$limits{'max_text_size'} = 8000; # Limit in Innobase
$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) &&
$main::opt_create_options =~ /type=gemini/i)
{
@ -266,7 +251,6 @@ sub create
{
$field =~ s/ decimal/ double(10,2)/i;
$field =~ s/ big_decimal/ double(10,2)/i;
$field =~ s/ date/ int/i; # Because of tcp ?
$query.= $field . ',';
}
foreach $index (@$index)
@ -575,7 +559,6 @@ sub new
$self->{'cmp_name'} = "pg";
$self->{'data_source'} = "DBI:Pg:dbname=$database";
$self->{'limits'} = \%limits;
$self->{'smds'} = \%smds;
$self->{'blob'} = "text";
$self->{'text'} = "text";
$self->{'double_quotes'} = 1;
@ -626,27 +609,6 @@ sub new
$limits{'working_all_fields'} = 1;
$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;
}
@ -871,7 +833,6 @@ sub new
$self->{'cmp_name'} = "solid";
$self->{'data_source'} = "DBI:Solid:";
$self->{'limits'} = \%limits;
$self->{'smds'} = \%smds;
$self->{'blob'} = "long varchar";
$self->{'text'} = "long varchar";
$self->{'double_quotes'} = 1;
@ -922,28 +883,6 @@ sub new
$limits{'order_by_unused'} = 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;
}
@ -1119,7 +1058,6 @@ sub new
$self->{'cmp_name'} = "empress";
$self->{'data_source'} = "DBI:EmpressNet:SERVER=$host;Database=/usr/local/empress/rdbms/bin/$database";
$self->{'limits'} = \%limits;
$self->{'smds'} = \%smds;
$self->{'blob'} = "text";
$self->{'text'} = "text";
$self->{'double_quotes'} = 1; # Can handle: 'Walker''s'
@ -1172,28 +1110,6 @@ sub new
$limits{'order_by_unused'} = 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;
}
@ -1410,7 +1326,6 @@ sub new
$self->{'cmp_name'} = "Oracle";
$self->{'data_source'} = "DBI:Oracle:$database";
$self->{'limits'} = \%limits;
$self->{'smds'} = \%smds;
$self->{'blob'} = "long";
$self->{'text'} = "long";
$self->{'double_quotes'} = 1; # Can handle: 'Walker''s'
@ -1464,24 +1379,6 @@ sub new
$limits{'order_by_unused'} = 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;
}
@ -1675,7 +1572,6 @@ sub new
$self->{'cmp_name'} = "Informix";
$self->{'data_source'} = "DBI:Informix:$database";
$self->{'limits'} = \%limits;
$self->{'smds'} = \%smds;
$self->{'blob'} = "byte in table";
$self->{'text'} = "byte in table";
$self->{'double_quotes'} = 0; # Can handle: 'Walker''s'
@ -1888,7 +1784,6 @@ sub new
$self->{'data_source'} .= ":$host";
}
$self->{'limits'} = \%limits;
$self->{'smds'} = \%smds;
$self->{'blob'} = "blob";
$self->{'text'} = "blob"; # text ?
$self->{'double_quotes'} = 1; # Can handle: 'Walker''s'
@ -2071,7 +1966,6 @@ sub new
$self->{'data_source'} .= ":$host";
}
$self->{'limits'} = \%limits;
$self->{'smds'} = \%smds;
$self->{'blob'} = "text";
$self->{'text'} = "text";
$self->{'double_quotes'} = 1; # Can handle: 'Walker''s'
@ -2264,7 +2158,6 @@ sub new
$self->{'data_source'} .= ";hostname=$host";
}
$self->{'limits'} = \%limits;
$self->{'smds'} = \%smds;
$self->{'blob'} = "text";
$self->{'text'} = "text";
$self->{'double_quotes'} = 1; # Can handle: 'Walker''s'
@ -2497,7 +2390,6 @@ sub new
$self->{'cmp_name'} = "Adabas";
$self->{'data_source'} = "DBI:Adabas:$database";
$self->{'limits'} = \%limits;
$self->{'smds'} = \%smds;
$self->{'blob'} = "long";
$self->{'text'} = "long";
$self->{'double_quotes'} = 1; # Can handle: 'Walker''s'
@ -2549,24 +2441,6 @@ sub new
$limits{'order_by_unused'} = 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;
}
@ -2718,7 +2592,6 @@ sub new
$self->{'data_source'} .= ":$host";
}
$self->{'limits'} = \%limits;
$self->{'smds'} = \%smds;
$self->{'blob'} = "varchar(255)";
$self->{'text'} = "varchar(255)";
$self->{'double_quotes'} = 1; # Can handle: 'Walker''s'
@ -2894,7 +2767,6 @@ sub new
$self->{'cmp_name'} = "mimer";
$self->{'data_source'} = "DBI:mimer:$database:$host";
$self->{'limits'} = \%limits;
$self->{'smds'} = \%smds;
$self->{'blob'} = "binary varying(15000)";
$self->{'text'} = "character varying(15000)";
$self->{'double_quotes'} = 1; # Can handle: 'Walker''s'
@ -2950,24 +2822,6 @@ sub new
$limits{'order_by_unused'} = 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;
}
@ -3112,7 +2966,6 @@ sub new
$self->{'cmp_name'} = "interbase";
$self->{'data_source'} = "DBI:InterBase:database=$database:ib_dialect=3";
$self->{'limits'} = \%limits;
$self->{'smds'} = \%smds;
$self->{'blob'} = "blob";
$self->{'text'} = "";
$self->{'double_quotes'} = 1; # Can handle: 'Walker''s'
@ -3166,24 +3019,6 @@ sub new
$limits{'order_by_unused'} = 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;
}
@ -3331,7 +3166,6 @@ sub new
$self->{'cmp_name'} = "FrontBase";
$self->{'data_source'} = "DBI:FB:dbname=$database;host=$host";
$self->{'limits'} = \%limits;
$self->{'smds'} = \%smds;
$self->{'blob'} = "varchar(8000000)";
$self->{'text'} = "varchar(8000000)";
$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,
enum utype unireg_check_arg, const char *field_name_arg,
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,
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)
{
flags|= BLOB_FLAG;
@ -3967,9 +3967,9 @@ String *Field_blob::val_str(String *val_buffer __attribute__((unused)),
char *blob;
memcpy_fixed(&blob,ptr+packlength,sizeof(char*));
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
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;
}
@ -4782,7 +4782,8 @@ Field *make_field(char *ptr, uint32 field_length,
if (f_is_blob(pack_flag))
return new Field_blob(ptr,null_pos,null_bit,
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))
return new Field_geom(ptr,null_pos,null_bit,
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,
enum utype unireg_check_arg, const char *field_name_arg,
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,
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,
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)
{
flags|= BLOB_FLAG;
@ -930,11 +930,12 @@ public:
struct st_table *table_arg,uint blob_pack_length,
bool binary_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,
struct st_table *table_arg, bool binary_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; }
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() &&
from->real_type() != FIELD_TYPE_STRING)
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;
}
if ((from->result_type() == STRING_RESULT &&
@ -520,7 +521,9 @@ void field_conv(Field *to,Field *from)
char buff[MAX_FIELD_WIDTH];
String result(buff,sizeof(buff),default_charset_info);
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)
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_AVG_ROW_LENGTH 64
#define HA_CREATE_USED_PACK_KEYS 128
#define HA_CREATE_USED_CHARSET 256
typedef struct st_thd_trans {
void *bdb_tid;

View File

@ -133,6 +133,9 @@ void Item_field::set_field(Field *field_par)
field_name=field_par->field_name;
binary=field_par->binary();
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
@ -443,12 +446,13 @@ String *Item_copy_string::val_str(String *str)
/* ARGSUSED */
bool Item::fix_fields(THD *thd,
struct st_table_list *list)
struct st_table_list *list,
Item ** ref)
{
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
{
@ -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
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();
sl && !tmp;
sl= sl->outer_select())
@ -473,6 +477,8 @@ bool Item_field::fix_fields(THD *thd,TABLE_LIST *tables)
if (!tmp)
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)
@ -491,6 +497,7 @@ bool Item_field::fix_fields(THD *thd,TABLE_LIST *tables)
tbl->shared= 1;
}
}
}
set_field(tmp);
}
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_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;
}
@ -784,12 +799,50 @@ bool Item_null::send(THD *thd, String *packet)
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= 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;
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;
maybe_null= (*ref)->maybe_null;
decimals= (*ref)->decimals;

View File

@ -52,7 +52,7 @@ public:
virtual ~Item() { name=0; } /*lint -e1509 */
void set_name(char* str,uint length=0);
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 void save_org_in_field(Field *field)
{ (void) save_in_field(field); }
@ -85,15 +85,18 @@ public:
};
class st_select_lex;
class Item_ident :public Item
{
public:
const char *db_name;
const char *table_name;
const char *field_name;
st_select_lex *depended_from;
Item_ident(const char *db_name_par,const char *table_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; }
const char *full_name() const;
};
@ -120,7 +123,7 @@ public:
String *str_result(String* tmp);
bool send(THD *thd, String *str_arg) { return result_field->send(thd,str_arg); }
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);
void save_org_in_field(Field *field);
table_map used_tables() const;
@ -390,7 +393,7 @@ public:
}
bool send(THD *thd, String *tmp) { return (*ref)->send(thd, tmp); }
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); }
void save_org_in_field(Field *field) { (*ref)->save_org_in_field(field); }
enum Item_result result_type () const { return (*ref)->result_type(); }

View File

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

View File

@ -177,9 +177,10 @@ public:
Item_func_interval(Item *a,List<Item> &list)
:Item_int_func(list),item(a),intervals(0) {}
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();
~Item_func_interval() { delete item; }
@ -259,7 +260,7 @@ public:
enum Item_result result_type () const { return cached_result_type; }
const char *func_name() const { return "case"; }
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);
};
@ -409,9 +410,10 @@ class Item_func_in :public Item_int_func
Item_func_in(Item *a,List<Item> &list)
:Item_int_func(list),item(a),array(0),in_item(0) {}
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();
~Item_func_in() { delete item; delete array; delete in_item; }
@ -505,7 +507,7 @@ public:
cond_result eq_cmp_result() const { return COND_TRUE; }
const char *func_name() const { return "like"; }
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
@ -523,7 +525,7 @@ public:
regex_compiled(0),regex_is_const(0) {}
~Item_func_regex();
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"; }
};
@ -552,7 +554,7 @@ public:
{ list.push_back(i1); list.push_back(i2); }
~Item_cond() { list.delete_elements(); }
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; }
List<Item>* argument_list() { return &list; }

View File

@ -58,7 +58,7 @@ Item_func::Item_func(List<Item> &list)
}
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;
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
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 */
if ((*arg)->maybe_null)
maybe_null=1;
if ((*arg)->binary)
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;
used_tables_cache|=(*arg)->used_tables();
const_item_cache&= (*arg)->const_item();
@ -1135,7 +1146,7 @@ udf_handler::fix_fields(THD *thd,TABLE_LIST *tables,Item_result_field *func,
arg != arg_end ;
arg++,i++)
{
if ((*arg)->fix_fields(thd,tables))
if ((*arg)->fix_fields(thd, tables, arg))
return 1;
if ((*arg)->binary)
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)
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)))
return 1;
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);
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
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");
return 1;
@ -2105,7 +2117,7 @@ bool Item_func_match::fix_fields(THD *thd,struct st_table_list *tlist)
while ((item=li++))
{
if (item->fix_fields(thd,tlist))
if (item->fix_fields(thd, tlist, li.ref()))
return 1;
if (item->type() == Item::REF_ITEM)
li.replace(item= *((Item_ref *)item)->ref);

View File

@ -99,7 +99,7 @@ public:
}
Item_func(List<Item> &list);
~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);
table_map used_tables() const;
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() { delete item; }
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()
{
@ -708,7 +709,7 @@ public:
:Item_func(list), udf(udf_arg) {}
~Item_udf_func() {}
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);
used_tables_cache= udf.used_tables_cache;
@ -867,7 +868,7 @@ public:
void update_hash(void *ptr, uint length, enum Item_result type);
bool update();
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 print(String *str);
const char *func_name() const { return "set_user_var"; }
@ -941,7 +942,7 @@ public:
}
enum Functype functype() const { return FT_FUNC; }
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;
longlong val_int() { return val()!=0.0; }
double val();

View File

@ -759,6 +759,7 @@ String *Item_func_left::val_str(String *str)
if (!res->alloced_length())
{ // Don't change const str
str_value= *res; // Not malloced string
str_value.set_charset(res->charset());
res= &str_value;
}
res->length((uint) length);
@ -1791,6 +1792,7 @@ String *Item_func_conv_charset::val_str(String *str)
null_value=1;
return 0;
}
null_value=0;
from=arg->charset();
to=conv_charset;
@ -1798,7 +1800,7 @@ String *Item_func_conv_charset::val_str(String *str)
s=(const uchar*)arg->ptr();
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);
d0=d=(unsigned char*)str->ptr();
de=d+dmaxlen;
@ -1840,7 +1842,7 @@ outp:
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;
}
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()
{
/* 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)
return result_field;
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,
default_charset_info);
str_value.charset());
}
};
@ -79,10 +80,10 @@ public:
String *val_str(String *);
void fix_length_and_dec();
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)
|| Item_func::fix_fields(thd,tlist));
return (separator->fix_fields(thd, tlist, &separator)
|| Item_func::fix_fields(thd, tlist, ref));
}
const char *func_name() const { return "concat_ws"; }
};
@ -325,9 +326,10 @@ public:
double val();
longlong val_int();
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 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() { delete item; }
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 update_used_tables();
@ -488,6 +491,7 @@ public:
{
conv_charset=cs;
}
bool fix_fields(THD *thd,struct st_table_list *tables);
String *val_str(String *);
void fix_length_and_dec();
const char *func_name() const { return "conv_charset"; }
@ -503,6 +507,18 @@ public:
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

View File

@ -35,12 +35,13 @@ SUBSELECT TODO:
#include "mysql_priv.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)
{
DBUG_ENTER("Item_subselect::Item_subselect");
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();
unit->offset_limit_cnt= unit->global_parameters->offset_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;
join= new JOIN(thd, select_lex->item_list, select_lex->options, result);
this->select_lex= select_lex;
maybe_null= 1;
assign_null();
/*
item value is NULL if select_subselect not changed this value
(i.e. some rows will be found returned)
*/
assign_null();
null_value= 1;
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)
{
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?
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));
return 1;
@ -131,13 +99,14 @@ bool Item_subselect::fix_fields(THD *thd,TABLE_LIST *tables)
int Item_subselect::exec()
{
DBUG_ENTER("Item_subselect::exec");
if (!optimized)
{
optimized=1;
if (join->optimize())
{
executed= 1;
return (join->error?join->error:1);
DBUG_RETURN(join->error?join->error:1);
}
}
if (join->select_lex->depended && executed)
@ -145,7 +114,7 @@ int Item_subselect::exec()
if (join->reinit())
{
error= 1;
return 1;
DBUG_RETURN(1);
}
assign_null();
executed= assigned= 0;
@ -157,7 +126,80 @@ int Item_subselect::exec()
join->exec();
join->thd->lex.select= save_select;
executed= 1;
return join->error;
DBUG_RETURN(join->error);
}
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 */
#endif
struct st_select_lex;
class st_select_lex;
class JOIN;
class select_subselect;
/* simple (not depended of covered select ) subselect */
/* base class for subselects */
class Item_subselect :public Item
{
protected:
longlong int_value;
double real_value;
uint max_columns;
my_bool assigned; /* value already assigned to subselect */
my_bool executed; /* simple subselect is executed */
my_bool optimized; /* simple subselect is optimized */
my_bool error; /* error in query */
enum Item_result res_type;
int exec();
void assign_null()
virtual void assign_null()
{
null_value= 1;
int_value= 0;
real_value= 0;
max_length= 4;
res_type= STRING_RESULT;
}
public:
st_select_lex *select_lex;
JOIN *join;
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)
{
null_value= item->null_value;
int_value= item->int_value;
real_value= item->real_value;
max_length= item->max_length;
decimals= item->decimals;
res_type= item->res_type;
max_columns= item->max_columns;
assigned= item->assigned;
executed= item->executed;
select_lex= item->select_lex;
@ -69,16 +61,75 @@ public:
error= item->error;
}
enum Type type() const;
double val ();
longlong val_int ();
String *val_str (String *);
bool is_null() { return null_value; }
void make_field (Send_field *);
bool fix_fields(THD *thd, TABLE_LIST *tables);
Item *new_item() { return new Item_subselect(this); }
enum Item_result result_type() const { return res_type; }
bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref);
table_map used_tables() const;
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
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)
{
@ -124,7 +124,7 @@ Item_sum_num::fix_fields(THD *thd,TABLE_LIST *tables)
maybe_null=0;
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;
if (decimals < args[i]->decimals)
decimals=args[i]->decimals;
@ -140,7 +140,7 @@ Item_sum_num::fix_fields(THD *thd,TABLE_LIST *tables)
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];
if (!thd->allow_sum_func)
@ -149,7 +149,7 @@ Item_sum_hybrid::fix_fields(THD *thd,TABLE_LIST *tables)
return 1;
}
thd->allow_sum_func=0; // No included group funcs
if (item->fix_fields(thd,tables))
if (item->fix_fields(thd, tables, args))
return 1;
hybrid_type=item->result_type();
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))
return 1;
return 0;

View File

@ -80,7 +80,7 @@ public:
Item_sum_num(Item *item_par) :Item_sum(item_par) {}
Item_sum_num(Item *a, Item* b) :Item_sum(a,b) {}
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 */
String *val_str(String*str);
void reset_field();
@ -146,7 +146,7 @@ class Item_sum_count_distinct :public Item_sum_int
{
TABLE *table;
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;
TMP_TABLE_PARAM *tmp_table_param;
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),
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; }
bool const_item() const { return !used_table_cache; }
@ -382,7 +382,7 @@ public:
{ quick_group=0;}
~Item_udf_sum() {}
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);
}

View File

@ -42,5 +42,5 @@ public:
bool add() { return 0; }
void reset_field() {}
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},
{ "CHAR", SYM(CHAR_SYM),0,0},
{ "CHARACTER", SYM(CHAR_SYM),0,0},
{ "CHARSET", SYM(CHARSET),0,0},
{ "CHANGE", SYM(CHANGE),0,0},
{ "CHANGED", SYM(CHANGED),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)
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);
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);
@ -471,6 +472,7 @@ int mysqld_show_logs(THD *thd);
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_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);
int mysqld_show_status(THD *thd);

View File

@ -1876,7 +1876,7 @@ int setup_fields(THD *thd, TABLE_LIST *tables, List<Item> &fields,
}
else
{
if (item->fix_fields(thd,tables))
if (item->fix_fields(thd, tables, it.ref()))
DBUG_RETURN(-1); /* purecov: inspected */
if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM &&
sum_func_list)
@ -2027,7 +2027,7 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
if (*conds)
{
thd->where="where clause";
if ((*conds)->fix_fields(thd,tables))
if ((*conds)->fix_fields(thd, tables, conds))
DBUG_RETURN(1);
}
@ -2038,7 +2038,7 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
{
/* Make a join an a expression */
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);
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),
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_or_ip="unknown ip";
@ -103,6 +103,7 @@ THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0),
file_id = 0;
cond_count=0;
convert_set=0;
db_charset=default_charset_info;
mysys_var=0;
#ifndef DBUG_OFF
dbug_sentry=THD_SENTRY_MAGIC;
@ -769,7 +770,6 @@ void select_dump::send_error(uint errcode,const char *err)
file= -1;
}
bool select_dump::send_eof()
{
int error=test(end_io_cache(&cache));
@ -788,10 +788,11 @@ select_subselect::select_subselect(Item_subselect *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");
if (item->assigned){
DBUG_ENTER("select_singleval_subselect::send_data");
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));
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()
calculate value on it & determinate "is it NULL?".
*/
item->real_value= val_item->val();
if ((item->null_value= val_item->is_null()))
it->real_value= val_item->val();
if ((it->null_value= val_item->is_null()))
{
item->assign_null();
it->assign_null();
} else {
item->max_length= val_item->max_length;
item->decimals= val_item->decimals;
item->binary= val_item->binary;
val_item->val_str(&item->str_value);
item->int_value= val_item->val_int();
item->res_type= val_item->result_type();
it->max_length= val_item->max_length;
it->decimals= val_item->decimals;
it->binary= val_item->binary;
val_item->val_str(&it->str_value);
it->int_value= val_item->val_int();
it->res_type= val_item->result_type();
}
item->assigned= 1;
it->assigned= 1;
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 safe_to_cache_query;
bool volatile killed;
bool having_fix_field; //TRUE when having fix field called
bool prepare_command;
ulong param_count,current_param_number;
Error<mysql_st_error> err_list;
@ -480,6 +479,7 @@ public:
ulong slave_proxy_id;
NET* slave_net; // network connection from slave -> m.
my_off_t log_pos;
CHARSET_INFO *db_charset;
THD();
~THD();
@ -749,19 +749,36 @@ class select_union :public select_result {
bool flush();
};
/* Single value subselect interface class */
/* Base subselect interface class */
class select_subselect :public select_result
{
protected:
Item_subselect *item;
public:
select_subselect(Item_subselect *item);
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; };
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 */
typedef struct st_sort_field {

View File

@ -25,18 +25,112 @@
#include <direct.h>
#endif
#define MY_DB_OPT_FILE ".db.opt"
static long mysql_rm_known_files(THD *thd, MY_DIR *dirp,
const char *db, const char *path,
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 */
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];
MY_DIR *dirp;
long result=1;
int error = 0;
uint create_options = create_info ? create_info->options : 0;
DBUG_ENTER("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 (!thd->query)
@ -104,7 +204,81 @@ exit2:
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=
{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 path[FN_REFLEN];
uint db_access;
HA_CREATE_INFO create;
DBUG_ENTER("mysql_change_db");
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_length=db_length;
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);
}

View File

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

View File

@ -525,6 +525,18 @@ int yylex(void *arg)
yylval->lex_str=get_token(lex,length);
if (lex->convert_set)
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);
case STATE_IDENT_SEP: // Found ident and now '.'
@ -931,7 +943,7 @@ void st_select_lex::init_select()
use_index.empty();
ftfunc_list.empty();
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_PROCESSLIST, SQLCOM_SHOW_MASTER_STAT, SQLCOM_SHOW_SLAVE_STAT,
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_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_CREATE_FUNCTION, SQLCOM_DROP_FUNCTION,
SQLCOM_REVOKE,SQLCOM_OPTIMIZE, SQLCOM_CHECK,
@ -234,11 +236,12 @@ private:
bool create_total_list_n_last_return(THD *thd, st_lex *lex,
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
*/
class JOIN;
class st_select_lex: public st_select_lex_node {
public:
char *db, *db1, *table1, *db2, *table2; /* For outer join using .. */
@ -250,10 +253,14 @@ public:
List<String> interval_list, use_index, *use_index_ptr,
ignore_index, *ignore_index_ptr;
List<Item_func_match> ftfunc_list;
JOIN *join; /* after JOIN::prepare it is pointer to corresponding JOIN */
uint in_sum_expr;
bool create_refs,
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_select();
st_select_lex_unit* master_unit() { return (st_select_lex_unit*) master; }
@ -277,7 +284,7 @@ public:
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 {
public:

View File

@ -2310,7 +2310,7 @@ mysql_execute_command(void)
}
if (check_access(thd,CREATE_ACL,lex->name,0,1))
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;
}
case SQLCOM_DROP_DB:
@ -2330,6 +2330,40 @@ mysql_execute_command(void)
res=mysql_rm_db(thd,lex->name,lex->drop_if_exists,0);
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:
if (check_access(thd,INSERT_ACL,"mysql",0,1))
break;

View File

@ -470,7 +470,7 @@ static bool mysql_test_select_fields(THD *thd, TABLE_LIST *tables,
{
thd->where="having clause";
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);
if (having->with_sum_func)
having->split_sum_func(all_fields);

View File

@ -211,6 +211,7 @@ JOIN::prepare(TABLE_LIST *tables_init,
proc_param= proc_param_init;
tables_list= tables_init;
select_lex= select;
select->join= this;
union_part= (unit->first_select()->next_select() != 0);
/* 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->allow_sum_func=1;
bool having_fix_field_store= thd->having_fix_field;
thd->having_fix_field= 1;
bool having_fix_rc= having->fix_fields(thd,tables_list);
thd->having_fix_field= having_fix_field_store;
select_lex->having_fix_field= 1;
bool having_fix_rc= having->fix_fields(thd, tables_list, &having);
select_lex->having_fix_field= 0;
if (having_fix_rc || thd->fatal_error)
DBUG_RETURN(-1); /* purecov: inspected */
if (having->with_sum_func)
@ -349,7 +349,7 @@ JOIN::optimize()
}
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);
having= 0;
}
@ -613,6 +613,15 @@ JOIN::reinit()
if (setup_tables(tables_list))
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);
}
@ -966,6 +975,21 @@ JOIN::cleanup(THD *thd)
delete select;
delete_dynamic(&keyuse);
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;
}
@ -3381,7 +3405,7 @@ remove_eq_conds(COND *cond,Item::cond_result *cond_value)
21))))
{
cond=new_cond;
cond->fix_fields(thd,0);
cond->fix_fields(thd, 0, &cond);
}
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))))
{
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:
if (item_sum->max_length > 255)
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,
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:
if (item->max_length > 255)
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
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;
}
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;
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->start= keyinfo->key_part[i].offset;
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;
}
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
all_fields.push_front(*order->item); // Add new field to field list
order->item=(Item**) all_fields.head_ref();
@ -6526,7 +6554,7 @@ setup_new_fields(THD *thd,TABLE_LIST *tables,List<Item> &fields,
else
{
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 */
thd->where=0;
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
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)
{
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* p;
if (table->table_charset)
{
packet->append(" CHARSET=");
packet->append(table->table_charset->name);
}
if (table->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);
if (my_net_write(&thd->net, (char*) packet2.ptr(),packet2.length()))
goto err; /* purecov: inspected */
goto err;
}
}
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;
if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
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;
}
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;
if (!(used_fields & HA_CREATE_USED_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);
if ((create_info->table_options &

View File

@ -162,6 +162,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token CACHE_SYM
%token CASCADE
%token CAST_SYM
%token CHARSET
%token CHECKSUM_SYM
%token CHECK_SYM
%token CIPHER
@ -333,6 +334,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token UDF_SONAME_SYM
%token UDF_SYM
%token UNCOMMITTED_SYM
%token UNDERSCORE_CHARSET
%token UNION_SYM
%token UNIQUE_SYM
%token USAGE
@ -524,7 +526,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%type <lex_str>
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>
opt_table_alias
@ -554,7 +556,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
literal text_literal insert_ident order_ident
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
using_list param_marker subselect subselect_init
using_list param_marker singleval_subselect singleval_subselect_init
exists_subselect exists_subselect_init
%type <item_list>
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));
lex->create_info.options=$2 | $4;
lex->create_info.db_type= default_table_type;
lex->create_info.table_charset=default_charset_info;
lex->create_info.table_charset=NULL;
}
create2
@ -795,6 +798,7 @@ create:
lex->sql_command=SQLCOM_CREATE_DB;
lex->name=$4.str;
lex->create_info.options=$3;
lex->create_info.table_charset=lex->charset;
}
| CREATE udf_func_type UDF_SYM ident
{
@ -881,6 +885,11 @@ create_table_option:
table_list->next=0;
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;}
| 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; };
@ -965,7 +974,7 @@ field_spec:
LEX *lex=Lex;
lex->length=lex->dec=0; lex->type=0; lex->interval=0;
lex->default_value=lex->comment=0;
lex->charset=default_charset_info;
lex->charset=NULL;
}
type opt_attribute
{
@ -1115,32 +1124,28 @@ attribute:
| UNIQUE_SYM KEY_SYM { Lex->type|= UNIQUE_KEY_FLAG; }
| COMMENT_SYM text_literal { Lex->comment= $2; };
opt_binary:
/* empty */ { Lex->charset=default_charset_info; }
| BINARY { Lex->type|=BINARY_FLAG; Lex->charset=default_charset_info; }
| CHAR_SYM SET ident
charset:
ident
{
CHARSET_INFO *cs=get_charset_by_name($3.str,MYF(MY_WME));
if (!cs)
if (!(Lex->charset=get_charset_by_name($1.str,MYF(0))))
{
net_printf(&current_thd->net,ER_UNKNOWN_CHARACTER_SET,$3);
net_printf(&current_thd->net,ER_UNKNOWN_CHARACTER_SET,$1);
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:
/* empty */ { Lex->charset-default_charset_info; }
| DEFAULT CHAR_SYM SET ident
{
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;
};
/* empty */ { Lex->charset=NULL; }
| DEFAULT CHAR_SYM SET charset_or_nocharset ;
references:
REFERENCES table_ident
@ -1259,12 +1264,21 @@ alter:
bzero((char*) &lex->create_info,sizeof(lex->create_info));
lex->create_info.db_type= DB_TYPE_DEFAULT;
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->simple_alter=1;
}
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_item
| alter_list ',' alter_list_item;
@ -1745,7 +1759,8 @@ simple_expr:
| NOT expr %prec NEG { $$= new Item_func_not($2); }
| '!' expr %prec NEG { $$= new Item_func_not($2); }
| '(' expr ')' { $$= $2; }
| subselect { $$= $1; }
| EXISTS exists_subselect { $$= $2; }
| singleval_subselect { $$= $1; }
| '{' ident expr '}' { $$= $3; }
| MATCH ident_list_arg AGAINST '(' expr ')'
{ 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
{ $$= new Item_func_case(* $4, $2, $5 ); }
| CONVERT_SYM '(' expr ',' cast_type ')' { $$= create_func_cast($3, $5); }
| CONVERT_SYM '(' expr USING IDENT ')'
{
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 USING charset ')'
{ $$= new Item_func_conv_charset($3,Lex->charset); }
| CONVERT_SYM '(' expr ',' expr ',' expr ')'
{
$$= new Item_func_conv_charset3($3,$7,$5);
@ -1786,6 +1793,8 @@ simple_expr:
{ $$= new Item_func_atan($3,$5); }
| CHAR_SYM '(' expr_list ')'
{ $$= new Item_func_char(*$3); }
| CHARSET '(' expr ')'
{ $$= new Item_func_charset($3); }
| COALESCE '(' expr_list ')'
{ $$= new Item_func_coalesce(* $3); }
| CONCAT '(' expr_list ')'
@ -2842,6 +2851,11 @@ show_param:
lex->grant_user=$3;
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
{
Lex->sql_command = SQLCOM_SHOW_CREATE;
@ -2972,7 +2986,7 @@ kill:
KILL_SYM expr
{
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);
YYABORT;
@ -3075,6 +3089,7 @@ opt_ignore_lines:
text_literal:
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
{ ((Item_string*) $1)->append($2.str,$2.length); };
@ -3467,7 +3482,8 @@ option_value:
| '@' ident_or_text equal expr
{
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);
YYABORT;
@ -3499,7 +3515,7 @@ option_value:
{
THD *thd=current_thd;
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);
YYABORT;
@ -3973,17 +3989,30 @@ union_option:
/* empty */ {}
| ALL {Lex->union_option=1;};
subselect:
subselect_start subselect_init
singleval_subselect:
subselect_start singleval_subselect_init
subselect_end
{
$$= $2;
};
subselect_init:
singleval_subselect_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:

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_chunksize= uint4korr(head+43);
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;
}
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);
field_type=(enum_field_types) (uint) strpos[11];
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)
{
comment.str= (char*) "";
@ -375,7 +375,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
{
/* old frm file */
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));
}
*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);
fileinfo[32]=0; // No filename anymore
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[41]= (uchar) create_info->raid_type;
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_chunks=table->raid_chunks;
create_info->raid_chunksize=table->raid_chunksize;
create_info->table_charset=table->table_charset;
DBUG_VOID_RETURN;
}
@ -1094,7 +1095,7 @@ char *get_field(MEM_ROOT *mem, TABLE *table, uint fieldnr)
{
Field *field=table->field[fieldnr];
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);
uint length=str.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);
buff[10]= (uchar) field->interval_id;
buff[11]= (uchar) field->sql_type;
buff[12]= (uchar) (field->charset ? field->charset->number :
default_charset_info->number);
buff[12]= (uchar) field->charset->number;
int2store(buff+13, field->comment.length);
comment_length+= field->comment.length;
set_if_bigger(int_count,field->interval_id);