summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorTatjana Azundris Nuernberg <tatjana.nuernberg@oracle.com>2011-10-10 15:34:29 +0100
committerTatjana Azundris Nuernberg <tatjana.nuernberg@oracle.com>2011-10-10 15:34:29 +0100
commit2a8a76537ff7486286b463084da2f6d9ac905d40 (patch)
tree051108b8abaf436cda3123271518e2ace579674f /sql
parent12f5e01403cf8cb3601b23632ff5d9a952496327 (diff)
parente02c3d7fb7e59bcede73392ab0da5a5228859e0f (diff)
downloadmariadb-git-2a8a76537ff7486286b463084da2f6d9ac905d40.tar.gz
auto-merge
Diffstat (limited to 'sql')
-rw-r--r--sql/sp_head.cc12
-rw-r--r--sql/sql_cache.cc33
-rw-r--r--sql/sql_parse.cc21
3 files changed, 58 insertions, 8 deletions
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index 95a7eda0540..70ffb0a36ab 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -1029,12 +1029,22 @@ subst_spvars(THD *thd, sp_instr *instr, LEX_STRING *query_str)
/*
Allocate additional space at the end of the new query string for the
query_cache_send_result_to_client function.
+
+ The query buffer layout is:
+ buffer :==
+ <statement> The input statement(s)
+ '\0' Terminating null char
+ <length> Length of following current database name (size_t)
+ <db_name> Name of current database
+ <flags> Flags struct
*/
- buf_len= qbuf.length() + thd->db_length + 1 + QUERY_CACHE_FLAGS_SIZE + 1;
+ buf_len= qbuf.length() + 1 + sizeof(size_t) + thd->db_length +
+ QUERY_CACHE_FLAGS_SIZE + 1;
if ((pbuf= (char *) alloc_root(thd->mem_root, buf_len)))
{
memcpy(pbuf, qbuf.ptr(), qbuf.length());
pbuf[qbuf.length()]= 0;
+ *(size_t *)(pbuf+qbuf.length()+1)= thd->db_length;
}
else
DBUG_RETURN(TRUE);
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index b791428eef0..4800fdedbe5 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -1241,8 +1241,8 @@ def_week_frmt: %lu, in_trans: %d, autocommit: %d",
/* Key is query + database + flag */
if (thd->db_length)
{
- memcpy(thd->query() + thd->query_length() + 1, thd->db,
- thd->db_length);
+ memcpy(thd->query() + thd->query_length() + 1 + sizeof(size_t),
+ thd->db, thd->db_length);
DBUG_PRINT("qcache", ("database: %s length: %u",
thd->db, (unsigned) thd->db_length));
}
@@ -1251,7 +1251,7 @@ def_week_frmt: %lu, in_trans: %d, autocommit: %d",
DBUG_PRINT("qcache", ("No active database"));
}
tot_length= thd->query_length() + thd->db_length + 1 +
- QUERY_CACHE_FLAGS_SIZE;
+ sizeof(size_t) + QUERY_CACHE_FLAGS_SIZE;
/*
We should only copy structure (don't use it location directly)
because of alignment issue
@@ -1462,7 +1462,28 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
goto err;
}
}
+ {
+ /*
+ We have allocated buffer space (in alloc_query) to hold the
+ SQL statement(s) + the current database name + a flags struct.
+ If the database name has changed during execution, which might
+ happen if there are multiple statements, we need to make
+ sure the new current database has a name with the same length
+ as the previous one.
+ */
+ size_t *db_len= (size_t *) (sql + query_length + 1);
+ if (thd->db_length != *db_len)
+ {
+ /*
+ We should probably reallocate the buffer in this case,
+ but for now we just leave it uncached
+ */
+ DBUG_PRINT("qcache",
+ ("Current database has changed since start of query"));
+ goto err;
+ }
+ }
/*
Try to obtain an exclusive lock on the query cache. If the cache is
disabled or if a full cache flush is in progress, the attempt to
@@ -1484,10 +1505,12 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
Query_cache_block *query_block;
- tot_length= query_length + thd->db_length + 1 + QUERY_CACHE_FLAGS_SIZE;
+ tot_length= query_length + 1 + sizeof(size_t) +
+ thd->db_length + QUERY_CACHE_FLAGS_SIZE;
+
if (thd->db_length)
{
- memcpy(sql+query_length+1, thd->db, thd->db_length);
+ memcpy(sql + query_length + 1 + sizeof(size_t), thd->db, thd->db_length);
DBUG_PRINT("qcache", ("database: '%s' length: %u",
thd->db, (unsigned)thd->db_length));
}
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index b5864fef19d..55509a31f77 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -1912,13 +1912,30 @@ bool alloc_query(THD *thd, const char *packet, uint packet_length)
pos--;
packet_length--;
}
- /* We must allocate some extra memory for query cache */
+ /* We must allocate some extra memory for query cache
+
+ The query buffer layout is:
+ buffer :==
+ <statement> The input statement(s)
+ '\0' Terminating null char (1 byte)
+ <length> Length of following current database name (size_t)
+ <db_name> Name of current database
+ <flags> Flags struct
+ */
if (! (query= (char*) thd->memdup_w_gap(packet,
packet_length,
- 1 + thd->db_length +
+ 1 + sizeof(size_t) + thd->db_length +
QUERY_CACHE_FLAGS_SIZE)))
return TRUE;
query[packet_length]= '\0';
+ /*
+ Space to hold the name of the current database is allocated. We
+ also store this length, in case current database is changed during
+ execution. We might need to reallocate the 'query' buffer
+ */
+ size_t *len = (size_t *) (query + packet_length + 1);
+ *len= thd->db_length;
+
thd->set_query(query, packet_length);
/* Reclaim some memory */