Commit 9625a39d authored by unknown's avatar unknown

Fixed access privilege bug in query cache.

Change tests to use database 'mysqltest' instead of 'foo'
Add option to not print access denied messages to check_table_access()


Docs/manual.texi:
  Updated query cache information.
client/mysqltest.c:
  When connection to the database '*NO-ONE*, connect without specify a database.
include/raid.h:
  Portability fix
mysql-test/r/drop.result:
  Change test to use database 'mysqltest' instead of 'foo'
mysql-test/r/flush.result:
  Change test to use database 'mysqltest' instead of 'foo'
mysql-test/r/innodb.result:
  Change test to use database 'mysqltest' instead of 'foo'
mysql-test/r/query_cache.result:
  Change test to use database 'mysqltest' instead of 'foo'
mysql-test/t/drop.test:
  Change test to use database 'mysqltest' instead of 'foo'
mysql-test/t/flush.test:
  Change test to use database 'mysqltest' instead of 'foo'
mysql-test/t/innodb.test:
  Change test to use database 'mysqltest' instead of 'foo'
mysql-test/t/query_cache.test:
  Change test to use database 'mysqltest' instead of 'foo'
sql/mysql_priv.h:
  Add option to not print access denied messages
sql/net_pkg.cc:
  Fix for query cache
sql/net_serv.cc:
  Speed improvment
sql/sql_cache.cc:
  Fixed access privilege bug in query cache
sql/sql_cache.h:
  Always compiled with integrity check function prototypes.
sql/sql_do.cc:
  Removed warning
sql/sql_parse.cc:
  Add option to not print access denied messages
