summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Docs/manual.texi46
-rw-r--r--include/hash.h1
-rw-r--r--include/myisam.h2
-rw-r--r--libmysql/net.c42
-rw-r--r--myisam/mi_write.c6
-rw-r--r--myisammrg/myrg_extra.c3
-rw-r--r--mysys/hash.c3
-rw-r--r--sql/field.cc235
-rw-r--r--sql/field.h140
-rw-r--r--sql/ha_myisam.cc4
-rw-r--r--sql/item.h4
-rw-r--r--sql/log_event.cc248
-rw-r--r--sql/log_event.h265
-rw-r--r--sql/mf_iocache.cc4
-rw-r--r--sql/mysql_priv.h2
-rw-r--r--sql/mysqld.cc12
-rw-r--r--sql/net_serv.cc36
-rw-r--r--sql/opt_range.h6
-rw-r--r--sql/sql_cache.cc2610
-rw-r--r--sql/sql_cache.h198
-rw-r--r--sql/sql_class.h83
-rw-r--r--sql/sql_insert.cc8
-rw-r--r--sql/sql_parse.cc110
-rw-r--r--sql/sql_select.cc43
-rw-r--r--sql/sql_select.h18
-rw-r--r--sql/sql_show.cc5
-rw-r--r--sql/sql_table.cc2
-rw-r--r--sql/table.cc3
28 files changed, 2197 insertions, 1942 deletions
diff --git a/Docs/manual.texi b/Docs/manual.texi
index 7b9479861b9..74520cd9586 100644
--- a/Docs/manual.texi
+++ b/Docs/manual.texi
@@ -18100,6 +18100,9 @@ differ somewhat:
| protocol_version | 10 |
| record_buffer | 131072 |
| query_buffer_size | 0 |
+| query_cache_limit | 1048576 |
+| query_cache_size | 16768060 |
+| query_cache_startup_type | 1 |
| safe_show_database | OFF |
| server_id | 0 |
| skip_locking | ON |
@@ -18497,6 +18500,18 @@ buffer to avoid a disk seeks. If not set, then it's set to the value of
The initial allocation of the query buffer. If most of your queries are
long (like when inserting blobs), you should increase this!
+@item @code{query_cache_limit}
+Don't cache results that are bigger than this. (Default 1M).
+
+@item @code{query_cache_size}
+The memory allocated to store results from old queries. If this is zero
+the query cache is disabled.
+
+@item @code{query_cache_startup_type}
+This may have be set to 0 (cache results but don't retrieve results from
+cache), 1 (cache results by defaults) or 2 (only cache @code{SELECT}'s marked
+with @code{SQL_CACHE}).
+
@item @code{safe_show_databases}
Don't show databases for which the user doesn't have any database or
table privileges. This can improve security if you're concerned about
@@ -25730,6 +25745,17 @@ flag again, the @code{SQL_MAX_JOIN_SIZE} variable will be ignored.
You can set a default value for this variable by starting @code{mysqld} with
@code{-O max_join_size=#}.
+@item SQL_QUERY_CACHE_TYPE = [OFF | ON | DEMAND]
+@item SQL_QUERY_CACHE_TYPE = [0 | 1 | 2]
+
+The numbers are standing for the correspoding verbose option.
+
+@multitable @columnfractions .3 .7
+@item 0 or OFF @tab Cache @code{SELECT} results, but don't retrieve results from cache.
+@item 1 or ON @tab Cache all @code{SELECT}'s that are not marked with @code{SQL_NO_CACHE}.
+@item 2 or DEMAND @tab Cache only @code{SELECT SQL_CACHE}) queries.
+@end multitable
+
@item SQL_SAFE_UPDATES = 0 | 1
If set to @code{1}, MySQL will abort if an @code{UPDATE} or
@code{DELETE} is attempted that doesn't use a key or @code{LIMIT} in the
@@ -31085,7 +31111,7 @@ mysql> SELECT id,FLOOR(value/100) FROM tbl_name ORDER BY RAND();
@c help SELECT
@example
SELECT [STRAIGHT_JOIN] [SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT]
- [HIGH_PRIORITY]
+ [SQL_CACHE | SQL_NO_CACHE] [HIGH_PRIORITY]
[DISTINCT | DISTINCTROW | ALL]
select_expression,...
[INTO @{OUTFILE | DUMPFILE@} 'file_name' export_options]
@@ -31213,9 +31239,8 @@ mysql> select user,max(salary) AS sum from users
@end example
@item
-@code{SQL_SMALL_RESULT}, @code{SQL_BIG_RESULT}, @code{SQL_BUFFER_RESULT},
-@code{STRAIGHT_JOIN}, and @code{HIGH_PRIORITY} are MySQL extensions
-to ANSI SQL92.
+All options beginning with @code{SQL_}, @code{STRAIGHT_JOIN}, and
+@code{HIGH_PRIORITY} are MySQL extensions to ANSI SQL.
@item
@code{HIGH_PRIORITY} will give the @code{SELECT} higher priority than
@@ -31244,6 +31269,14 @@ temporary tables to store the resulting table instead of using sorting. In
MySQL Version 3.23 this shouldn't normally be needed.
@item
+@code{SQL_CACHE} tells MySQL to store the query result in the query cache
+even if you are using @code{SQL_QUERY_CACHE_METHOD} 2 (= @code{DEMAND}).
+
+@item
+@code{SQL_NO_CACHE} tells MySL to not store the query result in the
+query cache.
+
+@item
@cindex @code{GROUP BY}, extensions to ANSI SQL
If you use @code{GROUP BY}, the output rows will be sorted according to the
@code{GROUP BY} as if you would have had an @code{ORDER BY} over all the fields
@@ -46164,6 +46197,11 @@ Our TODO section contains what we plan to have in 4.0. @xref{TODO MySQL 4.0}.
@itemize @bullet
@item
+A new query cache to cache results from identical @code{SELECT} queries.
+@item
+Fixed core dump bug on 64 bit machines when it got a wrong communication
+packet.
+@item
@code{MATCH ... AGAINST(... IN BOOLEAN MODE)} can now work
without @code{FULLTEXT} index.
@item
diff --git a/include/hash.h b/include/hash.h
index c98b0851645..b6ca7e354b9 100644
--- a/include/hash.h
+++ b/include/hash.h
@@ -54,6 +54,7 @@ gptr hash_next(HASH *info,const byte *key,uint length);
my_bool hash_insert(HASH *info,const byte *data);
my_bool hash_delete(HASH *hash,byte *record);
my_bool hash_update(HASH *hash,byte *record,byte *old_key,uint old_key_length);
+void hash_replace(HASH *hash, uint idx, byte *new_row);
my_bool hash_check(HASH *hash); /* Only in debug library */
#define hash_clear(H) bzero((char*) (H),sizeof(*(H)))
diff --git a/include/myisam.h b/include/myisam.h
index 352b87c82c2..99e21304108 100644
--- a/include/myisam.h
+++ b/include/myisam.h
@@ -192,7 +192,7 @@ typedef struct st_columndef /* column information */
} MI_COLUMNDEF;
/* invalidator function reference for Query Cache */
-typedef void (* invalidator_by_filename) (char * filename);
+typedef void (* invalidator_by_filename)(const char * filename);
extern my_string myisam_log_filename; /* Name of logfile */
extern uint myisam_block_size;
diff --git a/libmysql/net.c b/libmysql/net.c
index 5e002a0f63e..5a39b071b4f 100644
--- a/libmysql/net.c
+++ b/libmysql/net.c
@@ -94,6 +94,7 @@ inline int local_thr_alarm(my_bool *A,int B __attribute__((unused)),ALARM *C __a
#ifdef MYSQL_SERVER
extern ulong bytes_sent, bytes_received;
extern pthread_mutex_t LOCK_bytes_sent , LOCK_bytes_received;
+extern void query_cache_insert(NET *net, const char *packet, ulong length);
#else
#undef statistic_add
#define statistic_add(A,B,C)
@@ -108,7 +109,7 @@ static int net_write_buff(NET *net,const char *packet,ulong len);
int my_net_init(NET *net, Vio* vio)
{
- if (!(net->buff=(uchar*) my_malloc(net_buffer_length+
+ if (!(net->buff=(uchar*) my_malloc((uint32) net_buffer_length+
NET_HEADER_SIZE + COMP_HEADER_SIZE,
MYF(MY_WME))))
return 1;
@@ -125,6 +126,7 @@ int my_net_init(NET *net, Vio* vio)
net->compress=0; net->reading_or_writing=0;
net->where_b = net->remain_in_buf=0;
net->last_errno=0;
+ net->query_cache_query=0;
if (vio != 0) /* If real connection */
{
@@ -160,7 +162,7 @@ static my_bool net_realloc(NET *net, ulong length)
pkt_length = (length+IO_SIZE-1) & ~(IO_SIZE-1);
/* We must allocate some extra bytes for the end 0 and to be able to
read big compressed blocks */
- if (!(buff=(uchar*) my_realloc((char*) net->buff, pkt_length +
+ if (!(buff=(uchar*) my_realloc((char*) net->buff, (uint32) pkt_length +
NET_HEADER_SIZE + COMP_HEADER_SIZE,
MYF(MY_WME))))
{
@@ -187,7 +189,7 @@ void net_clear(NET *net)
if (!vio_is_blocking(net->vio)) /* Safety if SSL */
{
while ( (count = vio_read(net->vio, (char*) (net->buff),
- net->max_packet)) > 0)
+ (uint32) net->max_packet)) > 0)
DBUG_PRINT("info",("skipped %d bytes from file: %s",
count,vio_description(net->vio)));
if (is_blocking)
@@ -241,7 +243,7 @@ my_net_write(NET *net,const char *packet,ulong len)
{
const ulong z_size = MAX_THREE_BYTES;
int3store(buff, z_size);
- buff[3]= net->pkt_nr++;
+ buff[3]= (uchar) net->pkt_nr++;
if (net_write_buff(net, (char*) buff, NET_HEADER_SIZE) ||
net_write_buff(net, packet, z_size))
return 1;
@@ -250,7 +252,7 @@ my_net_write(NET *net,const char *packet,ulong len)
}
/* Write last packet */
int3store(buff,len);
- buff[3]= net->pkt_nr++;
+ buff[3]= (uchar) net->pkt_nr++;
if (net_write_buff(net,(char*) buff,NET_HEADER_SIZE))
return 1;
return net_write_buff(net,packet,len);
@@ -280,7 +282,7 @@ net_write_command(NET *net,uchar command,const char *packet,ulong len)
do
{
int3store(buff, MAX_THREE_BYTES);
- buff[3]= net->pkt_nr++;
+ buff[3]= (uchar) net->pkt_nr++;
if (net_write_buff(net,(char*) buff, header_size) ||
net_write_buff(net,packet,len))
return 1;
@@ -292,7 +294,7 @@ net_write_command(NET *net,uchar command,const char *packet,ulong len)
len=length; /* Data left to be written */
}
int3store(buff,length);
- buff[3]= net->pkt_nr++;
+ buff[3]= (uchar) net->pkt_nr++;
return test(net_write_buff(net,(char*) buff,header_size) ||
net_write_buff(net,packet,len) || net_flush(net));
}
@@ -341,6 +343,10 @@ net_real_write(NET *net,const char *packet,ulong len)
my_bool net_blocking = vio_is_blocking(net->vio);
DBUG_ENTER("net_real_write");
+#ifdef MYSQL_SERVER
+ query_cache_insert(net, packet, len);
+#endif
+
if (net->error == 2)
DBUG_RETURN(-1); /* socket can't be used */
@@ -351,8 +357,8 @@ net_real_write(NET *net,const char *packet,ulong len)
ulong complen;
uchar *b;
uint header_length=NET_HEADER_SIZE+COMP_HEADER_SIZE;
- if (!(b=(uchar*) my_malloc(len + NET_HEADER_SIZE + COMP_HEADER_SIZE,
- MYF(MY_WME))))
+ if (!(b=(uchar*) my_malloc((uint32) len + NET_HEADER_SIZE +
+ COMP_HEADER_SIZE, MYF(MY_WME))))
{
#ifdef MYSQL_SERVER
net->last_errno=ER_OUT_OF_RESOURCES;
@@ -389,7 +395,7 @@ net_real_write(NET *net,const char *packet,ulong len)
pos=(char*) packet; end=pos+len;
while (pos != end)
{
- if ((long) (length=vio_write(net->vio,pos,(ulong) (end-pos))) <= 0)
+ if ((long) (length=vio_write(net->vio,pos,(uint32) (end-pos))) <= 0)
{
my_bool interrupted = vio_should_retry(net->vio);
#if (!defined(__WIN__) && !defined(__EMX__) && !defined(OS2))
@@ -473,7 +479,7 @@ net_real_write(NET *net,const char *packet,ulong len)
big packet
*/
-static void my_net_skip_rest(NET *net, ulong remain, thr_alarm_t *alarmed)
+static void my_net_skip_rest(NET *net, uint32 remain, thr_alarm_t *alarmed)
{
ALARM alarm_buff;
uint retry_count=0;
@@ -496,7 +502,7 @@ static void my_net_skip_rest(NET *net, ulong remain, thr_alarm_t *alarmed)
}
return;
}
- remain -= length;
+ remain -= (uint32) length;
statistic_add(bytes_received,length,&LOCK_bytes_received);
}
}
@@ -521,8 +527,8 @@ my_real_read(NET *net, ulong *complen)
ALARM alarm_buff;
#endif
my_bool net_blocking=vio_is_blocking(net->vio);
- ulong remain= (net->compress ? NET_HEADER_SIZE+COMP_HEADER_SIZE :
- NET_HEADER_SIZE);
+ uint32 remain= (net->compress ? NET_HEADER_SIZE+COMP_HEADER_SIZE :
+ NET_HEADER_SIZE);
*complen = 0;
net->reading_or_writing=1;
@@ -599,7 +605,7 @@ my_real_read(NET *net, ulong *complen)
continue;
}
#endif
- DBUG_PRINT("error",("Couldn't read packet: remain: %d errno: %d length: %d alarmed: %d", remain,vio_errno(net->vio),length,alarmed));
+ DBUG_PRINT("error",("Couldn't read packet: remain: %lu errno: %d length: %ld alarmed: %d", remain,vio_errno(net->vio),length,alarmed));
len= packet_error;
net->error=2; /* Close socket */
#ifdef MYSQL_SERVER
@@ -608,7 +614,7 @@ my_real_read(NET *net, ulong *complen)
#endif
goto end;
}
- remain -= (ulong) length;
+ remain -= (uint32) length;
pos+= (ulong) length;
statistic_add(bytes_received,(ulong) length,&LOCK_bytes_received);
}
@@ -655,14 +661,14 @@ my_real_read(NET *net, ulong *complen)
{
#ifdef MYSQL_SERVER
if (i == 1)
- my_net_skip_rest(net, len, &alarmed);
+ my_net_skip_rest(net, (uint32) len, &alarmed);
#endif
len= packet_error; /* Return error */
goto end;
}
}
pos=net->buff + net->where_b;
- remain = len;
+ remain = (uint32) len;
}
}
diff --git a/myisam/mi_write.c b/myisam/mi_write.c
index 5c6db053829..1dd4820bc03 100644
--- a/myisam/mi_write.c
+++ b/myisam/mi_write.c
@@ -149,6 +149,12 @@ int mi_write(MI_INFO *info, byte *record)
info->lastpos=filepos;
myisam_log_record(MI_LOG_WRITE,info,record,filepos,0);
VOID(_mi_writeinfo(info, WRITEINFO_UPDATE_KEYFILE));
+ if (info->invalidator != 0)
+ {
+ DBUG_PRINT("info", ("invalidator... '%s' (update)", info->filename));
+ (*info->invalidator)(info->filename);
+ info->invalidator=0;
+ }
allow_break(); /* Allow SIGHUP & SIGINT */
DBUG_RETURN(0);
diff --git a/myisammrg/myrg_extra.c b/myisammrg/myrg_extra.c
index 912eeb1f9e6..5434d30a50e 100644
--- a/myisammrg/myrg_extra.c
+++ b/myisammrg/myrg_extra.c
@@ -50,9 +50,10 @@ int myrg_extra(MYRG_INFO *info,enum ha_extra_function function)
void myrg_extrafunc(MYRG_INFO *info, invalidator_by_filename inv)
{
MYRG_TABLE *file;
-
DBUG_ENTER("myrg_extrafunc");
+
for (file=info->open_tables ; file != info->end_table ; file++)
file->table->s->invalidator = inv;
+
DBUG_VOID_RETURN;
}
diff --git a/mysys/hash.c b/mysys/hash.c
index acb5a9b4310..7129b62ba89 100644
--- a/mysys/hash.c
+++ b/mysys/hash.c
@@ -583,7 +583,8 @@ byte *hash_element(HASH *hash,uint idx)
void hash_replace(HASH *hash, uint idx, byte *new_row)
{
- dynamic_element(&hash->array,idx,HASH_LINK*)->data=new_row;
+ if (idx != NO_RECORD) /* Safety */
+ dynamic_element(&hash->array,idx,HASH_LINK*)->data=new_row;
}
diff --git a/sql/field.cc b/sql/field.cc
index 2f98d2e0fe8..fc5feba8eb8 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -219,14 +219,15 @@ static bool test_if_real(const char *str,int length)
****************************************************************************/
Field::Field(char *ptr_arg,uint32 length_arg,uchar *null_ptr_arg,
- uint null_bit_arg,
+ uchar null_bit_arg,
utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg)
- :ptr(ptr_arg),null_ptr(null_ptr_arg),null_bit(null_bit_arg),
- table(table_arg),query_id(0),key_start(0),part_of_key(0),part_of_sortkey(0),
- table_name(table_arg ? table_arg->table_name : 0),
- field_name(field_name_arg), unireg_check(unireg_check_arg),
- field_length(length_arg)
+ :ptr(ptr_arg),null_ptr(null_ptr_arg),
+ table(table_arg),table_name(table_arg ? table_arg->table_name : 0),
+ field_name(field_name_arg),
+ query_id(0),key_start(0),part_of_key(0),part_of_sortkey(0),
+ unireg_check(unireg_check_arg),
+ field_length(length_arg),null_bit(null_bit_arg)
{
flags=null_ptr ? 0: NOT_NULL_FLAG;
}
@@ -242,8 +243,8 @@ void Field::copy_from_tmp(int row_offset)
memcpy(ptr,ptr+row_offset,pack_length());
if (null_ptr)
{
- *null_ptr= ((null_ptr[0] & (uchar) ~(uint) null_bit) |
- null_ptr[row_offset] & (uchar) null_bit);
+ *null_ptr= (uchar) ((null_ptr[0] & (uchar) ~(uint) null_bit) |
+ null_ptr[row_offset] & (uchar) null_bit);
}
}
@@ -1049,7 +1050,7 @@ void Field_short::sort_string(char *to,uint length __attribute__((unused)))
if (unsigned_flag)
to[0] = ptr[0];
else
- to[0] = ptr[0] ^ 128; /* Revers signbit */
+ to[0] = (char) (ptr[0] ^ 128); /* Revers signbit */
to[1] = ptr[1];
}
else
@@ -1058,7 +1059,7 @@ void Field_short::sort_string(char *to,uint length __attribute__((unused)))
if (unsigned_flag)
to[0] = ptr[1];
else
- to[0] = ptr[1] ^ 128; /* Revers signbit */
+ to[0] = (char) (ptr[1] ^ 128); /* Revers signbit */
to[1] = ptr[0];
}
}
@@ -1129,12 +1130,12 @@ void Field_medium::store(double nr)
}
else if (nr >= (double) (long) (1L << 24))
{
- ulong tmp=(ulong) (1L << 24)-1L;
+ uint32 tmp=(uint32) (1L << 24)-1L;
int3store(ptr,tmp);
current_thd->cuted_fields++;
}
else
- int3store(ptr,(ulong) nr);
+ int3store(ptr,(uint32) nr);
}
else
{
@@ -1171,7 +1172,7 @@ void Field_medium::store(longlong nr)
current_thd->cuted_fields++;
}
else
- int3store(ptr,(ulong) nr);
+ int3store(ptr,(uint32) nr);
}
else
{
@@ -1449,7 +1450,7 @@ int Field_long::cmp(const char *a_ptr, const char *b_ptr)
longget(b,b_ptr);
}
if (unsigned_flag)
- return ((ulong) a < (ulong) b) ? -1 : ((ulong) a > (ulong) b) ? 1 : 0;
+ return ((uint32) a < (uint32) b) ? -1 : ((uint32) a > (uint32) b) ? 1 : 0;
return (a < b) ? -1 : (a > b) ? 1 : 0;
}
@@ -1461,7 +1462,7 @@ void Field_long::sort_string(char *to,uint length __attribute__((unused)))
if (unsigned_flag)
to[0] = ptr[0];
else
- to[0] = ptr[0] ^ 128; /* Revers signbit */
+ to[0] = (char) (ptr[0] ^ 128); /* Revers signbit */
to[1] = ptr[1];
to[2] = ptr[2];
to[3] = ptr[3];
@@ -1472,7 +1473,7 @@ void Field_long::sort_string(char *to,uint length __attribute__((unused)))
if (unsigned_flag)
to[0] = ptr[3];
else
- to[0] = ptr[3] ^ 128; /* Revers signbit */
+ to[0] = (char) (ptr[3] ^ 128); /* Revers signbit */
to[1] = ptr[2];
to[2] = ptr[1];
to[3] = ptr[0];
@@ -1660,7 +1661,7 @@ void Field_longlong::sort_string(char *to,uint length __attribute__((unused)))
if (unsigned_flag)
to[0] = ptr[0];
else
- to[0] = ptr[0] ^ 128; /* Revers signbit */
+ to[0] = (char) (ptr[0] ^ 128); /* Revers signbit */
to[1] = ptr[1];
to[2] = ptr[2];
to[3] = ptr[3];
@@ -1675,7 +1676,7 @@ void Field_longlong::sort_string(char *to,uint length __attribute__((unused)))
if (unsigned_flag)
to[0] = ptr[7];
else
- to[0] = ptr[7] ^ 128; /* Revers signbit */
+ to[0] = (char) (ptr[7] ^ 128); /* Revers signbit */
to[1] = ptr[6];
to[2] = ptr[5];
to[3] = ptr[4];
@@ -1910,7 +1911,7 @@ void Field_float::sort_string(char *to,uint length __attribute__((unused)))
{ /* make complement */
uint i;
for (i=0 ; i < sizeof(nr); i++)
- tmp[i]=tmp[i] ^ (uchar) 255;
+ tmp[i]= (uchar) (tmp[i] ^ (uchar) 255);
}
else
{
@@ -2278,10 +2279,10 @@ void Field_timestamp::store(longlong nr)
{
part1=(long) (nr/LL(1000000));
part2=(long) (nr - (longlong) part1*LL(1000000));
- l_time.year= part1/10000L; part1%=10000L;
+ l_time.year= (int) (part1/10000L); part1%=10000L;
l_time.month= (int) part1 / 100;
- l_time.day= (int) part1 % 100;
- l_time.hour= part2/10000L; part2%=10000L;
+ l_time.day= (int) part1 % 100;
+ l_time.hour= (int) (part2/10000L); part2%=10000L;
l_time.minute=(int) part2 / 100;
l_time.second=(int) part2 % 100;
timestamp=my_gmt_sec(&l_time);
@@ -2295,7 +2296,7 @@ void Field_timestamp::store(longlong nr)
}
else
#endif
- longstore(ptr,(ulong)timestamp);
+ longstore(ptr,(uint32) timestamp);
}
@@ -2596,7 +2597,7 @@ void Field_time::store(longlong nr)
double Field_time::val_real(void)
{
- ulong j= (ulong) uint3korr(ptr);
+ uint32 j= (uint32) uint3korr(ptr);
return (double) j;
}
@@ -2632,19 +2633,19 @@ bool Field_time::get_time(TIME *ltime)
ltime->neg= 1;
tmp=-tmp;
}
- ltime->hour=tmp/10000;
+ ltime->hour= (int) (tmp/10000);
tmp-=ltime->hour*10000;
- ltime->minute= tmp/100;
- ltime->second= tmp % 100;
+ ltime->minute= (int) tmp/100;
+ ltime->second= (int) tmp % 100;
ltime->second_part=0;
return 0;
}
int Field_time::cmp(const char *a_ptr, const char *b_ptr)
{
- long a,b;
- a=(long) sint3korr(a_ptr);
- b=(long) sint3korr(b_ptr);
+ int32 a,b;
+ a=(int32) sint3korr(a_ptr);
+ b=(int32) sint3korr(b_ptr);
return (a < b) ? -1 : (a > b) ? 1 : 0;
}
@@ -2755,14 +2756,14 @@ void Field_year::sql_type(String &res) const
** Stored as a 4 byte unsigned int
****************************************************************************/
-void Field_date::store(const char *from,uint len)
+void Field_date::store(const char *from, uint len)
{
TIME l_time;
- ulong tmp;
+ uint32 tmp;
if (str_to_TIME(from,len,&l_time,1) == TIMESTAMP_NONE)
tmp=0;
else
- tmp=(ulong) l_time.year*10000L + (ulong) (l_time.month*100+l_time.day);
+ tmp=(uint32) l_time.year*10000L + (uint32) (l_time.month*100+l_time.day);
#ifdef WORDS_BIGENDIAN
if (table->db_low_byte_first)
{
@@ -2934,7 +2935,7 @@ void Field_newdate::store(double nr)
void Field_newdate::store(longlong nr)
{
- long tmp;
+ int32 tmp;
if (nr >= LL(100000000) && nr <= LL(99991231235959))
nr=nr/LL(1000000); // Timestamp to date
if (nr < 0L || nr > 99991231L)
@@ -2944,16 +2945,16 @@ void Field_newdate::store(longlong nr)
}
else
{
- tmp=(long) nr;
+ tmp=(int32) nr;
if (tmp)
{
if (tmp < YY_PART_YEAR*10000L) // Fix short dates
- tmp+=20000000L;
+ tmp+= (uint32) 20000000L;
else if (tmp < 999999L)
- tmp+=19000000L;
+ tmp+= (uint32) 19000000L;
}
- uint month=((tmp/100) % 100);
- uint day= tmp%100;
+ uint month= (uint) ((tmp/100) % 100);
+ uint day= (uint) (tmp%100);
if (month > 12 || day > 31)
{
tmp=0L; // Don't allow date to change
@@ -2962,7 +2963,7 @@ void Field_newdate::store(longlong nr)
else
tmp= day + month*32 + (tmp/10000)*16*32;
}
- int3store(ptr,tmp);
+ int3store(ptr,(int32) tmp);
}
void Field_newdate::store_time(TIME *ltime,timestamp_type type)
@@ -2987,7 +2988,7 @@ double Field_newdate::val_real(void)
longlong Field_newdate::val_int(void)
{
- ulong j=uint3korr(ptr);
+ ulong j= uint3korr(ptr);
j= (j % 32L)+(j / 32L % 16L)*100L + (j/(16L*32L))*10000L;
return (longlong) j;
}
@@ -2997,25 +2998,25 @@ String *Field_newdate::val_str(String *val_buffer,
{
val_buffer->alloc(field_length);
val_buffer->length(field_length);
- ulong tmp=(ulong) uint3korr(ptr);
+ uint32 tmp=(uint32) uint3korr(ptr);
int part;
char *pos=(char*) val_buffer->ptr()+10;
/* Open coded to get more speed */
- *pos--=0;
+ *pos--=0; // End NULL
part=(int) (tmp & 31);
- *pos--='0'+part%10;
- *pos--='0'+part/10;
- *pos--='-';
+ *pos--= (char) ('0'+part%10);
+ *pos--= (char) ('0'+part/10);
+ *pos--= '-';
part=(int) (tmp >> 5 & 15);
- *pos--='0'+part%10;
- *pos--='0'+part/10;
- *pos--='-';
+ *pos--= (char) ('0'+part%10);
+ *pos--= (char) ('0'+part/10);
+ *pos--= '-';
part=(int) (tmp >> 9);
- *pos--='0'+part%10; part/=10;
- *pos--='0'+part%10; part/=10;
- *pos--='0'+part%10; part/=10;
- *pos='0'+part;
+ *pos--= (char) ('0'+part%10); part/=10;
+ *pos--= (char) ('0'+part%10); part/=10;
+ *pos--= (char) ('0'+part%10); part/=10;
+ *pos= (char) ('0'+part);
return val_buffer;
}
@@ -3023,7 +3024,7 @@ bool Field_newdate::get_date(TIME *ltime,bool fuzzydate)
{
if (is_null())
return 1;
- ulong tmp=(ulong) uint3korr(ptr);
+ uint32 tmp=(uint32) uint3korr(ptr);
bzero((char*) ltime,sizeof(*ltime));
ltime->day= tmp & 31;
ltime->month= (tmp >> 5) & 15;
@@ -3039,9 +3040,9 @@ bool Field_newdate::get_time(TIME *ltime)
int Field_newdate::cmp(const char *a_ptr, const char *b_ptr)
{
- ulong a,b;
- a=(ulong) uint3korr(a_ptr);
- b=(ulong) uint3korr(b_ptr);
+ uint32 a,b;
+ a=(uint32) uint3korr(a_ptr);
+ b=(uint32) uint3korr(b_ptr);
return (a < b) ? -1 : (a > b) ? 1 : 0;
}
@@ -3175,44 +3176,44 @@ String *Field_datetime::val_str(String *val_buffer,
pos=(char*) val_buffer->ptr()+19;
*pos--=0;
- *pos--='0'+(char) (part2%10); part2/=10;
- *pos--='0'+(char) (part2%10); part3= (int) (part2 / 10);
- *pos--=':';
- *pos--='0'+(char) (part3%10); part3/=10;
- *pos--='0'+(char) (part3%10); part3/=10;
- *pos--=':';
- *pos--='0'+(char) (part3%10); part3/=10;
- *pos--='0'+(char) part3;
- *pos--=' ';
- *pos--='0'+(char) (part1%10); part1/=10;
- *pos--='0'+(char) (part1%10); part1/=10;
- *pos--='-';
- *pos--='0'+(char) (part1%10); part1/=10;
- *pos--='0'+(char) (part1%10); part3= (int) (part1/10);
- *pos--='-';
- *pos--='0'+(char) (part3%10); part3/=10;
- *pos--='0'+(char) (part3%10); part3/=10;
- *pos--='0'+(char) (part3%10); part3/=10;
- *pos='0'+(char) part3;
+ *pos--= (char) ('0'+(char) (part2%10)); part2/=10;
+ *pos--= (char) ('0'+(char) (part2%10)); part3= (int) (part2 / 10);
+ *pos--= ':';
+ *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
+ *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
+ *pos--= ':';
+ *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
+ *pos--= (char) ('0'+(char) part3);
+ *pos--= ' ';
+ *pos--= (char) ('0'+(char) (part1%10)); part1/=10;
+ *pos--= (char) ('0'+(char) (part1%10)); part1/=10;
+ *pos--= '-';
+ *pos--= (char) ('0'+(char) (part1%10)); part1/=10;
+ *pos--= (char) ('0'+(char) (part1%10)); part3= (int) (part1/10);
+ *pos--= '-';
+ *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
+ *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
+ *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
+ *pos=(char) ('0'+(char) part3);
return val_buffer;
}
bool Field_datetime::get_date(TIME *ltime,bool fuzzydate)
{
longlong tmp=Field_datetime::val_int();
- long part1,part2;
- part1=(long) (tmp/LL(1000000));
- part2=(long) (tmp - (ulonglong) part1*LL(1000000));
+ uint32 part1,part2;
+ part1=(uint32) (tmp/LL(1000000));
+ part2=(uint32) (tmp - (ulonglong) part1*LL(1000000));
ltime->time_type= TIMESTAMP_FULL;
- ltime->neg=0;
- ltime->second_part=0;
- ltime->second= part2%100;
- ltime->minute= part2/100%100;
- ltime->hour= part2/10000;
- ltime->day= part1%100;
- ltime->month= part1/100%100;
- ltime->year= part1/10000;
+ ltime->neg= 0;
+ ltime->second_part= 0;
+ ltime->second= (int) (part2%100);
+ ltime->minute= (int) (part2/100%100);
+ ltime->hour= (int) (part2/10000);
+ ltime->day= (int) (part1%100);
+ ltime->month= (int) (part1/100%100);
+ ltime->year= (int) (part1/10000);
return (!fuzzydate && (!ltime->month || !ltime->day)) ? 1 : 0;
}
@@ -3331,7 +3332,7 @@ void Field_string::store(longlong nr)
{
char buff[22];
char *end=longlong10_to_str(nr,buff,-10);
- Field_string::store(buff,end-buff);
+ Field_string::store(buff,(uint) (end-buff));
}
@@ -3522,7 +3523,7 @@ void Field_varstring::store(longlong nr)
{
char buff[22];
char *end=longlong10_to_str(nr,buff,-10);
- Field_varstring::store(buff,end-buff);
+ Field_varstring::store(buff,(uint) (end-buff));
}
@@ -3613,9 +3614,9 @@ char *Field_varstring::pack(char *to, const char *from, uint max_length)
uint length=uint2korr(from);
if (length > max_length)
length=max_length;
- *to++= (length & 255);
+ *to++= (char) (length & 255);
if (max_length > 255)
- *to++= (uchar) (length >> 8);
+ *to++= (char) (length >> 8);
if (length)
memcpy(to, from+2, length);
return to+length;
@@ -3704,7 +3705,7 @@ uint Field_varstring::max_packed_col_length(uint max_length)
** packlength slot and may be from 1-4.
****************************************************************************/
-Field_blob::Field_blob(char *ptr_arg, uchar *null_ptr_arg, uint null_bit_arg,
+Field_blob::Field_blob(char *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg,uint blob_pack_length,
bool binary_arg)
@@ -3721,7 +3722,7 @@ Field_blob::Field_blob(char *ptr_arg, uchar *null_ptr_arg, uint null_bit_arg,
}
-void Field_blob::store_length(ulong number)
+void Field_blob::store_length(uint32 number)
{
switch (packlength) {
case 1:
@@ -3748,9 +3749,9 @@ void Field_blob::store_length(ulong number)
shortstore(ptr,(unsigned short) number);
break;
case 3:
- if (number > (ulong) (1L << 24))
+ if (number > (uint32) (1L << 24))
{
- number= (ulong) (1L << 24)-1L;
+ number= (uint32) (1L << 24)-1L;
current_thd->cuted_fields++;
}
int3store(ptr,number);
@@ -3768,11 +3769,11 @@ void Field_blob::store_length(ulong number)
}
-ulong Field_blob::get_length(const char *pos)
+uint32 Field_blob::get_length(const char *pos)
{
switch (packlength) {
case 1:
- return (ulong) (uchar) pos[0];
+ return (uint32) (uchar) pos[0];
case 2:
{
uint16 tmp;
@@ -3782,10 +3783,10 @@ ulong Field_blob::get_length(const char *pos)
else
#endif
shortget(tmp,pos);
- return (ulong) tmp;
+ return (uint32) tmp;
}
case 3:
- return (ulong) uint3korr(pos);
+ return (uint32) uint3korr(pos);
case 4:
{
uint32 tmp;
@@ -3795,7 +3796,7 @@ ulong Field_blob::get_length(const char *pos)
else
#endif
longget(tmp,pos);
- return (ulong) tmp;
+ return (uint32) tmp;
}
}
return 0; // Impossible
@@ -3841,14 +3842,14 @@ void Field_blob::store(const char *from,uint len)
void Field_blob::store(double nr)
{
value.set(nr);
- Field_blob::store(value.ptr(),value.length());
+ Field_blob::store(value.ptr(),(uint) value.length());
}
void Field_blob::store(longlong nr)
{
value.set(nr);
- Field_blob::store(value.ptr(),value.length());
+ Field_blob::store(value.ptr(), (uint) value.length());
}
@@ -3859,7 +3860,7 @@ double Field_blob::val_real(void)
memcpy_fixed(&blob,ptr+packlength,sizeof(char*));
if (!blob)
return 0.0;
- ulong length=get_length(ptr);
+ uint32 length=get_length(ptr);
char save=blob[length]; // Ok to patch blob in NISAM
blob[length]=0;
@@ -3875,7 +3876,7 @@ longlong Field_blob::val_int(void)
memcpy_fixed(&blob,ptr+packlength,sizeof(char*));
if (!blob)
return 0;
- ulong length=get_length(ptr);
+ uint32 length=get_length(ptr);
char save=blob[length]; // Ok to patch blob in NISAM
blob[length]=0;
@@ -3898,8 +3899,8 @@ String *Field_blob::val_str(String *val_buffer __attribute__((unused)),
}
-int Field_blob::cmp(const char *a,ulong a_length, const char *b,
- ulong b_length)
+int Field_blob::cmp(const char *a,uint32 a_length, const char *b,
+ uint32 b_length)
{
int diff;
if (binary_flag)
@@ -3933,11 +3934,11 @@ int Field_blob::cmp_binary_offset(uint row_offset)
int Field_blob::cmp_binary(const char *a_ptr, const char *b_ptr,
- ulong max_length)
+ uint32 max_length)
{
char *a,*b;
uint diff;
- ulong a_length,b_length;
+ uint32 a_length,b_length;
memcpy_fixed(&a,a_ptr+packlength,sizeof(char*));
memcpy_fixed(&b,b_ptr+packlength,sizeof(char*));
a_length=get_length(a_ptr);
@@ -3956,9 +3957,9 @@ int Field_blob::cmp_binary(const char *a_ptr, const char *b_ptr,
void Field_blob::get_key_image(char *buff,uint length)
{
length-=HA_KEY_BLOB_LENGTH;
- ulong blob_length=get_length(ptr);
+ uint32 blob_length=get_length(ptr);
char *blob;
- if ((ulong) length > blob_length)
+ if ((uint32) length > blob_length)
{
#ifdef HAVE_purify
bzero(buff+2+blob_length, (length-blob_length));
@@ -4052,7 +4053,7 @@ char *Field_blob::pack(char *to, const char *from, uint max_length)
{
char *save=ptr;
ptr=(char*) from;
- ulong length=get_length(); // Length of from string
+ uint32 length=get_length(); // Length of from string
if (length > max_length)
{
ptr=to;
@@ -4075,7 +4076,7 @@ char *Field_blob::pack(char *to, const char *from, uint max_length)
const char *Field_blob::unpack(char *to, const char *from)
{
memcpy(to,from,packlength);
- ulong length=get_length(from);
+ uint32 length=get_length(from);
from+=packlength;
if (length)
memcpy_fixed(to+packlength, &from, sizeof(from));
@@ -4140,7 +4141,7 @@ char *Field_blob::pack_key(char *to, const char *from, uint max_length)
{
char *save=ptr;
ptr=(char*) from;
- ulong length=get_length(); // Length of from string
+ uint32 length=get_length(); // Length of from string
if (length > max_length)
length=max_length;
*to++= (uchar) length;
@@ -4163,9 +4164,9 @@ char *Field_blob::pack_key_from_key_image(char *to, const char *from,
uint length=uint2korr(from);
if (length > max_length)
length=max_length;
- *to++= (length & 255);
+ *to++= (char) (length & 255);
if (max_length > 255)
- *to++= (uchar) (length >> 8);
+ *to++= (char) (length >> 8);
if (length)
memcpy(to, from+2, length);
return to+length;
@@ -4278,7 +4279,7 @@ void Field_enum::store(const char *from,uint length)
conv=buff;
}
my_errno=0;
- tmp=strtoul(conv,&end,10);
+ tmp=(uint) strtoul(conv,&end,10);
if (my_errno || end != conv+length || tmp > typelib->count)
{
tmp=0;
@@ -4624,7 +4625,7 @@ uint pack_length_to_packflag(uint type)
Field *make_field(char *ptr, uint32 field_length,
- uchar *null_pos, uint null_bit,
+ uchar *null_pos, uchar null_bit,
uint pack_flag,
Field::utype unireg_check,
TYPELIB *interval,
diff --git a/sql/field.h b/sql/field.h
index e2af9853512..03fd6d46a78 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -16,8 +16,8 @@
/*
-** Because of the function new_field all field classes that have static
-** variables must declare the size_of() member function.
+ Because of the function new_field() all field classes that have static
+ variables must declare the size_of() member function.
*/
#ifdef __GNUC__
@@ -37,21 +37,22 @@ public:
static void *operator new(size_t size) {return (void*) sql_alloc((uint) size); }
static void operator delete(void *ptr_arg, size_t size) {} /*lint -e715 */
- enum utype { NONE,DATE,SHIELD,NOEMPTY,CASEUP,PNR,BGNR,PGNR,YES,NO,REL,
- CHECK,EMPTY,UNKNOWN_FIELD,CASEDN,NEXT_NUMBER,INTERVAL_FIELD,
- BIT_FIELD, TIMESTAMP_FIELD,CAPITALIZE,BLOB_FIELD};
- char *ptr; // Position to field in record
+ char *ptr; // Position to field in record
uchar *null_ptr; // Byte where null_bit is
- uint8 null_bit; // And position to it
struct st_table *table; // Pointer for table
- ulong query_id; // For quick test of used fields
- key_map key_start,part_of_key,part_of_sortkey;// Field is part of these keys.
- const char *table_name,*field_name;
- utype unireg_check;
- uint32 field_length; // Length of field
- uint16 flags;
-
- Field(char *ptr_arg,uint32 length_arg,uchar *null_ptr_arg,uint null_bit_arg,
+ const char *table_name,*field_name;
+ ulong query_id; // For quick test of used fields
+ // Field is part of the following keys
+ key_map key_start,part_of_key,part_of_sortkey;
+ enum utype { NONE,DATE,SHIELD,NOEMPTY,CASEUP,PNR,BGNR,PGNR,YES,NO,REL,
+ CHECK,EMPTY,UNKNOWN_FIELD,CASEDN,NEXT_NUMBER,INTERVAL_FIELD,
+ BIT_FIELD, TIMESTAMP_FIELD,CAPITALIZE,BLOB_FIELD};
+ utype unireg_check;
+ uint32 field_length; // Length of field
+ uint16 flags;
+ uchar null_bit; // Bit used to test null bit
+
+ Field(char *ptr_arg,uint32 length_arg,uchar *null_ptr_arg,uchar null_bit_arg,
utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg);
virtual ~Field() {}
@@ -77,7 +78,7 @@ public:
virtual enum_field_types real_type() const { return type(); }
inline int cmp(const char *str) { return cmp(ptr,str); }
virtual int cmp(const char *,const char *)=0;
- virtual int cmp_binary(const char *a,const char *b, ulong max_length=~0L)
+ virtual int cmp_binary(const char *a,const char *b, uint32 max_length=~0L)
{ return memcmp(a,b,pack_length()); }
virtual int cmp_offset(uint row_offset)
{ return memcmp(ptr,ptr+row_offset,pack_length()); }
@@ -101,30 +102,30 @@ public:
inline void set_null(int row_offset=0)
{ if (null_ptr) null_ptr[row_offset]|= null_bit; }
inline void set_notnull(int row_offset=0)
- { if (null_ptr) null_ptr[row_offset]&= ~null_bit; }
+ { if (null_ptr) null_ptr[row_offset]&= (uchar) ~null_bit; }
inline bool maybe_null(void) { return null_ptr != 0 || table->maybe_null; }
inline bool real_maybe_null(void) { return null_ptr != 0; }
virtual void make_field(Send_field *)=0;
virtual void sort_string(char *buff,uint length)=0;
virtual bool optimize_range();
virtual bool store_for_compare() { return 0; }
- inline Field *new_field(struct st_table *new_table)
- {
- Field *tmp= (Field*) sql_memdup((char*) this,size_of());
- if (tmp)
- {
- tmp->table=new_table;
- tmp->key_start=tmp->part_of_key=tmp->part_of_sortkey=0;
- tmp->unireg_check=Field::NONE;
- tmp->flags&= (NOT_NULL_FLAG | BLOB_FLAG | UNSIGNED_FLAG | ZEROFILL_FLAG | BINARY_FLAG | ENUM_FLAG | SET_FLAG);
- tmp->reset_fields();
- }
- return tmp;
- }
- inline void move_field(char *ptr_arg,uchar *null_ptr_arg,uint null_bit_arg)
+ Field *new_field(MEM_ROOT *root, struct st_table *new_table)
+ {
+ Field *tmp= (Field*) memdup_root(root,(char*) this,size_of());
+ if (tmp)
{
- ptr=ptr_arg; null_ptr=null_ptr_arg; null_bit=null_bit_arg;
+ tmp->table=new_table;
+ tmp->key_start=tmp->part_of_key=tmp->part_of_sortkey=0;
+ tmp->unireg_check=Field::NONE;
+ tmp->flags&= (NOT_NULL_FLAG | BLOB_FLAG | UNSIGNED_FLAG | ZEROFILL_FLAG | BINARY_FLAG | ENUM_FLAG | SET_FLAG);
+ tmp->reset_fields();
}
+ return tmp;
+ }
+ inline void move_field(char *ptr_arg,uchar *null_ptr_arg,uchar null_bit_arg)
+ {
+ ptr=ptr_arg; null_ptr=null_ptr_arg; null_bit=null_bit_arg;
+ }
inline void move_field(char *ptr_arg) { ptr=ptr_arg; }
inline void move_field(my_ptrdiff_t ptr_diff)
{
@@ -157,7 +158,7 @@ public:
bool send(THD *thd, String *packet);
virtual char *pack(char* to, const char *from, uint max_length=~(uint) 0)
{
- uint length=pack_length();
+ uint32 length=pack_length();
memcpy(to,from,length);
return to+length;
}
@@ -212,10 +213,10 @@ public:
const uint8 dec;
bool zerofill,unsigned_flag; // Purify cannot handle bit fields
Field_num(char *ptr_arg,uint32 len_arg, uchar *null_ptr_arg,
- uint null_bit_arg, utype unireg_check_arg,
+ uchar null_bit_arg, utype unireg_check_arg,
const char *field_name_arg,
struct st_table *table_arg,
- uint dec_arg,bool zero_arg,bool unsigned_arg)
+ uint8 dec_arg,bool zero_arg,bool unsigned_arg)
:Field(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg, table_arg),
dec(dec_arg),zerofill(zero_arg),unsigned_flag(unsigned_arg)
@@ -230,7 +231,7 @@ public:
void add_zerofill_and_unsigned(String &res) const;
friend class create_field;
void make_field(Send_field *);
- uint decimals() const { return dec; }
+ uint decimals() const { return (uint) dec; }
uint size_of() const { return sizeof(*this); }
bool eq_def(Field *field);
};
@@ -239,7 +240,7 @@ public:
class Field_str :public Field {
public:
Field_str(char *ptr_arg,uint32 len_arg, uchar *null_ptr_arg,
- uint null_bit_arg, utype unireg_check_arg,
+ uchar null_bit_arg, utype unireg_check_arg,
const char *field_name_arg,
struct st_table *table_arg)
:Field(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
@@ -256,10 +257,10 @@ public:
class Field_decimal :public Field_num {
public:
Field_decimal(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
- uint null_bit_arg,
+ uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg,
- uint dec_arg,bool zero_arg,bool unsigned_arg)
+ uint8 dec_arg,bool zero_arg,bool unsigned_arg)
:Field_num(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg, table_arg,
dec_arg, zero_arg,unsigned_arg)
@@ -285,7 +286,7 @@ public:
class Field_tiny :public Field_num {
public:
Field_tiny(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
- uint null_bit_arg,
+ uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg,
bool zero_arg, bool unsigned_arg)
@@ -314,7 +315,7 @@ public:
class Field_short :public Field_num {
public:
Field_short(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
- uint null_bit_arg,
+ uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg,
bool zero_arg, bool unsigned_arg)
@@ -343,7 +344,7 @@ public:
class Field_medium :public Field_num {
public:
Field_medium(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
- uint null_bit_arg,
+ uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg,
bool zero_arg, bool unsigned_arg)
@@ -372,7 +373,7 @@ public:
class Field_long :public Field_num {
public:
Field_long(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
- uint null_bit_arg,
+ uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg,
bool zero_arg, bool unsigned_arg)
@@ -407,7 +408,7 @@ public:
class Field_longlong :public Field_num {
public:
Field_longlong(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
- uint null_bit_arg,
+ uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg,
bool zero_arg, bool unsigned_arg)
@@ -442,10 +443,10 @@ public:
class Field_float :public Field_num {
public:
Field_float(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
- uint null_bit_arg,
+ uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg,
- uint dec_arg,bool zero_arg,bool unsigned_arg)
+ uint8 dec_arg,bool zero_arg,bool unsigned_arg)
:Field_num(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg, table_arg,
dec_arg, zero_arg,unsigned_arg)
@@ -469,16 +470,16 @@ public:
class Field_double :public Field_num {
public:
Field_double(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
- uint null_bit_arg,
+ uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg,
- uint dec_arg,bool zero_arg,bool unsigned_arg)
+ uint8 dec_arg,bool zero_arg,bool unsigned_arg)
:Field_num(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg, table_arg,
dec_arg, zero_arg,unsigned_arg)
{}
Field_double(uint32 len_arg, bool maybe_null_arg, const char *field_name_arg,
- struct st_table *table_arg, uint dec_arg)
+ struct st_table *table_arg, uint8 dec_arg)
:Field_num((char*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0, (uint) 0,
NONE, field_name_arg, table_arg,dec_arg,0,0)
{}
@@ -567,7 +568,7 @@ public:
class Field_year :public Field_tiny {
public:
Field_year(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
- uint null_bit_arg,
+ uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg)
:Field_tiny(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
@@ -586,7 +587,7 @@ public:
class Field_date :public Field_str {
public:
- Field_date(char *ptr_arg, uchar *null_ptr_arg, uint null_bit_arg,
+ Field_date(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)
:Field_str(ptr_arg, 10, null_ptr_arg, null_bit_arg,
@@ -612,7 +613,7 @@ public:
class Field_newdate :public Field_str {
public:
- Field_newdate(char *ptr_arg, uchar *null_ptr_arg, uint null_bit_arg,
+ Field_newdate(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)
:Field_str(ptr_arg, 10, null_ptr_arg, null_bit_arg,
@@ -643,7 +644,7 @@ public:
class Field_time :public Field_str {
public:
- Field_time(char *ptr_arg, uchar *null_ptr_arg, uint null_bit_arg,
+ Field_time(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)
:Field_str(ptr_arg, 8, null_ptr_arg, null_bit_arg,
@@ -671,7 +672,7 @@ public:
class Field_datetime :public Field_str {
public:
- Field_datetime(char *ptr_arg, uchar *null_ptr_arg, uint null_bit_arg,
+ Field_datetime(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)
:Field_str(ptr_arg, 19, null_ptr_arg, null_bit_arg,
@@ -705,7 +706,7 @@ class Field_string :public Field_str {
bool binary_flag;
public:
Field_string(char *ptr_arg, uint32 len_arg,uchar *null_ptr_arg,
- uint null_bit_arg,
+ uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg,bool binary_arg)
:Field_str(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
@@ -760,7 +761,7 @@ class Field_varstring :public Field_str {
bool binary_flag;
public:
Field_varstring(char *ptr_arg, uint32 len_arg,uchar *null_ptr_arg,
- uint null_bit_arg,
+ uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg,bool binary_arg)
:Field_str(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
@@ -813,7 +814,7 @@ class Field_blob :public Field_str {
String value; // For temporaries
bool binary_flag;
public:
- Field_blob(char *ptr_arg, uchar *null_ptr_arg, uint null_bit_arg,
+ Field_blob(char *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg,uint blob_pack_length,
bool binary_arg);
@@ -837,21 +838,22 @@ public:
longlong val_int(void);
String *val_str(String*,String *);
int cmp(const char *,const char*);
- int cmp(const char *a, ulong a_length, const char *b, ulong b_length);
+ int cmp(const char *a, uint32 a_length, const char *b, uint32 b_length);
int cmp_offset(uint offset);
- int cmp_binary(const char *a,const char *b, ulong max_length=~0L);
+ int cmp_binary(const char *a,const char *b, uint32 max_length=~0L);
int cmp_binary_offset(uint row_offset);
int key_cmp(const byte *,const byte*);
int key_cmp(const byte *str, uint length);
uint32 key_length() const { return 0; }
void sort_string(char *buff,uint length);
- uint32 pack_length() const { return (uint32) (packlength+table->blob_ptr_size); }
- void reset(void) { bzero(ptr,packlength+sizeof(char*)); }
+ uint32 pack_length() const
+ { return (uint32) (packlength+table->blob_ptr_size); }
+ void reset(void) { bzero(ptr, packlength+sizeof(char*)); }
void reset_fields() { bzero((char*) &value,sizeof(value)); }
- void store_length(ulong number);
- inline ulong get_length(uint row_offset=0)
+ void store_length(uint32 number);
+ inline uint32 get_length(uint row_offset=0)
{ return get_length(ptr+row_offset); }
- ulong get_length(const char *ptr);
+ uint32 get_length(const char *ptr);
bool binary() const { return binary_flag; }
inline void get_ptr(char **str)
{
@@ -862,7 +864,7 @@ public:
memcpy(ptr,length,packlength);
memcpy_fixed(ptr+packlength,&data,sizeof(char*));
}
- inline void set_ptr(ulong length,char *data)
+ inline void set_ptr(uint32 length,char *data)
{
store_length(length);
memcpy_fixed(ptr+packlength,&data,sizeof(char*));
@@ -902,7 +904,7 @@ protected:
public:
TYPELIB *typelib;
Field_enum(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
- uint null_bit_arg,
+ uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg,uint packlength_arg,
TYPELIB *typelib_arg)
@@ -939,7 +941,7 @@ public:
class Field_set :public Field_enum {
public:
Field_set(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
- uint null_bit_arg,
+ uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg,uint32 packlength_arg,
TYPELIB *typelib_arg)
@@ -1022,7 +1024,7 @@ public:
Field *make_field(char *ptr, uint32 field_length,
- uchar *null_pos, uint null_bit,
+ uchar *null_pos, uchar null_bit,
uint pack_flag, Field::utype unireg_check,
TYPELIB *interval, const char *field_name,
struct st_table *table);
@@ -1065,7 +1067,7 @@ bool test_if_int(const char *str,int length);
#define f_is_zerofill(x) ((x) & FIELDFLAG_ZEROFILL)
#define f_is_packed(x) ((x) & FIELDFLAG_PACK)
#define f_packtype(x) (((x) >> FIELDFLAG_PACK_SHIFT) & 15)
-#define f_decimals(x) (((x) >> FIELDFLAG_DEC_SHIFT) & FIELDFLAG_MAX_DEC)
+#define f_decimals(x) ((uint8) (((x) >> FIELDFLAG_DEC_SHIFT) & FIELDFLAG_MAX_DEC))
#define f_is_alpha(x) (!f_is_num(x))
#define f_is_binary(x) ((x) & FIELDFLAG_BINARY)
#define f_is_enum(x) ((x) & FIELDFLAG_INTERVAL)
diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc
index 7a8585975cc..fa130c59a88 100644
--- a/sql/ha_myisam.cc
+++ b/sql/ha_myisam.cc
@@ -130,7 +130,7 @@ int ha_myisam::net_read_dump(NET* net)
my_seek(data_fd, 0L, MY_SEEK_SET, MYF(MY_WME));
for(;;)
{
- uint packet_len = my_net_read(net);
+ ulong packet_len = my_net_read(net);
if (!packet_len)
break ; // end of file
if (packet_len == packet_error)
@@ -139,7 +139,7 @@ int ha_myisam::net_read_dump(NET* net)
error= -1;
goto err;
}
- if (my_write(data_fd, (byte*)net->read_pos, packet_len,
+ if (my_write(data_fd, (byte*)net->read_pos, (uint) packet_len,
MYF(MY_WME|MY_FNABP)))
{
error = errno;
diff --git a/sql/item.h b/sql/item.h
index a52860528f1..355d81d0c6c 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -206,14 +206,14 @@ public:
Item_real(const char *str_arg,uint length) :value(atof(str_arg))
{
name=(char*) str_arg;
- decimals=nr_of_decimals(str_arg);
+ decimals=(uint8) nr_of_decimals(str_arg);
max_length=length;
}
Item_real(const char *str,double val_arg,uint decimal_par,uint length)
:value(val_arg)
{
name=(char*) str;
- decimals=decimal_par;
+ decimals=(uint8) decimal_par;
max_length=length;
}
Item_real(double value_par) :value(value_par) {}
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 72198038a07..b8c2435e84e 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -193,14 +193,14 @@ void Query_log_event::pack_info(String* packet)
char buf[256];
String tmp(buf, sizeof(buf));
tmp.length(0);
- if(db && db_len)
+ if (db && db_len)
{
tmp.append("use ");
tmp.append(db, db_len);
tmp.append("; ", 2);
}
- if(query && q_len)
+ if (query && q_len)
tmp.append(query, q_len);
net_store_data(packet, (char*)tmp.ptr(), tmp.length());
}
@@ -224,7 +224,7 @@ void Load_log_event::pack_info(String* packet)
char buf[256];
String tmp(buf, sizeof(buf));
tmp.length(0);
- if(db && db_len)
+ if (db && db_len)
{
tmp.append("use ");
tmp.append(db, db_len);
@@ -234,9 +234,9 @@ void Load_log_event::pack_info(String* packet)
tmp.append("LOAD DATA INFILE '");
tmp.append(fname, fname_len);
tmp.append("' ", 2);
- if(sql_ex.opt_flags && REPLACE_FLAG )
+ if (sql_ex.opt_flags && REPLACE_FLAG )
tmp.append(" REPLACE ");
- else if(sql_ex.opt_flags && IGNORE_FLAG )
+ else if (sql_ex.opt_flags && IGNORE_FLAG )
tmp.append(" IGNORE ");
tmp.append("INTO TABLE ");
@@ -278,12 +278,11 @@ void Load_log_event::pack_info(String* packet)
if (num_fields)
{
- uint i;
const char* field = fields;
tmp.append(" (");
- for(i = 0; i < num_fields; i++)
+ for (uint i = 0; i < num_fields; i++)
{
- if(i)
+ if (i)
tmp.append(" ,");
tmp.append( field);
@@ -304,7 +303,7 @@ void Rotate_log_event::pack_info(String* packet)
tmp.append(new_log_ident, ident_len);
tmp.append(";pos=");
tmp.append(llstr(pos,buf));
- if(flags & LOG_EVENT_FORCED_ROTATE_F)
+ if (flags & LOG_EVENT_FORCED_ROTATE_F)
tmp.append("; forced by master");
net_store_data(packet, tmp.ptr(), tmp.length());
}
@@ -414,7 +413,7 @@ int Log_event::read_log_event(IO_CACHE* file, String* packet,
// if the read hits eof, we must report it as eof
// so the caller will know it can go into cond_wait to be woken up
// on the next update to the log
- if(!file->error) return LOG_READ_EOF;
+ if (!file->error) return LOG_READ_EOF;
return file->error > 0 ? LOG_READ_TRUNC: LOG_READ_IO;
}
data_len = uint4korr(buf + EVENT_LEN_OFFSET);
@@ -430,7 +429,7 @@ int Log_event::read_log_event(IO_CACHE* file, String* packet,
{
if (packet->append(file, data_len))
{
- if(log_lock)
+ if (log_lock)
pthread_mutex_unlock(log_lock);
// here we should never hit eof in a non-error condtion
// eof means we are reading the event partially, which should
@@ -445,13 +444,13 @@ int Log_event::read_log_event(IO_CACHE* file, String* packet,
#endif // MYSQL_CLIENT
#ifndef MYSQL_CLIENT
-#define UNLOCK_MUTEX if(log_lock) pthread_mutex_unlock(log_lock);
+#define UNLOCK_MUTEX if (log_lock) pthread_mutex_unlock(log_lock);
#else
#define UNLOCK_MUTEX
#endif
#ifndef MYSQL_CLIENT
-#define LOCK_MUTEX if(log_lock) pthread_mutex_lock(log_lock);
+#define LOCK_MUTEX if (log_lock) pthread_mutex_lock(log_lock);
#else
#define LOCK_MUTEX
#endif
@@ -501,7 +500,7 @@ Log_event* Log_event::read_log_event(IO_CACHE* file, bool old_format)
}
buf[data_len] = 0;
memcpy(buf, head, header_size);
- if(my_b_read(file, (byte*) buf + header_size,
+ if (my_b_read(file, (byte*) buf + header_size,
data_len - header_size))
{
error = "read error";
@@ -511,7 +510,7 @@ Log_event* Log_event::read_log_event(IO_CACHE* file, bool old_format)
res->register_temp_buf(buf);
err:
UNLOCK_MUTEX;
- if(error)
+ if (error)
{
sql_print_error(error);
my_free(buf, MYF(MY_ALLOW_ZERO_PTR));
@@ -679,7 +678,7 @@ Rotate_log_event::Rotate_log_event(const char* buf, int event_len,
// EVENT_LEN_OFFSET
int header_size = (old_format) ? OLD_HEADER_LEN : LOG_EVENT_HEADER_LEN;
uint ident_offset;
- if(event_len < header_size)
+ if (event_len < header_size)
return;
buf += header_size;
if (old_format)
@@ -775,9 +774,9 @@ void Query_log_event::print(FILE* file, bool short_form, char* last_db)
bool same_db = 0;
- if(db && last_db)
+ if (db && last_db)
{
- if(!(same_db = !memcmp(last_db, db, db_len + 1)))
+ if (!(same_db = !memcmp(last_db, db, db_len + 1)))
memcpy(last_db, db, db_len + 1);
}
@@ -838,7 +837,7 @@ int Intvar_log_event::write_data(IO_CACHE* file)
void Intvar_log_event::print(FILE* file, bool short_form, char* last_db)
{
char llbuff[22];
- if(!short_form)
+ if (!short_form)
{
print_header(file);
fprintf(file, "\tIntvar\n");
@@ -971,86 +970,83 @@ char* sql_ex_info::init(char* buf,char* buf_end,bool use_new_format)
#ifndef MYSQL_CLIENT
Load_log_event::Load_log_event(THD* thd, sql_exchange* ex,
const char* db_arg, const char* table_name_arg,
- List<Item>& fields_arg, enum enum_duplicates handle_dup):
- Log_event(thd),thread_id(thd->thread_id),
- num_fields(0),fields(0),field_lens(0),field_block_len(0),
- table_name(table_name_arg),
- db(db_arg),
- fname(ex->file_name)
- {
- time_t end_time;
- time(&end_time);
- exec_time = (ulong) (end_time - thd->start_time);
- db_len = (db) ? (uint32) strlen(db) : 0;
- table_name_len = (table_name) ? (uint32) strlen(table_name) : 0;
- fname_len = (fname) ? (uint) strlen(fname) : 0;
- sql_ex.field_term = (char*) ex->field_term->ptr();
- sql_ex.field_term_len = (uint8) ex->field_term->length();
- sql_ex.enclosed = (char*) ex->enclosed->ptr();
- sql_ex.enclosed_len = (uint8) ex->enclosed->length();
- sql_ex.line_term = (char*) ex->line_term->ptr();
- sql_ex.line_term_len = (uint8) ex->line_term->length();
- sql_ex.line_start = (char*) ex->line_start->ptr();
- sql_ex.line_start_len = (uint8) ex->line_start->length();
- sql_ex.escaped = (char*) ex->escaped->ptr();
- sql_ex.escaped_len = (uint8) ex->escaped->length();
- sql_ex.opt_flags = 0;
- sql_ex.cached_new_format = -1;
+ List<Item>& fields_arg,
+ enum enum_duplicates handle_dup):
+ Log_event(thd), fields(0), field_lens(0),
+ table_name(table_name_arg), db(db_arg), fname(ex->file_name),
+ thread_id(thd->thread_id), num_fields(0), field_block_len(0)
+{
+ time_t end_time;
+ time(&end_time);
+ exec_time = (ulong) (end_time - thd->start_time);
+ db_len = (db) ? (uint32) strlen(db) : 0;
+ table_name_len = (table_name) ? (uint32) strlen(table_name) : 0;
+ fname_len = (fname) ? (uint) strlen(fname) : 0;
+ sql_ex.field_term = (char*) ex->field_term->ptr();
+ sql_ex.field_term_len = (uint8) ex->field_term->length();
+ sql_ex.enclosed = (char*) ex->enclosed->ptr();
+ sql_ex.enclosed_len = (uint8) ex->enclosed->length();
+ sql_ex.line_term = (char*) ex->line_term->ptr();
+ sql_ex.line_term_len = (uint8) ex->line_term->length();
+ sql_ex.line_start = (char*) ex->line_start->ptr();
+ sql_ex.line_start_len = (uint8) ex->line_start->length();
+ sql_ex.escaped = (char*) ex->escaped->ptr();
+ sql_ex.escaped_len = (uint8) ex->escaped->length();
+ sql_ex.opt_flags = 0;
+ sql_ex.cached_new_format = -1;
- if(ex->dumpfile)
- sql_ex.opt_flags |= DUMPFILE_FLAG;
- if(ex->opt_enclosed)
- sql_ex.opt_flags |= OPT_ENCLOSED_FLAG;
-
- sql_ex.empty_flags = 0;
-
- switch(handle_dup)
- {
- case DUP_IGNORE: sql_ex.opt_flags |= IGNORE_FLAG; break;
- case DUP_REPLACE: sql_ex.opt_flags |= REPLACE_FLAG; break;
- case DUP_ERROR: break;
- }
-
-
- if(!ex->field_term->length())
- sql_ex.empty_flags |= FIELD_TERM_EMPTY;
- if(!ex->enclosed->length())
- sql_ex.empty_flags |= ENCLOSED_EMPTY;
- if(!ex->line_term->length())
- sql_ex.empty_flags |= LINE_TERM_EMPTY;
- if(!ex->line_start->length())
- sql_ex.empty_flags |= LINE_START_EMPTY;
- if(!ex->escaped->length())
- sql_ex.empty_flags |= ESCAPED_EMPTY;
+ if (ex->dumpfile)
+ sql_ex.opt_flags |= DUMPFILE_FLAG;
+ if (ex->opt_enclosed)
+ sql_ex.opt_flags |= OPT_ENCLOSED_FLAG;
+
+ sql_ex.empty_flags = 0;
+
+ switch(handle_dup) {
+ case DUP_IGNORE: sql_ex.opt_flags |= IGNORE_FLAG; break;
+ case DUP_REPLACE: sql_ex.opt_flags |= REPLACE_FLAG; break;
+ case DUP_ERROR: break;
+ }
+
+
+ if (!ex->field_term->length())
+ sql_ex.empty_flags |= FIELD_TERM_EMPTY;
+ if (!ex->enclosed->length())
+ sql_ex.empty_flags |= ENCLOSED_EMPTY;
+ if (!ex->line_term->length())
+ sql_ex.empty_flags |= LINE_TERM_EMPTY;
+ if (!ex->line_start->length())
+ sql_ex.empty_flags |= LINE_START_EMPTY;
+ if (!ex->escaped->length())
+ sql_ex.empty_flags |= ESCAPED_EMPTY;
- skip_lines = ex->skip_lines;
-
- List_iterator<Item> li(fields_arg);
- field_lens_buf.length(0);
- fields_buf.length(0);
- Item* item;
- while((item = li++))
- {
- num_fields++;
- uchar len = (uchar) strlen(item->name);
- field_block_len += len + 1;
- fields_buf.append(item->name, len + 1);
- field_lens_buf.append((char*)&len, 1);
- }
+ skip_lines = ex->skip_lines;
- field_lens = (const uchar*)field_lens_buf.ptr();
- fields = fields_buf.ptr();
+ List_iterator<Item> li(fields_arg);
+ field_lens_buf.length(0);
+ fields_buf.length(0);
+ Item* item;
+ while((item = li++))
+ {
+ num_fields++;
+ uchar len = (uchar) strlen(item->name);
+ field_block_len += len + 1;
+ fields_buf.append(item->name, len + 1);
+ field_lens_buf.append((char*)&len, 1);
}
+ field_lens = (const uchar*)field_lens_buf.ptr();
+ fields = fields_buf.ptr();
+}
+
#endif
// the caller must do buf[event_len] = 0 before he starts using the
// constructed event
Load_log_event::Load_log_event(const char* buf, int event_len,
bool old_format):
- Log_event(buf, old_format),num_fields(0),fields(0),
- field_lens(0),field_block_len(0),
- table_name(0),db(0),fname(0)
+ Log_event(buf, old_format),fields(0),
+ field_lens(0), num_fields(0), field_block_len(0)
{
if (!event_len) // derived class, will call copy_log_event() itself
return;
@@ -1112,32 +1108,32 @@ void Load_log_event::print(FILE* file, bool short_form, char* last_db)
bool same_db = 0;
- if(db && last_db)
+ if (db && last_db)
{
- if(!(same_db = !memcmp(last_db, db, db_len + 1)))
+ if (!(same_db = !memcmp(last_db, db, db_len + 1)))
memcpy(last_db, db, db_len + 1);
}
- if(db && db[0] && !same_db)
+ if (db && db[0] && !same_db)
fprintf(file, "use %s;\n", db);
fprintf(file, "LOAD DATA INFILE '%-*s' ", fname_len, fname);
- if(sql_ex.opt_flags && REPLACE_FLAG )
+ if (sql_ex.opt_flags && REPLACE_FLAG )
fprintf(file," REPLACE ");
- else if(sql_ex.opt_flags && IGNORE_FLAG )
+ else if (sql_ex.opt_flags && IGNORE_FLAG )
fprintf(file," IGNORE ");
fprintf(file, "INTO TABLE %s ", table_name);
- if(sql_ex.field_term)
+ if (sql_ex.field_term)
{
fprintf(file, " FIELDS TERMINATED BY ");
pretty_print_str(file, sql_ex.field_term, sql_ex.field_term_len);
}
- if(sql_ex.enclosed)
+ if (sql_ex.enclosed)
{
- if(sql_ex.opt_flags && OPT_ENCLOSED_FLAG )
+ if (sql_ex.opt_flags && OPT_ENCLOSED_FLAG )
fprintf(file," OPTIONALLY ");
fprintf(file, " ENCLOSED BY ");
pretty_print_str(file, sql_ex.enclosed, sql_ex.enclosed_len);
@@ -1161,7 +1157,7 @@ void Load_log_event::print(FILE* file, bool short_form, char* last_db)
pretty_print_str(file, sql_ex.line_start, sql_ex.line_start_len);
}
- if((int)skip_lines > 0)
+ if ((int)skip_lines > 0)
fprintf(file, " IGNORE %ld LINES ", (long) skip_lines);
if (num_fields)
@@ -1169,9 +1165,9 @@ void Load_log_event::print(FILE* file, bool short_form, char* last_db)
uint i;
const char* field = fields;
fprintf( file, " (");
- for(i = 0; i < num_fields; i++)
+ for (i = 0; i < num_fields; i++)
{
- if(i)
+ if (i)
fputc(',', file);
fprintf(file, field);
@@ -1197,24 +1193,24 @@ void Load_log_event::set_fields(List<Item> &fields)
{
uint i;
const char* field = this->fields;
- for(i = 0; i < num_fields; i++)
- {
- fields.push_back(new Item_field(db, table_name, field));
- field += field_lens[i] + 1;
- }
+ for (i = 0; i < num_fields; i++)
+ {
+ fields.push_back(new Item_field(db, table_name, field));
+ field += field_lens[i] + 1;
+ }
}
Slave_log_event::Slave_log_event(THD* thd_arg,struct st_master_info* mi):
Log_event(thd_arg),mem_pool(0),master_host(0)
{
- if(!mi->inited)
+ if (!mi->inited)
return;
pthread_mutex_lock(&mi->lock);
master_host_len = strlen(mi->host);
master_log_len = strlen(mi->log_file_name);
// on OOM, just do not initialize the structure and print the error
- if((mem_pool = (char*)my_malloc(get_data_size() + 1,
+ if ((mem_pool = (char*)my_malloc(get_data_size() + 1,
MYF(MY_WME))))
{
master_host = mem_pool + SL_MASTER_HOST_OFFSET ;
@@ -1243,7 +1239,7 @@ Slave_log_event::~Slave_log_event()
void Slave_log_event::print(FILE* file, bool short_form, char* last_db)
{
char llbuff[22];
- if(short_form)
+ if (short_form)
return;
print_header(file);
fputc('\n', file);
@@ -1275,7 +1271,7 @@ void Slave_log_event::init_from_mem_pool(int data_size)
master_host_len = strlen(master_host);
// safety
master_log = master_host + master_host_len + 1;
- if(master_log > mem_pool + data_size)
+ if (master_log > mem_pool + data_size)
{
master_host = 0;
return;
@@ -1287,9 +1283,9 @@ Slave_log_event::Slave_log_event(const char* buf, int event_len):
Log_event(buf,0),mem_pool(0),master_host(0)
{
event_len -= LOG_EVENT_HEADER_LEN;
- if(event_len < 0)
+ if (event_len < 0)
return;
- if(!(mem_pool = (char*)my_malloc(event_len + 1, MYF(MY_WME))))
+ if (!(mem_pool = (char*)my_malloc(event_len + 1, MYF(MY_WME))))
return;
memcpy(mem_pool, buf + LOG_EVENT_HEADER_LEN, event_len);
mem_pool[event_len] = 0;
@@ -1396,7 +1392,7 @@ Append_block_log_event::Append_block_log_event(THD* thd_arg, char* block_arg,
Append_block_log_event::Append_block_log_event(const char* buf, int len):
Log_event(buf, 0),block(0)
{
- if((uint)len < APPEND_BLOCK_EVENT_OVERHEAD)
+ if ((uint)len < APPEND_BLOCK_EVENT_OVERHEAD)
return;
file_id = uint4korr(buf + LOG_EVENT_HEADER_LEN + AB_FILE_ID_OFFSET);
block = (char*)buf + APPEND_BLOCK_EVENT_OVERHEAD;
@@ -1448,7 +1444,7 @@ Delete_file_log_event::Delete_file_log_event(THD* thd_arg):
Delete_file_log_event::Delete_file_log_event(const char* buf, int len):
Log_event(buf, 0),file_id(0)
{
- if((uint)len < DELETE_FILE_EVENT_OVERHEAD)
+ if ((uint)len < DELETE_FILE_EVENT_OVERHEAD)
return;
file_id = uint4korr(buf + LOG_EVENT_HEADER_LEN + AB_FILE_ID_OFFSET);
}
@@ -1495,7 +1491,7 @@ Execute_load_log_event::Execute_load_log_event(THD* thd_arg):
Execute_load_log_event::Execute_load_log_event(const char* buf,int len):
Log_event(buf, 0),file_id(0)
{
- if((uint)len < EXEC_LOAD_EVENT_OVERHEAD)
+ if ((uint)len < EXEC_LOAD_EVENT_OVERHEAD)
return;
file_id = uint4korr(buf + LOG_EVENT_HEADER_LEN + EL_FILE_ID_OFFSET);
}
@@ -1551,8 +1547,10 @@ int Query_log_event::exec_event(struct st_master_info* mi)
thd->net.last_error[0] = 0;
thd->slave_proxy_id = thread_id; // for temp tables
- // sanity check to make sure the master did not get a really bad
- // error on the query
+ /*
+ sanity check to make sure the master did not get a really bad
+ error on the query
+ */
if (!check_expected_error(thd, (expected_error = error_code)))
{
mysql_parse(thd, thd->query, q_len);
@@ -1609,7 +1607,7 @@ int Load_log_event::exec_event(NET* net, struct st_master_info* mi)
thd->query = 0;
thd->query_error = 0;
- if(db_ok(thd->db, replicate_do_db, replicate_ignore_db))
+ if (db_ok(thd->db, replicate_do_db, replicate_ignore_db))
{
thd->set_time((time_t)when);
thd->current_tablenr = 0;
@@ -1623,7 +1621,7 @@ int Load_log_event::exec_event(NET* net, struct st_master_info* mi)
tables.name = tables.real_name = (char*)table_name;
tables.lock_type = TL_WRITE;
// the table will be opened in mysql_load
- if(table_rules_on && !tables_ok(thd, &tables))
+ if (table_rules_on && !tables_ok(thd, &tables))
{
if (net)
skip_load_data_infile(net);
@@ -1632,7 +1630,7 @@ int Load_log_event::exec_event(NET* net, struct st_master_info* mi)
{
char llbuff[22];
enum enum_duplicates handle_dup = DUP_IGNORE;
- if(sql_ex.opt_flags && REPLACE_FLAG)
+ if (sql_ex.opt_flags && REPLACE_FLAG)
handle_dup = DUP_REPLACE;
sql_exchange ex((char*)fname, sql_ex.opt_flags &&
DUMPFILE_FLAG );
@@ -1658,14 +1656,14 @@ int Load_log_event::exec_event(NET* net, struct st_master_info* mi)
// about the packet sequence
thd->net.pkt_nr = net->pkt_nr;
}
- if(mysql_load(thd, &ex, &tables, fields, handle_dup, net != 0,
+ if (mysql_load(thd, &ex, &tables, fields, handle_dup, net != 0,
TL_WRITE))
thd->query_error = 1;
- if(thd->cuted_fields)
+ if (thd->cuted_fields)
sql_print_error("Slave: load data infile at position %s in log \
'%s' produced %d warning(s)", llstr(mi->pos,llbuff), RPL_LOG_NAME,
thd->cuted_fields );
- if(net)
+ if (net)
net->pkt_nr = thd->net.pkt_nr;
}
}
@@ -1680,10 +1678,10 @@ int Load_log_event::exec_event(NET* net, struct st_master_info* mi)
thd->net.vio = 0;
thd->db = 0;// prevent db from being freed
close_thread_tables(thd);
- if(thd->query_error)
+ if (thd->query_error)
{
int sql_error = thd->net.last_errno;
- if(!sql_error)
+ if (!sql_error)
sql_error = ER_UNKNOWN_ERROR;
slave_print_error(sql_error, "Slave: Error '%s' running load data infile ",
@@ -1693,7 +1691,7 @@ int Load_log_event::exec_event(NET* net, struct st_master_info* mi)
}
free_root(&thd->mem_root,0);
- if(thd->fatal_error)
+ if (thd->fatal_error)
{
sql_print_error("Slave: Fatal error running LOAD DATA INFILE ");
return 1;
@@ -1788,7 +1786,7 @@ int Intvar_log_event::exec_event(struct st_master_info* mi)
int Slave_log_event::exec_event(struct st_master_info* mi)
{
- if(mysql_bin_log.is_open())
+ if (mysql_bin_log.is_open())
mysql_bin_log.write(this);
return Log_event::exec_event(mi);
}
diff --git a/sql/log_event.h b/sql/log_event.h
index 329d748025d..4426232008b 100644
--- a/sql/log_event.h
+++ b/sql/log_event.h
@@ -244,42 +244,31 @@ public:
virtual bool is_valid() = 0;
virtual bool get_cache_stmt() { return 0; }
Log_event(const char* buf, bool old_format);
-#ifndef MYSQL_CLIENT
- Log_event(THD* thd_arg, uint16 flags_arg = 0);
-#endif
virtual ~Log_event() { free_temp_buf();}
void register_temp_buf(char* buf) { temp_buf = buf; }
void free_temp_buf()
+ {
+ if (temp_buf)
{
- if (temp_buf)
- {
- my_free(temp_buf, MYF(0));
- temp_buf = 0;
- }
+ my_free(temp_buf, MYF(0));
+ temp_buf = 0;
}
+ }
virtual int get_data_size() { return 0;}
virtual int get_data_body_offset() { return 0; }
int get_event_len() { return cached_event_len ? cached_event_len :
(cached_event_len = LOG_EVENT_HEADER_LEN + get_data_size()); }
-#ifdef MYSQL_CLIENT
- virtual void print(FILE* file, bool short_form = 0, char* last_db = 0) = 0;
- void print_timestamp(FILE* file, time_t *ts = 0);
- void print_header(FILE* file);
-#endif
-
-#ifndef MYSQL_CLIENT
- // if mutex is 0, the read will proceed without mutex
- static Log_event* read_log_event(IO_CACHE* file,
- pthread_mutex_t* log_lock,
- bool old_format);
-#else // avoid having to link mysqlbinlog against libpthread
- static Log_event* read_log_event(IO_CACHE* file, bool old_format);
-#endif
+
static Log_event* read_log_event(const char* buf, int event_len,
const char **error, bool old_format);
const char* get_type_str();
#ifndef MYSQL_CLIENT
+ // if mutex is 0, the read will proceed without mutex
+ Log_event(THD* thd_arg, uint16 flags_arg = 0);
+ static Log_event* read_log_event(IO_CACHE* file,
+ pthread_mutex_t* log_lock,
+ bool old_format);
static int read_log_event(IO_CACHE* file, String* packet,
pthread_mutex_t* log_lock);
void set_log_seq(THD* thd, MYSQL_LOG* log);
@@ -291,6 +280,13 @@ public:
{
return thd ? thd->db : 0;
}
+#else
+ // avoid having to link mysqlbinlog against libpthread
+ static Log_event* read_log_event(IO_CACHE* file, bool old_format);
+
+ virtual void print(FILE* file, bool short_form = 0, char* last_db = 0) = 0;
+ void print_timestamp(FILE* file, time_t *ts = 0);
+ void print_header(FILE* file);
#endif
};
@@ -303,13 +299,16 @@ protected:
public:
const char* query;
const char* db;
- uint32 q_len; // if we already know the length of the query string
- // we pass it here, so we would not have to call strlen()
- // otherwise, set it to 0, in which case, we compute it with strlen()
+ /*
+ If we already know the length of the query string
+ we pass it here, so we would not have to call strlen()
+ otherwise, set it to 0, in which case, we compute it with strlen()
+ */
+ uint32 q_len;
uint32 db_len;
uint16 error_code;
ulong thread_id;
-#if !defined(MYSQL_CLIENT)
+#ifndef MYSQL_CLIENT
bool cache_stmt;
Query_log_event(THD* thd_arg, const char* query_arg,
@@ -318,6 +317,8 @@ public:
void pack_info(String* packet);
int exec_event(struct st_master_info* mi);
bool get_cache_stmt() { return cache_stmt; }
+#else
+ void print(FILE* file, bool short_form = 0, char* last_db = 0);
#endif
Query_log_event(const char* buf, int event_len, bool old_format);
@@ -340,9 +341,6 @@ public:
+ 2 // error_code
;
}
-#ifdef MYSQL_CLIENT
- void print(FILE* file, bool short_form = 0, char* last_db = 0);
-#endif
};
class Slave_log_event: public Log_event
@@ -352,24 +350,22 @@ protected:
void init_from_mem_pool(int data_size);
public:
char* master_host;
- int master_host_len;
- uint16 master_port;
char* master_log;
- int master_log_len;
ulonglong master_pos;
+ int master_host_len;
+ int master_log_len;
+ uint16 master_port;
-#ifndef MYSQL_CLIENT
- Slave_log_event(THD* thd_arg, struct st_master_info* mi);
- void pack_info(String* packet);
- int exec_event(struct st_master_info* mi);
-#endif
-
Slave_log_event(const char* buf, int event_len);
~Slave_log_event();
int get_data_size();
bool is_valid() { return master_host != 0; }
Log_event_type get_type_code() { return SLAVE_EVENT; }
-#ifdef MYSQL_CLIENT
+#ifndef MYSQL_CLIENT
+ Slave_log_event(THD* thd_arg, struct st_master_info* mi);
+ void pack_info(String* packet);
+ int exec_event(struct st_master_info* mi);
+#else
void print(FILE* file, bool short_form = 0, char* last_db = 0);
#endif
int write_data(IO_CACHE* file );
@@ -382,22 +378,21 @@ protected:
int copy_log_event(const char *buf, ulong event_len, bool old_format);
public:
+ const char* fields;
+ const uchar* field_lens;
+ const char* table_name;
+ const char* db;
+ const char* fname;
ulong thread_id;
uint32 table_name_len;
uint32 db_len;
uint32 fname_len;
uint32 num_fields;
- const char* fields;
- const uchar* field_lens;
uint32 field_block_len;
-
- const char* table_name;
- const char* db;
- const char* fname;
uint32 skip_lines;
sql_ex_info sql_ex;
-#if !defined(MYSQL_CLIENT)
+#ifndef MYSQL_CLIENT
String field_lens_buf;
String fields_buf;
@@ -408,10 +403,12 @@ public:
void pack_info(String* packet);
const char* get_db() { return db; }
int exec_event(struct st_master_info* mi)
- {
- return exec_event(thd->slave_net,mi);
- }
+ {
+ return exec_event(thd->slave_net,mi);
+ }
int exec_event(NET* net, struct st_master_info* mi);
+#else
+ void print(FILE* file, bool short_form = 0, char* last_db = 0);
#endif
Load_log_event(const char* buf, int event_len, bool old_format);
@@ -434,9 +431,6 @@ public:
;
}
int get_data_body_offset() { return LOAD_EVENT_OVERHEAD; }
-#ifdef MYSQL_CLIENT
- void print(FILE* file, bool short_form = 0, char* last_db = 0);
-#endif
};
extern char server_version[SERVER_VERSION_LENGTH];
@@ -447,13 +441,7 @@ public:
uint32 created;
uint16 binlog_version;
char server_version[ST_SERVER_VER_LEN];
-#ifndef MYSQL_CLIENT
- Start_log_event() :Log_event((THD*)0),binlog_version(BINLOG_VERSION)
- {
- created = (uint32) when;
- memcpy(server_version, ::server_version, ST_SERVER_VER_LEN);
- }
-#endif
+
Start_log_event(const char* buf, bool old_format);
~Start_log_event() {}
Log_event_type get_type_code() { return START_EVENT;}
@@ -464,10 +452,14 @@ public:
return START_HEADER_LEN;
}
#ifndef MYSQL_CLIENT
+ Start_log_event() :Log_event((THD*)0),binlog_version(BINLOG_VERSION)
+ {
+ created = (uint32) when;
+ memcpy(server_version, ::server_version, ST_SERVER_VER_LEN);
+ }
void pack_info(String* packet);
int exec_event(struct st_master_info* mi);
-#endif
-#ifdef MYSQL_CLIENT
+#else
void print(FILE* file, bool short_form = 0, char* last_db = 0);
#endif
};
@@ -477,11 +469,7 @@ class Intvar_log_event: public Log_event
public:
ulonglong val;
uchar type;
-#ifndef MYSQL_CLIENT
- Intvar_log_event(THD* thd_arg,uchar type_arg, ulonglong val_arg)
- :Log_event(thd_arg),val(val_arg),type(type_arg)
- {}
-#endif
+
Intvar_log_event(const char* buf, bool old_format);
~Intvar_log_event() {}
Log_event_type get_type_code() { return INTVAR_EVENT;}
@@ -490,11 +478,12 @@ public:
int write_data(IO_CACHE* file);
bool is_valid() { return 1; }
#ifndef MYSQL_CLIENT
+ Intvar_log_event(THD* thd_arg,uchar type_arg, ulonglong val_arg)
+ :Log_event(thd_arg),val(val_arg),type(type_arg)
+ {}
void pack_info(String* packet);
int exec_event(struct st_master_info* mi);
-#endif
-
-#ifdef MYSQL_CLIENT
+#else
void print(FILE* file, bool short_form = 0, char* last_db = 0);
#endif
};
@@ -502,10 +491,6 @@ public:
class Stop_log_event: public Log_event
{
public:
-#ifndef MYSQL_CLIENT
- Stop_log_event() :Log_event((THD*)0)
- {}
-#endif
Stop_log_event(const char* buf, bool old_format):Log_event(buf,
old_format)
{
@@ -513,11 +498,11 @@ public:
~Stop_log_event() {}
Log_event_type get_type_code() { return STOP_EVENT;}
bool is_valid() { return 1; }
-#ifdef MYSQL_CLIENT
- void print(FILE* file, bool short_form = 0, char* last_db = 0);
-#endif
-#ifndef MYSQL_CLIENT
+#ifndef MYSQL_CLIENT
+ Stop_log_event() :Log_event((THD*)0) {}
int exec_event(struct st_master_info* mi);
+#else
+ void print(FILE* file, bool short_form = 0, char* last_db = 0);
#endif
};
@@ -525,19 +510,10 @@ class Rotate_log_event: public Log_event
{
public:
const char* new_log_ident;
- uchar ident_len;
ulonglong pos;
+ uint8 ident_len;
bool alloced;
-#ifndef MYSQL_CLIENT
- Rotate_log_event(THD* thd_arg, const char* new_log_ident_arg,
- uint ident_len_arg = 0,ulonglong pos_arg = 4) :
- Log_event(thd_arg),
- new_log_ident(new_log_ident_arg),
- ident_len(ident_len_arg ? ident_len_arg :
- (uint) strlen(new_log_ident_arg)), pos(pos_arg),
- alloced(0)
- {}
-#endif
+
Rotate_log_event(const char* buf, int event_len, bool old_format);
~Rotate_log_event()
{
@@ -548,64 +524,81 @@ public:
int get_data_size() { return ident_len + ROTATE_HEADER_LEN;}
bool is_valid() { return new_log_ident != 0; }
int write_data(IO_CACHE* file);
-#ifdef MYSQL_CLIENT
- void print(FILE* file, bool short_form = 0, char* last_db = 0);
-#endif
-#ifndef MYSQL_CLIENT
+#ifndef MYSQL_CLIENT
+ Rotate_log_event(THD* thd_arg, const char* new_log_ident_arg,
+ uint8 ident_len_arg = 0,ulonglong pos_arg = 4) :
+ Log_event(thd_arg), new_log_ident(new_log_ident_arg),
+ pos(pos_arg),
+ ident_len(ident_len_arg ? ident_len_arg :
+ (uint8) strlen(new_log_ident_arg)),
+ alloced(0)
+ {}
void pack_info(String* packet);
int exec_event(struct st_master_info* mi);
+#else
+ void print(FILE* file, bool short_form = 0, char* last_db = 0);
#endif
};
+
/* the classes below are for the new LOAD DATA INFILE logging */
class Create_file_log_event: public Load_log_event
{
protected:
- // pretend we are Load event, so we can write out just
- // our Load part - used on the slave when writing event out to
- // SQL_LOAD-*.info file
+ /*
+ Pretend we are Load event, so we can write out just
+ our Load part - used on the slave when writing event out to
+ SQL_LOAD-*.info file
+ */
bool fake_base;
public:
char* block;
uint block_len;
uint file_id;
-#ifndef MYSQL_CLIENT
- Create_file_log_event(THD* thd, sql_exchange* ex, const char* db_arg,
- const char* table_name_arg,
- List<Item>& fields_arg,
- enum enum_duplicates handle_dup,
- char* block_arg, uint block_len_arg);
-#endif
-
+
Create_file_log_event(const char* buf, int event_len);
~Create_file_log_event()
{
}
Log_event_type get_type_code()
- {
- return fake_base ? Load_log_event::get_type_code() : CREATE_FILE_EVENT;
- }
- int get_data_size() { return fake_base ? Load_log_event::get_data_size() :
- Load_log_event::get_data_size() +
- 4 + 1 + block_len;}
- int get_data_body_offset() { return fake_base ? LOAD_EVENT_OVERHEAD:
- LOAD_EVENT_OVERHEAD + CREATE_FILE_HEADER_LEN; }
+ {
+ return fake_base ? Load_log_event::get_type_code() : CREATE_FILE_EVENT;
+ }
+ int get_data_size()
+ {
+ return (fake_base ? Load_log_event::get_data_size() :
+ Load_log_event::get_data_size() +
+ 4 + 1 + block_len);
+ }
+ int get_data_body_offset()
+ {
+ return (fake_base ? LOAD_EVENT_OVERHEAD:
+ LOAD_EVENT_OVERHEAD + CREATE_FILE_HEADER_LEN);
+ }
bool is_valid() { return block != 0; }
int write_data_header(IO_CACHE* file);
int write_data_body(IO_CACHE* file);
- int write_base(IO_CACHE* file); // cut out Create_file extentions and
- // write it as Load event - used on the slave
+ /*
+ Cut out Create_file extentions and write it as Load event - used on the
+ slave.
+ */
+ int write_base(IO_CACHE* file);
-#ifdef MYSQL_CLIENT
- void print(FILE* file, bool short_form = 0, char* last_db = 0);
-#endif
#ifndef MYSQL_CLIENT
+ Create_file_log_event(THD* thd, sql_exchange* ex, const char* db_arg,
+ const char* table_name_arg,
+ List<Item>& fields_arg,
+ enum enum_duplicates handle_dup,
+ char* block_arg, uint block_len_arg);
void pack_info(String* packet);
int exec_event(struct st_master_info* mi);
+#else
+ void print(FILE* file, bool short_form = 0, char* last_db = 0);
#endif
};
+
class Append_block_log_event: public Log_event
{
public:
@@ -613,12 +606,6 @@ public:
uint block_len;
uint file_id;
-#ifndef MYSQL_CLIENT
- Append_block_log_event(THD* thd, char* block_arg,
- uint block_len_arg);
- int exec_event(struct st_master_info* mi);
-#endif
-
Append_block_log_event(const char* buf, int event_len);
~Append_block_log_event()
{
@@ -628,23 +615,22 @@ public:
bool is_valid() { return block != 0; }
int write_data(IO_CACHE* file);
-#ifdef MYSQL_CLIENT
- void print(FILE* file, bool short_form = 0, char* last_db = 0);
-#endif
#ifndef MYSQL_CLIENT
+ Append_block_log_event(THD* thd, char* block_arg,
+ uint block_len_arg);
+ int exec_event(struct st_master_info* mi);
void pack_info(String* packet);
+#else
+ void print(FILE* file, bool short_form = 0, char* last_db = 0);
#endif
};
+
class Delete_file_log_event: public Log_event
{
public:
uint file_id;
-#ifndef MYSQL_CLIENT
- Delete_file_log_event(THD* thd);
-#endif
-
Delete_file_log_event(const char* buf, int event_len);
~Delete_file_log_event()
{
@@ -654,12 +640,12 @@ public:
bool is_valid() { return file_id != 0; }
int write_data(IO_CACHE* file);
-#ifdef MYSQL_CLIENT
- void print(FILE* file, bool short_form = 0, char* last_db = 0);
-#endif
#ifndef MYSQL_CLIENT
+ Delete_file_log_event(THD* thd);
void pack_info(String* packet);
int exec_event(struct st_master_info* mi);
+#else
+ void print(FILE* file, bool short_form = 0, char* last_db = 0);
#endif
};
@@ -668,10 +654,6 @@ class Execute_load_log_event: public Log_event
public:
uint file_id;
-#ifndef MYSQL_CLIENT
- Execute_load_log_event(THD* thd);
-#endif
-
Execute_load_log_event(const char* buf, int event_len);
~Execute_load_log_event()
{
@@ -681,16 +663,13 @@ public:
bool is_valid() { return file_id != 0; }
int write_data(IO_CACHE* file);
-#ifdef MYSQL_CLIENT
- void print(FILE* file, bool short_form = 0, char* last_db = 0);
-#endif
#ifndef MYSQL_CLIENT
+ Execute_load_log_event(THD* thd);
void pack_info(String* packet);
int exec_event(struct st_master_info* mi);
+#else
+ void print(FILE* file, bool short_form = 0, char* last_db = 0);
#endif
};
-#endif
-
-
-
+#endif /* _LOG_EVENT_H */
diff --git a/sql/mf_iocache.cc b/sql/mf_iocache.cc
index 2a7b25eab2f..860318d5a79 100644
--- a/sql/mf_iocache.cc
+++ b/sql/mf_iocache.cc
@@ -50,14 +50,14 @@ extern "C" {
int _my_b_net_read(register IO_CACHE *info, byte *Buffer,
uint Count __attribute__((unused)))
{
- int read_length;
+ ulong read_length;
NET *net= &(current_thd)->net;
DBUG_ENTER("_my_b_net_read");
if (!info->end_of_file)
DBUG_RETURN(1); /* because my_b_get (no _) takes 1 byte at a time */
read_length=my_net_read(net);
- if (read_length == (int) packet_error)
+ if (read_length == packet_error)
{
info->error= -1;
DBUG_RETURN(1);
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 5830c946372..4e3757d3f23 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -332,7 +332,7 @@ int mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &list,COND *conds,
ORDER *order, ORDER *group,Item *having,ORDER *proc_param,
ulong select_type,select_result *result);
int mysql_union(THD *thd,LEX *lex,select_result *result);
-Field *create_tmp_field(TABLE *table,Item *item, Item::Type type,
+Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
Item_result_field ***copy_func, Field **from_field,
bool group,bool modify_item);
int mysql_create_table(THD *thd,const char *db, const char *table_name,
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 1cb06c8a461..bc3fb3f7cb7 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -3091,8 +3091,8 @@ struct show_var_st init_vars[]= {
{"record_rnd_buffer", (char*) &record_rnd_cache_size, SHOW_LONG},
{"rpl_recovery_rank", (char*) &rpl_recovery_rank, SHOW_LONG},
{"query_buffer_size", (char*) &query_buff_size, SHOW_LONG},
- {"query_cache_limit", (char*) &query_cache_limit, SHOW_LONG},
- {"query_cache_size", (char*) &query_cache_size, SHOW_LONG},
+ {"query_cache_limit", (char*) &query_cache.query_cache_limit, SHOW_LONG},
+ {"query_cache_size", (char*) &query_cache.query_cache_size, SHOW_LONG},
{"query_cache_startup_type",(char*) &query_cache_startup_type, SHOW_LONG},
{"safe_show_database", (char*) &opt_safe_show_db, SHOW_BOOL},
{"server_id", (char*) &server_id, SHOW_LONG},
@@ -3157,11 +3157,11 @@ struct show_var_st status_vars[]= {
{"Open_streams", (char*) &my_stream_opened, SHOW_INT_CONST},
{"Opened_tables", (char*) &opened_tables, SHOW_LONG},
{"Questions", (char*) 0, SHOW_QUESTION},
- {"Qcache_queries", (char*) &query_cache.queries_in_cache,
+ {"Qcache_queries_in_cache", (char*) &query_cache.queries_in_cache,
SHOW_LONG},
{"Qcache_inserts", (char*) &query_cache.inserts, SHOW_LONG},
{"Qcache_hits", (char*) &query_cache.hits, SHOW_LONG},
- {"Qcache_refused", (char*) &query_cache.refused, SHOW_LONG},
+ {"Qcache_not_cached", (char*) &query_cache.refused, SHOW_LONG},
{"Qcache_free_memory", (char*) &query_cache.free_memory,SHOW_LONG},
{"Rpl_status", (char*) 0, SHOW_RPL_STATUS},
{"Select_full_join", (char*) &select_full_join_count, SHOW_LONG},
@@ -3726,12 +3726,11 @@ static void get_options(int argc,char **argv)
opt_slow_log=1;
opt_slow_logname=optarg;
break;
- case (int)OPT_SKIP_SLAVE_START:
+ case (int) OPT_SKIP_SLAVE_START:
opt_skip_slave_start = 1;
break;
case (int) OPT_SKIP_NEW:
opt_specialflag|= SPECIAL_NO_NEW_FUNC;
- default_table_type=DB_TYPE_ISAM;
myisam_delay_key_write=0;
myisam_concurrent_insert=0;
myisam_recover_options= HA_RECOVER_NONE;
@@ -3739,6 +3738,7 @@ static void get_options(int argc,char **argv)
my_use_symdir=0;
have_symlink=SHOW_OPTION_DISABLED;
ha_open_options&= ~HA_OPEN_ABORT_IF_CRASHED;
+ query_cache_size=0;
break;
case (int) OPT_SAFE:
opt_specialflag|= SPECIAL_SAFE_MODE;
diff --git a/sql/net_serv.cc b/sql/net_serv.cc
index ac622bca254..5a39b071b4f 100644
--- a/sql/net_serv.cc
+++ b/sql/net_serv.cc
@@ -109,7 +109,7 @@ static int net_write_buff(NET *net,const char *packet,ulong len);
int my_net_init(NET *net, Vio* vio)
{
- if (!(net->buff=(uchar*) my_malloc(net_buffer_length+
+ if (!(net->buff=(uchar*) my_malloc((uint32) net_buffer_length+
NET_HEADER_SIZE + COMP_HEADER_SIZE,
MYF(MY_WME))))
return 1;
@@ -162,7 +162,7 @@ static my_bool net_realloc(NET *net, ulong length)
pkt_length = (length+IO_SIZE-1) & ~(IO_SIZE-1);
/* We must allocate some extra bytes for the end 0 and to be able to
read big compressed blocks */
- if (!(buff=(uchar*) my_realloc((char*) net->buff, pkt_length +
+ if (!(buff=(uchar*) my_realloc((char*) net->buff, (uint32) pkt_length +
NET_HEADER_SIZE + COMP_HEADER_SIZE,
MYF(MY_WME))))
{
@@ -189,7 +189,7 @@ void net_clear(NET *net)
if (!vio_is_blocking(net->vio)) /* Safety if SSL */
{
while ( (count = vio_read(net->vio, (char*) (net->buff),
- net->max_packet)) > 0)
+ (uint32) net->max_packet)) > 0)
DBUG_PRINT("info",("skipped %d bytes from file: %s",
count,vio_description(net->vio)));
if (is_blocking)
@@ -243,7 +243,7 @@ my_net_write(NET *net,const char *packet,ulong len)
{
const ulong z_size = MAX_THREE_BYTES;
int3store(buff, z_size);
- buff[3]= net->pkt_nr++;
+ buff[3]= (uchar) net->pkt_nr++;
if (net_write_buff(net, (char*) buff, NET_HEADER_SIZE) ||
net_write_buff(net, packet, z_size))
return 1;
@@ -252,7 +252,7 @@ my_net_write(NET *net,const char *packet,ulong len)
}
/* Write last packet */
int3store(buff,len);
- buff[3]= net->pkt_nr++;
+ buff[3]= (uchar) net->pkt_nr++;
if (net_write_buff(net,(char*) buff,NET_HEADER_SIZE))
return 1;
return net_write_buff(net,packet,len);
@@ -282,7 +282,7 @@ net_write_command(NET *net,uchar command,const char *packet,ulong len)
do
{
int3store(buff, MAX_THREE_BYTES);
- buff[3]= net->pkt_nr++;
+ buff[3]= (uchar) net->pkt_nr++;
if (net_write_buff(net,(char*) buff, header_size) ||
net_write_buff(net,packet,len))
return 1;
@@ -294,7 +294,7 @@ net_write_command(NET *net,uchar command,const char *packet,ulong len)
len=length; /* Data left to be written */
}
int3store(buff,length);
- buff[3]= net->pkt_nr++;
+ buff[3]= (uchar) net->pkt_nr++;
return test(net_write_buff(net,(char*) buff,header_size) ||
net_write_buff(net,packet,len) || net_flush(net));
}
@@ -357,8 +357,8 @@ net_real_write(NET *net,const char *packet,ulong len)
ulong complen;
uchar *b;
uint header_length=NET_HEADER_SIZE+COMP_HEADER_SIZE;
- if (!(b=(uchar*) my_malloc(len + NET_HEADER_SIZE + COMP_HEADER_SIZE,
- MYF(MY_WME))))
+ if (!(b=(uchar*) my_malloc((uint32) len + NET_HEADER_SIZE +
+ COMP_HEADER_SIZE, MYF(MY_WME))))
{
#ifdef MYSQL_SERVER
net->last_errno=ER_OUT_OF_RESOURCES;
@@ -395,7 +395,7 @@ net_real_write(NET *net,const char *packet,ulong len)
pos=(char*) packet; end=pos+len;
while (pos != end)
{
- if ((long) (length=vio_write(net->vio,pos,(ulong) (end-pos))) <= 0)
+ if ((long) (length=vio_write(net->vio,pos,(uint32) (end-pos))) <= 0)
{
my_bool interrupted = vio_should_retry(net->vio);
#if (!defined(__WIN__) && !defined(__EMX__) && !defined(OS2))
@@ -479,7 +479,7 @@ net_real_write(NET *net,const char *packet,ulong len)
big packet
*/
-static void my_net_skip_rest(NET *net, ulong remain, thr_alarm_t *alarmed)
+static void my_net_skip_rest(NET *net, uint32 remain, thr_alarm_t *alarmed)
{
ALARM alarm_buff;
uint retry_count=0;
@@ -502,7 +502,7 @@ static void my_net_skip_rest(NET *net, ulong remain, thr_alarm_t *alarmed)
}
return;
}
- remain -= length;
+ remain -= (uint32) length;
statistic_add(bytes_received,length,&LOCK_bytes_received);
}
}
@@ -527,8 +527,8 @@ my_real_read(NET *net, ulong *complen)
ALARM alarm_buff;
#endif
my_bool net_blocking=vio_is_blocking(net->vio);
- ulong remain= (net->compress ? NET_HEADER_SIZE+COMP_HEADER_SIZE :
- NET_HEADER_SIZE);
+ uint32 remain= (net->compress ? NET_HEADER_SIZE+COMP_HEADER_SIZE :
+ NET_HEADER_SIZE);
*complen = 0;
net->reading_or_writing=1;
@@ -605,7 +605,7 @@ my_real_read(NET *net, ulong *complen)
continue;
}
#endif
- DBUG_PRINT("error",("Couldn't read packet: remain: %d errno: %d length: %d alarmed: %d", remain,vio_errno(net->vio),length,alarmed));
+ DBUG_PRINT("error",("Couldn't read packet: remain: %lu errno: %d length: %ld alarmed: %d", remain,vio_errno(net->vio),length,alarmed));
len= packet_error;
net->error=2; /* Close socket */
#ifdef MYSQL_SERVER
@@ -614,7 +614,7 @@ my_real_read(NET *net, ulong *complen)
#endif
goto end;
}
- remain -= (ulong) length;
+ remain -= (uint32) length;
pos+= (ulong) length;
statistic_add(bytes_received,(ulong) length,&LOCK_bytes_received);
}
@@ -661,14 +661,14 @@ my_real_read(NET *net, ulong *complen)
{
#ifdef MYSQL_SERVER
if (i == 1)
- my_net_skip_rest(net, len, &alarmed);
+ my_net_skip_rest(net, (uint32) len, &alarmed);
#endif
len= packet_error; /* Return error */
goto end;
}
}
pos=net->buff + net->where_b;
- remain = len;
+ remain = (uint32) len;
}
}
diff --git a/sql/opt_range.h b/sql/opt_range.h
index 07d1216a42f..83eb10235ea 100644
--- a/sql/opt_range.h
+++ b/sql/opt_range.h
@@ -48,9 +48,9 @@ class QUICK_RANGE :public Sql_alloc {
uint flag_arg)
: min_key((char*) sql_memdup(min_key_arg,min_length_arg+1)),
max_key((char*) sql_memdup(max_key_arg,max_length_arg+1)),
- min_length(min_length_arg),
- max_length(max_length_arg),
- flag(flag_arg)
+ min_length((uint16) min_length_arg),
+ max_length((uint16) max_length_arg),
+ flag((uint16) flag_arg)
{}
};
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index 38db67ba38f..bc9b95fe773 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -14,6 +14,194 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+/*
+ Description of the query cache:
+
+1. Query_cache object consists of
+ - query cache memory pool (cache)
+ - queries hash (queries)
+ - tables hash (tables)
+ - list of blocks ordered as they allocated in memory
+(first_block)
+ - list of queries block (queries_blocks)
+ - list of used tables (tables_blocks)
+
+2. Query cache memory pool (cache) consists of
+ - table of steps of memory bins allocation
+ - table of free memory bins
+ - blocks of memory
+
+3. Memory blocks
+
+Every memory block has the following structure:
+
++----------------------------------------------------------+
+| Block header (Query_cache_block structure) |
++----------------------------------------------------------+
+|Table of database table lists (used for queries & tables) |
++----------------------------------------------------------+
+| Type depended header |
+|(Query_cache_query, Query_cache_table, Query_cache_result)|
++----------------------------------------------------------+
+| Data ... |
++----------------------------------------------------------+
+
+Block header consists of:
+- type:
+ FREE Free memory block
+ QUERY Query block
+ RESULT Ready to send result
+ RES_CONT Result's continuation
+ RES_BEG First block of results, that is not yet complete,
+ written to cache
+ RES_INCOMPLETE Allocated for results data block
+ TABLE Block with database table description
+ INCOMPLETE The destroyed block
+- length of block (length)
+- length of data & headers (used)
+- physical list links (pnext/pprev) - used for the list of
+ blocks ordered as they are allocated in physical memory
+- logical list links (next/prev) - used for queries block list, tables block
+ list, free memory block lists and list of results block in query
+- number of elements in table of database table list (n_tables)
+
+4. Query & results blocks
+
+Query stored in cache consists of following blocks:
+
+more more
+recent+-------------+ old
+<-----|Query block 1|------> double linked list of queries block
+ prev | | next
+ +-------------+
+ <-| table 0 |-> (see "Table of database table lists" description)
+ <-| table 1 |->
+ | ... | +--------------------------+
+ +-------------+ +-------------------------+ |
+NET | | | V V |
+struct| | +-+------------+ +------------+ |
+<-----|query header |----->|Result block|-->|Result block|-+ doublelinked
+writer| |result| |<--| | list of results
+ +-------------+ +------------+ +------------+
+ |charset | +------------+ +------------+ no table of dbtables
+ |encoding + | | result | | result |
+ |query text |<-----| header | | header |------+
+ +-------------+parent| | | |parent|
+ ^ +------------+ +------------+ |
+ | |result data | |result data | |
+ | +------------+ +------------+ |
+ +---------------------------------------------------+
+
+First query is registered. During the registration query block is
+allocated. This query block is included in query hash and is linked
+with appropriate database tables lists (if there is no appropriate
+list exists it will be created).
+
+Later when query has performed results is written into the result blocks.
+A result block cannot be smaller then QUERY_CACHE_MIN_RESULT_DATA_SIZE.
+
+When new result is written to cache it is appended to the last result
+block, if no more free space left in the last block, new block is
+allocated.
+
+5. Table of database table lists.
+
+For quick invalidation of queries all query are linked in lists on used
+database tables basis (when table will be changed (insert/delete/...)
+this queries will be removed from cache).
+
+Root of such list is table block:
+
+ +------------+ list of used tables (used while invalidation of
+<----| Table |-----> whole database)
+ prev| block |next +-----------+
+ | | +-----------+ |Query block|
+ | | |Query block| +-----------+
+ +------------+ +-----------+ | ... |
+ +->| table 0 |------>|table 0 |----->| table N |---+
+ |+-| |<------| |<-----| |<-+|
+ || +------------+ | ... | | ... | ||
+ || |table header| +-----------+ +-----------+ ||
+ || +------------+ | ... | | ... | ||
+ || |db name + | +-----------+ +-----------+ ||
+ || |table name | ||
+ || +------------+ ||
+ |+--------------------------------------------------------+|
+ +----------------------------------------------------------+
+
+Table block is included into the tables hash (tables).
+
+6. Free blocks, free blocks bins & steps of freeblock bins.
+
+When we just started only one free memory block existed. All query
+cache memory (that will be used for block allocation) were
+containing in this block.
+When a new block is allocated we find most suitable memory block
+(minimal of >= required size). If such a block can not be found, we try
+to find max block < required size (if we allocate block for results).
+If there is no free memory, oldest query is removed from cache, and then
+we try to allocate memory. Last step should be repeated until we find
+suitable block or until there is no unlocked query found.
+
+If the block is found and its length more then we need, it should be
+split into 2 blocks.
+New blocks cannot be smaller then min_allocation_unit_bytes.
+
+When a block becomes free, its neighbor-blocks should be tested and if
+there are free blocks among them, they should be joined into one block.
+
+Free memory blocks are stored in bins according to their sizes.
+The bins are stored in size-descending order.
+These bins are distributed (by size) approximately logarithmically.
+
+First bin (number 0) stores free blocks with
+size <= query_cache_size>>QUERY_CACHE_MEM_BIN_FIRST_STEP_PWR2.
+It is first (number 0) step.
+On the next step distributed (1 + QUERY_CACHE_MEM_BIN_PARTS_INC) *
+QUERY_CACHE_MEM_BIN_PARTS_MUL bins. This bins allocated in interval from
+query_cache_size>>QUERY_CACHE_MEM_BIN_FIRST_STEP_PWR2 to
+query_cache_size>>QUERY_CACHE_MEM_BIN_FIRST_STEP_PWR2 >>
+QUERY_CACHE_MEM_BIN_STEP_PWR2
+...
+On each step interval decreases in 2 power of
+QUERY_CACHE_MEM_BIN_STEP_PWR2
+times, number of bins (that distributed on this step) increases. If on
+the previous step there were N bins distributed , on the current there
+would be distributed
+(N + QUERY_CACHE_MEM_BIN_PARTS_INC) * QUERY_CACHE_MEM_BIN_PARTS_MUL
+bins.
+Last distributed bin stores blocks with size near min_allocation_unit
+bytes.
+
+For example:
+ query_cache_size>>QUERY_CACHE_MEM_BIN_FIRST_STEP_PWR2 = 100,
+ min_allocation_unit = 17,
+ QUERY_CACHE_MEM_BIN_STEP_PWR2 = 1,
+ QUERY_CACHE_MEM_BIN_PARTS_INC = 1,
+ QUERY_CACHE_MEM_BIN_PARTS_MUL = 1
+ (in followed picture showed right (low) bound of bin):
+
+ | 100>>1 50>>1 |25>>1|
+ | | | | | |
+ | 100 75 50 41 33 25 21 18 15| 12 | - bins right (low) bounds
+
+ |\---/\-----/\--------/\--------|---/ |
+ | 0 1 2 3 | | - steps
+ \-----------------------------/ \---/
+ bins that we store in cache this bin showed for example only
+
+
+Calculation of steps/bins distribution is performed only when query cache
+is resized.
+
+When we need to find appropriate bin, first we should find appropriate
+step, then we should calculate number of bins that are using data
+stored in Query_cache_memory_bin_step structure.
+
+Free memory blocks are sorted in bins in lists with size-ascending order
+(more small blocks needed frequently then bigger one).
+*/
+
#include "mysql_priv.h"
#include <m_ctype.h>
#include <my_dir.h>
@@ -25,36 +213,36 @@
#else
#include "../myisammrg/myrg_def.h"
#endif
+#include <assert.h>
-#ifdef EXTRA_DEBUG
-#define MUTEX_LOCK(M) { DBUG_PRINT("info", ("mutex lock 0x%lx", (ulong)(M))); \
+#if defined(EXTRA_DEBUG) && !defined(DBUG_OFF)
+#define MUTEX_LOCK(M) { DBUG_PRINT("lock", ("mutex lock 0x%lx", (ulong)(M))); \
pthread_mutex_lock(M);}
#define SEM_LOCK(M) { int val = 0; sem_getvalue (M, &val); \
- DBUG_PRINT("info", ("sem lock 0x%lx (%d)", (ulong)(M), val)); \
- sem_wait(M); DBUG_PRINT("info", ("sem lock ok")); }
-#define MUTEX_UNLOCK(M) {DBUG_PRINT("info", ("mutex unlock 0x%lx",\
+ DBUG_PRINT("lock", ("sem lock 0x%lx (%d)", (ulong)(M), val)); \
+ sem_wait(M); DBUG_PRINT("lock", ("sem lock ok")); }
+#define MUTEX_UNLOCK(M) {DBUG_PRINT("lock", ("mutex unlock 0x%lx",\
(ulong)(M))); pthread_mutex_unlock(M);}
-#define SEM_UNLOCK(M) {DBUG_PRINT("info", ("sem unlock 0x%lx", (ulong)(M))); \
- sem_post(M); DBUG_PRINT("info", ("sem unlock ok")); }
-#define STRUCT_LOCK(M) {DBUG_PRINT("info", ("%d struct lock...",__LINE__)); \
- pthread_mutex_lock(M);DBUG_PRINT("info", ("struct lock OK"));}
+#define SEM_UNLOCK(M) {DBUG_PRINT("lock", ("sem unlock 0x%lx", (ulong)(M))); \
+ sem_post(M); DBUG_PRINT("lock", ("sem unlock ok")); }
+#define STRUCT_LOCK(M) {DBUG_PRINT("lock", ("%d struct lock...",__LINE__)); \
+ pthread_mutex_lock(M);DBUG_PRINT("lock", ("struct lock OK"));}
#define STRUCT_UNLOCK(M) { \
- DBUG_PRINT("info", ("%d struct unlock...",__LINE__)); \
- pthread_mutex_unlock(M);DBUG_PRINT("info", ("struct unlock OK"));}
-#define BLOCK_LOCK_WR(B) {DBUG_PRINT("info", ("%d LOCK_WR 0x%lx",\
+ DBUG_PRINT("lock", ("%d struct unlock...",__LINE__)); \
+ pthread_mutex_unlock(M);DBUG_PRINT("lock", ("struct unlock OK"));}
+#define BLOCK_LOCK_WR(B) {DBUG_PRINT("lock", ("%d LOCK_WR 0x%lx",\
__LINE__,(ulong)(B))); \
B->query()->lock_writing();}
-#define BLOCK_LOCK_RD(B) {DBUG_PRINT("info", ("%d LOCK_RD 0x%lx",\
+#define BLOCK_LOCK_RD(B) {DBUG_PRINT("lock", ("%d LOCK_RD 0x%lx",\
__LINE__,(ulong)(B))); \
B->query()->lock_reading();}
#define BLOCK_UNLOCK_WR(B) { \
- DBUG_PRINT("info", ("%d UNLOCK_WR 0x%lx",\
+ DBUG_PRINT("lock", ("%d UNLOCK_WR 0x%lx",\
__LINE__,(ulong)(B)));B->query()->unlock_writing();}
#define BLOCK_UNLOCK_RD(B) { \
- DBUG_PRINT("info", ("%d UNLOCK_RD 0x%lx",\
+ DBUG_PRINT("lock", ("%d UNLOCK_RD 0x%lx",\
__LINE__,(ulong)(B)));B->query()->unlock_reading();}
-#define DUMP(C) {C->bins_dump();C->cache_dump();\
- C->queries_dump();C->tables_dump();}
+#define DUMP(C) DBUG_EXECUTE("qcache", {(C)->queries_dump();(C)->tables_dump();})
#else
#define MUTEX_LOCK(M) pthread_mutex_lock(M)
#define SEM_LOCK(M) sem_wait(M)
@@ -70,24 +258,24 @@
#endif
/*****************************************************************************
- * Query_cache_block_table method(s)
- *****************************************************************************/
+ Query_cache_block_table method(s)
+*****************************************************************************/
inline Query_cache_block * Query_cache_block_table::block()
{
- return (Query_cache_block *)( ((byte*)this) -
- ALIGN_SIZE(sizeof(Query_cache_block_table))*n -
- ALIGN_SIZE(sizeof(Query_cache_block)));
+ return (Query_cache_block *)(((byte*)this) -
+ sizeof(Query_cache_block_table)*n -
+ ALIGN_SIZE(sizeof(Query_cache_block)));
};
/*****************************************************************************
- * Query_cache_block method(s)
- *****************************************************************************/
+ Query_cache_block method(s)
+*****************************************************************************/
void Query_cache_block::init(ulong block_length)
{
DBUG_ENTER("Query_cache_block::init");
- DBUG_PRINT("info", ("init block 0x%lx", (ulong) this));
+ DBUG_PRINT("qcache", ("init block 0x%lx", (ulong) this));
length = block_length;
used = 0;
type = Query_cache_block::FREE;
@@ -98,15 +286,15 @@ void Query_cache_block::init(ulong block_length)
void Query_cache_block::destroy()
{
DBUG_ENTER("Query_cache_block::destroy");
- DBUG_PRINT("info", ("destroy block 0x%lx, type %d",
- (ulong)this, type));
+ DBUG_PRINT("qcache", ("destroy block 0x%lx, type %d",
+ (ulong) this, type));
type = INCOMPLETE;
DBUG_VOID_RETURN;
}
inline uint Query_cache_block::headers_len()
{
- return (ALIGN_SIZE(sizeof(Query_cache_block_table))*n_tables +
+ return (ALIGN_SIZE(sizeof(Query_cache_block_table)*n_tables) +
ALIGN_SIZE(sizeof(Query_cache_block)));
}
@@ -147,7 +335,7 @@ inline Query_cache_block_table * Query_cache_block::table(TABLE_COUNTER_TYPE n)
{
return ((Query_cache_block_table *)
(((byte*)this)+ALIGN_SIZE(sizeof(Query_cache_block)) +
- n*ALIGN_SIZE(sizeof(Query_cache_block_table))));
+ n*sizeof(Query_cache_block_table)));
}
@@ -155,8 +343,10 @@ inline Query_cache_block_table * Query_cache_block::table(TABLE_COUNTER_TYPE n)
* Query_cache_table method(s)
*****************************************************************************/
-byte * Query_cache_table::cache_key(const byte *record, uint *length,
- my_bool not_used __attribute__((unused)))
+extern "C"
+{
+byte *query_cache_table_get_key(const byte *record, uint *length,
+ my_bool not_used __attribute__((unused)))
{
Query_cache_block* table_block = (Query_cache_block*) record;
*length = (table_block->used - table_block->headers_len() -
@@ -164,15 +354,11 @@ byte * Query_cache_table::cache_key(const byte *record, uint *length,
return (((byte *) table_block->data()) +
ALIGN_SIZE(sizeof(Query_cache_table)));
}
-
-void Query_cache_table::free_cache(void *entry)
-{
- //NOP
}
/*****************************************************************************
- * Query_cache_query methods
- *****************************************************************************/
+ Query_cache_query methods
+*****************************************************************************/
void Query_cache_query::init_n_lock()
{
@@ -182,17 +368,18 @@ void Query_cache_query::init_n_lock()
pthread_mutex_init(&clients_guard,MY_MUTEX_INIT_FAST);
clients = 0;
lock_writing();
- DBUG_PRINT("info", ("inited & locked query for block 0x%lx",
- ((byte*) this)-ALIGN_SIZE(sizeof(Query_cache_block))));
+ DBUG_PRINT("qcache", ("inited & locked query for block 0x%lx",
+ ((byte*) this)-ALIGN_SIZE(sizeof(Query_cache_block))));
DBUG_VOID_RETURN;
}
+
void Query_cache_query::unlock_n_destroy()
{
DBUG_ENTER("Query_cache_query::unlock_n_destroy");
this->unlock_writing();
- DBUG_PRINT("info", ("destroyed & unlocked query for block 0x%lx",
- ((byte*)this)-ALIGN_SIZE(sizeof(Query_cache_block))));
+ DBUG_PRINT("qcache", ("destroyed & unlocked query for block 0x%lx",
+ ((byte*)this)-ALIGN_SIZE(sizeof(Query_cache_block))));
sem_destroy(&lock);
pthread_mutex_destroy(&clients_guard);
DBUG_VOID_RETURN;
@@ -200,10 +387,10 @@ void Query_cache_query::unlock_n_destroy()
/*
- Following methods work for block rwad/write locking only in this
+ Following methods work for block read/write locking only in this
particular case and in interaction with structure_guard_mutex.
- Lock for write prevents any other locking.
+ Lock for write prevents any other locking. (exclusive use)
Lock for read prevents only locking for write.
*/
@@ -215,9 +402,9 @@ void Query_cache_query::lock_writing()
/*
Needed for finding queries, that we may delete from cache.
- We don't want wait while block become unlocked, in addition
- block locking mean that query now used and we not need to
- remove it
+ We don't want to wait while block become unlocked. In addition,
+ block locking means that query is now used and we don't need to
+ remove it.
*/
my_bool Query_cache_query::try_lock_writing()
@@ -225,10 +412,10 @@ my_bool Query_cache_query::try_lock_writing()
DBUG_ENTER("Query_cache_block::try_lock_writing");
if (sem_trywait(&lock)!=0 || clients != 0)
{
- DBUG_PRINT("info", ("can't lock mutex"));
+ DBUG_PRINT("qcache", ("can't lock mutex"));
DBUG_RETURN(0);
}
- DBUG_PRINT("info", ("mutex 'lock' 0x%lx locked", (ulong) &lock));
+ DBUG_PRINT("qcache", ("mutex 'lock' 0x%lx locked", (ulong) &lock));
DBUG_RETURN(1);
}
@@ -236,8 +423,8 @@ my_bool Query_cache_query::try_lock_writing()
void Query_cache_query::lock_reading()
{
MUTEX_LOCK(&clients_guard);
- clients++;
- if (clients == 1) SEM_LOCK(&lock);
+ if (!clients++)
+ SEM_LOCK(&lock);
MUTEX_UNLOCK(&clients_guard);
}
@@ -251,32 +438,27 @@ void Query_cache_query::unlock_writing()
void Query_cache_query::unlock_reading()
{
MUTEX_LOCK(&clients_guard);
- clients--;
- if (clients == 0) SEM_UNLOCK(&lock);
+ if (--clients == 0)
+ SEM_UNLOCK(&lock);
MUTEX_UNLOCK(&clients_guard);
-
}
-
-byte * Query_cache_query::cache_key( const byte *record, uint *length,
- my_bool not_used)
+extern "C"
+{
+byte *query_cache_query_get_key(const byte *record, uint *length,
+ my_bool not_used)
{
- Query_cache_block * query_block = (Query_cache_block *) record;
+ Query_cache_block *query_block = (Query_cache_block*) record;
*length = (query_block->used - query_block->headers_len() -
ALIGN_SIZE(sizeof(Query_cache_query)));
- return (((byte *)query_block->data()) +
+ return (((byte *) query_block->data()) +
ALIGN_SIZE(sizeof(Query_cache_query)));
}
-
-
-void Query_cache_query::free_cache(void *entry)
-{
- //NOP
}
/*****************************************************************************
- * Query cache store functions
- *****************************************************************************/
+ Functions to store things into the query cache
+*****************************************************************************/
void query_cache_insert(NET *net, const char *packet, ulong length)
{
@@ -292,27 +474,29 @@ void query_cache_insert(NET *net, const char *packet, ulong length)
if (net->query_cache_query != 0)
{
STRUCT_LOCK(&query_cache.structure_guard_mutex);
- if (net->query_cache_query != 0)
+ Query_cache_block *query_block = ((Query_cache_block*)
+ net->query_cache_query);
+ if (query_block)
{
- Query_cache_block * query_block = (Query_cache_block*)
- net->query_cache_query;
- DUMP((&query_cache));
+ Query_cache_query *header = query_block->query();
+ Query_cache_block *result = header->result();
+
+ DUMP(&query_cache);
BLOCK_LOCK_WR(query_block);
- DBUG_PRINT("info", ("insert packet %lu bytes long",length));
- Query_cache_query * header = query_block->query();
+ DBUG_PRINT("qcache", ("insert packet %lu bytes long",length));
- Query_cache_block * result = header->result();
/*
- STRUCT_UNLOCK(&query_cache.structure_guard_mutex); will be done by
- query_cache.append_result_data if success (if no success we need
+ On success STRUCT_UNLOCK(&query_cache.structure_guard_mutex) will be
+ done by query_cache.append_result_data if success (if not we need
query_cache.structure_guard_mutex locked to free query)
*/
- if (!query_cache.append_result_data( result, length, (gptr) packet,
- query_block, result))
+ if (!query_cache.append_result_data(&result, length, (gptr) packet,
+ query_block))
{
DBUG_PRINT("warning", ("Can't append data"));
header->result(result);
- DBUG_PRINT("info", ("free query 0x%lx", (ulong)query_block));
+ DBUG_PRINT("qcache", ("free query 0x%lx", (ulong) query_block));
+ // The following call will remove the lock on query_block
query_cache.free_query(query_block);
// append_result_data no success => we need unlock
STRUCT_UNLOCK(&query_cache.structure_guard_mutex);
@@ -327,26 +511,26 @@ void query_cache_insert(NET *net, const char *packet, ulong length)
DBUG_VOID_RETURN;
}
+
void query_cache_abort(NET *net)
{
DBUG_ENTER("query_cache_abort");
#ifndef DBUG_OFF
- // debuging method wreck may cause this
+ // Debugging method wreck may cause this
if (query_cache.query_cache_size == 0)
DBUG_VOID_RETURN;
#endif
-
- // quick check on unlocked structure
- if (net->query_cache_query != 0)
+ if (net->query_cache_query != 0) // Quick check on unlocked structure
{
STRUCT_LOCK(&query_cache.structure_guard_mutex);
- DUMP((&query_cache));
- Query_cache_block * query_block = ((Query_cache_block*)
+ Query_cache_block *query_block = ((Query_cache_block*)
net->query_cache_query);
- if (query_block)
+ if (query_block) // Test if changed by other thread
{
+ DUMP(&query_cache);
BLOCK_LOCK_WR(query_block);
+ // The following call will remove the lock on query_block
query_cache.free_query(query_block);
net->query_cache_query=0;
}
@@ -355,37 +539,30 @@ void query_cache_abort(NET *net)
DBUG_VOID_RETURN;
}
-void query_cache_end_of_result(NET * net)
+
+void query_cache_end_of_result(NET *net)
{
DBUG_ENTER("query_cache_end_of_result");
#ifndef DBUG_OFF
- // debuging method wreck may couse this
+ // Debugging method wreck may cause this
if (query_cache.query_cache_size == 0) DBUG_VOID_RETURN;
#endif
- //quick check on unlocked structure
- if (net->query_cache_query != 0)
+ if (net->query_cache_query != 0) // Quick check on unlocked structure
{
STRUCT_LOCK(&query_cache.structure_guard_mutex);
- if (net->query_cache_query != 0)
+ Query_cache_block *query_block = ((Query_cache_block*)
+ net->query_cache_query);
+ if (query_block)
{
- Query_cache_block * query_block = (Query_cache_block*)
- net->query_cache_query;
- DUMP((&query_cache));
+ DUMP(&query_cache);
BLOCK_LOCK_WR(query_block);
STRUCT_UNLOCK(&query_cache.structure_guard_mutex);
- Query_cache_query * header = query_block->query();
-#ifndef DBUG_OFF
- if (header->result() != 0)
- {
-#endif
- header->found_rows(current_thd->limit_found_rows);
- header->result()->type = Query_cache_block::RESULT;
+ Query_cache_query *header = query_block->query();
#ifndef DBUG_OFF
- }
- else
+ if (header->result() == 0)
{
DBUG_PRINT("error", ("end of data whith no result. query '%s'",
header->query()));
@@ -393,13 +570,15 @@ void query_cache_end_of_result(NET * net)
DBUG_VOID_RETURN;
}
#endif
+ header->found_rows(current_thd->limit_found_rows);
+ header->result()->type = Query_cache_block::RESULT;
net->query_cache_query=0;
header->writer(0);
BLOCK_UNLOCK_WR(query_block);
}
else
{
- //cache was flushed or resized and query was deleted => do nothing
+ // Cache was flushed or resized and query was deleted => do nothing
STRUCT_UNLOCK(&query_cache.structure_guard_mutex);
}
net->query_cache_query=0;
@@ -407,48 +586,39 @@ void query_cache_end_of_result(NET * net)
DBUG_VOID_RETURN;
}
-void query_cache_invalidate_by_MyISAM_filename(char * filename)
+void query_cache_invalidate_by_MyISAM_filename(const char *filename)
{
query_cache.invalidate_by_MyISAM_filename(filename);
}
-/*****************************************************************************
- * Query_cache methods
- *****************************************************************************/
/*****************************************************************************
- * interface methods
- *****************************************************************************/
+ Query_cache methods
+*****************************************************************************/
-Query_cache::Query_cache(
- ulong query_cache_limit,
+Query_cache::Query_cache(ulong query_cache_limit,
ulong min_allocation_unit,
ulong min_result_data_size,
uint def_query_hash_size ,
- uint def_table_hash_size):
-
- query_cache_size(0),
- query_cache_limit(query_cache_limit),
- min_allocation_unit(min_allocation_unit),
- min_result_data_size(min_result_data_size),
- def_query_hash_size(def_query_hash_size),
- def_table_hash_size(def_table_hash_size),
- queries_in_cache(0), hits(0), inserts(0), refused(0),
- initialized(0)
-{
- if (min_allocation_unit < ALIGN_SIZE(sizeof(Query_cache_block)) +
- ALIGN_SIZE(sizeof(Query_cache_block_table)) +
- ALIGN_SIZE(sizeof(Query_cache_query)) + 3)
- {
- min_allocation_unit=ALIGN_SIZE(sizeof(Query_cache_block)) +
- ALIGN_SIZE(sizeof(Query_cache_block_table)) +
- ALIGN_SIZE(sizeof(Query_cache_query)) + 3;
- }
+ uint def_table_hash_size)
+ :query_cache_size(0),
+ query_cache_limit(query_cache_limit),
+ min_allocation_unit(min_allocation_unit),
+ min_result_data_size(min_result_data_size),
+ def_query_hash_size(def_query_hash_size),
+ def_table_hash_size(def_table_hash_size),
+ queries_in_cache(0), hits(0), inserts(0), refused(0),
+ initialized(0)
+{
+ ulong min_needed=(ALIGN_SIZE(sizeof(Query_cache_block)) +
+ ALIGN_SIZE(sizeof(Query_cache_block_table)) +
+ ALIGN_SIZE(sizeof(Query_cache_query)) + 3);
+ set_if_bigger(min_allocation_unit,min_needed);
this->min_allocation_unit = min_allocation_unit;
- if (min_result_data_size < min_allocation_unit)
- this->min_result_data_size = min_allocation_unit;
+ set_if_bigger(this->min_result_data_size,min_allocation_unit);
}
+
ulong Query_cache::resize(ulong query_cache_size)
{
/*
@@ -456,102 +626,93 @@ ulong Query_cache::resize(ulong query_cache_size)
query_cache_size < this->query_cache_size
*/
/*
- TODO: try to copy old cache in new mamory
+ TODO: try to copy old cache in new memory
*/
DBUG_ENTER("Query_cache::resize");
- DBUG_PRINT("info", ("from %lu to %lu",this->query_cache_size,\
- query_cache_size));
+ DBUG_PRINT("qcache", ("from %lu to %lu",this->query_cache_size,
+ query_cache_size));
free_cache(0);
this->query_cache_size=query_cache_size;
DBUG_RETURN(init_cache());
}
+
void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used)
{
/*
- TODO may be better convert keywords to upper case when query
- stored/compared
+ TODO:
+ Maybe better convert keywords to upper case when query stored/compared.
+ (Not important at this stage)
*/
+ TABLE_COUNTER_TYPE tables;
DBUG_ENTER("Query_cache::store_query");
if (query_cache_size == 0)
DBUG_VOID_RETURN;
- LEX * lex = &thd->lex;
- NET * net = &thd->net;
-
- TABLE_COUNTER_TYPE tables = 0;
-
- if ((tables = is_cachable(thd, thd->query_length,
- thd->query, lex, tables_used))){
+ if ((tables = is_cacheable(thd, thd->query_length,
+ thd->query, &thd->lex, tables_used)))
+ {
+ NET *net = &thd->net;
+ byte flags = (thd->client_capabilities & CLIENT_LONG_FLAG ? 0x80 : 0);
STRUCT_LOCK(&structure_guard_mutex);
+
if (query_cache_size == 0)
DBUG_VOID_RETURN;
-
DUMP(this);
/*
- prepare flags:
- most significant bit - CLIENT_LONG_FLAG,
- other - charset number (0 no charset convertion)
+ Prepare flags:
+ most significant bit - CLIENT_LONG_FLAG,
+ other - charset number (0 no charset convertion)
*/
- byte flags = (thd->client_capabilities & CLIENT_LONG_FLAG ? 0x80 : 0);
if (thd->convert_set != 0)
{
- flags |= (byte) thd->convert_set->number();
-#ifndef DBUG_OFF
- if ( (thd->convert_set->number() & QUERY_CACHE_CHARSET_CONVERT_MASK) !=
- thd->convert_set->number())
- {
- wreck(__LINE__,
- "charset number bigger than QUERY_CACHE_CHARSET_CONVERT_MASK");
- }
-#endif
+ flags|= (byte) thd->convert_set->number();
+ DBUG_ASSERT(thd->convert_set->number() < 128);
}
- /* check: Is it another thread who process same query? */
- thd->query[thd->query_length] = (char)flags;
+ /* Check if another thread is processing the same query? */
+ thd->query[thd->query_length] = (char) flags;
Query_cache_block *competitor = (Query_cache_block *)
hash_search(&queries, thd->query, thd->query_length+1);
- thd->query[thd->query_length] = '\0';
- DBUG_PRINT("info", ("competitor 0x%lx, flags %x", (ulong)competitor,
+ DBUG_PRINT("qcache", ("competitor 0x%lx, flags %x", (ulong) competitor,
flags));
-
if (competitor == 0)
{
- thd->query[thd->query_length] = (char)flags;
- Query_cache_block * query_block =
- write_block_data(thd->query_length+1,
- (gptr) thd->query,
- ALIGN_SIZE(sizeof(Query_cache_query)),
- Query_cache_block::QUERY, tables, 1);
- thd->query[thd->query_length] = '\0';
+ /* Query is not in cache and no one is working with it; Store it */
+ thd->query[thd->query_length] = (char) flags;
+ Query_cache_block *query_block;
+ query_block= write_block_data(thd->query_length+1,
+ (gptr) thd->query,
+ ALIGN_SIZE(sizeof(Query_cache_query)),
+ Query_cache_block::QUERY, tables, 1);
if (query_block != 0)
{
- DBUG_PRINT("info", ("query block 0x%lx allocated, %lu",
- (ulong)query_block, query_block->used));
+ DBUG_PRINT("qcache", ("query block 0x%lx allocated, %lu",
+ (ulong) query_block, query_block->used));
- Query_cache_query * header = query_block->query();
+ Query_cache_query *header = query_block->query();
header->init_n_lock();
- if (hash_insert(&queries, (byte*)query_block))
+ if (hash_insert(&queries, (byte*) query_block))
{
refused++;
- DBUG_PRINT("info", ("insertion in query hash"));
+ DBUG_PRINT("qcache", ("insertion in query hash"));
header->unlock_n_destroy();
free_memory_block(query_block);
STRUCT_UNLOCK(&structure_guard_mutex);
- DBUG_VOID_RETURN;
+ goto end;
}
if (!register_all_tables(query_block, tables_used, tables))
{
refused++;
- DBUG_PRINT("warning", ("tables list incliding filed"));
+ DBUG_PRINT("warning", ("tables list including failed"));
hash_delete(&queries, (char *) query_block);
header->unlock_n_destroy();
free_memory_block(query_block);
STRUCT_UNLOCK(&structure_guard_mutex);
DBUG_VOID_RETURN;
}
- double_linked_list_simple_include(query_block, queries_blocks);
+ double_linked_list_simple_include(query_block, &queries_blocks);
inserts++;
queries_in_cache++;
STRUCT_UNLOCK(&structure_guard_mutex);
@@ -563,29 +724,36 @@ void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used)
}
else
{
- refused++;
// We have not enough memory to store query => do nothing
+ refused++;
STRUCT_UNLOCK(&structure_guard_mutex);
DBUG_PRINT("warning", ("Can't allocate query"));
}
}
else
{
+ // Another thread is processing the same query => do nothing
refused++;
- // Another thread already procass same query => do nothing
- DBUG_PRINT("info", ("Another thread process same query"));
STRUCT_UNLOCK(&structure_guard_mutex);
+ DBUG_PRINT("qcache", ("Another thread process same query"));
}
}
else
refused++;
+
+end:
+ thd->query[thd->query_length]= 0; // Restore end null
DBUG_VOID_RETURN;
}
-my_bool Query_cache::send_result_to_client(
- THD *thd, char *sql, uint query_length)
-{
+my_bool
+Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
+{
+ Query_cache_query *query;
+ Query_cache_block *first_result_block, *result_block;
+ Query_cache_block_table *block_table, *block_table_end;
+ byte flags;
DBUG_ENTER("Query_cache::send_result_to_client");
if (query_cache_size == 0 ||
@@ -597,138 +765,142 @@ my_bool Query_cache::send_result_to_client(
thd->query_cache_type == 0)
{
- DBUG_PRINT("info", ("query cache disabled on not in autocommit mode"));
- DBUG_RETURN(1);
+ DBUG_PRINT("qcache", ("query cache disabled on not in autocommit mode"));
+ goto err;
+ }
+ /*
+ We can't cache the query if we are using a temporary table because
+ we don't know if the query is using a temporary table.
+
+ TODO: We could parse the query and then check if the query used
+ a temporary table.
+ */
+ if (thd->temporary_tables != 0 || !thd->safe_to_cache_query)
+ {
+ DBUG_PRINT("qcache", ("SELECT is non-cacheable"));
+ goto err;
}
- char *begin = sql;
- while(*begin == ' ' || *begin == '\t') begin++;
- if ( toupper(begin[0])!='S' ||
- toupper(begin[1])!='E' ||
- toupper(begin[2])!='L')
+ /* Test if the query is a SELECT */
+ while (*sql == ' ' || *sql == '\t')
{
- DBUG_PRINT("info", ("Not look like SELECT"));
- DBUG_RETURN(1);
+ sql++;
+ query_length--;
}
- if (thd->temporary_tables != 0 || !thd->safe_to_cache_query )
+ if (toupper(sql[0]) != 'S' || toupper(sql[1]) != 'E' ||
+ toupper(sql[2]) !='L')
{
- DBUG_PRINT("info", ("SELECT is non-cachable"));
- DBUG_RETURN(1);
+ DBUG_PRINT("qcache", ("The statement is not a SELECT; Not cached"));
+ goto err;
}
STRUCT_LOCK(&structure_guard_mutex);
if (query_cache_size == 0)
{
- DBUG_PRINT("info", ("query cache disabled on not in autocommit mode"));
- DBUG_RETURN(1);
+ DBUG_PRINT("qcache", ("query cache disabled and not in autocommit mode"));
+ STRUCT_UNLOCK(&structure_guard_mutex);
+ goto err;
}
- DBUG_PRINT("info", (" sql %u '%s'", query_length, sql));
- Query_cache_block *query_block = 0;
+ DBUG_PRINT("qcache", (" sql %u '%s'", query_length, sql));
+ Query_cache_block *query_block;
/*
prepare flags:
- most significant bit - CLIENT_LONG_FLAG,
- other - charset number (0 no charset convertion)
+ Most significant bit - CLIENT_LONG_FLAG,
+ Other - charset number (0 no charset convertion)
*/
- byte flags = (thd->client_capabilities & CLIENT_LONG_FLAG ? 0x80 : 0);
+ flags = (thd->client_capabilities & CLIENT_LONG_FLAG ? 0x80 : 0);
if (thd->convert_set != 0)
{
flags |= (byte) thd->convert_set->number();
-#ifndef DBUG_OFF
- if ( (thd->convert_set->number() & QUERY_CACHE_CHARSET_CONVERT_MASK) !=
- thd->convert_set->number())
- {
- wreck(__LINE__,
- "charset number bigger than QUERY_CACHE_CHARSET_CONVERT_MASK");
- }
-#endif
+ DBUG_ASSERT(thd->convert_set->number() < 128);
}
sql[query_length] = (char) flags;
- query_block = (Query_cache_block *)
- hash_search(&queries, sql, query_length+1);
+ query_block = (Query_cache_block *) hash_search(&queries, sql,
+ query_length+1);
sql[query_length] = '\0';
- /*quick abort on unlocked data*/
+ /* Quick abort on unlocked data */
if (query_block == 0 ||
query_block->query()->result() == 0 ||
query_block->query()->result()->type != Query_cache_block::RESULT)
{
STRUCT_UNLOCK(&structure_guard_mutex);
- DBUG_PRINT("info", ("No query in query hash or no results"));
- DBUG_RETURN(1);
+ DBUG_PRINT("qcache", ("No query in query hash or no results"));
+ goto err;
}
- DBUG_PRINT("info", ("Query in query hash 0x%lx", (ulong)query_block));
+ DBUG_PRINT("qcache", ("Query in query hash 0x%lx", (ulong)query_block));
- /* now lock and test that nothing changed while blocks was unlocked */
+ /* Now lock and test that nothing changed while blocks was unlocked */
BLOCK_LOCK_RD(query_block);
STRUCT_UNLOCK(&structure_guard_mutex);
- Query_cache_query * query = query_block->query();
- Query_cache_block * first_result_block = query->result();
- Query_cache_block * result_block = first_result_block;
- if (result_block == 0 ||
- result_block->type != Query_cache_block::RESULT)
- {
- DBUG_PRINT("info", ("query found, but no data or data incomplete"));
- DBUG_RETURN(1); //no data in query
- }
- DBUG_PRINT("info", ("Query have result 0x%lx", (ulong)query));
-
- //check access;
- TABLE_COUNTER_TYPE t = 0;
- for(; t < query_block->n_tables; t++)
- {
- TABLE_LIST table_list;
- table_list.next = 0;
- table_list.use_index = table_list.ignore_index = 0;
- table_list.table = 0;
- table_list.grant.grant_table = 0;
- table_list.grant.version = table_list.grant.privilege =
- table_list.grant.want_privilege = 0;
- table_list.outer_join = 0;
- table_list.straight = 0;
- table_list.updating = 0;
- table_list.shared = 0;
-
- Query_cache_table * table = query_block->table(t)->parent;
- table_list.db = table->db();
- table_list.name = table_list.real_name = table->table();
- if (check_table_access(thd,SELECT_ACL,&table_list))
- {
- DBUG_PRINT("info",
- ("probably no SELECT access to %s.%s =>\
- return to normal processing",
- table_list.db, table_list.name));
- DBUG_RETURN(1); //no access
- }
+ query = query_block->query();
+ result_block= first_result_block= query->result();
+
+ if (result_block == 0 || result_block->type != Query_cache_block::RESULT)
+ {
+ /* The query is probably yet processed */
+ DBUG_PRINT("qcache", ("query found, but no data or data incomplete"));
+ goto err;
}
+ DBUG_PRINT("qcache", ("Query have result 0x%lx", (ulong) query));
+
+ // Check access;
+ block_table= query_block->table(0);
+ block_table_end= block_table+query_block->n_tables;
+ for ( ; block_table != block_table_end; block_table++)
+ {
+ TABLE_LIST table_list;
+ bzero((char*) &table_list,sizeof(table_list));
+ Query_cache_table *table = block_table->parent;
+ table_list.db = table->db();
+ table_list.name = table_list.real_name = table->table();
+ if (check_table_access(thd,SELECT_ACL,&table_list))
+ {
+ DBUG_PRINT("qcache",
+ ("probably no SELECT access to %s.%s => return to normal processing",
+ table_list.db, table_list.name));
+ goto err;
+ }
+ }
move_to_query_list_end(query_block);
hits++;
+ /*
+ Send cached result to client
+ */
do
{
- DBUG_PRINT("info", ("Results (len %lu, used %lu, headers %lu)",
+ DBUG_PRINT("qcache", ("Results (len %lu, used %lu, headers %lu)",
result_block->length, result_block->used,
result_block->headers_len()+
ALIGN_SIZE(sizeof(Query_cache_result))));
- Query_cache_result * result = result_block->result();
- net_real_write(&thd->net, result->data(),
- result_block->used -
- result_block->headers_len() -
- ALIGN_SIZE(sizeof(Query_cache_result)));
+ Query_cache_result *result = result_block->result();
+ if (net_real_write(&thd->net, result->data(),
+ result_block->used -
+ result_block->headers_len() -
+ ALIGN_SIZE(sizeof(Query_cache_result))))
+ break; // Client aborted
result_block = result_block->next;
} while (result_block != first_result_block);
thd->limit_found_rows = query->found_rows();
BLOCK_UNLOCK_RD(query_block);
-
DBUG_RETURN(0);
+
+err:
+ DBUG_RETURN(1);
}
+/*
+ Remove all cached queries that uses any of the tables in the list
+*/
+
void Query_cache::invalidate(TABLE_LIST *tables_used)
{
DBUG_ENTER("Query_cache::invalidate (table list)");
@@ -746,6 +918,10 @@ void Query_cache::invalidate(TABLE_LIST *tables_used)
DBUG_VOID_RETURN;
}
+/*
+ Remove all cached queries that uses the given table
+*/
+
void Query_cache::invalidate(TABLE *table)
{
DBUG_ENTER("Query_cache::invalidate (table)");
@@ -759,6 +935,14 @@ void Query_cache::invalidate(TABLE *table)
DBUG_VOID_RETURN;
}
+
+/*
+ Remove all cached queries that uses the given table type.
+ TODO: This is currently used to invalidate InnoDB tables on commit.
+ We should remove this function and only invalidate tables
+ used in the transaction.
+*/
+
void Query_cache::invalidate(Query_cache_table::query_cache_table_type type)
{
DBUG_ENTER("Query_cache::invalidate (type)");
@@ -771,25 +955,27 @@ void Query_cache::invalidate(Query_cache_table::query_cache_table_type type)
Query_cache_block *table_block = tables_blocks[type];
do
{
- /*
- store next block address defore deletetion of current block
- */
+ /* Store next block address defore deleting the current block */
Query_cache_block *next = table_block->next;
invalidate_table(table_block);
- if (next == table_block)
+ if (next == table_block) // End of list
break;
table_block = next;
- } while (table_block != tables_blocks[type]);
-
+ } while (table_block != tables_blocks[type]);
}
STRUCT_UNLOCK(&structure_guard_mutex);
}
DBUG_VOID_RETURN;
}
+
+/*
+ Remove all cached queries that uses the given database
+*/
+
void Query_cache::invalidate(char *db)
{
DBUG_ENTER("Query_cache::invalidate (db)");
@@ -802,13 +988,13 @@ void Query_cache::invalidate(char *db)
int i = 0;
for(; i < (int) Query_cache_table::TYPES_NUMBER; i++)
{
- if (tables_blocks[i] != 0) //cache not empty
+ if (tables_blocks[i] != 0) // Cache not empty
{
Query_cache_block *table_block = tables_blocks[i];
do
{
/*
- store next block address defore deletetion of current block
+ Store next block address defore deletetion of current block
*/
Query_cache_block *next = table_block->next;
@@ -827,27 +1013,29 @@ void Query_cache::invalidate(char *db)
DBUG_VOID_RETURN;
}
-void Query_cache::invalidate_by_MyISAM_filename(char * filename)
+
+void Query_cache::invalidate_by_MyISAM_filename(const char *filename)
{
DBUG_ENTER("Query_cache::invalidate_by_MyISAM_filename");
if (query_cache_size > 0)
{
+ /* Calculate the key outside the lock to make the lock shorter */
+ char key[MAX_DBKEY_LENGTH];
+ uint key_length= filename_2_table_key(key, filename);
STRUCT_LOCK(&structure_guard_mutex);
- if (query_cache_size > 0)
+ if (query_cache_size > 0) // Safety if cache removed
{
- char key[MAX_DBKEY_LENGTH];
- uint key_length =
- Query_cache::filename_2_table_key(key, filename);
-
- Query_cache_block *table_block;
- if ((table_block = (Query_cache_block*)
- hash_search(&tables, key, key_length)))
- invalidate_table(table_block);
+ Query_cache_block *table_block;
+ if ((table_block = (Query_cache_block*) hash_search(&tables, key,
+ key_length)))
+ invalidate_table(table_block);
}
STRUCT_UNLOCK(&structure_guard_mutex);
}
DBUG_VOID_RETURN;
}
+
+
void Query_cache::flush()
{
DBUG_ENTER("Query_cache::flush");
@@ -873,6 +1061,7 @@ void Query_cache::pack(ulong join_limit, uint iteration_limit)
DBUG_VOID_RETURN;
}
+
void Query_cache::destroy()
{
DBUG_ENTER("Query_cache::destroy");
@@ -882,161 +1071,10 @@ void Query_cache::destroy()
DBUG_VOID_RETURN;
}
-#ifndef DBUG_OFF
-
-void Query_cache::wreck(uint line, const char * message)
-{
- DBUG_ENTER("Query_cache::wreck");
- query_cache_size = 0;
- DBUG_PRINT("error", (" %s", message));
- DBUG_PRINT("warning", ("=================================="));
- DBUG_PRINT("warning", ("%5d QUERY CACHE WRECK => DISABLED",line));
- DBUG_PRINT("warning", ("=================================="));
- current_thd->killed = 1;
- bins_dump();
- cache_dump();
- DBUG_VOID_RETURN;
-}
-
-void Query_cache::bins_dump()
-{
- DBUG_PRINT("info", ("mem_bin_num=%u, mem_bin_steps=%u",
- mem_bin_num, mem_bin_steps));
- DBUG_PRINT("info", ("-------------------------"));
- DBUG_PRINT("info", (" size idx step"));
- DBUG_PRINT("info", ("-------------------------"));
- uint i = 0;
- for(; i < mem_bin_steps; i++)
- {
- DBUG_PRINT("info", ("%10lu %3d %10lu", steps[i].size, steps[i].idx,
- steps[i].increment));
- }
- DBUG_PRINT("info", ("-------------------------"));
- DBUG_PRINT("info", (" size num"));
- DBUG_PRINT("info", ("-------------------------"));
- i = 0;
- for(; i < mem_bin_num; i++)
- {
- DBUG_PRINT("info", ("%10lu %3d 0x%lx", bins[i].size, bins[i].number,
- (ulong)&(bins[i])));
- if (bins[i].free_blocks)
- {
- Query_cache_block * block = bins[i].free_blocks;
- do{
- DBUG_PRINT("info", ("\\-- %lu 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx",
- block->length, (ulong)block,
- (ulong)block->next, (ulong)block->prev,
- (ulong)block->pnext, (ulong)block->pprev));
- block = block->next;
- } while ( block != bins[i].free_blocks );
- }
- }
- DBUG_PRINT("info", ("-------------------------"));
-}
-
-void Query_cache::cache_dump()
-{
- DBUG_PRINT("info", ("-------------------------------------"));
- DBUG_PRINT("info", (" length used t nt"));
- DBUG_PRINT("info", ("-------------------------------------"));
- Query_cache_block * i = first_block;
- do
- {
- DBUG_PRINT("info",
- ("%10lu %10lu %1d %2d 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx",
- i->length, i->used, (int)i->type,
- i->n_tables, (ulong)i,
- (ulong)i->next, (ulong)i->prev, (ulong)i->pnext,
- (ulong)i->pprev));
- i = i->pnext;
- } while ( i != first_block );
- DBUG_PRINT("info", ("-------------------------------------"));
-}
-void Query_cache::queries_dump()
-{
- DBUG_PRINT("info", ("------------------"));
- DBUG_PRINT("info", (" QUERIES"));
- DBUG_PRINT("info", ("------------------"));
- if (queries_blocks != 0)
- {
- Query_cache_block * i = queries_blocks;
- do
- {
- uint len;
- char * str = (char*) Query_cache_query::cache_key((byte*) i, &len, 0);
- byte flags = (byte) str[len-1];
- str[len-1] = 0; //safe only under structure_guard_mutex locked
- DBUG_PRINT("info", ("%u (%u,%u) %s",len,
- ((flags & QUERY_CACHE_CLIENT_LONG_FLAG_MASK)?1:0),
- (flags & QUERY_CACHE_CHARSET_CONVERT_MASK), str));
- str[len-1] = (char)flags;
- DBUG_PRINT("info", ("-b- 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx", (ulong)i,
- (ulong)i->next, (ulong)i->prev, (ulong)i->pnext,
- (ulong)i->pprev));
- TABLE_COUNTER_TYPE t = 0;
- for (; t < i->n_tables; t++)
- {
- Query_cache_table * table = i->table(t)->parent;
- DBUG_PRINT("info", ("-t- '%s' '%s'", table->db(), table->table()));
- }
- Query_cache_query * header = i->query();
- if (header->result())
- {
- Query_cache_block * result_block = header->result();
- Query_cache_block * result_beg = result_block;
- do
- {
- DBUG_PRINT("info", ("-r- %u %lu/%lu 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx",
- (uint) result_block->type,
- result_block->length, result_block->used,
- (ulong) result_block,
- (ulong) result_block->next,
- (ulong) result_block->prev,
- (ulong) result_block->pnext,
- (ulong) result_block->pprev));
- result_block = result_block->next;
- } while ( result_block != result_beg );
- }
- i = i->next;
- } while ( i != queries_blocks );
- }
- else
- {
- DBUG_PRINT("info", ("no queries in list"));
- }
- DBUG_PRINT("info", ("------------------"));
-}
-
-void Query_cache::tables_dump()
-{
- DBUG_PRINT("info", ("--------------------"));
- DBUG_PRINT("info", ("TABLES"));
- DBUG_PRINT("info", ("--------------------"));
- int i = 0;
- for(; i < (int) Query_cache_table::TYPES_NUMBER; i++)
- {
- DBUG_PRINT("info", ("--- type %u", i));
- if (tables_blocks[i] != 0)
- {
- Query_cache_block * table_block = tables_blocks[i];
- do
- {
- Query_cache_table * table = table_block->table();
- DBUG_PRINT("info", ("'%s' '%s'", table->db(), table->table()));
- table_block = table_block->next;
- } while ( table_block != tables_blocks[i]);
- }
- else
- DBUG_PRINT("info", ("no tables in list"));
- }
- DBUG_PRINT("info", ("--------------------"));
-}
-
-#endif
/*****************************************************************************
- * init/destroy
- *****************************************************************************/
+ init/destroy
+*****************************************************************************/
void Query_cache::init()
{
@@ -1046,205 +1084,174 @@ void Query_cache::init()
DBUG_VOID_RETURN;
}
+
ulong Query_cache::init_cache()
{
+ uint mem_bin_count, num, step;
+ ulong mem_bin_size, prev_size, inc;
+ ulong additional_data_size, max_mem_bin_size, approx_additional_data_size;
+
DBUG_ENTER("Query_cache::init_cache");
if (!initialized)
- {
- DBUG_PRINT("info", ("first time init"));
init();
- }
- ulong additional_data_size = 0,
- approx_additional_data_size = sizeof(Query_cache) +
- sizeof(gptr)*(def_query_hash_size+def_query_hash_size);
-
- ulong max_mem_bin_size = 0;
+ approx_additional_data_size = (sizeof(Query_cache) +
+ sizeof(gptr)*(def_query_hash_size+
+ def_query_hash_size));
if (query_cache_size < approx_additional_data_size)
- {
- additional_data_size = 0;
- approx_additional_data_size = 0;
- make_disabled();
- }
- else
- {
- query_cache_size -= approx_additional_data_size;
+ goto err;
- //Count memory bins number.
+ query_cache_size -= approx_additional_data_size;
- /*
- The idea is inherited from GNU malloc with some add-ons.
- Free memory blocks are stored in bins according to their sizes.
- The bins are stored in size-descending order.
- The bins are approximately logarithmically separated by size.
-
- Opposite to GNU malloc bin splitting is not fixed but calculated
- depending on cache size. Spliting calculating stored in cache and
- then used for bin finding.
-
- For example:
- query_cache_size>>QUERY_CACHE_MEM_BIN_FIRST_STEP_PWR2 = 100,
- min_allocation_unit = 17,
- QUERY_CACHE_MEM_BIN_STEP_PWR2 = 1,
- QUERY_CACHE_MEM_BIN_PARTS_INC = 1,
- QUERY_CACHE_MEM_BIN_PARTS_MUL = 1
- (in followed picture showed right (low) bound of bin):
+ /*
+ Count memory bins number.
+ Check section 6. in start comment for the used algorithm.
+ */
- | 100>>1 50>>1 |25>>1|
- | | | | | |
- | 100 75 50 41 33 25 21 18 15| 12 | - bins right (low) bounds
- |\---/\-----/\--------/\--------|---/ |
- | 0 1 2 3 | | - steps
- \-----------------------------/ \---/
- bins that we store in cache this bin showed for example only
- */
- max_mem_bin_size =
- query_cache_size >> QUERY_CACHE_MEM_BIN_FIRST_STEP_PWR2;
- uint mem_bin_count = 1 + QUERY_CACHE_MEM_BIN_PARTS_INC;
- mem_bin_count = (uint) (mem_bin_count * QUERY_CACHE_MEM_BIN_PARTS_MUL);
- mem_bin_num = 1;
- mem_bin_steps = 1;
- ulong mem_bin_size = max_mem_bin_size >> QUERY_CACHE_MEM_BIN_STEP_PWR2;
- ulong prev_size = 0;
- while (mem_bin_size > min_allocation_unit)
- {
- mem_bin_num += mem_bin_count;
- prev_size = mem_bin_size;
- mem_bin_size >>= QUERY_CACHE_MEM_BIN_STEP_PWR2;
- mem_bin_steps++;
- mem_bin_count += QUERY_CACHE_MEM_BIN_PARTS_INC;
- mem_bin_count = (uint) (mem_bin_count * QUERY_CACHE_MEM_BIN_PARTS_MUL);
-
- //prevent too small bins spacing
- if (mem_bin_count > (mem_bin_size>>QUERY_CACHE_MEM_BIN_SPC_LIM_PWR2))
- mem_bin_count=(mem_bin_size>>QUERY_CACHE_MEM_BIN_SPC_LIM_PWR2);
- }
- ulong inc = (prev_size - mem_bin_size) / mem_bin_count;
- mem_bin_num += (mem_bin_count - (min_allocation_unit - mem_bin_size)/inc);
+ max_mem_bin_size = query_cache_size >> QUERY_CACHE_MEM_BIN_FIRST_STEP_PWR2;
+ mem_bin_count = (uint) ((1 + QUERY_CACHE_MEM_BIN_PARTS_INC) *
+ QUERY_CACHE_MEM_BIN_PARTS_MUL);
+ mem_bin_num = 1;
+ mem_bin_steps = 1;
+ mem_bin_size = max_mem_bin_size >> QUERY_CACHE_MEM_BIN_STEP_PWR2;
+ prev_size = 0;
+ while (mem_bin_size > min_allocation_unit)
+ {
+ mem_bin_num += mem_bin_count;
+ prev_size = mem_bin_size;
+ mem_bin_size >>= QUERY_CACHE_MEM_BIN_STEP_PWR2;
mem_bin_steps++;
- additional_data_size = mem_bin_num *
- ALIGN_SIZE(sizeof(Query_cache_memory_bin))+
- mem_bin_steps * ALIGN_SIZE(sizeof(Query_cache_memory_bin_step));
+ mem_bin_count += QUERY_CACHE_MEM_BIN_PARTS_INC;
+ mem_bin_count = (uint) (mem_bin_count * QUERY_CACHE_MEM_BIN_PARTS_MUL);
+
+ // Prevent too small bins spacing
+ if (mem_bin_count > (mem_bin_size >> QUERY_CACHE_MEM_BIN_SPC_LIM_PWR2))
+ mem_bin_count= (mem_bin_size >> QUERY_CACHE_MEM_BIN_SPC_LIM_PWR2);
}
+ inc = (prev_size - mem_bin_size) / mem_bin_count;
+ mem_bin_num += (mem_bin_count - (min_allocation_unit - mem_bin_size)/inc);
+ mem_bin_steps++;
+ additional_data_size = ((mem_bin_num+1) *
+ ALIGN_SIZE(sizeof(Query_cache_memory_bin))+
+ (mem_bin_steps *
+ ALIGN_SIZE(sizeof(Query_cache_memory_bin_step))));
+
if (query_cache_size < additional_data_size)
- {
- additional_data_size = 0;
- approx_additional_data_size = 0;
- make_disabled();
- }
- else
- query_cache_size -= additional_data_size;
+ goto err;
+ query_cache_size -= additional_data_size;
STRUCT_LOCK(&structure_guard_mutex);
if (query_cache_size <= min_allocation_unit)
{
- DBUG_PRINT("info",
+ DBUG_PRINT("qcache",
(" query_cache_size <= min_allocation_unit => cache disabled"));
- make_disabled();
+ STRUCT_UNLOCK(&structure_guard_mutex);
+ goto err;
}
- else
+
+ if (!(cache = (byte *)
+ my_malloc_lock(query_cache_size+additional_data_size, MYF(0))))
{
- if ( (cache = (byte *)
- my_malloc_lock(query_cache_size+additional_data_size, MYF(0)))==0 )
- {
- DBUG_PRINT("warning",
- ("can't allocate query cache memory => cache disabled"));
- make_disabled();
- }
- else
- {
- DBUG_PRINT("info",
- ("cache length %lu, min unit %lu, %u bins",
- query_cache_size, min_allocation_unit, mem_bin_num));
-
- steps = (Query_cache_memory_bin_step *) cache;
- bins = (Query_cache_memory_bin *)
- (cache +
- mem_bin_steps * ALIGN_SIZE(sizeof(Query_cache_memory_bin_step)));
-
- first_block = (Query_cache_block *) (cache + additional_data_size);
- first_block->init(query_cache_size);
- first_block->pnext=first_block->pprev=first_block;
- first_block->next=first_block->prev=first_block;
-
- free_memory = query_cache_size;
-
- /* prepare bins */
-
- bins[0].init(max_mem_bin_size);
- steps[0].init(max_mem_bin_size,0,0);
- uint mem_bin_count = 1 + QUERY_CACHE_MEM_BIN_PARTS_INC;
- mem_bin_count = (uint) (mem_bin_count * QUERY_CACHE_MEM_BIN_PARTS_MUL);
- uint num = 1;
- ulong mem_bin_size = max_mem_bin_size >> QUERY_CACHE_MEM_BIN_STEP_PWR2;
- uint step = 1;
- while (mem_bin_size > min_allocation_unit)
- {
- ulong inc = (steps[step-1].size - mem_bin_size) / mem_bin_count;
+ STRUCT_UNLOCK(&structure_guard_mutex);
+ goto err;
+ }
- unsigned long size = mem_bin_size;
- uint i = mem_bin_count;
- for(; i > 0; i--)
- {
- bins[num+i-1].init(size);
- size += inc;
- }
- num += mem_bin_count;
- steps[step].init(mem_bin_size, num-1, inc);
- mem_bin_size >>= QUERY_CACHE_MEM_BIN_STEP_PWR2;
- step++;
- mem_bin_count += QUERY_CACHE_MEM_BIN_PARTS_INC;
- mem_bin_count = (uint) (mem_bin_count * QUERY_CACHE_MEM_BIN_PARTS_MUL);
- if (mem_bin_count > (mem_bin_size>>QUERY_CACHE_MEM_BIN_SPC_LIM_PWR2))
- mem_bin_count=(mem_bin_size>>QUERY_CACHE_MEM_BIN_SPC_LIM_PWR2);
- }
- ulong inc = (steps[step-1].size - mem_bin_size) / mem_bin_count;
- /*
- num + mem_bin_count > mem_bin_num, but index never be > mem_bin_num
- because block with size < min_allocated_unit never will be requested
- */
- steps[step].init(mem_bin_size, num + mem_bin_count - 1, inc);
- uint skiped = (min_allocation_unit - mem_bin_size)/inc;
- ulong size = mem_bin_size + inc*skiped;
- uint i = mem_bin_count - skiped;
- for(; i > 0; i--)
- {
- bins[num+i-1].init(size);
- size += inc;
- }
+ DBUG_PRINT("qcache", ("cache length %lu, min unit %lu, %u bins",
+ query_cache_size, min_allocation_unit, mem_bin_num));
- insert_into_free_memory_list(first_block);
+ steps = (Query_cache_memory_bin_step *) cache;
+ bins = ((Query_cache_memory_bin *)
+ (cache + mem_bin_steps *
+ ALIGN_SIZE(sizeof(Query_cache_memory_bin_step))));
- DUMP(this);
+ first_block = (Query_cache_block *) (cache + additional_data_size);
+ first_block->init(query_cache_size);
+ first_block->pnext=first_block->pprev=first_block;
+ first_block->next=first_block->prev=first_block;
- VOID(hash_init(&queries,def_query_hash_size, 0, 0,
- Query_cache_query::cache_key,
- (void (*)(void*))Query_cache_query::free_cache,
- 0));
- VOID(hash_init(&tables,def_table_hash_size, 0, 0,
- Query_cache_table::cache_key,
- (void (*)(void*))Query_cache_table::free_cache,
- 0));
+ /* Prepare bins */
+
+ bins[0].init(max_mem_bin_size);
+ steps[0].init(max_mem_bin_size,0,0);
+ mem_bin_count = (uint) ((1 + QUERY_CACHE_MEM_BIN_PARTS_INC) *
+ QUERY_CACHE_MEM_BIN_PARTS_MUL);
+ num= step= 1;
+ mem_bin_size = max_mem_bin_size >> QUERY_CACHE_MEM_BIN_STEP_PWR2;
+ while (mem_bin_size > min_allocation_unit)
+ {
+ ulong incr = (steps[step-1].size - mem_bin_size) / mem_bin_count;
+ unsigned long size = mem_bin_size;
+ for (uint i= mem_bin_count; i > 0; i--)
+ {
+ bins[num+i-1].init(size);
+ size += incr;
}
+ num += mem_bin_count;
+ steps[step].init(mem_bin_size, num-1, incr);
+ mem_bin_size >>= QUERY_CACHE_MEM_BIN_STEP_PWR2;
+ step++;
+ mem_bin_count += QUERY_CACHE_MEM_BIN_PARTS_INC;
+ mem_bin_count = (uint) (mem_bin_count * QUERY_CACHE_MEM_BIN_PARTS_MUL);
+ if (mem_bin_count > (mem_bin_size >> QUERY_CACHE_MEM_BIN_SPC_LIM_PWR2))
+ mem_bin_count=(mem_bin_size >> QUERY_CACHE_MEM_BIN_SPC_LIM_PWR2);
}
+ inc = (steps[step-1].size - mem_bin_size) / mem_bin_count;
+
+ /*
+ num + mem_bin_count > mem_bin_num, but index never be > mem_bin_num
+ because block with size < min_allocated_unit never will be requested
+ */
+
+ steps[step].init(mem_bin_size, num + mem_bin_count - 1, inc);
+ {
+ uint skiped = (min_allocation_unit - mem_bin_size)/inc;
+ ulong size = mem_bin_size + inc*skiped;
+ uint i = mem_bin_count - skiped;
+ while (i-- > 0)
+ {
+ bins[num+i].init(size);
+ size += inc;
+ }
+ }
+ bins[mem_bin_num].number= 1; // For easy end test
+ free_memory= 0;
+ insert_into_free_memory_list(first_block);
+
+ DUMP(this);
+
+ VOID(hash_init(&queries,def_query_hash_size, 0, 0,
+ query_cache_query_get_key, 0, 0));
+ VOID(hash_init(&tables,def_table_hash_size, 0, 0,
+ query_cache_table_get_key, 0, 0));
+
queries_in_cache = 0;
queries_blocks = 0;
STRUCT_UNLOCK(&structure_guard_mutex);
DBUG_RETURN(query_cache_size +
additional_data_size + approx_additional_data_size);
+
+err:
+ make_disabled();
+ DBUG_RETURN(0);
}
+
+/* Disable the use of the query cache */
+
void Query_cache::make_disabled()
{
DBUG_ENTER("Query_cache::make_disabled");
- query_cache_size = 0;
- free_memory = 0;
- bins = 0;
- steps = 0;
- cache = 0;
- mem_bin_num = mem_bin_steps = 0;
+ query_cache_size= 0;
+ free_memory= 0;
+ bins= 0;
+ steps= 0;
+ cache= 0;
+ mem_bin_num= mem_bin_steps= 0;
+ queries_in_cache= 0;
+ first_block= 0;
DBUG_VOID_RETURN;
}
+
void Query_cache::free_cache(my_bool destruction)
{
DBUG_ENTER("Query_cache::free_cache");
@@ -1261,20 +1268,14 @@ void Query_cache::free_cache(my_bool destruction)
}
#endif
- bins[0].free_blocks->destroy(); /* all cache memory must be
- in one this block */
- DBUG_PRINT("info", ("free memory %lu (should be %lu)",
- free_memory , query_cache_size));
- free_memory = 0;
-
- my_free((gptr)cache, MYF(MY_ALLOW_ZERO_PTR));
- first_block = 0;
- bins = 0;
- cache = 0;
- query_cache_size = 0;
+ /* Becasue we did a flush, all cache memory must be in one this block */
+ bins[0].free_blocks->destroy();
+ DBUG_PRINT("qcache", ("free memory %lu (should be %lu)",
+ free_memory , query_cache_size));
+ my_free((gptr) cache, MYF(MY_ALLOW_ZERO_PTR));
+ make_disabled();
hash_free(&queries);
hash_free(&tables);
- queries_in_cache = 0;
if (!destruction)
STRUCT_UNLOCK(&structure_guard_mutex);
}
@@ -1282,85 +1283,100 @@ void Query_cache::free_cache(my_bool destruction)
}
/*****************************************************************************
- * free block data
- *****************************************************************************/
+ Free block data
+*****************************************************************************/
+
+/*
+ The following assumes we have a lock on the cache
+*/
void Query_cache::flush_cache()
{
- while(queries_blocks != 0){
+ while (queries_blocks != 0)
+ {
BLOCK_LOCK_WR(queries_blocks);
free_query(queries_blocks);
}
}
+/*
+ Free oldest query that is not in use by another thread.
+ Returns 1 if we couldn't remove anything
+*/
+
my_bool Query_cache::free_old_query()
{
DBUG_ENTER("Query_cache::free_old_query");
- if (queries_blocks == 0)
+ if (!queries_blocks)
{
- DBUG_RETURN(0);
- }
- /*
- try_lock_writing used to prevent clinch because
- here lock sequence is breached, also we don't need remove
- locked queries at this point
- */
- Query_cache_block *query_block = 0;
- if (queries_blocks != 0)
- {
- Query_cache_block *i = queries_blocks;
- do
+ /*
+ try_lock_writing used to prevent client because here lock
+ sequence is breached.
+ Also we don't need remove locked queries at this point.
+ */
+ Query_cache_block *query_block = 0;
+ if (queries_blocks != 0)
{
- Query_cache_query * header = i->query();
- if (header->result() != 0 &&
- header->result()->type == Query_cache_block::RESULT &&
- i->query()->try_lock_writing())
+ Query_cache_block *block = queries_blocks;
+ /* Search until we find first query that we can remove */
+ do
{
- query_block = i;
- break;
- }
- i = i->next;
- } while ( i != queries_blocks );
- }
+ Query_cache_query *header = block->query();
+ if (header->result() != 0 &&
+ header->result()->type == Query_cache_block::RESULT &&
+ block->query()->try_lock_writing())
+ {
+ query_block = block;
+ break;
+ }
+ } while ((block=block->next) != queries_blocks );
+ }
- if (query_block != 0)
- {
- free_query(query_block);
- DBUG_RETURN(1);
+ if (query_block != 0)
+ {
+ free_query(query_block);
+ DBUG_RETURN(0);
+ }
}
- else
- DBUG_RETURN(0);
+ DBUG_RETURN(1); // Nothing to remove
}
-/* query_block must be lock_writing() */
-void Query_cache::free_query(Query_cache_block * query_block)
+/*
+ Free query from query cache.
+ query_block must be locked for writing.
+ This function will remove (and destroy) the lock for the query.
+*/
+
+void Query_cache::free_query(Query_cache_block *query_block)
{
DBUG_ENTER("Query_cache::free_query");
- DBUG_PRINT("info", ("free query 0x%lx %lu bytes result",
- (ulong)query_block,
+ DBUG_PRINT("qcache", ("free query 0x%lx %lu bytes result",
+ (ulong) query_block,
query_block->query()->length() ));
+
queries_in_cache--;
hash_delete(&queries,(byte *) query_block);
- Query_cache_query * query = query_block->query();
+ Query_cache_query *query = query_block->query();
+
if (query->writer() != 0)
{
+ /* Tell MySQL that this query should not be cached anymore */
query->writer()->query_cache_query = 0;
query->writer(0);
}
- double_linked_list_exclude(query_block, queries_blocks);
- TABLE_COUNTER_TYPE i = 0;
- for(; i < query_block->n_tables; i++)
- {
- unlink_table(query_block->table(i));
- }
+ double_linked_list_exclude(query_block, &queries_blocks);
+ Query_cache_block_table *table=query_block->table(0);
+
+ for (TABLE_COUNTER_TYPE i=0; i < query_block->n_tables; i++)
+ unlink_table(table++);
Query_cache_block *result_block = query->result();
if (result_block != 0)
{
- Query_cache_block * block = result_block;
+ Query_cache_block *block = result_block;
do
{
- Query_cache_block * current = block;
+ Query_cache_block *current = block;
block = block->next;
free_memory_block(current);
} while (block != result_block);
@@ -1373,8 +1389,8 @@ void Query_cache::free_query(Query_cache_block * query_block)
}
/*****************************************************************************
- * query data creation
- *****************************************************************************/
+ Query data creation
+*****************************************************************************/
Query_cache_block *
Query_cache::write_block_data(ulong data_len, gptr data,
@@ -1383,217 +1399,223 @@ Query_cache::write_block_data(ulong data_len, gptr data,
TABLE_COUNTER_TYPE ntab,
my_bool under_guard)
{
+ ulong all_headers_len = (ALIGN_SIZE(sizeof(Query_cache_block)) +
+ ALIGN_SIZE(ntab*sizeof(Query_cache_block_table)) +
+ header_len);
+ ulong len = data_len + all_headers_len;
DBUG_ENTER("Query_cache::write_block_data");
- ulong all_headers_len = ALIGN_SIZE(sizeof(Query_cache_block)) +
- ntab*ALIGN_SIZE(sizeof(Query_cache_block_table)) +
- header_len;
- DBUG_PRINT("info", ("data: %ld, header: %ld, all header: %ld",
+ DBUG_PRINT("qcache", ("data: %ld, header: %ld, all header: %ld",
data_len, header_len, all_headers_len));
- ulong len = data_len + all_headers_len;
- Query_cache_block * block = allocate_block(max(len, min_allocation_unit),
- 1, 0, under_guard);
+ Query_cache_block *block = allocate_block(max(len, min_allocation_unit),
+ 1, 0, under_guard);
if (block != 0)
{
block->type = type;
block->n_tables = ntab;
block->used = len;
- memcpy((void*)(((byte *) block)+
- all_headers_len),
- (void*)data,
- data_len);
+ memcpy((void*) (((byte *) block)+ all_headers_len),
+ (void*) data, data_len);
}
DBUG_RETURN(block);
}
+
+/*
+ On success STRUCT_UNLOCK(&query_cache.structure_guard_mutex) will be done.
+*/
+
my_bool
-Query_cache::append_result_data(Query_cache_block * &result,
+Query_cache::append_result_data(Query_cache_block **current_block,
ulong data_len, gptr data,
- Query_cache_block * query_block,
- Query_cache_block * first_data_block)
+ Query_cache_block *query_block)
{
- DBUG_ENTER("Query_cache::uppend_result_data");
- DBUG_PRINT("info", ("append %lu bytes to 0x%lx query"));
+ DBUG_ENTER("Query_cache::append_result_data");
+ DBUG_PRINT("qcache", ("append %lu bytes to 0x%lx query",
+ data_len, query_block));
+
if (query_block->query()->add(data_len) > query_cache_limit)
{
- DBUG_PRINT("info", ("size limit reached %lu > %lu",
+ DBUG_PRINT("qcache", ("size limit reached %lu > %lu",
query_block->query()->length(),
query_cache_limit));
- result=0;
+ *current_block=0; // Mark error
DBUG_RETURN(0);
}
- if (first_data_block == 0)
+ if (*current_block == 0)
{
- DBUG_PRINT("info", ("allocated first result data block 0x%xl", data_len));
+ DBUG_PRINT("qcache", ("allocated first result data block %lu", data_len));
/*
- STRUCT_UNLOCK(&structure_guard_mutex); will be done by
- query_cache.append_result_data if success;
+ STRUCT_UNLOCK(&structure_guard_mutex) Will be done by
+ write_result_data if success;
*/
- DBUG_RETURN(write_result_data(result, data_len, data, query_block,
+ DBUG_RETURN(write_result_data(current_block, data_len, data, query_block,
Query_cache_block::RES_BEG));
}
- else
- {
- result = first_data_block;
- }
- Query_cache_block * last_block = first_data_block->prev;
+ Query_cache_block *last_block = (*current_block)->prev;
- DBUG_PRINT("info", ("lastblock 0x%lx len %lu used %lu",
- (ulong)last_block, last_block->length,
+ DBUG_PRINT("qcache", ("lastblock 0x%lx len %lu used %lu",
+ (ulong) last_block, last_block->length,
last_block->used));
my_bool success = 1;
+ ulong last_block_free_space= last_block->length - last_block->used;
- ulong last_block_free_space = last_block->length - last_block->used;
-
- //write 'tail' of data, that can't be appended to last block
+ /*
+ We will first allocate and write the 'tail' of data, that doesn't fit
+ in the 'last_block'. Only if this succeeds, we will fill the last_block.
+ This saves us a memcpy if the query doesn't fit in the query cache.
+ */
- //try join blocks if physicaly next block is free...
+ // Try join blocks if physically next block is free...
if (last_block_free_space < data_len &&
append_next_free_block(last_block,
max(data_len - last_block_free_space,
QUERY_CACHE_MIN_RESULT_DATA_SIZE)))
last_block_free_space = last_block->length - last_block->used;
- //if no space in last block (even after join) allocate new block
+ // If no space in last block (even after join) allocate new block
if (last_block_free_space < data_len)
{
- //TODO try get memory from next free block (if exist) (is it needed?)
- DBUG_PRINT("info", ("allocate new block for %lu bytes",
+ // TODO: Try get memory from next free block (if exist) (is it needed?)
+ DBUG_PRINT("qcache", ("allocate new block for %lu bytes",
data_len-last_block_free_space));
Query_cache_block *new_block = 0;
/*
- STRUCT_UNLOCK(&structure_guard_mutex); will be done by
- query_cache.append_result_data
+ On success STRUCT_UNLOCK(&structure_guard_mutex) will be done
+ by the next call
*/
- success = write_result_data(new_block, data_len-last_block_free_space,
+ success = write_result_data(&new_block, data_len-last_block_free_space,
(gptr)(((byte*)data)+last_block_free_space),
query_block,
Query_cache_block::RES_CONT);
/*
new_block may be not 0 even !success (if write_result_data
- allocate small block but filed allocate continue
+ allocate small block but failed allocate continue
*/
if (new_block != 0)
double_linked_list_join(last_block, new_block);
}
else
- //it is success (nobody can prevent us write data)
+ {
+ // It is success (nobody can prevent us write data)
STRUCT_UNLOCK(&structure_guard_mutex);
+ }
- // append last block (if it is possible)
- if (last_block_free_space > 0)
+ // Now finally write data to the last block
+ if (success && last_block_free_space > 0)
{
ulong to_copy = min(data_len,last_block_free_space);
- DBUG_PRINT("info", ("use free space %lub at block 0x%lx to copy %lub",
+ DBUG_PRINT("qcache", ("use free space %lub at block 0x%lx to copy %lub",
last_block_free_space, (ulong)last_block, to_copy));
- memcpy((void*)(((byte*)last_block)+last_block->used),
- (void*)data,to_copy);
+ memcpy((void*) (((byte*) last_block) + last_block->used), (void*) data,
+ to_copy);
last_block->used+=to_copy;
}
-
DBUG_RETURN(success);
}
-my_bool Query_cache::write_result_data(Query_cache_block * &result_block,
+
+my_bool Query_cache::write_result_data(Query_cache_block **result_block,
ulong data_len, gptr data,
- Query_cache_block * query_block,
+ Query_cache_block *query_block,
Query_cache_block::block_type type)
{
DBUG_ENTER("Query_cache::write_result_data");
- DBUG_PRINT("info", ("data_len %lu",data_len));
+ DBUG_PRINT("qcache", ("data_len %lu",data_len));
- //reserve block(s) for filling
+ // Reserve block(s) for filling
my_bool success = allocate_data_chain(result_block, data_len, query_block);
if (success)
{
- //it is success (nobody can prevent us write data)
+ // It is success (nobody can prevent us write data)
STRUCT_UNLOCK(&structure_guard_mutex);
- byte * rest = (byte*) data;
- Query_cache_block * block = result_block;
- uint headers_len = ALIGN_SIZE(sizeof(Query_cache_block)) +
- ALIGN_SIZE(sizeof(Query_cache_result));
- // now fill list of blocks that created by allocate_data_chain
+ byte *rest = (byte*) data;
+ Query_cache_block *block = *result_block;
+ uint headers_len = (ALIGN_SIZE(sizeof(Query_cache_block)) +
+ ALIGN_SIZE(sizeof(Query_cache_result)));
+ // Now fill list of blocks that created by allocate_data_chain
do
{
block->type = type;
ulong length = block->used - headers_len;
- DBUG_PRINT("info", ("write %lu byte in block 0x%lx",length,
+ DBUG_PRINT("qcache", ("write %lu byte in block 0x%lx",length,
(ulong)block));
- memcpy((void*)(((byte*)block)+headers_len),
- (void*)rest,length);
-
+ memcpy((void*)(((byte*) block)+headers_len), (void*) rest, length);
rest += length;
block = block->next;
type = Query_cache_block::RES_CONT;
- } while (block != result_block);
+ } while (block != *result_block);
}
else
{
- if (result_block != 0)
+ if (*result_block != 0)
{
- // destroy list of blocks that created & locked by lock_result_data
- Query_cache_block * block = result_block;
+ // Destroy list of blocks that was created & locked by lock_result_data
+ Query_cache_block *block = *result_block;
do
{
- Query_cache_block * current = block;
+ Query_cache_block *current = block;
block = block->next;
free_memory_block(current);
- } while (block != result_block);
- result_block = 0;
+ } while (block != *result_block);
+ *result_block = 0;
/*
- it is not success => not unlock structure_guard_mutex (we need it to
- free query)
+ It is not success => not unlock structure_guard_mutex (we need it to
+ free query)
*/
}
}
- DBUG_PRINT("info", ("success %d", (int) success));
+ DBUG_PRINT("qcache", ("success %d", (int) success));
DBUG_RETURN(success);
}
-my_bool Query_cache::allocate_data_chain(Query_cache_block * &result_block,
+/*
+ Allocate one or more blocks to hold data
+*/
+
+my_bool Query_cache::allocate_data_chain(Query_cache_block **result_block,
ulong data_len,
- Query_cache_block * query_block)
+ Query_cache_block *query_block)
{
- DBUG_ENTER("Query_cache::allocate_data_chain");
-
- ulong all_headers_len = ALIGN_SIZE(sizeof(Query_cache_block)) +
- ALIGN_SIZE(sizeof(Query_cache_result));
+ ulong all_headers_len = (ALIGN_SIZE(sizeof(Query_cache_block)) +
+ ALIGN_SIZE(sizeof(Query_cache_result)));
ulong len = data_len + all_headers_len;
- DBUG_PRINT("info", ("data_len %lu, all_headers_len %lu",
+ DBUG_ENTER("Query_cache::allocate_data_chain");
+ DBUG_PRINT("qcache", ("data_len %lu, all_headers_len %lu",
data_len, all_headers_len));
- result_block = allocate_block(max(min_result_data_size,len),
- min_result_data_size == 0,
- all_headers_len + min_result_data_size,
- 1);
- my_bool success = (result_block != 0);
+ *result_block = allocate_block(max(min_result_data_size,len),
+ min_result_data_size == 0,
+ all_headers_len + min_result_data_size,
+ 1);
+ my_bool success = (*result_block != 0);
if (success)
{
- result_block->n_tables = 0;
- result_block->used = 0;
- result_block->type = Query_cache_block::RES_INCOMPLETE;
- result_block->next = result_block->prev = result_block;
- Query_cache_result * header = result_block->result();
+ Query_cache_block *new_block= *result_block;
+ new_block->n_tables = 0;
+ new_block->used = 0;
+ new_block->type = Query_cache_block::RES_INCOMPLETE;
+ new_block->next = new_block->prev = new_block;
+ Query_cache_result *header = new_block->result();
header->parent(query_block);
- Query_cache_block * next_block = 0;
- if (result_block->length < len)
+ if (new_block->length < len)
{
/*
- allocated less memory then we need (no big memory blocks) =>
- to be continue
+ We got less memory then we need (no big memory blocks) =>
+ Continue to allocated more blocks until we got everything we need.
*/
- Query_cache_block * next_block;
- if ((success = allocate_data_chain(next_block,
- len - result_block->length,
+ Query_cache_block *next_block;
+ if ((success = allocate_data_chain(&next_block,
+ len - new_block->length,
query_block)))
- double_linked_list_join(result_block, next_block);
+ double_linked_list_join(new_block, next_block);
}
if (success)
{
- result_block->used = min(len, result_block->length);
+ new_block->used = min(len, new_block->length);
- DBUG_PRINT("info", ("Block len %lu used %lu",
- result_block->length, result_block->used));
+ DBUG_PRINT("qcache", ("Block len %lu used %lu",
+ new_block->length, new_block->used));
}
else
DBUG_PRINT("warning", ("Can't allocate block for continue"));
@@ -1604,25 +1626,28 @@ my_bool Query_cache::allocate_data_chain(Query_cache_block * &result_block,
}
/*****************************************************************************
- * tables management
- *****************************************************************************/
+ Tables management
+*****************************************************************************/
+
+/*
+ Invalidate the first table in the table_list
+*/
void Query_cache::invalidate_table(TABLE_LIST *table_list)
{
if (table_list->table != 0)
- invalidate_table(table_list->table);
+ invalidate_table(table_list->table); // Table is open
else
{
- char key[MAX_DBKEY_LENGTH], *key_ptr;
+ char key[MAX_DBKEY_LENGTH];
uint key_length;
Query_cache_block *table_block;
key_length=(uint) (strmov(strmov(key,table_list->db)+1,
table_list->real_name) -key)+ 1;
- key_ptr = key;
- // we dont store temporary tables => no key_length+=4 ...
+ // We don't store temporary tables => no key_length+=4 ...
if ((table_block = (Query_cache_block*)
- hash_search(&tables,key_ptr,key_length)))
+ hash_search(&tables,key,key_length)))
invalidate_table(table_block);
}
}
@@ -1630,302 +1655,328 @@ void Query_cache::invalidate_table(TABLE_LIST *table_list)
void Query_cache::invalidate_table(TABLE *table)
{
Query_cache_block *table_block;
- if ((table_block = (Query_cache_block*)
- hash_search(&tables,table->table_cache_key,table->key_length)))
+ if ((table_block = ((Query_cache_block*)
+ hash_search(&tables, table->table_cache_key,
+ table->key_length))))
invalidate_table(table_block);
}
void Query_cache::invalidate_table_in_db(Query_cache_block *table_block,
- char * db)
+ char *db)
{
/*
table key consist of data_base_name + '\0' + table_name +'\0'...
- => we may use strcmp.
+ => we may use strcmp to compare database names.
*/
- if (strcmp(db, (char*)(table_block->table()->db()))==0)
- {
+ if (strcmp(db, (char*)(table_block->table()->db())) == 0)
invalidate_table(table_block);
- }
}
+
void Query_cache::invalidate_table(Query_cache_block *table_block)
{
- Query_cache_block_table * list_root = table_block->table(0);
- while(list_root->next != list_root)
+ Query_cache_block_table *list_root = table_block->table(0);
+ while (list_root->next != list_root)
{
- Query_cache_block * query_block = list_root->next->block();
+ Query_cache_block *query_block = list_root->next->block();
BLOCK_LOCK_WR(query_block);
free_query(query_block);
}
}
-my_bool Query_cache::register_all_tables(Query_cache_block * block,
- TABLE_LIST * tables_used,
+
+my_bool Query_cache::register_all_tables(Query_cache_block *block,
+ TABLE_LIST *tables_used,
TABLE_COUNTER_TYPE tables)
{
- DBUG_PRINT("info", ("register tables block 0x%lx, n %d, header %x",
- (ulong)block, (int) tables,
- (int)ALIGN_SIZE(sizeof(Query_cache_block)) ));
+ TABLE_COUNTER_TYPE n;
+ DBUG_PRINT("qcache", ("register tables block 0x%lx, n %d, header %x",
+ (ulong) block, (int) tables,
+ (int) ALIGN_SIZE(sizeof(Query_cache_block))));
- TABLE_COUNTER_TYPE n = 0;
- TABLE_LIST * i = tables_used;
- for(; i != 0; i=i->next, n++)
+ Query_cache_block_table *block_table = block->table(0);
+
+ for (n=0; tables_used; tables_used=tables_used->next, n++, block_table++)
{
- DBUG_PRINT("info",
+ DBUG_PRINT("qcache",
("table %s, db %s, openinfo at 0x%lx, keylen %u, key at 0x%lx",
- i->real_name, i->db, (ulong) i->table,
- i->table->key_length,
- (ulong) i->table->table_cache_key));
- Query_cache_block_table * block_table = block->table(n);
+ tables_used->real_name, tables_used->db,
+ (ulong) tables_used->table,
+ tables_used->table->key_length,
+ (ulong) tables_used->table->table_cache_key));
block_table->n=n;
- if (!insert_table(i->table->key_length,
- i->table->table_cache_key, block_table,
- Query_cache_table::type_convertion(i->table->db_type)))
+ if (!insert_table(tables_used->table->key_length,
+ tables_used->table->table_cache_key, block_table,
+ Query_cache_table::type_convertion(tables_used->table->
+ db_type)))
break;
- if (i->table->db_type == DB_TYPE_MRG_MYISAM)
+ /*
+ TODO: (Low priority)
+ The following has to be recoded to not test for a specific table
+ type but instead call a handler function that does this for us.
+ Something like the following:
+
+ tables_used->table->file->register_used_filenames(callback,
+ first_argument);
+ */
+ if (tables_used->table->db_type == DB_TYPE_MRG_MYISAM)
{
- ha_myisammrg * handler = (ha_myisammrg *)i->table->file;
+ ha_myisammrg *handler = (ha_myisammrg *) tables_used->table->file;
MYRG_INFO *file = handler->myrg_info();
- MYRG_TABLE *table = file->open_tables;
- for(;table != file->end_table ; table++)
+ for (MYRG_TABLE *table = file->open_tables;
+ table != file->end_table ;
+ table++)
{
char key[MAX_DBKEY_LENGTH];
- uint key_length =
- Query_cache::filename_2_table_key(key, table->table->filename);
- n++;
- Query_cache_block_table * block_table = block->table(n);
- block_table->n=n;
+ uint key_length =filename_2_table_key(key, table->table->filename);
+ (++block_table)->n= ++n;
if (!insert_table(key_length, key, block_table,
Query_cache_table::type_convertion(DB_TYPE_MYISAM)))
goto err;
}
}
}
+
err:
- if (i != 0)
- {
- n--;
- DBUG_PRINT("info", ("filed at table %d", (int)n));
- TABLE_COUNTER_TYPE idx = 0;
- for(i = tables_used;
- idx < n;
- idx++)
- {
- unlink_table(block->table(n));
- }
+ if (tables_used)
+ {
+ DBUG_PRINT("qcache", ("failed at table %d", (int) n));
+ /* Unlink the tables we allocated above */
+ for (Query_cache_block_table *tmp = block->table(0) ;
+ tmp != block_table;
+ tmp++)
+ unlink_table(tmp);
}
- return(i == 0);
+ return (tables_used == 0);
}
-my_bool Query_cache::insert_table(uint key_len, char * key,
- Query_cache_block_table * node,
- Query_cache_table::query_cache_table_type
- type)
+/*
+ Insert used tablename in cache
+ Returns 0 on error
+*/
+
+my_bool
+Query_cache::insert_table(uint key_len, char *key,
+ Query_cache_block_table *node,
+ Query_cache_table::query_cache_table_type type)
{
DBUG_ENTER("Query_cache::insert_table");
- DBUG_PRINT("info", ("insert table node 0x%lx, len %d",
+ DBUG_PRINT("qcache", ("insert table node 0x%lx, len %d",
(ulong)node, key_len));
- Query_cache_block *table_block = (Query_cache_block *)
- hash_search(&tables, key, key_len);
+
+ Query_cache_block *table_block = ((Query_cache_block *)
+ hash_search(&tables, key, key_len));
if (table_block == 0)
{
- DBUG_PRINT("info", ("new table block from 0x%lx (%u)",
- (ulong)key, (int) key_len));
+ DBUG_PRINT("qcache", ("new table block from 0x%lx (%u)",
+ (ulong) key, (int) key_len));
table_block = write_block_data(key_len, (gptr) key,
ALIGN_SIZE(sizeof(Query_cache_table)),
Query_cache_block::TABLE,
1, 1);
if (table_block == 0)
{
- DBUG_PRINT("info", ("Can't write table name to cache"));
+ DBUG_PRINT("qcache", ("Can't write table name to cache"));
DBUG_RETURN(0);
}
- Query_cache_table * header = table_block->table();
+ Query_cache_table *header = table_block->table();
header->type(type);
double_linked_list_simple_include(table_block,
- tables_blocks[type]);
- Query_cache_block_table * list_root = table_block->table(0);
+ &tables_blocks[type]);
+ Query_cache_block_table *list_root = table_block->table(0);
list_root->n = 0;
list_root->next = list_root->prev = list_root;
- if (hash_insert(&tables, (const byte *)table_block))
+ if (hash_insert(&tables, (const byte *) table_block))
{
- DBUG_PRINT("info", ("Can't insert table to hash"));
+ DBUG_PRINT("qcache", ("Can't insert table to hash"));
// write_block_data return locked block
free_memory_block(table_block);
DBUG_RETURN(0);
}
- char * db = header->db();
+ char *db = header->db();
+ /*
+ TODO: Eliminate strlen() by sending this to the function
+ To do this we have to add db_len to the TABLE_LIST and TABLE structures.
+ */
header->table(db + strlen(db) + 1);
}
- Query_cache_block_table * list_root = table_block->table(0);
- node->next = list_root->next; list_root->next = node;
- node->next->prev = node; node->prev = list_root;
+ Query_cache_block_table *list_root = table_block->table(0);
+ node->next = list_root->next;
+ list_root->next = node;
+ node->next->prev = node;
+ node->prev = list_root;
node->parent = table_block->table();
DBUG_RETURN(1);
}
-void Query_cache::unlink_table(Query_cache_block_table * node)
+
+void Query_cache::unlink_table(Query_cache_block_table *node)
{
- node->prev->next = node->next; node->next->prev = node->prev;
- Query_cache_block_table * neighbour = node->next;
+ node->prev->next = node->next;
+ node->next->prev = node->prev;
+ Query_cache_block_table *neighbour = node->next;
if (neighbour->next == neighbour)
{
- // list is empty (neighbour is root of list)
- Query_cache_block * table_block = neighbour->block();
+ // list is empty (neighbor is root of list)
+ Query_cache_block *table_block = neighbour->block();
double_linked_list_exclude(table_block,
- tables_blocks[table_block->table()->type()]);
+ &tables_blocks[table_block->table()->type()]);
hash_delete(&tables,(byte *) table_block);
free_memory_block(table_block);
}
}
/*****************************************************************************
- * free memory management
- *****************************************************************************/
+ Free memory management
+*****************************************************************************/
-Query_cache_block * Query_cache::allocate_block(ulong len,
- my_bool not_less,
- ulong min,
- my_bool under_guard)
+Query_cache_block *
+Query_cache::allocate_block(ulong len, my_bool not_less, ulong min,
+ my_bool under_guard)
{
DBUG_ENTER("Query_cache::allocate_n_lock_block");
- DBUG_PRINT("info", ("len %lu, not less %d, min %lu, uder_guard %d",
+ DBUG_PRINT("qcache", ("len %lu, not less %d, min %lu, uder_guard %d",
len, not_less,min,under_guard));
if (len >= min(query_cache_size, query_cache_limit))
{
- DBUG_PRINT("info", ("Query cache hase only %lu memory and limit %lu",
+ DBUG_PRINT("qcache", ("Query cache hase only %lu memory and limit %lu",
query_cache_size, query_cache_limit));
DBUG_RETURN(0); // in any case we don't have such piece of memory
}
- if (!under_guard){STRUCT_LOCK(&structure_guard_mutex);};
+ if (!under_guard)
+ STRUCT_LOCK(&structure_guard_mutex);
- Query_cache_block *block = get_free_block(len, not_less, min);
- while( block == 0 && free_old_query())
+ /* Free old queries until we have enough memory to store this block */
+ Query_cache_block *block;
+ do
{
- block = get_free_block(len, not_less, min);
+ block= get_free_block(len, not_less, min);
}
+ while (block == 0 && !free_old_query());
- if (block!=0)
+ if (block != 0) // If we found a suitable block
{
if (block->length > ALIGN_SIZE(len) + min_allocation_unit)
split_block(block,ALIGN_SIZE(len));
}
- if (!under_guard){STRUCT_UNLOCK(&structure_guard_mutex);};
+ if (!under_guard)
+ STRUCT_UNLOCK(&structure_guard_mutex);
DBUG_RETURN(block);
}
-Query_cache_block * Query_cache::get_free_block (ulong len,
- my_bool not_less,
- ulong min)
+
+Query_cache_block *
+Query_cache::get_free_block(ulong len, my_bool not_less, ulong min)
{
- DBUG_ENTER("Query_cache::get_free_block");
Query_cache_block *block = 0, *first = 0;
- DBUG_PRINT("info",("length %lu, not_less %d, min %lu", len,
+ DBUG_ENTER("Query_cache::get_free_block");
+ DBUG_PRINT("qcache",("length %lu, not_less %d, min %lu", len,
(int)not_less, min));
- /* find block with minimal size > len */
-
+ /* Find block with minimal size > len */
uint start = find_bin(len);
// try matching bin
if (bins[start].number != 0)
{
- Query_cache_block * list = bins[start].free_blocks;
+ Query_cache_block *list = bins[start].free_blocks;
first = list;
- while(first->next != list && first->length < len)
- {
+ while (first->next != list && first->length < len)
first=first->next;
- }
if (first->length >= len)
block=first;
}
if (block == 0 && start > 0)
{
- DBUG_PRINT("info",("try bins whith more bigger blocks"));
- //try more big bins
+ DBUG_PRINT("qcache",("Try bins with bigger block size"));
+ // Try more big bins
int i = start - 1;
- while(i > 0 && bins[i].number == 0)
+ while (i > 0 && bins[i].number == 0)
i--;
if (bins[i].number > 0)
block = bins[i].free_blocks;
}
- // if no big blocks => try less size (if it is possible)
+
+ // If no big blocks => try less size (if it is possible)
if (block == 0 && ! not_less)
{
- DBUG_PRINT("info",("try smaller blocks"));
+ DBUG_PRINT("qcache",("Try to allocate a smaller block"));
if (first != 0 && first->length > min)
block = first;
else
{
uint i = start + 1;
- while( i < mem_bin_num && bins[i].number == 0)
- i++;
- if (i < mem_bin_num && bins[i].number > 0 &&
- bins[i].free_blocks->prev->length >= min)
+ /* bins[mem_bin_num].number contains 1 for easy end test */
+ for (i= start+1 ; bins[i].number == 0 ; i++) ;
+ if (i < mem_bin_num && bins[i].free_blocks->prev->length >= min)
block = bins[i].free_blocks->prev;
}
}
if (block != 0)
exclude_from_free_memory_list(block);
- DBUG_PRINT("info",("getting block 0x%lx", (ulong) block));
+ DBUG_PRINT("qcache",("getting block 0x%lx", (ulong) block));
DBUG_RETURN(block);
}
-void Query_cache::free_memory_block(Query_cache_block * block)
+
+void Query_cache::free_memory_block(Query_cache_block *block)
{
DBUG_ENTER("Query_cache::free_n_unlock_memory_block");
block->used=0;
- DBUG_PRINT("info",("first_block 0x%lx, block 0x%lx, pnext 0x%lx pprev 0x%lx",
+ DBUG_PRINT("qcache",("first_block 0x%lx, block 0x%lx, pnext 0x%lx pprev 0x%lx",
(ulong) first_block, (ulong) block,block->pnext,
(ulong) block->pprev));
+
if (block->pnext != first_block && block->pnext->is_free())
- {
block = join_free_blocks(block, block->pnext);
- }
if (block != first_block && block->pprev->is_free())
- {
block = join_free_blocks(block->pprev, block->pprev);
- }
insert_into_free_memory_list(block);
DBUG_VOID_RETURN;
}
-void Query_cache::split_block(Query_cache_block * block,ulong len)
+
+void Query_cache::split_block(Query_cache_block *block,ulong len)
{
DBUG_ENTER("Query_cache::split_block");
- Query_cache_block * new_block = (Query_cache_block *)(((byte*)block)+len);
+ Query_cache_block *new_block = (Query_cache_block*)(((byte*) block)+len);
new_block->init(block->length - len);
block->length=len;
- new_block->pnext = block->pnext; block->pnext = new_block;
- new_block->pprev = block; new_block->pnext->pprev = new_block;
+ new_block->pnext = block->pnext;
+ block->pnext = new_block;
+ new_block->pprev = block;
+ new_block->pnext->pprev = new_block;
insert_into_free_memory_list(new_block);
- DBUG_PRINT("info", ("split 0x%lx (%lu) new 0x%lx",
+ DBUG_PRINT("qcache", ("split 0x%lx (%lu) new 0x%lx",
(ulong) block, len, (ulong) new_block));
DBUG_VOID_RETURN;
}
+
Query_cache_block *
Query_cache::join_free_blocks(Query_cache_block *first_block,
- Query_cache_block * block_in_list)
+ Query_cache_block *block_in_list)
{
+ Query_cache_block *second_block;
DBUG_ENTER("Query_cache::join_free_blocks");
- DBUG_PRINT("info",
+ DBUG_PRINT("qcache",
("join first 0x%lx, pnext 0x%lx, in list 0x%lx",
(ulong) first_block, (ulong) first_block->pnext,
(ulong) block_in_list));
- exclude_from_free_memory_list(block_in_list);
- Query_cache_block * second_block = first_block->pnext;
- // may be was not free block
- second_block->type = Query_cache_block::FREE;second_block->used=0;
+ exclude_from_free_memory_list(block_in_list);
+ second_block = first_block->pnext;
+ // May be was not free block
+ second_block->type = Query_cache_block::FREE;
+ second_block->used=0;
second_block->destroy();
first_block->length += second_block->length;
@@ -1935,136 +1986,135 @@ Query_cache::join_free_blocks(Query_cache_block *first_block,
DBUG_RETURN(first_block);
}
-my_bool Query_cache::append_next_free_block(Query_cache_block * block,
+
+my_bool Query_cache::append_next_free_block(Query_cache_block *block,
ulong add_size)
{
+ Query_cache_block *next_block = block->pnext;
DBUG_ENTER("Query_cache::append_next_free_block");
DBUG_PRINT("enter", ("block 0x%lx, add_size %lu", (ulong) block,
add_size));
- Query_cache_block * next_block = block->pnext;
+
if (next_block->is_free())
{
- exclude_from_free_memory_list(next_block);
ulong old_len = block->length;
-
+ exclude_from_free_memory_list(next_block);
next_block->destroy();
block->length += next_block->length;
block->pnext = next_block->pnext;
next_block->pnext->pprev = block;
- if (block->length >
- ALIGN_SIZE(old_len + add_size) + min_allocation_unit)
+ if (block->length > ALIGN_SIZE(old_len + add_size) + min_allocation_unit)
split_block(block,ALIGN_SIZE(old_len + add_size));
DBUG_PRINT("exit", ("block was appended"));
DBUG_RETURN(1);
}
- else
- {
- DBUG_PRINT("exit", ("block was not appended"));
- DBUG_RETURN(0);
- }
+ DBUG_RETURN(0);
}
-void Query_cache::exclude_from_free_memory_list(Query_cache_block * free_block)
+
+void Query_cache::exclude_from_free_memory_list(Query_cache_block *free_block)
{
DBUG_ENTER("Query_cache::exclude_from_free_memory_list");
- Query_cache_memory_bin * bin = *((Query_cache_memory_bin **)
- free_block->data());
- double_linked_list_exclude(free_block ,bin->free_blocks);
+ Query_cache_memory_bin *bin = *((Query_cache_memory_bin **)
+ free_block->data());
+ double_linked_list_exclude(free_block, &bin->free_blocks);
bin->number--;
free_memory-=free_block->length;
- DBUG_PRINT("info",("exclude block 0x%lx, bin 0x%lx", (ulong) free_block,
- (ulong)bin));
+ DBUG_PRINT("qcache",("exclude block 0x%lx, bin 0x%lx", (ulong) free_block,
+ (ulong) bin));
DBUG_VOID_RETURN;
}
-void Query_cache::insert_into_free_memory_list(Query_cache_block * free_block)
+void Query_cache::insert_into_free_memory_list(Query_cache_block *free_block)
{
DBUG_ENTER("Query_cache::insert_into_free_memory_list");
uint idx = find_bin(free_block->length);
- insert_into_free_memory_sorted_list(free_block, bins[idx].free_blocks);
+ insert_into_free_memory_sorted_list(free_block, &bins[idx].free_blocks);
/*
- we have enough memory in block for storing bin reference due to
+ We have enough memory in block for storing bin reference due to
min_allocation_unit choice
*/
- Query_cache_memory_bin * *bin_ptr = (Query_cache_memory_bin**)
- free_block->data();
- *bin_ptr = &(bins[idx]);
- bins[idx].number++;
- DBUG_PRINT("info",("insert block 0x%lx, bin[%d] 0x%lx",
- (ulong) free_block, idx,
- (ulong) &(bins[idx])));
+ Query_cache_memory_bin **bin_ptr = ((Query_cache_memory_bin**)
+ free_block->data());
+ *bin_ptr = bins+idx;
+ (*bin_ptr)->number++;
+ DBUG_PRINT("qcache",("insert block 0x%lx, bin[%d] 0x%lx",
+ (ulong) free_block, idx, (ulong) *bin_ptr));
DBUG_VOID_RETURN;
}
uint Query_cache::find_bin(ulong size)
{
+ int i;
DBUG_ENTER("Query_cache::find_bin");
- //begin small blocks to big (small blocks frequently asked)
- int i = mem_bin_steps - 1;
- for(; i > 0 && steps[i-1].size < size; i--);
+ // Begin small blocks to big (small blocks frequently asked)
+ for (i=mem_bin_steps - 1; i > 0 && steps[i-1].size < size; i--) ;
if (i == 0)
{
// first bin not subordinate of common rules
- DBUG_PRINT("info", ("first bin (# 0), size %lu",size));
+ DBUG_PRINT("qcache", ("first bin (# 0), size %lu",size));
DBUG_RETURN(0);
}
uint bin = steps[i].idx - (uint)((size - steps[i].size)/steps[i].increment);
- DBUG_PRINT("info", ("bin %u step %u, size %lu", bin, i, size));
+ DBUG_PRINT("qcache", ("bin %u step %u, size %lu", bin, i, size));
DBUG_RETURN(bin);
}
+
/*****************************************************************************
- * lists management
- *****************************************************************************/
+ Lists management
+*****************************************************************************/
-void Query_cache::move_to_query_list_end(Query_cache_block * query_block)
+void Query_cache::move_to_query_list_end(Query_cache_block *query_block)
{
DBUG_ENTER("Query_cache::move_to_query_list_end");
- double_linked_list_exclude(query_block, queries_blocks);
- double_linked_list_simple_include(query_block, queries_blocks);
+ double_linked_list_exclude(query_block, &queries_blocks);
+ double_linked_list_simple_include(query_block, &queries_blocks);
DBUG_VOID_RETURN;
}
+
void Query_cache::insert_into_free_memory_sorted_list(Query_cache_block *
new_block,
- Query_cache_block *
- &list)
+ Query_cache_block **
+ list)
{
DBUG_ENTER("Query_cache::insert_into_free_memory_sorted_list");
/*
list sorted by size in ascendant order, because we need small blocks
- frequently than big one
+ more frequently than bigger ones
*/
new_block->used = 0;
new_block->n_tables = 0;
new_block->type = Query_cache_block::FREE;
- if (list == 0)
+ if (*list == 0)
{
- list = new_block->next=new_block->prev=new_block;
- DBUG_PRINT("info", ("inserted into empty list"));
+ *list = new_block->next=new_block->prev=new_block;
+ DBUG_PRINT("qcache", ("inserted into empty list"));
}
else
{
- Query_cache_block *point = list;
+ Query_cache_block *point = *list;
if (point->length >= new_block->length)
{
point = point->prev;
- list = new_block;
+ *list = new_block;
}
else
{
- while(point->next != list &&
- point->next->length < new_block->length)
- {
+ /* Find right position in sorted list to put block */
+ while (point->next != *list &&
+ point->next->length < new_block->length)
point=point->next;
- }
}
- new_block->prev = point; new_block->next = point->next;
- new_block->next->prev = new_block; point->next = new_block;
+ new_block->prev = point;
+ new_block->next = point->next;
+ new_block->next->prev = new_block;
+ point->next = new_block;
}
free_memory+=new_block->length;
DBUG_VOID_RETURN;
@@ -2072,48 +2122,50 @@ void Query_cache::insert_into_free_memory_sorted_list(Query_cache_block *
void
-Query_cache::double_linked_list_simple_include(Query_cache_block * point,
- Query_cache_block *
- &list_pointer)
+Query_cache::double_linked_list_simple_include(Query_cache_block *point,
+ Query_cache_block **
+ list_pointer)
{
DBUG_ENTER("Query_cache::double_linked_list_simple_include");
- DBUG_PRINT("info", ("including block 0x%lx", (ulong) point));
- if (list_pointer == 0)
- list_pointer=point->next=point->prev=point;
+ DBUG_PRINT("qcache", ("including block 0x%lx", (ulong) point));
+ if (*list_pointer == 0)
+ *list_pointer=point->next=point->prev=point;
else
{
- point->next = list_pointer;
- point->prev = list_pointer->prev;
+ point->next = (*list_pointer);
+ point->prev = (*list_pointer)->prev;
point->prev->next = point;
- list_pointer->prev = point;
- list_pointer = point;
+ (*list_pointer)->prev = point;
+ (*list_pointer) = point;
}
DBUG_VOID_RETURN;
}
void
Query_cache::double_linked_list_exclude(Query_cache_block *point,
- Query_cache_block * &list_pointer)
+ Query_cache_block **list_pointer)
{
DBUG_ENTER("Query_cache::double_linked_list_exclude");
- DBUG_PRINT("info", ("excluding block 0x%lx, list 0x%lx",
+ DBUG_PRINT("qcache", ("excluding block 0x%lx, list 0x%lx",
(ulong) point, (ulong) list_pointer));
if (point->next == point)
- list_pointer = 0; // empty list
+ *list_pointer = 0; // empty list
else
{
point->next->prev = point->prev;
point->prev->next = point->next;
- if (point == list_pointer) list_pointer = point->next;
+ if (point == *list_pointer)
+ *list_pointer = point->next;
}
DBUG_VOID_RETURN;
}
+
void Query_cache::double_linked_list_join(Query_cache_block *head_tail,
Query_cache_block *tail_head)
{
Query_cache_block *head_head = head_tail->next,
- *tail_tail = tail_head->prev;
+ *tail_tail = tail_head->prev;
head_head->prev = tail_tail;
head_tail->next = tail_head;
tail_head->prev = head_tail;
@@ -2121,72 +2173,68 @@ void Query_cache::double_linked_list_join(Query_cache_block *head_tail,
}
/*****************************************************************************
- * query
- *****************************************************************************/
+ Query
+*****************************************************************************/
/*
- if query is cachable return numder tables in query
- (query whithout tables tot chached)
+ if query is cacheable return number tables in query
+ (query without tables are not cached)
*/
-TABLE_COUNTER_TYPE Query_cache::is_cachable(THD *thd,
- uint query_len, char *query,
- LEX *lex, TABLE_LIST* tables_used)
+
+TABLE_COUNTER_TYPE Query_cache::is_cacheable(THD *thd, uint32 query_len,
+ char *query,
+ LEX *lex, TABLE_LIST *tables_used)
{
TABLE_COUNTER_TYPE tables = 0;
- DBUG_ENTER("Query_cache::is_cachable");
+ DBUG_ENTER("Query_cache::is_cacheable");
+
if (lex->sql_command == SQLCOM_SELECT &&
thd->temporary_tables == 0 &&
- (thd->query_cache_type == 1 || (thd->query_cache_type == 2 &&
- (lex->select->options &
+ (thd->query_cache_type == 1 ||
+ (thd->query_cache_type == 2 && (lex->select->options &
OPTION_TO_QUERY_CACHE))) &&
thd->safe_to_cache_query)
{
- DBUG_PRINT("info", ("options %lx %lx, type %u",
+ my_bool has_transactions = 0;
+ DBUG_PRINT("qcache", ("options %lx %lx, type %u",
OPTION_TO_QUERY_CACHE,
lex->select->options,
(int) thd->query_cache_type));
- my_bool has_transactions = 0;
- TABLE_LIST * i = tables_used;
- for(; i != 0; i=i->next)
+
+ for (; tables_used; tables_used=tables_used->next)
{
tables++;
- DBUG_PRINT("info", ("table %s, db %s, type %u", i->real_name,
- i->db, i->table->db_type));
+ DBUG_PRINT("qcache", ("table %s, db %s, type %u",
+ tables_used->real_name,
+ tables_used->db, tables_used->table->db_type));
has_transactions = (has_transactions ||
- i->table->file->has_transactions());
- if (i->table->db_type == DB_TYPE_MRG_ISAM)
+ tables_used->table->file->has_transactions());
+
+ if (tables_used->table->db_type == DB_TYPE_MRG_ISAM)
{
- DBUG_PRINT("info", ("select not cachable: used MRG_ISAM table(s)"));
+ DBUG_PRINT("qcache", ("select not cacheable: used MRG_ISAM table(s)"));
DBUG_RETURN(0);
}
- if (i->table->db_type == DB_TYPE_MRG_MYISAM)
+ if (tables_used->table->db_type == DB_TYPE_MRG_MYISAM)
{
- ha_myisammrg * handler = (ha_myisammrg *)i->table->file;
+ ha_myisammrg *handler = (ha_myisammrg *)tables_used->table->file;
MYRG_INFO *file = handler->myrg_info();
- MYRG_TABLE *table = file->open_tables;
- for(;table != file->end_table ; table++)
- {
- tables++;
- DBUG_PRINT("loop", (" + 1 table (mrg_MyISAM)"));
- }
+ tables+= (file->end_table - file->open_tables);
}
}
if ((thd->options & (OPTION_NOT_AUTO_COMMIT | OPTION_BEGIN)) &&
has_transactions)
{
- DBUG_PRINT("info", ("not in autocommin mode"));
+ DBUG_PRINT("qcache", ("not in autocommin mode"));
DBUG_RETURN(0);
}
- else
- {
- DBUG_PRINT("info", ("select have %d tables", tables));
- DBUG_RETURN(tables);
- }
+ DBUG_PRINT("qcache", ("select is using %d tables", tables));
+ DBUG_RETURN(tables);
}
- DBUG_PRINT("info",
- ("not interest query: %d or not cachable, \
-options %lx %lx, type %u",
+
+ DBUG_PRINT("qcache",
+ ("not interesting query: %d or not cacheable, options %lx %lx, type %u",
(int) lex->sql_command,
OPTION_TO_QUERY_CACHE,
lex->select->options,
@@ -2194,31 +2242,36 @@ options %lx %lx, type %u",
DBUG_RETURN(0);
}
+
/*****************************************************************************
- * packing
- *****************************************************************************/
+ Packing
+*****************************************************************************/
void Query_cache::pack_cache()
{
- DBUG_ENTER("Query_cache::pack_cache");
STRUCT_LOCK(&structure_guard_mutex);
- DUMP(this);
- byte * border = 0;
- Query_cache_block * before = 0;
+ byte *border = 0;
+ Query_cache_block *before = 0;
ulong gap = 0;
my_bool ok = 1;
- Query_cache_block * i = first_block;
+ Query_cache_block *i = first_block;
+ DBUG_ENTER("Query_cache::pack_cache");
+ DUMP(this);
+
do
{
- ok = move_by_type(border, before, gap, i);
+ ok = move_by_type(&border, &before, &gap, i);
i = i->pnext;
} while (ok && i != first_block);
+
if (border != 0)
{
- Query_cache_block * new_block = (Query_cache_block *) border;
+ Query_cache_block *new_block = (Query_cache_block *) border;
new_block->init(gap);
- new_block->pnext = before->pnext; before->pnext = new_block;
- new_block->pprev = before; new_block->pnext->pprev = new_block;
+ new_block->pnext = before->pnext;
+ before->pnext = new_block;
+ new_block->pprev = before;
+ new_block->pnext->pprev = new_block;
insert_into_free_memory_list(new_block);
}
DUMP(this);
@@ -2226,219 +2279,225 @@ void Query_cache::pack_cache()
DBUG_VOID_RETURN;
}
-my_bool Query_cache::move_by_type(byte * &border,
- Query_cache_block * &before, ulong &gap, Query_cache_block * i)
+
+my_bool Query_cache::move_by_type(byte **border,
+ Query_cache_block **before, ulong *gap,
+ Query_cache_block *block)
{
DBUG_ENTER("Query_cache::move_by_type");
+
my_bool ok = 1;
- switch(i->type)
- {
+ switch (block->type) {
case Query_cache_block::FREE:
+ {
+ DBUG_PRINT("qcache", ("block 0x%lx FREE", (ulong) block));
+ if (*border == 0)
{
- DBUG_PRINT("info", ("block 0x%lx FREE", (ulong) i));
- if (border == 0)
- {
- border = (byte *) i;
- before = i->pprev;
- DBUG_PRINT("info", ("gap begining here"));
- }
- exclude_from_free_memory_list(i);
- gap +=i->length;
- i->pprev->pnext=i->pnext;
- i->pnext->pprev=i->pprev;
- i->destroy();
- DBUG_PRINT("info", ("added to gap (%lu)", gap));
- break;
+ *border = (byte *) block;
+ *before = block->pprev;
+ DBUG_PRINT("qcache", ("gap beginning here"));
}
+ exclude_from_free_memory_list(block);
+ *gap +=block->length;
+ block->pprev->pnext=block->pnext;
+ block->pnext->pprev=block->pprev;
+ block->destroy();
+ DBUG_PRINT("qcache", ("added to gap (%lu)", *gap));
+ break;
+ }
case Query_cache_block::TABLE:
- {
- DBUG_PRINT("info", ("block 0x%lx TABLE", (ulong) i));
- if (border == 0) break;
- ulong len = i->length,
- used = i->used;
- Query_cache_block_table * list_root = i->table(0);
- Query_cache_block_table
- *tprev = list_root->prev,
- *tnext = list_root->next;
- Query_cache_block
- *prev = i->prev,
- *next = i->next,
- *pprev = i->pprev,
- *pnext = i->pnext,
- *new_block =(Query_cache_block *) border;
- char * data = (char*)i->data();
- hash_delete(&tables, (byte *)i);
- i->destroy();
- new_block->init(len);
- new_block->type=Query_cache_block::TABLE;
- new_block->used=used;
- new_block->n_tables=1;
- memcpy((char*)new_block->data(), data,
- len-new_block->headers_len());
- relink(i, new_block, next, prev, pnext, pprev);
- if (tables_blocks[new_block->table()->type()] == i)
- {
- tables_blocks[new_block->table()->type()] = new_block;
- }
- Query_cache_block_table * nlist_root = new_block->table(0);
- nlist_root->n = 0;
- nlist_root->next = (tnext==list_root?nlist_root:tnext);
- nlist_root->prev = (tprev==list_root?nlist_root:tnext);
- tnext->prev = list_root;
- tprev->next = list_root;
- border += len;
- before = new_block;
- hash_insert(&tables, (const byte *)new_block);
- DBUG_PRINT("info", ("moved %lu bytes to 0x%lx, new gap at 0x%lx",
- len, (ulong) new_block, (ulong) border));
+ {
+ DBUG_PRINT("qcache", ("block 0x%lx TABLE", (ulong) block));
+ if (*border == 0)
break;
- }
+ ulong len = block->length, used = block->used;
+ Query_cache_block_table *list_root = block->table(0);
+ Query_cache_block_table *tprev = list_root->prev,
+ *tnext = list_root->next;
+ Query_cache_block *prev = block->prev,
+ *next = block->next,
+ *pprev = block->pprev,
+ *pnext = block->pnext,
+ *new_block =(Query_cache_block *) *border;
+ char *data = (char*) block->data();
+ byte *key;
+ uint key_length;
+ key=query_cache_table_get_key((byte*) block, &key_length,0);
+ hash_search(&tables, key, key_length);
+
+ block->destroy();
+ new_block->init(len);
+ new_block->type=Query_cache_block::TABLE;
+ new_block->used=used;
+ new_block->n_tables=1;
+ memcpy((char*) new_block->data(), data, len-new_block->headers_len());
+ relink(block, new_block, next, prev, pnext, pprev);
+ if (tables_blocks[new_block->table()->type()] == block)
+ tables_blocks[new_block->table()->type()] = new_block;
+
+ Query_cache_block_table *nlist_root = new_block->table(0);
+ nlist_root->n = 0;
+ nlist_root->next = (tnext == list_root ? nlist_root : tnext);
+ nlist_root->prev = (tprev == list_root ? nlist_root: tnext);
+ tnext->prev = list_root;
+ tprev->next = list_root;
+ *border += len;
+ *before = new_block;
+ /* Fix hash to point at moved block */
+ hash_replace(&tables, tables.current_record, (byte*) new_block);
+
+ DBUG_PRINT("qcache", ("moved %lu bytes to 0x%lx, new gap at 0x%lx",
+ len, (ulong) new_block, (ulong) *border));
+ break;
+ }
case Query_cache_block::QUERY:
+ {
+ DBUG_PRINT("qcache", ("block 0x%lx QUERY", (ulong) block));
+ if (*border == 0)
+ break;
+ BLOCK_LOCK_WR(block);
+ ulong len = block->length, used = block->used;
+ TABLE_COUNTER_TYPE n_tables = block->n_tables;
+ Query_cache_block *prev = block->prev,
+ *next = block->next,
+ *pprev = block->pprev,
+ *pnext = block->pnext,
+ *new_block =(Query_cache_block*) *border;
+ char *data = (char*) block->data();
+ Query_cache_block *first_result_block = ((Query_cache_query *)
+ block->data())->result();
+ byte *key;
+ uint key_length;
+ key=query_cache_query_get_key((byte*) block, &key_length,0);
+ hash_search(&queries, key, key_length);
+
+ memcpy((char*) new_block->table(0), (char*) block->table(0),
+ ALIGN_SIZE(n_tables*sizeof(Query_cache_block_table)));
+ block->query()->unlock_n_destroy();
+ block->destroy();
+ new_block->init(len);
+ new_block->type=Query_cache_block::QUERY;
+ new_block->used=used;
+ new_block->n_tables=n_tables;
+ memcpy((char*) new_block->data(), data, len - new_block->headers_len());
+ relink(block, new_block, next, prev, pnext, pprev);
+ if (queries_blocks == block)
+ queries_blocks = new_block;
+ for (TABLE_COUNTER_TYPE j=0; j < n_tables; j++)
{
- DBUG_PRINT("info", ("block 0x%lx QUERY", (ulong) i));
- if (border == 0) break;
- BLOCK_LOCK_WR(i);
- ulong len = i->length,
- used = i->used;
- TABLE_COUNTER_TYPE n_tables = i->n_tables;
- Query_cache_block
- *prev = i->prev,
- *next = i->next,
- *pprev = i->pprev,
- *pnext = i->pnext,
- *new_block =(Query_cache_block *) border;
- char * data = (char*)i->data();
- Query_cache_block * first_result_block = ((Query_cache_query *)
- i->data())->result();
- hash_delete(&queries, (byte *)i);
- memcpy((char*)new_block->table(0), (char*)i->table(0),
- n_tables * ALIGN_SIZE(sizeof(Query_cache_block_table)));
- i->query()->unlock_n_destroy();
- i->destroy();
- new_block->init(len);
- new_block->type=Query_cache_block::QUERY;
- new_block->used=used;
- new_block->n_tables=n_tables;
- memcpy((char*)new_block->data(), data,
- len - new_block->headers_len());
- relink(i, new_block, next, prev, pnext, pprev);
- if (queries_blocks == i)
- queries_blocks = new_block;
- TABLE_COUNTER_TYPE j=0;
- for(; j< n_tables; j++)
- {
- Query_cache_block_table * block_table = new_block->table(j);
- block_table->next->prev = block_table;
- block_table->prev->next = block_table;
- }
- DBUG_PRINT("info", ("after cicle tt"));
- border += len;
- before = new_block;
- new_block->query()->result(first_result_block);
- if (first_result_block != 0)
- {
- Query_cache_block * result_block = first_result_block;
- do
- {
- result_block->result()->parent(new_block);
- result_block = result_block->next;
- } while ( result_block != first_result_block );
- }
- NET * net = new_block->query()->writer();
- if (net != 0)
+ Query_cache_block_table *block_table = new_block->table(j);
+ block_table->next->prev = block_table;
+ block_table->prev->next = block_table;
+ }
+ DBUG_PRINT("qcache", ("after circle tt"));
+ *border += len;
+ *before = new_block;
+ new_block->query()->result(first_result_block);
+ if (first_result_block != 0)
+ {
+ Query_cache_block *result_block = first_result_block;
+ do
{
- net->query_cache_query = (gptr) new_block;
- }
- hash_insert(&queries, (const byte *)new_block);
- DBUG_PRINT("info", ("moved %lu bytes to 0x%lx, new gap at 0x%lx",
- len, (ulong) new_block, (ulong) border));
- break;
+ result_block->result()->parent(new_block);
+ result_block = result_block->next;
+ } while ( result_block != first_result_block );
}
+ NET *net = new_block->query()->writer();
+ if (net != 0)
+ {
+ net->query_cache_query = (gptr) new_block;
+ }
+ /* Fix hash to point at moved block */
+ hash_replace(&queries, queries.current_record, (byte*) new_block);
+ DBUG_PRINT("qcache", ("moved %lu bytes to 0x%lx, new gap at 0x%lx",
+ len, (ulong) new_block, (ulong) *border));
+ break;
+ }
case Query_cache_block::RES_INCOMPLETE:
case Query_cache_block::RES_BEG:
case Query_cache_block::RES_CONT:
case Query_cache_block::RESULT:
- {
- DBUG_PRINT("info", ("block 0x%lx RES* (%d)", (ulong) i, (int)i->type));
- if (border == 0) break;
- Query_cache_block
- *query_block = i->result()->parent(),
- *next = i->next,
- *prev = i->prev;
- Query_cache_block::block_type type = i->type;
- BLOCK_LOCK_WR(query_block);
- ulong len = i->length,
- used = i->used;
- Query_cache_block
- *pprev = i->pprev,
- *pnext = i->pnext,
- *new_block =(Query_cache_block *) border;
- char * data = (char*)i->data();
- i->destroy();
- new_block->init(len);
- new_block->type=type;
- new_block->used=used;
- memcpy((char*)new_block->data(), data,
- len - new_block->headers_len());
- relink(i, new_block, next, prev, pnext, pprev);
- new_block->result()->parent(query_block);
- Query_cache_query * query = query_block->query();
- if (query->result() == i)
- query->result(new_block);
- border += len;
- before = new_block;
- /* if result writing complete && we have free space in block */
- ulong free_space = new_block->length - new_block->used;
- if (query->result()->type == Query_cache_block::RESULT &&
- new_block->length > new_block->used &&
- gap + free_space > min_allocation_unit &&
- new_block->length - free_space > min_allocation_unit)
- {
- border -= free_space;
- gap += free_space;
- new_block->length -= free_space;
- }
- BLOCK_UNLOCK_WR(query_block);
- DBUG_PRINT("info", ("moved %lu bytes to 0x%lx, new gap at 0x%lx",
- len, (ulong) new_block, (ulong) border));
+ {
+ DBUG_PRINT("qcache", ("block 0x%lx RES* (%d)", (ulong) block,
+ (int) block->type));
+ if (*border == 0)
break;
+ Query_cache_block *query_block = block->result()->parent(),
+ *next = block->next,
+ *prev = block->prev;
+ Query_cache_block::block_type type = block->type;
+ BLOCK_LOCK_WR(query_block);
+ ulong len = block->length, used = block->used;
+ Query_cache_block *pprev = block->pprev,
+ *pnext = block->pnext,
+ *new_block =(Query_cache_block*) *border;
+ char *data = (char*) block->data();
+ block->destroy();
+ new_block->init(len);
+ new_block->type=type;
+ new_block->used=used;
+ memcpy((char*) new_block->data(), data, len - new_block->headers_len());
+ relink(block, new_block, next, prev, pnext, pprev);
+ new_block->result()->parent(query_block);
+ Query_cache_query *query = query_block->query();
+ if (query->result() == block)
+ query->result(new_block);
+ *border += len;
+ *before = new_block;
+ /* If result writing complete && we have free space in block */
+ ulong free_space = new_block->length - new_block->used;
+ if (query->result()->type == Query_cache_block::RESULT &&
+ new_block->length > new_block->used &&
+ *gap + free_space > min_allocation_unit &&
+ new_block->length - free_space > min_allocation_unit)
+ {
+ *border -= free_space;
+ *gap += free_space;
+ new_block->length -= free_space;
}
+ BLOCK_UNLOCK_WR(query_block);
+ DBUG_PRINT("qcache", ("moved %lu bytes to 0x%lx, new gap at 0x%lx",
+ len, (ulong) new_block, (ulong) *border));
+ break;
+ }
default:
- DBUG_PRINT("error", ("unexpectet block type %d, block 0x%lx",
- (int)i->type, (ulong) i));
+ DBUG_PRINT("error", ("unexpected block type %d, block 0x%lx",
+ (int)block->type, (ulong) block));
ok = 0;
}
DBUG_RETURN(ok);
}
-void Query_cache::relink(Query_cache_block * oblock,
- Query_cache_block * nblock,
- Query_cache_block * next, Query_cache_block * prev,
- Query_cache_block * pnext, Query_cache_block * pprev)
+
+void Query_cache::relink(Query_cache_block *oblock,
+ Query_cache_block *nblock,
+ Query_cache_block *next, Query_cache_block *prev,
+ Query_cache_block *pnext, Query_cache_block *pprev)
{
- nblock->prev = (prev==oblock?nblock:prev); //check pointer to himself
- nblock->next = (next==oblock?nblock:next);
+ nblock->prev = (prev == oblock ? nblock : prev); //check pointer to himself
+ nblock->next = (next == oblock ? nblock : next);
prev->next=nblock;
next->prev=nblock;
- nblock->pprev = pprev; //physical pointer to himself have only 1 free block
+ nblock->pprev = pprev; // Physical pointer to himself have only 1 free block
nblock->pnext = pnext;
pprev->pnext=nblock;
pnext->pprev=nblock;
}
+
my_bool Query_cache::join_results(ulong join_limit)
{
//TODO
- DBUG_ENTER("Query_cache::join_results");
my_bool has_moving = 0;
- Query_cache_block *query_block = 0;
+ DBUG_ENTER("Query_cache::join_results");
+
STRUCT_LOCK(&structure_guard_mutex);
if (queries_blocks != 0)
{
- Query_cache_block *i = queries_blocks;
+ Query_cache_block *block = queries_blocks;
do
{
- Query_cache_query * header = i->query();
+ Query_cache_query *header = block->query();
if (header->result() != 0 &&
header->result()->type == Query_cache_block::RESULT &&
header->length() > join_limit)
@@ -2451,32 +2510,32 @@ my_bool Query_cache::join_results(ulong join_limit)
{
has_moving = 1;
Query_cache_block *first_result = header->result();
- ulong new_len = header->length() +
- ALIGN_SIZE(sizeof(Query_cache_block)) +
- ALIGN_SIZE(sizeof(Query_cache_result));
+ ulong new_len = (header->length() +
+ ALIGN_SIZE(sizeof(Query_cache_block)) +
+ ALIGN_SIZE(sizeof(Query_cache_result)));
if (new_result_block->length >
ALIGN_SIZE(new_len) + min_allocation_unit)
- split_block(new_result_block,ALIGN_SIZE(new_len));
- BLOCK_LOCK_WR(i);
+ split_block(new_result_block, ALIGN_SIZE(new_len));
+ BLOCK_LOCK_WR(block);
header->result(new_result_block);
new_result_block->type = Query_cache_block::RESULT;
new_result_block->n_tables = 0;
new_result_block->used = new_len;
new_result_block->next = new_result_block->prev = new_result_block;
- DBUG_PRINT("info", ("new block %lu/%lu (%lu)",
+ DBUG_PRINT("qcache", ("new block %lu/%lu (%lu)",
new_result_block->length,
new_result_block->used,
header->length()));
Query_cache_result *new_result = new_result_block->result();
- new_result->parent(i);
+ new_result->parent(block);
byte *write_to = (byte*) new_result->data();
Query_cache_block *result_block = first_result;
do
{
- ulong len = result_block->used - result_block->headers_len() -
- ALIGN_SIZE(sizeof(Query_cache_result));
+ ulong len = (result_block->used - result_block->headers_len() -
+ ALIGN_SIZE(sizeof(Query_cache_result)));
DBUG_PRINT("loop", ("add block %lu/%lu (%lu)",
result_block->length,
result_block->used,
@@ -2485,36 +2544,197 @@ my_bool Query_cache::join_results(ulong join_limit)
(char*) result_block->result()->data(),
len);
write_to += len;
- Query_cache_block * old_result_block = result_block;
+ Query_cache_block *old_result_block = result_block;
result_block = result_block->next;
free_memory_block(old_result_block);
} while (result_block != first_result);
- BLOCK_UNLOCK_WR(i);
+ BLOCK_UNLOCK_WR(block);
}
}
- i = i->next;
- } while ( i != queries_blocks );
+ block = block->next;
+ } while ( block != queries_blocks );
}
STRUCT_UNLOCK(&structure_guard_mutex);
DBUG_RETURN(has_moving);
}
-uint Query_cache::filename_2_table_key (char * key, char *filename)
+
+uint Query_cache::filename_2_table_key (char *key, const char *path)
{
- DBUG_ENTER("Query_cache::filename_2_table_key");
- char tablename[FN_REFLEN];
- char dbbuff[FN_REFLEN];
- char *dbname;
+ char tablename[FN_REFLEN+2], *filename, *dbname;
Query_cache_block *table_block;
- fn_format(tablename,filename,"","",3);
+ uint db_length;
+ DBUG_ENTER("Query_cache::filename_2_table_key");
+
+ /* Safety if filename didn't have a directory name */
+ tablename[0]= FN_LIBCHAR;
+ tablename[1]= FN_LIBCHAR;
+ /* Convert filename to this OS's format in tablename */
+ fn_format(tablename + 2, path, "", "", MY_REPLACE_EXT);
+ filename= tablename + dirname_length(tablename + 2) + 2;
+ /* Find start of databasename */
+ for (dbname= filename - 2 ; dbname[-1] != FN_LIBCHAR ; dbname--) ;
+ db_length= (filename - dbname) - 1;
+ DBUG_PRINT("qcache", ("table '%-.*s.%s'", db_length, dbname, filename));
+
+ DBUG_RETURN((uint) (strmov(strnmov(key, dbname, db_length) + 1,
+ filename) -key) + 1);
+}
+
+
+/****************************************************************************
+ Functions to be used when debugging
+****************************************************************************/
+
+#ifndef DBUG_OFF
+
+void Query_cache::wreck(uint line, const char *message)
+{
+ DBUG_ENTER("Query_cache::wreck");
+ query_cache_size = 0;
+ if (*message)
+ DBUG_PRINT("error", (" %s", message));
+ DBUG_PRINT("warning", ("=================================="));
+ DBUG_PRINT("warning", ("%5d QUERY CACHE WRECK => DISABLED",line));
+ DBUG_PRINT("warning", ("=================================="));
+ current_thd->killed = 1;
+ bins_dump();
+ cache_dump();
+ DBUG_VOID_RETURN;
+}
+
+
+void Query_cache::bins_dump()
+{
+ uint i;
+ DBUG_PRINT("qcache", ("mem_bin_num=%u, mem_bin_steps=%u",
+ mem_bin_num, mem_bin_steps));
+ DBUG_PRINT("qcache", ("-------------------------"));
+ DBUG_PRINT("qcache", (" size idx step"));
+ DBUG_PRINT("qcache", ("-------------------------"));
+ for (i=0; i < mem_bin_steps; i++)
+ {
+ DBUG_PRINT("qcache", ("%10lu %3d %10lu", steps[i].size, steps[i].idx,
+ steps[i].increment));
+ }
+ DBUG_PRINT("qcache", ("-------------------------"));
+ DBUG_PRINT("qcache", (" size num"));
+ DBUG_PRINT("qcache", ("-------------------------"));
+ for (i=0; i < mem_bin_num; i++)
+ {
+ DBUG_PRINT("qcache", ("%10lu %3d 0x%lx", bins[i].size, bins[i].number,
+ (ulong)&(bins[i])));
+ if (bins[i].free_blocks)
+ {
+ Query_cache_block *block = bins[i].free_blocks;
+ do{
+ DBUG_PRINT("qcache", ("\\-- %lu 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx",
+ block->length, (ulong)block,
+ (ulong)block->next, (ulong)block->prev,
+ (ulong)block->pnext, (ulong)block->pprev));
+ block = block->next;
+ } while ( block != bins[i].free_blocks );
+ }
+ }
+ DBUG_PRINT("qcache", ("-------------------------"));
+}
- int path_len = (strrchr(filename, '/') - filename);
- strncpy(dbbuff, filename, path_len);
- dbbuff[path_len] = '\0';
- dbname = strrchr(dbbuff, '/') + 1;
- DBUG_PRINT("info", ("table %s.%s", dbname, tablename));
+void Query_cache::cache_dump()
+{
+ DBUG_PRINT("qcache", ("-------------------------------------"));
+ DBUG_PRINT("qcache", (" length used t nt"));
+ DBUG_PRINT("qcache", ("-------------------------------------"));
+ Query_cache_block *i = first_block;
+ do
+ {
+ DBUG_PRINT("qcache",
+ ("%10lu %10lu %1d %2d 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx",
+ i->length, i->used, (int)i->type,
+ i->n_tables, (ulong)i,
+ (ulong)i->next, (ulong)i->prev, (ulong)i->pnext,
+ (ulong)i->pprev));
+ i = i->pnext;
+ } while ( i != first_block );
+ DBUG_PRINT("qcache", ("-------------------------------------"));
+}
+
- DBUG_RETURN( (uint) (strmov(strmov(key, dbname) + 1,
- tablename) -key) + 1);
+void Query_cache::queries_dump()
+{
+ DBUG_PRINT("qcache", ("------------------"));
+ DBUG_PRINT("qcache", (" QUERIES"));
+ DBUG_PRINT("qcache", ("------------------"));
+ if (queries_blocks != 0)
+ {
+ Query_cache_block *block = queries_blocks;
+ do
+ {
+ uint len;
+ char *str = (char*) query_cache_query_get_key((byte*) block, &len, 0);
+ byte flags = (byte) str[len-1];
+ DBUG_PRINT("qcache", ("%u (%u,%u) %.*s",len,
+ ((flags & QUERY_CACHE_CLIENT_LONG_FLAG_MASK)? 1:0),
+ (flags & QUERY_CACHE_CHARSET_CONVERT_MASK), len,
+ str));
+ DBUG_PRINT("qcache", ("-b- 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx", (ulong) block,
+ (ulong) block->next, (ulong) block->prev,
+ (ulong)block->pnext, (ulong)block->pprev));
+
+ for (TABLE_COUNTER_TYPE t = 0; t < block->n_tables; t++)
+ {
+ Query_cache_table *table = block->table(t)->parent;
+ DBUG_PRINT("qcache", ("-t- '%s' '%s'", table->db(), table->table()));
+ }
+ Query_cache_query *header = block->query();
+ if (header->result())
+ {
+ Query_cache_block *result_block = header->result();
+ Query_cache_block *result_beg = result_block;
+ do
+ {
+ DBUG_PRINT("qcache", ("-r- %u %lu/%lu 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx",
+ (uint) result_block->type,
+ result_block->length, result_block->used,
+ (ulong) result_block,
+ (ulong) result_block->next,
+ (ulong) result_block->prev,
+ (ulong) result_block->pnext,
+ (ulong) result_block->pprev));
+ result_block = result_block->next;
+ } while ( result_block != result_beg );
+ }
+ } while ((block=block->next) != queries_blocks);
+ }
+ else
+ {
+ DBUG_PRINT("qcache", ("no queries in list"));
+ }
+ DBUG_PRINT("qcache", ("------------------"));
+}
+
+
+void Query_cache::tables_dump()
+{
+ DBUG_PRINT("qcache", ("--------------------"));
+ DBUG_PRINT("qcache", ("TABLES"));
+ DBUG_PRINT("qcache", ("--------------------"));
+ for (int i=0; i < (int) Query_cache_table::TYPES_NUMBER; i++)
+ {
+ DBUG_PRINT("qcache", ("--- type %u", i));
+ if (tables_blocks[i] != 0)
+ {
+ Query_cache_block *table_block = tables_blocks[i];
+ do
+ {
+ Query_cache_table *table = table_block->table();
+ DBUG_PRINT("qcache", ("'%s' '%s'", table->db(), table->table()));
+ table_block = table_block->next;
+ } while ( table_block != tables_blocks[i]);
+ }
+ else
+ DBUG_PRINT("qcache", ("no tables in list"));
+ }
+ DBUG_PRINT("qcache", ("--------------------"));
}
+#endif /* DBUG_OFF */
diff --git a/sql/sql_cache.h b/sql/sql_cache.h
index 0b786fb1560..09eb745e405 100644
--- a/sql/sql_cache.h
+++ b/sql/sql_cache.h
@@ -66,7 +66,7 @@ struct Query_cache_block_table
TABLE_COUNTER_TYPE n; // numbr in table (from 0)
Query_cache_block_table *next, *prev;
Query_cache_table *parent;
- inline Query_cache_block * block();
+ inline Query_cache_block *block();
};
@@ -82,30 +82,28 @@ struct Query_cache_block
*pprev to join free blocks
*prev to access to opposite side of list in cyclic sorted list
*/
- Query_cache_block
- *pnext,*pprev, // physical next/previous block
- *next,*prev; // logical next/previous block
+ Query_cache_block *pnext,*pprev, // physical next/previous block
+ *next,*prev; // logical next/previous block
block_type type;
TABLE_COUNTER_TYPE n_tables; // number of tables in query
inline my_bool is_free(void) { return type == FREE; }
-
void init(ulong length);
void destroy();
inline uint headers_len();
inline gptr data(void);
- inline Query_cache_query * query();
- inline Query_cache_table * table();
- inline Query_cache_result * result();
- inline Query_cache_block_table * table(TABLE_COUNTER_TYPE n);
+ inline Query_cache_query *query();
+ inline Query_cache_table *table();
+ inline Query_cache_result *result();
+ inline Query_cache_block_table *table(TABLE_COUNTER_TYPE n);
};
struct Query_cache_query
{
ulonglong limit_found_rows;
- Query_cache_block * res;
- NET * wri;
+ Query_cache_block *res;
+ NET *wri;
ulong len;
sem_t lock; // R/W lock of block
pthread_mutex_t clients_guard;
@@ -115,9 +113,9 @@ struct Query_cache_query
void unlock_n_destroy();
inline ulonglong found_rows() { return limit_found_rows; }
inline void found_rows(ulonglong rows) { limit_found_rows = rows; }
- inline Query_cache_block * result() { return res; }
+ inline Query_cache_block *result() { return res; }
inline void result(Query_cache_block *p) { res=p; }
- inline NET * writer() { return wri; }
+ inline NET *writer() { return wri; }
inline void writer(NET *p) { wri=p; }
inline ulong length() { return len; }
inline ulong add(ulong packet_len) { return(len += packet_len); }
@@ -132,9 +130,7 @@ struct Query_cache_query
my_bool try_lock_writing();
void unlock_writing();
void unlock_reading();
- static byte * cache_key(const byte *record, uint *length,
- my_bool not_used);
- static void free_cache(void *entry);
+ static byte *cache_key(const byte *record, uint *length, my_bool not_used);
};
@@ -146,44 +142,45 @@ struct Query_cache_table
return (type == DB_TYPE_INNODB ? INNODB : OTHER);
}
- char * tbl;
+ char *tbl;
query_cache_table_type tp;
inline query_cache_table_type type() { return tp; }
inline void type(query_cache_table_type t) { tp = t;}
- inline char * db() { return (char *) data(); }
- inline char * table() { return tbl; }
- inline void table(char * table) { tbl = table; }
+ inline char *db() { return (char *) data(); }
+ inline char *table() { return tbl; }
+ inline void table(char *table) { tbl = table; }
inline gptr data()
{
return (gptr)(((byte*)this)+
ALIGN_SIZE(sizeof(Query_cache_table)));
}
-
- static byte * cache_key(const byte *record, uint *length,
- my_bool not_used);
- static void free_cache(void *entry);
};
-
struct Query_cache_result
{
Query_cache_block *query;
- inline gptr data(){return (gptr)(((byte*)this)+
- ALIGN_SIZE(sizeof(Query_cache_result)));}
-
+ inline gptr data()
+ {
+ return (gptr)(((byte*) this)+
+ ALIGN_SIZE(sizeof(Query_cache_result)));
+ }
/* data_continue (if not whole packet contained by this block) */
- inline Query_cache_block * parent() { return query; }
+ inline Query_cache_block *parent() { return query; }
inline void parent (Query_cache_block *p) { query=p; }
};
extern "C" {
+ byte *query_cache_query_get_key(const byte *record, uint *length,
+ my_bool not_used);
+ byte *query_cache_table_get_key(const byte *record, uint *length,
+ my_bool not_used);
void query_cache_insert(THD *thd, const char *packet, ulong length);
void query_cache_end_of_result(THD *thd);
void query_cache_abort(THD *thd);
- void query_cache_invalidate_by_MyISAM_filename(char* filename);
+ void query_cache_invalidate_by_MyISAM_filename(const char* filename);
}
struct Query_cache_memory_bin
@@ -192,7 +189,7 @@ struct Query_cache_memory_bin
ulong size;
#endif
uint number;
- Query_cache_block * free_blocks;
+ Query_cache_block *free_blocks;
inline void init(ulong size)
{
@@ -219,94 +216,92 @@ struct Query_cache_memory_bin_step
class Query_cache
{
- protected:
- byte * cache; // cache memory
- Query_cache_block *first_block; // physical location block list
- Query_cache_block *queries_blocks; // query list (LIFO)
- Query_cache_block *tables_blocks[Query_cache_table::TYPES_NUMBER];
-
- Query_cache_memory_bin * bins; // free block lists
- Query_cache_memory_bin_step * steps; // bins spacing info
- uint mem_bin_num, mem_bin_steps; // See at init_cache & find_bin
-
- /* options */
- ulong query_cache_size, query_cache_limit,
- min_allocation_unit, min_result_data_size;
- uint def_query_hash_size, def_table_hash_size;
-
- /* statistics */
public:
+ /* Info */
+ ulong query_cache_size, query_cache_limit;
+ /* statistics */
ulong free_memory, queries_in_cache, hits, inserts, refused;
-protected:
- my_bool initialized;
+protected:
/*
- Locked when searched or changed global query or
- tables lists or hashes. When operate inside
- query structure locked own query block mutex
- LOCK SEQUENCE (to prevent clinch):
+ The following mutex is locked when searching or changing global
+ query, tables lists or hashes. When we are operating inside the
+ query structure we locked an internal query block mutex.
+ LOCK SEQUENCE (to prevent deadlocks):
1. structure_guard_mutex
2. query block / table block / free block
3. results blocks (only when must become free).
*/
pthread_mutex_t structure_guard_mutex;
+ byte *cache; // cache memory
+ Query_cache_block *first_block; // physical location block list
+ Query_cache_block *queries_blocks; // query list (LIFO)
+ Query_cache_block *tables_blocks[Query_cache_table::TYPES_NUMBER];
+ Query_cache_memory_bin *bins; // free block lists
+ Query_cache_memory_bin_step *steps; // bins spacing info
HASH queries, tables;
+ uint mem_bin_num, mem_bin_steps; // See at init_cache & find_bin
+ my_bool initialized;
+
+ /* options */
+ ulong min_allocation_unit, min_result_data_size;
+ uint def_query_hash_size, def_table_hash_size;
/* Exclude/include from cyclic double linked list */
- static void double_linked_list_exclude(Query_cache_block * point,
- Query_cache_block * &list_pointer);
- static void double_linked_list_simple_include(Query_cache_block * point,
- Query_cache_block *
- &list_pointer);
+ static void double_linked_list_exclude(Query_cache_block *point,
+ Query_cache_block **list_pointer);
+ static void double_linked_list_simple_include(Query_cache_block *point,
+ Query_cache_block **
+ list_pointer);
static void double_linked_list_join(Query_cache_block *head_tail,
Query_cache_block *tail_head);
/* Table key generation */
- static uint filename_2_table_key (char * key, char *filename);
+ static uint filename_2_table_key (char *key, const char *filename);
- /* Following function work properly only when structure_guard_mutex locked */
+ /* The following functions require that structure_guard_mutex is locked */
void flush_cache();
my_bool free_old_query();
- void free_query(Query_cache_block * point);
- my_bool allocate_data_chain(Query_cache_block * &result_block,
+ void free_query(Query_cache_block *point);
+ my_bool allocate_data_chain(Query_cache_block **result_block,
ulong data_len,
- Query_cache_block * query_block);
+ Query_cache_block *query_block);
void invalidate_table(TABLE_LIST *table);
void invalidate_table(TABLE *table);
void invalidate_table_in_db(Query_cache_block *table_block,
- char * db);
+ char *db);
void invalidate_table(Query_cache_block *table_block);
- my_bool register_all_tables(Query_cache_block * block,
- TABLE_LIST * tables_used,
+ my_bool register_all_tables(Query_cache_block *block,
+ TABLE_LIST *tables_used,
TABLE_COUNTER_TYPE tables);
- my_bool insert_table(uint key_len, char * key,
- Query_cache_block_table * node,
+ my_bool insert_table(uint key_len, char *key,
+ Query_cache_block_table *node,
Query_cache_table::query_cache_table_type type);
- void unlink_table(Query_cache_block_table * node);
- Query_cache_block * get_free_block (ulong len, my_bool not_less,
+ void unlink_table(Query_cache_block_table *node);
+ Query_cache_block *get_free_block (ulong len, my_bool not_less,
ulong min);
- void free_memory_block(Query_cache_block * point);
+ void free_memory_block(Query_cache_block *point);
void split_block(Query_cache_block *block, ulong len);
- Query_cache_block * join_free_blocks(Query_cache_block *first_block,
- Query_cache_block * block_in_list);
- my_bool append_next_free_block(Query_cache_block * block,
+ Query_cache_block *join_free_blocks(Query_cache_block *first_block,
+ Query_cache_block *block_in_list);
+ my_bool append_next_free_block(Query_cache_block *block,
ulong add_size);
- void exclude_from_free_memory_list(Query_cache_block * free_block);
- void insert_into_free_memory_list(Query_cache_block * new_block);
- my_bool move_by_type(byte * &border, Query_cache_block * &before,
- ulong &gap, Query_cache_block * i);
+ void exclude_from_free_memory_list(Query_cache_block *free_block);
+ void insert_into_free_memory_list(Query_cache_block *new_block);
+ my_bool move_by_type(byte **border, Query_cache_block **before,
+ ulong *gap, Query_cache_block *i);
uint find_bin(ulong size);
- void move_to_query_list_end(Query_cache_block * block);
- void insert_into_free_memory_sorted_list(Query_cache_block * new_block,
- Query_cache_block * &list);
+ void move_to_query_list_end(Query_cache_block *block);
+ void insert_into_free_memory_sorted_list(Query_cache_block *new_block,
+ Query_cache_block **list);
void pack_cache();
- void relink(Query_cache_block * oblock,
- Query_cache_block * nblock,
- Query_cache_block * next,
- Query_cache_block * prev,
- Query_cache_block * pnext,
- Query_cache_block * pprev);
+ void relink(Query_cache_block *oblock,
+ Query_cache_block *nblock,
+ Query_cache_block *next,
+ Query_cache_block *prev,
+ Query_cache_block *pnext,
+ Query_cache_block *pprev);
my_bool join_results(ulong join_limit);
/*
@@ -317,38 +312,35 @@ protected:
ulong init_cache();
void make_disabled();
void free_cache(my_bool destruction);
- Query_cache_block * write_block_data(ulong data_len, gptr data,
+ Query_cache_block *write_block_data(ulong data_len, gptr data,
ulong header_len,
Query_cache_block::block_type type,
TABLE_COUNTER_TYPE ntab = 0,
my_bool under_guard=0);
- my_bool append_result_data(Query_cache_block * &result,
+ my_bool append_result_data(Query_cache_block **result,
ulong data_len, gptr data,
- Query_cache_block * parent,
- Query_cache_block * first_data_block);
- my_bool write_result_data(Query_cache_block * &result,
+ Query_cache_block *parent);
+ my_bool write_result_data(Query_cache_block **result,
ulong data_len, gptr data,
- Query_cache_block * parent,
+ Query_cache_block *parent,
Query_cache_block::block_type
type=Query_cache_block::RESULT);
- Query_cache_block * allocate_block(ulong len, my_bool not_less,
+ Query_cache_block *allocate_block(ulong len, my_bool not_less,
ulong min,
my_bool under_guard=0);
/*
- If query is cachable return numder tables in query
+ If query is cacheable return number tables in query
(query without tables not cached)
*/
- TABLE_COUNTER_TYPE is_cachable(THD *thd, uint query_len, char *query,
- LEX *lex,
- TABLE_LIST *tables_used);
+ TABLE_COUNTER_TYPE is_cacheable(THD *thd, uint32 query_len, char *query,
+ LEX *lex, TABLE_LIST *tables_used);
public:
Query_cache(ulong query_cache_limit = ULONG_MAX,
ulong min_allocation_unit = QUERY_CACHE_MIN_ALLOCATION_UNIT,
ulong min_result_data_size = QUERY_CACHE_MIN_RESULT_DATA_SIZE,
uint def_query_hash_size = QUERY_CACHE_DEF_QUERY_HASH_SIZE,
- uint def_table_hash_size = QUERY_CACHE_DEF_TABLE_HASH_SIZE
- );
+ uint def_table_hash_size = QUERY_CACHE_DEF_TABLE_HASH_SIZE);
/* resize query cache (return real query size, 0 if disabled) */
ulong resize(ulong query_cache_size);
@@ -371,10 +363,10 @@ protected:
void invalidate(Query_cache_table::query_cache_table_type type);
/* Remove all queries that uses any of the tables in following database */
- void invalidate(char * db);
+ void invalidate(char *db);
/* Remove all queries that uses any of the listed following table */
- void invalidate_by_MyISAM_filename(char * filename);
+ void invalidate_by_MyISAM_filename(const char *filename);
/* Remove all queries from cache */
void flush();
@@ -386,7 +378,7 @@ protected:
void destroy();
#ifndef DBUG_OFF
- void wreck(uint line, const char * message);
+ void wreck(uint line, const char *message);
void bins_dump();
void cache_dump();
void queries_dump();
diff --git a/sql/sql_class.h b/sql/sql_class.h
index e036da982f0..5d20508e728 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -236,35 +236,35 @@ class delayed_insert;
class THD :public ilink {
public:
- NET net;
- LEX lex;
- MEM_ROOT mem_root;
- HASH user_vars;
- String packet; /* Room for 1 row */
- struct sockaddr_in remote;
- struct rand_struct rand;
- char *query,*thread_stack;
- char *host,*user,*priv_user,*db,*ip;
- const char *proc_info, *host_or_ip;
- uint client_capabilities,sql_mode,max_packet_length;
- uint master_access,db_access;
- TABLE *open_tables,*temporary_tables, *handler_tables;
+ NET net;
+ LEX lex;
+ MEM_ROOT mem_root;
+ HASH user_vars;
+ String packet; /* Room for 1 row */
+ struct sockaddr_in remote;
+ struct rand_struct rand;
+ char *query,*thread_stack;
+ char *host,*user,*priv_user,*db,*ip;
+ const char *proc_info, *host_or_ip;
+ uint client_capabilities,sql_mode,max_packet_length;
+ uint master_access,db_access;
+ TABLE *open_tables,*temporary_tables, *handler_tables;
MYSQL_LOCK *lock,*locked_tables;
- ULL *ull;
+ ULL *ull;
struct st_my_thread_var *mysys_var;
enum enum_server_command command;
- uint32 server_id;
- uint32 log_seq;
- uint32 file_id; // for LOAD DATA INFILE
+ uint32 server_id;
+ uint32 log_seq;
+ uint32 file_id; // for LOAD DATA INFILE
const char *where;
- time_t start_time,time_after_lock,user_time;
- time_t connect_time,thr_create_time; // track down slow pthread_create
+ time_t start_time,time_after_lock,user_time;
+ time_t connect_time,thr_create_time; // track down slow pthread_create
thr_lock_type update_lock_default;
delayed_insert *di;
struct st_transactions {
IO_CACHE trans_log;
- THD_TRANS all; /* Trans since BEGIN WORK */
- THD_TRANS stmt; /* Trans for current statement */
+ THD_TRANS all; // Trans since BEGIN WORK
+ THD_TRANS stmt; // Trans for current statement
uint bdb_lock_count;
} transaction;
Item *free_list, *handler_items;
@@ -277,17 +277,20 @@ public:
Vio* active_vio;
pthread_mutex_t active_vio_lock;
#endif
- ulonglong next_insert_id,last_insert_id,current_insert_id, limit_found_rows;
- ha_rows select_limit,offset_limit,default_select_limit,cuted_fields,
- max_join_size, sent_row_count, examined_row_count;
- table_map used_tables;
- ulong query_id,version, inactive_timeout,options,thread_id;
- long dbug_thread_id;
+ ulonglong next_insert_id,last_insert_id,current_insert_id,
+ limit_found_rows;
+ ha_rows select_limit,offset_limit,default_select_limit,cuted_fields,
+ max_join_size, sent_row_count, examined_row_count;
+ table_map used_tables;
+ ulong query_id,version, inactive_timeout,options,thread_id;
+ long dbug_thread_id;
pthread_t real_id;
- uint current_tablenr,tmp_table,cond_count,col_access,query_length;
- uint server_status,open_options;
+ uint current_tablenr,tmp_table,cond_count,col_access;
+ uint server_status,open_options;
+ uint32 query_length;
enum_tx_isolation tx_isolation, session_tx_isolation;
char scramble[9];
+ uint8 query_cache_type; // type of query cache processing
bool slave_thread;
bool set_query_id,locked,count_cuted_fields,some_tables_deleted;
bool no_errors, allow_sum_func, password, fatal_error;
@@ -296,18 +299,18 @@ public:
bool query_error, bootstrap, cleanup_done;
bool safe_to_cache_query;
bool volatile killed;
- //type of query cache processing
- byte query_cache_type;
+ /*
+ If we do a purge of binary logs, log index info of the threads
+ that are currently reading it needs to be adjusted. To do that
+ each thread that is using LOG_INFO needs to adjust the pointer to it
+ */
LOG_INFO* current_linfo;
- // if we do a purge of binary logs, log index info of the threads
- // that are currently reading it needs to be adjusted. To do that
- // each thread that is using LOG_INFO needs to adjust the pointer to it
-
- ulong slave_proxy_id; // in slave thread we need to know in behalf of which
- // thread the query is being run to replicate temp tables properly
-
- NET* slave_net; // network connection from slave to master
-
+ /*
+ In slave thread we need to know in behalf of which
+ thread the query is being run to replicate temp tables properly
+ */
+ ulong slave_proxy_id;
+ NET* slave_net; // network connection from slave -> m.
THD();
~THD();
void cleanup(void);
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 5c43cacd85b..548e7c9062f 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -739,9 +739,9 @@ TABLE *delayed_insert::get_local_table(THD* client_thd)
}
client_thd->proc_info="allocating local table";
- copy= (TABLE*) sql_alloc(sizeof(*copy)+
- (table->fields+1)*sizeof(Field**)+
- table->reclength);
+ copy= (TABLE*) client_thd->alloc(sizeof(*copy)+
+ (table->fields+1)*sizeof(Field**)+
+ table->reclength);
if (!copy)
goto error;
*copy= *table;
@@ -759,7 +759,7 @@ TABLE *delayed_insert::get_local_table(THD* client_thd)
found_next_number_field=table->found_next_number_field;
for (org_field=table->field ; *org_field ; org_field++,field++)
{
- if (!(*field= (*org_field)->new_field(copy)))
+ if (!(*field= (*org_field)->new_field(&client_thd->mem_root,copy)))
return 0;
(*field)->move_field(adjust_ptrs); // Point at copy->record[0]
if (*org_field == found_next_number_field)
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index ef06eaf9145..769527c92fe 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -29,25 +29,42 @@
#include <my_dir.h>
#include <assert.h>
+#ifdef HAVE_OPENSSL
+/*
+ Without SSL the handshake consists of one packet. This packet
+ has both client capabilites and scrambled password.
+ With SSL the handshake might consist of two packets. If the first
+ packet (client capabilities) has CLIENT_SSL flag set, we have to
+ switch to SSL and read the second packet. The scrambled password
+ is in the second packet and client_capabilites field will be ignored.
+ Maybe it is better to accept flags other than CLIENT_SSL from the
+ second packet?
+*/
+#define SSL_HANDSHAKE_SIZE 2
+#define NORMAL_HANDSHAKE_SIZE 6
+#define MIN_HANDSHAKE_SIZE 2
+#else
+#define MIN_HANDSHAKE_SIZE 6
+#endif /* HAVE_OPENSSL */
#define SCRAMBLE_LENGTH 8
+
extern int yyparse(void);
extern "C" pthread_mutex_t THR_LOCK_keycache;
#ifdef SOLARIS
extern "C" int gethostname(char *name, int namelen);
#endif
-static int check_for_max_user_connections(const char *user, int u_length,
- const char *host);
+static int check_for_max_user_connections(const char *user, const char *host);
static void decrease_user_connections(const char *user, const char *host);
static bool check_db_used(THD *thd,TABLE_LIST *tables);
static bool check_merge_table_access(THD *thd, char *db, TABLE_LIST *tables);
-static bool check_dup(THD *thd,const char *db,const char *name,
- TABLE_LIST *tables);
+static bool check_dup(const char *db, const char *name, TABLE_LIST *tables);
static void mysql_init_query(THD *thd);
static void remove_escape(char *name);
static void refresh_status(void);
-static bool append_file_to_dir(char **filename_ptr, char *table_name);
+static bool append_file_to_dir(THD *thd, char **filename_ptr,
+ char *table_name);
static bool create_total_list(THD *thd, LEX *lex, TABLE_LIST **result);
const char *any_db="*any*"; // Special symbol for check_access
@@ -160,7 +177,7 @@ static bool check_user(THD *thd,enum_server_command command, const char *user,
db ? db : (char*) "");
thd->db_access=0;
if (max_user_connections &&
- check_for_max_user_connections(user, strlen(user), thd->host))
+ check_for_max_user_connections(user, thd->host))
return -1;
if (db && db[0])
{
@@ -210,8 +227,7 @@ void init_max_user_conn(void)
}
-static int check_for_max_user_connections(const char *user, int u_length,
- const char *host)
+static int check_for_max_user_connections(const char *user, const char *host)
{
int error=1;
uint temp_len;
@@ -363,51 +379,35 @@ check_connections(THD *thd)
}
vio_keepalive(net->vio, TRUE);
- /* nasty, but any other way? */
- uint pkt_len = 0;
+ ulong pkt_len=0;
{
/* buff[] needs to big enough to hold the server_version variable */
char buff[SERVER_VERSION_LENGTH + SCRAMBLE_LENGTH+32],*end;
int client_flags = CLIENT_LONG_FLAG | CLIENT_CONNECT_WITH_DB;
+
if (opt_using_transactions)
client_flags|=CLIENT_TRANSACTIONS;
#ifdef HAVE_COMPRESS
client_flags |= CLIENT_COMPRESS;
#endif /* HAVE_COMPRESS */
+#ifdef HAVE_OPENSSL
+ if (ssl_acceptor_fd)
+ client_flags |= CLIENT_SSL; /* Wow, SSL is avalaible! */
+#endif /* HAVE_OPENSSL */
- end=strmov(buff,server_version)+1;
+ end=strnmov(buff,server_version,SERVER_VERSION_LENGTH)+1;
int4store((uchar*) end,thd->thread_id);
end+=4;
memcpy(end,thd->scramble,SCRAMBLE_LENGTH+1);
end+=SCRAMBLE_LENGTH +1;
-#ifdef HAVE_OPENSSL
- if (ssl_acceptor_fd)
- client_flags |= CLIENT_SSL; /* Wow, SSL is avalaible! */
- /*
- * Without SSL the handshake consists of one packet. This packet
- * has both client capabilites and scrambled password.
- * With SSL the handshake might consist of two packets. If the first
- * packet (client capabilities) has CLIENT_SSL flag set, we have to
- * switch to SSL and read the second packet. The scrambled password
- * is in the second packet and client_capabilites field will be ignored.
- * Maybe it is better to accept flags other than CLIENT_SSL from the
- * second packet?
- */
-#define SSL_HANDSHAKE_SIZE 2
-#define NORMAL_HANDSHAKE_SIZE 6
-#define MIN_HANDSHAKE_SIZE 2
-
-#else
-#define MIN_HANDSHAKE_SIZE 6
-#endif /* HAVE_OPENSSL */
int2store(end,client_flags);
- end[2]=MY_CHARSET_CURRENT;
+ end[2]=(char) MY_CHARSET_CURRENT;
int2store(end+3,thd->server_status);
bzero(end+5,13);
end+=18;
- if (net_write_command(net,protocol_version, buff,
+ if (net_write_command(net,(uchar) protocol_version, buff,
(uint) (end-buff)) ||
- (pkt_len=my_net_read(net)) == packet_error ||
+ (pkt_len= my_net_read(net)) == packet_error ||
pkt_len < MIN_HANDSHAKE_SIZE)
{
inc_host_errors(&thd->remote.sin_addr);
@@ -426,12 +426,9 @@ check_connections(THD *thd)
if (thd->client_capabilities & CLIENT_IGNORE_SPACE)
thd->sql_mode|= MODE_IGNORE_SPACE;
#ifdef HAVE_OPENSSL
- DBUG_PRINT("info",
- ("pkt_len:%d, client capabilities: %d",
- pkt_len, thd->client_capabilities) );
+ DBUG_PRINT("info", ("client capabilities: %d", thd->client_capabilities));
if (thd->client_capabilities & CLIENT_SSL)
{
- DBUG_PRINT("info", ("Agreed to change IO layer to SSL") );
/* Do the SSL layering. */
DBUG_PRINT("info", ("IO layer change in progress..."));
sslaccept(ssl_acceptor_fd, net->vio, thd->inactive_timeout);
@@ -439,8 +436,8 @@ check_connections(THD *thd)
if ((pkt_len=my_net_read(net)) == packet_error ||
pkt_len < NORMAL_HANDSHAKE_SIZE)
{
- DBUG_PRINT("info", ("pkt_len:%d", pkt_len));
- DBUG_PRINT("error", ("Failed to read user information"));
+ DBUG_PRINT("error", ("Failed to read user information (pkt_len= %lu)",
+ pkt_len));
inc_host_errors(&thd->remote.sin_addr);
return(ER_HANDSHAKE_ERROR);
}
@@ -469,7 +466,7 @@ check_connections(THD *thd)
if ((thd->client_capabilities & CLIENT_TRANSACTIONS) &&
opt_using_transactions)
thd->net.return_status= &thd->server_status;
- net->timeout=net_read_timeout;
+ net->timeout=(uint) net_read_timeout;
if (check_user(thd,COM_CONNECT, user, passwd, db, 1))
return (-1);
thd->password=test(passwd[0]);
@@ -693,8 +690,8 @@ int mysql_table_dump(THD* thd, char* db, char* tbl_name, int fd)
goto err;
thd->free_list = 0;
+ thd->query_length=(uint) strlen(tbl_name);
thd->query = tbl_name;
- thd->query_length=strlen(tbl_name);
if ((error = mysqld_dump_create_info(thd, table, -1)))
{
my_error(ER_GET_ERRNO, MYF(0));
@@ -715,7 +712,8 @@ err:
bool do_command(THD *thd)
{
char *packet;
- uint old_timeout,packet_length;
+ uint old_timeout;
+ ulong packet_length;
NET *net;
enum enum_server_command command;
DBUG_ENTER("do_command");
@@ -725,7 +723,7 @@ bool do_command(THD *thd)
packet=0;
old_timeout=net->timeout;
- net->timeout=thd->inactive_timeout; /* Wait max for 8 hours */
+ net->timeout=(uint) thd->inactive_timeout; // Wait max for 8 hours
net->last_error[0]=0; // Clear error message
net->last_errno=0;
@@ -745,7 +743,7 @@ bool do_command(THD *thd)
command_name[command]));
}
net->timeout=old_timeout; // Timeout for writing
- DBUG_RETURN(dispatch_command(command,thd, packet+1, packet_length));
+ DBUG_RETURN(dispatch_command(command,thd, packet+1, (uint) packet_length));
}
@@ -842,6 +840,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
pos--;
packet_length--;
}
+ thd->query_length= packet_length;
if (!(thd->query= (char*) thd->memdup((gptr) (packet),packet_length+1)))
break;
thd->query[packet_length]=0;
@@ -872,8 +871,8 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
}
thd->free_list=0;
table_list.name=table_list.real_name=thd->strdup(packet);
- thd->query=fields=thd->strdup(strend(packet)+1);
thd->query_length=strlen(thd->query);
+ thd->query=fields=thd->strdup(strend(packet)+1);
mysql_log.write(thd,command,"%s %s",table_list.real_name,fields);
remove_escape(table_list.real_name); // This can't have wildcards
@@ -1302,8 +1301,10 @@ mysql_execute_command(void)
lex->create_info.data_file_name=lex->create_info.index_file_name=0;
#else
/* Fix names if symlinked tables */
- if (append_file_to_dir(&lex->create_info.data_file_name, tables->name) ||
- append_file_to_dir(&lex->create_info.index_file_name, tables->name))
+ if (append_file_to_dir(thd, &lex->create_info.data_file_name,
+ tables->name) ||
+ append_file_to_dir(thd,&lex->create_info.index_file_name,
+ tables->name))
{
res=-1;
break;
@@ -1314,7 +1315,7 @@ mysql_execute_command(void)
select_result *result;
if (!(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) &&
- check_dup(thd,tables->db,tables->real_name,tables->next))
+ check_dup(tables->db, tables->real_name, tables->next))
{
net_printf(&thd->net,ER_INSERT_TABLE_USED,tables->real_name);
DBUG_VOID_RETURN;
@@ -1618,7 +1619,7 @@ mysql_execute_command(void)
if (thd->select_limit < select_lex->select_limit)
thd->select_limit= HA_POS_ERROR; // No limit
- if (check_dup(thd,tables->db,tables->real_name,tables->next))
+ if (check_dup(tables->db, tables->real_name, tables->next))
{
net_printf(&thd->net,ER_INSERT_TABLE_USED,tables->real_name);
DBUG_VOID_RETURN;
@@ -1906,7 +1907,7 @@ mysql_execute_command(void)
}
case SQLCOM_SET_OPTION:
{
- uint org_options=thd->options;
+ ulong org_options=thd->options;
thd->options=select_lex->options;
thd->update_lock_default= ((thd->options & OPTION_LOW_PRIORITY_UPDATES) ?
TL_WRITE_LOW_PRIORITY : TL_WRITE);
@@ -2975,8 +2976,7 @@ void add_join_natural(TABLE_LIST *a,TABLE_LIST *b)
/* Check if name is used in table list */
-static bool check_dup(THD *thd,const char *db,const char *name,
- TABLE_LIST *tables)
+static bool check_dup(const char *db, const char *name, TABLE_LIST *tables)
{
for (; tables ; tables=tables->next)
if (!strcmp(name,tables->real_name) && !strcmp(db,tables->db))
@@ -3083,7 +3083,7 @@ static void refresh_status(void)
/* If pointer is not a null pointer, append filename to it */
-static bool append_file_to_dir(char **filename_ptr, char *table_name)
+static bool append_file_to_dir(THD *thd, char **filename_ptr, char *table_name)
{
char buff[FN_REFLEN],*ptr, *end;
if (!*filename_ptr)
@@ -3099,7 +3099,7 @@ static bool append_file_to_dir(char **filename_ptr, char *table_name)
/* Fix is using unix filename format on dos */
strmov(buff,*filename_ptr);
end=convert_dirname(buff, *filename_ptr, NullS);
- if (!(ptr=sql_alloc((uint) (end-buff)+strlen(table_name)+1)))
+ if (!(ptr=thd->alloc((uint) (end-buff)+(uint) strlen(table_name)+1)))
return 1; // End of memory
*filename_ptr=ptr;
strxmov(ptr,buff,table_name,NullS);
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 2673c746bbc..5789e537a6a 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -47,7 +47,8 @@ static void find_best(JOIN *join,table_map rest_tables,uint index,
static uint cache_record_length(JOIN *join,uint index);
static double prev_record_reads(JOIN *join,table_map found_ref);
static bool get_best_combination(JOIN *join);
-static store_key *get_store_key(KEYUSE *keyuse, table_map used_tables,
+static store_key *get_store_key(THD *thd,
+ KEYUSE *keyuse, table_map used_tables,
KEY_PART_INFO *key_part, char *key_buff,
uint maybe_null);
static bool make_simple_join(JOIN *join,TABLE *tmp_table);
@@ -795,7 +796,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
(procedure && (procedure->flags & PROC_GROUP)))
{
alloc_group_fields(&join,group);
- setup_copy_fields(&join.tmp_table_param,all_fields);
+ setup_copy_fields(thd, &join.tmp_table_param,all_fields);
if (make_sum_func_list(&join,all_fields) || thd->fatal_error)
goto err; /* purecov: inspected */
}
@@ -2152,7 +2153,8 @@ get_best_combination(JOIN *join)
if (!keyuse->used_tables &&
!(join->select_options & SELECT_DESCRIBE))
{ // Compare against constant
- store_key_item *tmp=new store_key_item(keyinfo->key_part[i].field,
+ store_key_item *tmp=new store_key_item(thd,
+ keyinfo->key_part[i].field,
(char*)key_buff +
maybe_null,
maybe_null ?
@@ -2166,7 +2168,8 @@ get_best_combination(JOIN *join)
tmp->copy();
}
else
- *ref_key++= get_store_key(keyuse,join->const_table_map,
+ *ref_key++= get_store_key(join->thd,
+ keyuse,join->const_table_map,
&keyinfo->key_part[i],
(char*) key_buff,maybe_null);
key_buff+=keyinfo->key_part[i].store_length;
@@ -2208,25 +2211,28 @@ get_best_combination(JOIN *join)
static store_key *
-get_store_key(KEYUSE *keyuse, table_map used_tables, KEY_PART_INFO *key_part,
- char *key_buff, uint maybe_null)
+get_store_key(THD *thd, KEYUSE *keyuse, table_map used_tables,
+ KEY_PART_INFO *key_part, char *key_buff, uint maybe_null)
{
if (!((~used_tables) & keyuse->used_tables)) // if const item
{
- return new store_key_const_item(key_part->field,
+ return new store_key_const_item(thd,
+ key_part->field,
key_buff + maybe_null,
maybe_null ? key_buff : 0,
key_part->length,
keyuse->val);
}
else if (keyuse->val->type() == Item::FIELD_ITEM)
- return new store_key_field(key_part->field,
+ return new store_key_field(thd,
+ key_part->field,
key_buff + maybe_null,
maybe_null ? key_buff : 0,
key_part->length,
((Item_field*) keyuse->val)->field,
keyuse->val->full_name());
- return new store_key_item(key_part->field,
+ return new store_key_item(thd,
+ key_part->field,
key_buff + maybe_null,
maybe_null ? key_buff : 0,
key_part->length,
@@ -3272,7 +3278,7 @@ const_expression_in_where(COND *cond, Item *comp_item, Item **const_item)
** for send_fields
****************************************************************************/
-Field *create_tmp_field(TABLE *table,Item *item, Item::Type type,
+Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
Item_result_field ***copy_func, Field **from_field,
bool group, bool modify_item)
{
@@ -3314,7 +3320,7 @@ Field *create_tmp_field(TABLE *table,Item *item, Item::Type type,
item->name,table,item->binary);
}
}
- current_thd->fatal_error=1;
+ thd->fatal_error=1;
return 0; // Error
}
case Item::FIELD_ITEM:
@@ -3322,7 +3328,8 @@ Field *create_tmp_field(TABLE *table,Item *item, Item::Type type,
Field *org_field=((Item_field*) item)->field,*new_field;
*from_field=org_field;
- if ((new_field= org_field->new_field(table))) // Should always be true
+ // The following should always be true
+ if ((new_field= org_field->new_field(&thd->mem_root,table)))
{
if (modify_item)
((Item_field*) item)->result_field= new_field;
@@ -3510,8 +3517,8 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
if (!arg->const_item())
{
Field *new_field=
- create_tmp_field(table,arg,arg->type(),&copy_func,tmp_from_field,
- group != 0,not_all_columns);
+ create_tmp_field(thd, table,arg,arg->type(),&copy_func,
+ tmp_from_field, group != 0,not_all_columns);
if (!new_field)
goto err; // Should be OOM
tmp_from_field++;
@@ -3527,7 +3534,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
}
else
{
- Field *new_field=create_tmp_field(table,item,type,&copy_func,
+ Field *new_field=create_tmp_field(thd, table, item,type, &copy_func,
tmp_from_field, group != 0,
not_all_columns);
if (!new_field)
@@ -3708,7 +3715,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
if (!using_unique_constraint)
{
group->buff=(char*) group_buff;
- if (!(group->field=field->new_field(table)))
+ if (!(group->field=field->new_field(&thd->mem_root,table)))
goto err; /* purecov: inspected */
if (maybe_null)
{
@@ -6410,7 +6417,7 @@ test_if_group_changed(List<Item_buff> &list)
*/
bool
-setup_copy_fields(TMP_TABLE_PARAM *param,List<Item> &fields)
+setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields)
{
Item *pos;
List_iterator<Item> li(fields);
@@ -6438,7 +6445,7 @@ setup_copy_fields(TMP_TABLE_PARAM *param,List<Item> &fields)
/* set up save buffer and change result_field to point at saved value */
Field *field= item->field;
- item->result_field=field->new_field(field->table);
+ item->result_field=field->new_field(&thd->mem_root,field->table);
char *tmp=(char*) sql_alloc(field->pack_length()+1);
if (!tmp)
goto err;
diff --git a/sql/sql_select.h b/sql/sql_select.h
index 4fcffae31d2..1e62f1b7809 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -190,7 +190,7 @@ TABLE *create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
void free_tmp_table(THD *thd, TABLE *entry);
void count_field_types(TMP_TABLE_PARAM *param, List<Item> &fields,
bool reset_with_sum_func);
-bool setup_copy_fields(TMP_TABLE_PARAM *param,List<Item> &fields);
+bool setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param,List<Item> &fields);
void copy_fields(TMP_TABLE_PARAM *param);
void copy_funcs(Item_result_field **func_ptr);
bool create_myisam_from_heap(TABLE *table, TMP_TABLE_PARAM *param, int error,
@@ -210,7 +210,7 @@ class store_key :public Sql_alloc
char *null_ptr;
char err;
public:
- store_key(Field *field_arg, char *ptr, char *null, uint length)
+ store_key(THD *thd, Field *field_arg, char *ptr, char *null, uint length)
:null_ptr(null),err(0)
{
if (field_arg->type() == FIELD_TYPE_BLOB)
@@ -219,7 +219,7 @@ class store_key :public Sql_alloc
field_arg->table, field_arg->binary());
else
{
- to_field=field_arg->new_field(field_arg->table);
+ to_field=field_arg->new_field(&thd->mem_root,field_arg->table);
if (to_field)
to_field->move_field(ptr, (uchar*) null, 1);
}
@@ -235,9 +235,9 @@ class store_key_field: public store_key
Copy_field copy_field;
const char *field_name;
public:
- store_key_field(Field *to_field_arg, char *ptr, char *null_ptr_arg,
+ store_key_field(THD *thd, Field *to_field_arg, char *ptr, char *null_ptr_arg,
uint length, Field *from_field, const char *name_arg)
- :store_key(to_field_arg,ptr,
+ :store_key(thd, to_field_arg,ptr,
null_ptr_arg ? null_ptr_arg : from_field->maybe_null() ? &err
: NullS,length), field_name(name_arg)
{
@@ -260,9 +260,9 @@ class store_key_item :public store_key
protected:
Item *item;
public:
- store_key_item(Field *to_field_arg, char *ptr, char *null_ptr_arg,
+ store_key_item(THD *thd, Field *to_field_arg, char *ptr, char *null_ptr_arg,
uint length, Item *item_arg)
- :store_key(to_field_arg,ptr,
+ :store_key(thd, to_field_arg,ptr,
null_ptr_arg ? null_ptr_arg : item_arg->maybe_null ?
&err : NullS, length), item(item_arg)
{}
@@ -279,10 +279,10 @@ class store_key_const_item :public store_key_item
{
bool inited;
public:
- store_key_const_item(Field *to_field_arg, char *ptr,
+ store_key_const_item(THD *thd, Field *to_field_arg, char *ptr,
char *null_ptr_arg, uint length,
Item *item_arg)
- :store_key_item(to_field_arg,ptr,
+ :store_key_item(thd, to_field_arg,ptr,
null_ptr_arg ? null_ptr_arg : item_arg->maybe_null ?
&err : NullS, length, item_arg), inited(0)
{
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 19c3d89caaf..16790ac1621 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -1054,9 +1054,8 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose)
thd_info->query=0;
if (tmp->query)
{
- uint length=(uint) strlen(tmp->query);
- if (length > max_query_length)
- length=max_query_length;
+ /* query_length is always set before tmp->query */
+ uint length= min(max_query_length, tmp->query_length);
thd_info->query=(char*) thd->memdup(tmp->query,length+1);
thd_info->query[length]=0;
}
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index ae450680fbb..737c8fccd9d 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -704,7 +704,7 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
DBUG_RETURN(0);
}
- Field *field=create_tmp_field(&tmp_table,item,item->type(),
+ Field *field=create_tmp_field(thd, &tmp_table, item, item->type(),
(Item_result_field***) 0, &tmp_field,0,0);
if (!field ||
!(cr_field=new create_field(field,(item->type() == Item::FIELD_ITEM ?
diff --git a/sql/table.cc b/sql/table.cc
index eb6d8fbb9cd..11c30f12ca2 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -467,7 +467,8 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
key_part->key_part_flag|= HA_PART_KEY;
if (field->type() != FIELD_TYPE_BLOB)
{ // Create a new field
- field=key_part->field=field->new_field(outparam);
+ field=key_part->field=field->new_field(&outparam->mem_root,
+ outparam);
field->field_length=key_part->length;
}
}