parent 5478a2ad
...@@ -35574,6 +35574,10 @@ In addition, a query may be seen as different if for instance one ...@@ -35574,6 +35574,10 @@ In addition, a query may be seen as different if for instance one
client is using a new communication protocol format or another client is using a new communication protocol format or another
character set than another client. character set than another client.
Queries that uses different databases, uses different protocol versions
or the uses different default character sets are considered different
queries and cached separately.
The cache does work for @code{SELECT CALC_ROWS ...} and The cache does work for @code{SELECT CALC_ROWS ...} and
@code{SELECT FOUND_ROWS() ...} type queries because the number of @code{SELECT FOUND_ROWS() ...} type queries because the number of
found rows is also stored in the cache. found rows is also stored in the cache.
...@@ -35612,8 +35616,12 @@ of the form @code{SELECT * FROM AUTOINCREMENT_FIELD IS NULL} ...@@ -35612,8 +35616,12 @@ of the form @code{SELECT * FROM AUTOINCREMENT_FIELD IS NULL}
However, @code{FOUND ROWS()} will return the correct value, However, @code{FOUND ROWS()} will return the correct value,
even if the preceding query was fetched from the cache. even if the preceding query was fetched from the cache.
Queries that don't use any tables are not cached. Queries that don't use any tables or if the user has a column privilege for
any of the involved tables are not cached.
Before a query is fetched from the query cache, MySQL will check that
the user has SELECT privilege to all the involved databases and
tables. If this is not the case, the cached result will not be used.
@node Query Cache Configuration, Query Cache in SELECT, Query Cache How, Query Cache @node Query Cache Configuration, Query Cache in SELECT, Query Cache How, Query Cache
@subsection Query Cache Configuration @subsection Query Cache Configuration
...@@ -1248,7 +1248,8 @@ int close_connection(struct st_query* q) ...@@ -1248,7 +1248,8 @@ int close_connection(struct st_query* q)
} }
/* this one now is a hack - we may want to improve in in the /*
This one now is a hack - we may want to improve in in the
future to handle quotes. For now we assume that anything that is not future to handle quotes. For now we assume that anything that is not
a comma, a space or ) belongs to the argument. space is a chopper, comma or a comma, a space or ) belongs to the argument. space is a chopper, comma or
) are delimiters/terminators ) are delimiters/terminators
...@@ -1291,8 +1292,7 @@ int safe_connect(MYSQL* con, const char* host, const char* user, ...@@ -1291,8 +1292,7 @@ int safe_connect(MYSQL* con, const char* host, const char* user,
int i; int i;
for (i = 0; i < MAX_CON_TRIES; ++i) for (i = 0; i < MAX_CON_TRIES; ++i)
{ {
if(mysql_real_connect(con, host,user, pass, if (mysql_real_connect(con, host,user, pass, db, port, sock, 0))
db, port, sock, 0))
{ {
con_error = 0; con_error = 0;
break; break;
...@@ -1365,6 +1365,9 @@ int do_connect(struct st_query* q) ...@@ -1365,6 +1365,9 @@ int do_connect(struct st_query* q)
con_sock=fn_format(buff, con_sock, TMPDIR, "",0); con_sock=fn_format(buff, con_sock, TMPDIR, "",0);
if (!con_db[0]) if (!con_db[0])
con_db=db; con_db=db;
/* Special database to allow one to connect without a database name */
if (!strcmp(con_db,"*NO-ONE*"))
con_db=0;
if ((con_error = safe_connect(&next_con->mysql, con_host, if ((con_error = safe_connect(&next_con->mysql, con_host,
con_user, con_pass, con_user, con_pass,
con_db, con_port, con_sock ? con_sock: 0))) con_db, con_port, con_sock ? con_sock: 0)))
......
...@@ -22,8 +22,10 @@ ...@@ -22,8 +22,10 @@
#define RAID_DEFAULT_CHUNKS 4 #define RAID_DEFAULT_CHUNKS 4
#define RAID_DEFAULT_CHUNKSIZE 256*1024 /* 256kB */ #define RAID_DEFAULT_CHUNKSIZE 256*1024 /* 256kB */
extern const char *raid_type_string[]; C_MODE_START
#define my_raid_type(raid_type) raid_type_string[(int)(raid_type)] #define my_raid_type(raid_type) raid_type_string[(int)(raid_type)]
extern const char *raid_type_string[];
C_MODE_END
#if defined(USE_RAID) && !defined(DONT_USE_RAID) #if defined(USE_RAID) && !defined(DONT_USE_RAID)
......
...@@ -12,37 +12,37 @@ drop table t1; ...@@ -12,37 +12,37 @@ drop table t1;
select * from t1; select * from t1;
n n
1 1
drop database if exists foo; drop database if exists mysqltest;
create database foo; create database mysqltest;
drop database if exists foo; drop database if exists mysqltest;
create database foo; create database mysqltest;
create table foo.foo (n int); create table mysqltest.mysqltest (n int);
insert into foo.foo values (4); insert into mysqltest.mysqltest values (4);
select * from foo.foo; select * from mysqltest.mysqltest;
n n
4 4
drop database if exists foo; drop database if exists mysqltest;
create database foo; create database mysqltest;
drop database foo; drop database mysqltest;
drop database if exists foo; drop database if exists mysqltest;
flush tables with read lock; flush tables with read lock;
create database foo; create database mysqltest;
Got one of the listed errors Got one of the listed errors
unlock tables; unlock tables;
create database foo; create database mysqltest;
show databases; show databases;
Database Database
foo
mysql mysql
mysqltest
test test
flush tables with read lock; flush tables with read lock;
drop database foo; drop database mysqltest;
Got one of the listed errors Got one of the listed errors
unlock tables; unlock tables;
drop database foo; drop database mysqltest;
show databases; show databases;
Database Database
mysql mysql
test test
drop database foo; drop database mysqltest;
Can't drop database 'foo'. Database doesn't exist Can't drop database 'mysqltest'. Database doesn't exist
...@@ -11,13 +11,13 @@ drop table t2; ...@@ -11,13 +11,13 @@ drop table t2;
Table 't2' was locked with a READ lock and can't be updated Table 't2' was locked with a READ lock and can't be updated
drop table t2; drop table t2;
unlock tables; unlock tables;
drop database if exists foo; drop database if exists mysqltest;
create database foo; create database mysqltest;
create table foo.t1(n int); create table mysqltest.t1(n int);
insert into foo.t1 values (23); insert into mysqltest.t1 values (23);
flush tables with read lock; flush tables with read lock;
drop database foo; drop database mysqltest;
select * from foo.t1; select * from mysqltest.t1;
n n
23 23
unlock tables; unlock tables;
......
drop table if exists test.t1,mysqltest.t1,mysqltest.t2;
reset query cache;
flush status;
create database if not exists mysqltest;
create table mysqltest.t1 (a int,b int,c int);
create table mysqltest.t2 (a int,b int,c int);
insert into mysqltest.t1 values (1,1,1),(2,2,2);
insert into mysqltest.t2 values (3,3,3);
create table test.t1 (a char (10));
insert into test.t1 values ("test.t1");
select * from t1;
a
test.t1
select * from t1;
a b c
1 1 1
2 2 2
select a from t1;
a
1
2
select c from t1;
c
1
2
select * from t2;
a b c
3 3 3
select * from mysqltest.t1,test.t1;
a b c a
1 1 1 test.t1
2 2 2 test.t1
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 6
show status like "Qcache_hits%";
Variable_name Value
Qcache_hits 0
grant SELECT on mysqltest.* to mysqltest_1@localhost;
grant SELECT on mysqltest.t1 to mysqltest_2@localhost;
grant SELECT on test.t1 to mysqltest_2@localhost;
grant SELECT(a) on mysqltest.t1 to mysqltest_3@localhost;
select "user1";
user1
user1
select * from t1;
a b c
1 1 1
2 2 2
select a from t1 ;
a
1
2
select c from t1;
c
1
2
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 6
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 3
show status like "Qcache_not_cached";
Variable_name Value
Qcache_not_cached 1
select "user2";
user2
user2
select * from t1;
a b c
1 1 1
2 2 2
select a from t1;
a
1
2
select c from t1;
c
1
2
select * from mysqltest.t1,test.t1;
a b c a
1 1 1 test.t1
2 2 2 test.t1
select * from t2;
select command denied to user: 'mysqltest_2@localhost' for table 't2'
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 6
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 7
show status like "Qcache_not_cached";
Variable_name Value
Qcache_not_cached 3
select "user3";
user3
user3
select * from t1;
select command denied to user: 'mysqltest_3@localhost' for column 'b' in table 't1'
select a from t1;
a
1
2
select c from t1;
select command denied to user: 'mysqltest_3@localhost' for column 'c' in table 't1'
select * from t2;
select command denied to user: 'mysqltest_3@localhost' for table 't2'
select mysqltest.t1.c from test.t1,mysqltest.t1;
select command denied to user: 'mysqltest_3@localhost' for column 'c' in table 't1'
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 6
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 7
show status like "Qcache_not_cached";
Variable_name Value
Qcache_not_cached 8
select "user4";
user4
user4
select a from t1;
No Database Selected
select * from mysqltest.t1,test.t1;
a b c a
1 1 1 test.t1
2 2 2 test.t1
select a from mysqltest.t1;
a
1
2
select a from mysqltest.t1;
a
1
2
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 8
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 8
show status like "Qcache_not_cached";
Variable_name Value
Qcache_not_cached 9
delete from mysql.user where user in ("mysqltest_1","mysqltest_2","mysqltest_3");
delete from mysql.db where user in ("mysqltest_1","mysqltest_2","mysqltest_3");
delete from mysql.tables_priv where user in ("mysqltest_1","mysqltest_2","mysqltest_3");
delete from mysql.columns_priv where user in ("mysqltest_1","mysqltest_2","mysqltest_3");
flush privileges;
drop table test.t1,mysqltest.t1,mysqltest.t2;
drop database mysqltest;
...@@ -848,16 +848,16 @@ id name value uid ...@@ -848,16 +848,16 @@ id name value uid
3 three three value 103 3 three three value 103
6 two other value 102 6 two other value 102
drop table t1; drop table t1;
create database test_$1; create database mysqltest;
create table test_$1.t1 (a int not null) type= innodb; create table mysqltest.t1 (a int not null) type= innodb;
insert into test_$1.t1 values(1); insert into mysqltest.t1 values(1);
create table test_$1.t2 (a int not null) type= myisam; create table mysqltest.t2 (a int not null) type= myisam;
insert into test_$1.t2 values(1); insert into mysqltest.t2 values(1);
create table test_$1.t3 (a int not null) type= heap; create table mysqltest.t3 (a int not null) type= heap;
insert into test_$1.t3 values(1); insert into mysqltest.t3 values(1);
commit; commit;
drop database test_$1; drop database mysqltest;
show tables from test_$1; show tables from mysqltest;
Got one of the listed errors Got one of the listed errors
create table t1 (a int not null) type= innodb; create table t1 (a int not null) type= innodb;
insert into t1 values(1),(2); insert into t1 values(1),(2);
......
...@@ -346,19 +346,19 @@ show status like "Qcache_queries_in_cache"; ...@@ -346,19 +346,19 @@ show status like "Qcache_queries_in_cache";
Variable_name Value Variable_name Value
Qcache_queries_in_cache 0 Qcache_queries_in_cache 0
drop table t1,t2; drop table t1,t2;
create database foo; create database mysqltest;
create table foo.t1 (i int not null auto_increment, a int, primary key (i)); create table mysqltest.t1 (i int not null auto_increment, a int, primary key (i));
insert into foo.t1 (a) values (1); insert into mysqltest.t1 (a) values (1);
select * from foo.t1 where i is null; select * from mysqltest.t1 where i is null;
i a i a
1 1 1 1
select * from foo.t1; select * from mysqltest.t1;
i a i a
1 1 1 1
show status like "Qcache_queries_in_cache"; show status like "Qcache_queries_in_cache";
Variable_name Value Variable_name Value
Qcache_queries_in_cache 1 Qcache_queries_in_cache 1
drop database foo; drop database mysqltest;
show status like "Qcache_queries_in_cache"; show status like "Qcache_queries_in_cache";
Variable_name Value Variable_name Value
Qcache_queries_in_cache 0 Qcache_queries_in_cache 0
......
...@@ -11,33 +11,33 @@ create table t1(n int); ...@@ -11,33 +11,33 @@ create table t1(n int);
drop table t1; drop table t1;
select * from t1; select * from t1;
#now test for a bug in drop database - it is important that the name # now test for a bug in drop database - it is important that the name
#of the table is the same as the name of the database - in the original # of the table is the same as the name of the database - in the original
#code this triggered a bug # code this triggered a bug
drop database if exists foo; drop database if exists mysqltest;
create database foo; create database mysqltest;
drop database if exists foo; drop database if exists mysqltest;
create database foo; create database mysqltest;
create table foo.foo (n int); create table mysqltest.mysqltest (n int);
insert into foo.foo values (4); insert into mysqltest.mysqltest values (4);
select * from foo.foo; select * from mysqltest.mysqltest;
drop database if exists foo; drop database if exists mysqltest;
create database foo; create database mysqltest;
drop database foo; drop database mysqltest;
# test drop/create database and FLUSH TABLES WITH READ LOCK # test drop/create database and FLUSH TABLES WITH READ LOCK
drop database if exists foo; drop database if exists mysqltest;
flush tables with read lock; flush tables with read lock;
--error 1209,1223; --error 1209,1223;
create database foo; create database mysqltest;
unlock tables; unlock tables;
create database foo; create database mysqltest;
show databases; show databases;
flush tables with read lock; flush tables with read lock;
--error 1208,1223; --error 1208,1223;
drop database foo; drop database mysqltest;
unlock tables; unlock tables;
drop database foo; drop database mysqltest;
show databases; show databases;
--error 1008 --error 1008
drop database foo; drop database mysqltest;
...@@ -44,15 +44,15 @@ reap; ...@@ -44,15 +44,15 @@ reap;
#test if drop database will wait until we release the global read lock #test if drop database will wait until we release the global read lock
connection con1; connection con1;
drop database if exists foo; drop database if exists mysqltest;
create database foo; create database mysqltest;
create table foo.t1(n int); create table mysqltest.t1(n int);
insert into foo.t1 values (23); insert into mysqltest.t1 values (23);
flush tables with read lock; flush tables with read lock;
connection con2; connection con2;
send drop database foo; send drop database mysqltest;
connection con1; connection con1;
select * from foo.t1; select * from mysqltest.t1;
unlock tables; unlock tables;
connection con2; connection con2;
reap; reap;
......
--set-variable=query_cache_size=1355776
#
# Test grants with query cache
#
drop table if exists test.t1,mysqltest.t1,mysqltest.t2;
reset query cache;
flush status;
connect (root,localhost,root,,test,0,master.sock);
connection root;
create database if not exists mysqltest;
create table mysqltest.t1 (a int,b int,c int);
create table mysqltest.t2 (a int,b int,c int);
insert into mysqltest.t1 values (1,1,1),(2,2,2);
insert into mysqltest.t2 values (3,3,3);
create table test.t1 (a char (10));
insert into test.t1 values ("test.t1");
select * from t1;
connect (root2,localhost,root,,mysqltest,0,master.sock);
connection root2;
# put queries in cache
select * from t1;
select a from t1;
select c from t1;
select * from t2;
select * from mysqltest.t1,test.t1;
show status like "Qcache_queries_in_cache";
show status like "Qcache_hits%";
# Create the test users
grant SELECT on mysqltest.* to mysqltest_1@localhost;
grant SELECT on mysqltest.t1 to mysqltest_2@localhost;
grant SELECT on test.t1 to mysqltest_2@localhost;
grant SELECT(a) on mysqltest.t1 to mysqltest_3@localhost;
# The following queries should be fetched from cache
connect (user1,localhost,mysqltest_1,,mysqltest,0,master.sock);
connection user1;
select "user1";
select * from t1;
# The pre and end space are intentional
select a from t1 ;
select c from t1;
show status like "Qcache_queries_in_cache";
show status like "Qcache_hits";
show status like "Qcache_not_cached";
# The following queries should be fetched from cache
connect (user2,localhost,mysqltest_2,,mysqltest,0,master.sock);
connection user2;
select "user2";
select * from t1;
select a from t1;
select c from t1;
select * from mysqltest.t1,test.t1;
--error 1142
select * from t2;
show status like "Qcache_queries_in_cache";
show status like "Qcache_hits";
show status like "Qcache_not_cached";
# The following queries should not be fetched from cache
connect (user3,localhost,mysqltest_3,,mysqltest,0,master.sock);
connection user3;
select "user3";
--error 1143
select * from t1;
select a from t1;
--error 1143
select c from t1;
--error 1142
select * from t2;
--error 1143
select mysqltest.t1.c from test.t1,mysqltest.t1;
show status like "Qcache_queries_in_cache";
show status like "Qcache_hits";
show status like "Qcache_not_cached";
# Connect without a database
connect (user4,localhost,mysqltest_1,,*NO-ONE*,0,master.sock);
connection user4;
select "user4";
--error 1046
select a from t1;
# The following query is not cached before (different database)
select * from mysqltest.t1,test.t1;
# Cache a query with 'no database'
select a from mysqltest.t1;
select a from mysqltest.t1;
show status like "Qcache_queries_in_cache";
show status like "Qcache_hits";
show status like "Qcache_not_cached";
# Cleanup
connection root;
delete from mysql.user where user in ("mysqltest_1","mysqltest_2","mysqltest_3");
delete from mysql.db where user in ("mysqltest_1","mysqltest_2","mysqltest_3");
delete from mysql.tables_priv where user in ("mysqltest_1","mysqltest_2","mysqltest_3");
delete from mysql.columns_priv where user in ("mysqltest_1","mysqltest_2","mysqltest_3");
flush privileges;
drop table test.t1,mysqltest.t1,mysqltest.t2;
drop database mysqltest;
...@@ -518,18 +518,18 @@ drop table t1; ...@@ -518,18 +518,18 @@ drop table t1;
# Test DROP DATABASE # Test DROP DATABASE
# #
create database test_$1; create database mysqltest;
create table test_$1.t1 (a int not null) type= innodb; create table mysqltest.t1 (a int not null) type= innodb;
insert into test_$1.t1 values(1); insert into mysqltest.t1 values(1);
create table test_$1.t2 (a int not null) type= myisam; create table mysqltest.t2 (a int not null) type= myisam;
insert into test_$1.t2 values(1); insert into mysqltest.t2 values(1);
create table test_$1.t3 (a int not null) type= heap; create table mysqltest.t3 (a int not null) type= heap;
insert into test_$1.t3 values(1); insert into mysqltest.t3 values(1);
commit; commit;
drop database test_$1; drop database mysqltest;
# Don't check error message # Don't check error message
--error 12,12 --error 12,12
show tables from test_$1; show tables from mysqltest;
# #
# Test truncate table # Test truncate table
......
...@@ -235,17 +235,17 @@ drop table t1,t2; ...@@ -235,17 +235,17 @@ drop table t1,t2;
# #
# noncachable ODBC work around (and prepare cache for drop database) # noncachable ODBC work around (and prepare cache for drop database)
# #
create database foo; create database mysqltest;
create table foo.t1 (i int not null auto_increment, a int, primary key (i)); create table mysqltest.t1 (i int not null auto_increment, a int, primary key (i));
insert into foo.t1 (a) values (1); insert into mysqltest.t1 (a) values (1);
select * from foo.t1 where i is null; select * from mysqltest.t1 where i is null;
# #
# drop db # drop db
# #
select * from foo.t1; select * from mysqltest.t1;
show status like "Qcache_queries_in_cache"; show status like "Qcache_queries_in_cache";
drop database foo; drop database mysqltest;
show status like "Qcache_queries_in_cache"; show status like "Qcache_queries_in_cache";
# #
......
...@@ -283,8 +283,9 @@ uint cached_tables(void); ...@@ -283,8 +283,9 @@ uint cached_tables(void);
void kill_mysql(void); void kill_mysql(void);
void close_connection(NET *net,uint errcode=0,bool lock=1); void close_connection(NET *net,uint errcode=0,bool lock=1);
bool check_access(THD *thd,uint access,const char *db=0,uint *save_priv=0, bool check_access(THD *thd,uint access,const char *db=0,uint *save_priv=0,
bool no_grant=0); bool no_grant=0, bool no_errors=0);
bool check_table_access(THD *thd,uint want_access, TABLE_LIST *tables); bool check_table_access(THD *thd,uint want_access, TABLE_LIST *tables,
bool no_errors=0);
bool check_process_priv(THD *thd=0); bool check_process_priv(THD *thd=0);
int mysql_backup_table(THD* thd, TABLE_LIST* table_list); int mysql_backup_table(THD* thd, TABLE_LIST* table_list);
......
...@@ -30,6 +30,7 @@ void send_error(NET *net, uint sql_errno, const char *err) ...@@ -30,6 +30,7 @@ void send_error(NET *net, uint sql_errno, const char *err)
err ? err : net->last_error[0] ? err ? err : net->last_error[0] ?
net->last_error : "NULL")); net->last_error : "NULL"));
query_cache_abort(net);
if (thd) if (thd)
thd->query_error = 1; // needed to catch query errors during replication thd->query_error = 1; // needed to catch query errors during replication
if (!err) if (!err)
...@@ -102,9 +103,9 @@ net_printf(NET *net, uint errcode, ...) ...@@ -102,9 +103,9 @@ net_printf(NET *net, uint errcode, ...)
DBUG_ENTER("net_printf"); DBUG_ENTER("net_printf");
DBUG_PRINT("enter",("message: %u",errcode)); DBUG_PRINT("enter",("message: %u",errcode));
if(thd) thd->query_error = 1; if (thd)
// if we are here, something is wrong :-) thd->query_error = 1; // if we are here, something is wrong :-)
query_cache_abort(net); // Safety
va_start(args,errcode); va_start(args,errcode);
format=ER(errcode); format=ER(errcode);
offset= net->return_errno ? 2 : 0; offset= net->return_errno ? 2 : 0;
......
...@@ -330,7 +330,8 @@ net_real_write(NET *net,const char *packet,ulong len) ...@@ -330,7 +330,8 @@ net_real_write(NET *net,const char *packet,ulong len)
DBUG_ENTER("net_real_write"); DBUG_ENTER("net_real_write");
#ifdef MYSQL_SERVER #ifdef MYSQL_SERVER
query_cache_insert(net, packet, len); if (net->query_cache_query != 0)
query_cache_insert(net, packet, len);
#endif #endif
if (net->error == 2) if (net->error == 2)
......
This diff is collapsed.
...@@ -354,7 +354,7 @@ class Query_cache ...@@ -354,7 +354,7 @@ class Query_cache
Check if the query is in the cache and if this is true send the Check if the query is in the cache and if this is true send the
data to client. data to client.
*/ */
my_bool send_result_to_client(THD *thd, char *query, uint query_length); int send_result_to_client(THD *thd, char *query, uint query_length);
/* Remove all queries that uses any of the listed following tables */ /* Remove all queries that uses any of the listed following tables */
void invalidate(TABLE_LIST *tables_used); void invalidate(TABLE_LIST *tables_used);
...@@ -375,7 +375,15 @@ class Query_cache ...@@ -375,7 +375,15 @@ class Query_cache
void destroy(); void destroy();
#ifndef DBUG_OFF friend void query_cache_insert(NET *net, const char *packet, ulong length);
friend void query_cache_end_of_result(NET *net);
friend void query_cache_abort(NET *net);
/*
The following functions are only used when debugging
We don't protect these with ifndef DEBUG_OFF to not have to recompile
everything if we want to add checks of the cache at some places.
*/
void wreck(uint line, const char *message); void wreck(uint line, const char *message);
void bins_dump(); void bins_dump();
void cache_dump(); void cache_dump();
...@@ -385,10 +393,6 @@ class Query_cache ...@@ -385,10 +393,6 @@ class Query_cache
my_bool in_list(Query_cache_block * root, Query_cache_block * point, my_bool in_list(Query_cache_block * root, Query_cache_block * point,
const char *name); const char *name);
my_bool in_blocks(Query_cache_block * point); my_bool in_blocks(Query_cache_block * point);
#endif
friend void query_cache_insert(NET *net, const char *packet, ulong length);
friend void query_cache_end_of_result(NET *net);
friend void query_cache_abort(NET *net);
}; };
extern Query_cache query_cache; extern Query_cache query_cache;
......
...@@ -22,7 +22,6 @@ ...@@ -22,7 +22,6 @@
int mysql_do(THD *thd, List<Item> &values) int mysql_do(THD *thd, List<Item> &values)
{ {
int error;
List_iterator<Item> li(values); List_iterator<Item> li(values);
Item *value; Item *value;
DBUG_ENTER("mysql_do"); DBUG_ENTER("mysql_do");
......
...@@ -842,7 +842,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, ...@@ -842,7 +842,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
{ {
char *pos=packet-1+packet_length; // Point at end null char *pos=packet-1+packet_length; // Point at end null
/* Remove garage at end of query */ /* Remove garage at end of query */
while (packet_length > 0 && pos[-1] == ';') while (packet_length > 0 && (pos[-1] == ';' || isspace(pos[-1])))
{ {
pos--; pos--;
packet_length--; packet_length--;
...@@ -2261,7 +2261,7 @@ mysql_execute_command(void) ...@@ -2261,7 +2261,7 @@ mysql_execute_command(void)
bool bool
check_access(THD *thd,uint want_access,const char *db, uint *save_priv, check_access(THD *thd,uint want_access,const char *db, uint *save_priv,
bool dont_check_global_grants) bool dont_check_global_grants, bool no_errors)
{ {
uint db_access,dummy; uint db_access,dummy;
if (save_priv) if (save_priv)
...@@ -2271,7 +2271,8 @@ check_access(THD *thd,uint want_access,const char *db, uint *save_priv, ...@@ -2271,7 +2271,8 @@ check_access(THD *thd,uint want_access,const char *db, uint *save_priv,
if ((!db || !db[0]) && !thd->db && !dont_check_global_grants) if ((!db || !db[0]) && !thd->db && !dont_check_global_grants)
{ {
send_error(&thd->net,ER_NO_DB_ERROR); /* purecov: tested */ if (!no_errors)
send_error(&thd->net,ER_NO_DB_ERROR); /* purecov: tested */
return TRUE; /* purecov: tested */ return TRUE; /* purecov: tested */
} }
...@@ -2283,10 +2284,11 @@ check_access(THD *thd,uint want_access,const char *db, uint *save_priv, ...@@ -2283,10 +2284,11 @@ check_access(THD *thd,uint want_access,const char *db, uint *save_priv,
if ((want_access & ~thd->master_access) & ~(DB_ACLS | EXTRA_ACL) || if ((want_access & ~thd->master_access) & ~(DB_ACLS | EXTRA_ACL) ||
! db && dont_check_global_grants) ! db && dont_check_global_grants)
{ // We can never grant this { // We can never grant this
net_printf(&thd->net,ER_ACCESS_DENIED_ERROR, if (!no_errors)
thd->priv_user, net_printf(&thd->net,ER_ACCESS_DENIED_ERROR,
thd->host_or_ip, thd->priv_user,
thd->password ? ER(ER_YES) : ER(ER_NO));/* purecov: tested */ thd->host_or_ip,
thd->password ? ER(ER_YES) : ER(ER_NO));/* purecov: tested */
return TRUE; /* purecov: tested */ return TRUE; /* purecov: tested */
} }
...@@ -2306,10 +2308,11 @@ check_access(THD *thd,uint want_access,const char *db, uint *save_priv, ...@@ -2306,10 +2308,11 @@ check_access(THD *thd,uint want_access,const char *db, uint *save_priv,
((grant_option && !dont_check_global_grants) && ((grant_option && !dont_check_global_grants) &&
!(want_access & ~TABLE_ACLS))) !(want_access & ~TABLE_ACLS)))
return FALSE; /* Ok */ return FALSE; /* Ok */
net_printf(&thd->net,ER_DBACCESS_DENIED_ERROR, if (!no_errors)
thd->priv_user, net_printf(&thd->net,ER_DBACCESS_DENIED_ERROR,
thd->host_or_ip, thd->priv_user,
db ? db : thd->db ? thd->db : "unknown"); /* purecov: tested */ thd->host_or_ip,
db ? db : thd->db ? thd->db : "unknown"); /* purecov: tested */
return TRUE; /* purecov: tested */ return TRUE; /* purecov: tested */
} }
...@@ -2326,7 +2329,8 @@ bool check_process_priv(THD *thd) ...@@ -2326,7 +2329,8 @@ bool check_process_priv(THD *thd)
*/ */
bool bool
check_table_access(THD *thd,uint want_access,TABLE_LIST *tables) check_table_access(THD *thd,uint want_access,TABLE_LIST *tables,
bool no_errors)
{ {
uint found=0,found_access=0; uint found=0,found_access=0;
TABLE_LIST *org_tables=tables; TABLE_LIST *org_tables=tables;
...@@ -2341,18 +2345,20 @@ check_table_access(THD *thd,uint want_access,TABLE_LIST *tables) ...@@ -2341,18 +2345,20 @@ check_table_access(THD *thd,uint want_access,TABLE_LIST *tables)
tables->grant.privilege=found_access; tables->grant.privilege=found_access;
else else
{ {
if (check_access(thd,want_access,tables->db,&tables->grant.privilege)) if (check_access(thd,want_access,tables->db,&tables->grant.privilege,
0, no_errors))
return TRUE; // Access denied return TRUE; // Access denied
found_access=tables->grant.privilege; found_access=tables->grant.privilege;
found=1; found=1;
} }
} }
else if (check_access(thd,want_access,tables->db,&tables->grant.privilege)) else if (check_access(thd,want_access,tables->db,&tables->grant.privilege,
0, no_errors))
return TRUE; // Access denied return TRUE; // Access denied
} }
if (grant_option) if (grant_option)
return check_grant(thd,want_access & ~EXTRA_ACL,org_tables, return check_grant(thd,want_access & ~EXTRA_ACL,org_tables,
test(want_access & EXTRA_ACL)); test(want_access & EXTRA_ACL), no_errors);
return FALSE; return FALSE;
} }
...@@ -2474,6 +2480,7 @@ mysql_init_query(THD *thd) ...@@ -2474,6 +2480,7 @@ mysql_init_query(THD *thd)
thd->fatal_error=0; // Safety thd->fatal_error=0; // Safety
thd->last_insert_id_used=thd->query_start_used=thd->insert_id_used=0; thd->last_insert_id_used=thd->query_start_used=thd->insert_id_used=0;
thd->sent_row_count=thd->examined_row_count=0; thd->sent_row_count=thd->examined_row_count=0;
thd->safe_to_cache_query=1;
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
...@@ -2522,9 +2529,8 @@ mysql_parse(THD *thd,char *inBuf,uint length) ...@@ -2522,9 +2529,8 @@ mysql_parse(THD *thd,char *inBuf,uint length)
mysql_init_query(thd); mysql_init_query(thd);
thd->query_length = length; thd->query_length = length;
if (query_cache.send_result_to_client(thd, inBuf, length)) if (query_cache.send_result_to_client(thd, inBuf, length) <= 0)
{ {
thd->safe_to_cache_query=1;
LEX *lex=lex_start(thd, (uchar*) inBuf, length); LEX *lex=lex_start(thd, (uchar*) inBuf, length);
if (!yyparse() && ! thd->fatal_error) if (!yyparse() && ! thd->fatal_error)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment