Merge lp:~dedzone/drizzle/query-cache-hook into lp:~drizzle-trunk/drizzle/development

Proposed by Djellel E. Difallah
Status: Merged
Merge reported by: Monty Taylor
Merged at revision: not available
Proposed branch: lp:~dedzone/drizzle/query-cache-hook
Merge into: lp:~drizzle-trunk/drizzle/development
Diff against target: 640 lines (+224/-214)
6 files modified
drizzled/plugin/query_cache.cc (+135/-181)
drizzled/plugin/query_cache.h (+28/-22)
drizzled/select_send.h (+5/-0)
drizzled/session.cc (+5/-0)
drizzled/session.h (+26/-1)
drizzled/sql_parse.cc (+25/-10)
To merge this branch: bzr merge lp:~dedzone/drizzle/query-cache-hook
Reviewer Review Type Date Requested Status
Brian Aker Needs Information
Monty Taylor Pending
Review via email: mp+29729@code.launchpad.net

This proposal supersedes a proposal from 2010-07-07.

To post a comment you must log in.
Revision history for this message
Monty Taylor (mordred) wrote : Posted in a previous version of this proposal

One little thing:

cout << "Results are cached" << endl;

Looks like a debugging statement. Could you please remove this?

In general looks fine to me, although I have not examined codeflow through the runtime - Brian?

review: Needs Fixing
Revision history for this message
Toru Maesaka (tmaesaka) wrote : Posted in a previous version of this proposal

Agreed. It looks fine from first glimpse but I'm also not 100% sure
whether the hook points are placed in appropriate places in terms of
code flow.

I think it would be awesome if Djelle could provide us with arguments
on why the hooks are placed where they are atm.

Cheers,
Toru

On Thu, Jul 8, 2010 at 1:41 PM, Monty Taylor <email address hidden> wrote:
> Review: Needs Fixing
> One little thing:
>
> cout << "Results are cached" << endl;
>
> Looks like a debugging statement. Could you please remove this?
>
> In general looks fine to me, although I have not examined codeflow through the runtime - Brian?
> --
> https://code.launchpad.net/~dedzone/drizzle/query-cache-hook/+merge/29359
> You are subscribed to branch lp:drizzle.
>

--
Toru Maesaka <email address hidden>

Revision history for this message
Djellel E. Difallah (dedzone) wrote :

Hello,

I have added a wiki page explaining the Query Cache interface and the hooks into the code base.

Can you please review it.

Thanks!

~Djellel

Revision history for this message
Monty Taylor (mordred) wrote :

For those following along at home, the wiki page is:

http://drizzle.org/wiki/Query_cache

lp:~dedzone/drizzle/query-cache-hook updated
1647. By Djellel E. Difallah <ded@ubuntu>

merge with trunk

Revision history for this message
Toru Maesaka (tmaesaka) wrote :

Fantastic!

This is exactly what I wanted to see. From engineering perspective, I
wanted to see this much earlier in the project but I'm happy to see
progress regardless :)

-Toru

On Tuesday, July 13, 2010, Monty Taylor <email address hidden> wrote:
> For those following along at home, the wiki page is:
>
> http://drizzle.org/wiki/Query_cache
> --
> https://code.launchpad.net/~dedzone/drizzle/query-cache-hook/+merge/29729
> You are subscribed to branch lp:drizzle.
>

--
Toru Maesaka <email address hidden>

Revision history for this message
Brian Aker (brianaker) wrote :

It would be good to see some test cases. How is the invalidation work within a transaction?

Cheers,
  -Brian

review: Needs Information
Revision history for this message
Padraig O'Sullivan (posulliv) wrote :

Hey Brian,

We were planning on doing invalidation using the replication API for this project. Would you mind expanding on what you mean here?

Thanks,
Padraig

Revision history for this message
Toru Maesaka (tmaesaka) wrote :

Hi Brian,

Regarding test cases for Djellel's code, his changeset only includes
hooks and no real implementation of the plugin. So, I'm wondering how
we could write tests for it at this point. Would a "dummy" plugin
work? for example a module called "query-cache-test" or something
along that line.

As for invalidation in transactions, it shouldn't be a problem if we
use the Replication API since the transaction should have succeeded
when the query cache invalidator is called.

Cheers,
Toru

On Tue, Jul 20, 2010 at 10:17 AM, Brian Aker <email address hidden> wrote:
> Review: Needs Information
> It would be good to see some test cases. How is the invalidation work within a transaction?
>
> Cheers,
>  -Brian
>
>
> --
> https://code.launchpad.net/~dedzone/drizzle/query-cache-hook/+merge/29729
> You are subscribed to branch lp:drizzle.
>

--
Toru Maesaka <email address hidden>

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'drizzled/plugin/query_cache.cc'
2--- drizzled/plugin/query_cache.cc 2010-05-15 18:23:34 +0000
3+++ drizzled/plugin/query_cache.cc 2010-07-12 19:31:41 +0000
4@@ -2,6 +2,7 @@
5 * vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
6 *
7 * Copyright (C) 2008 Sun Microsystems
8+ * Copyright (C) 2010 Djellel Eddine Difallah
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12@@ -37,122 +38,144 @@
13
14 /* Namespaces are here to prevent global symbol clashes with these classes */
15
16-class TryFetchAndSendIterate
17- : public unary_function<plugin::QueryCache *, bool>
18-{
19- Session *session;
20- bool is_transactional;
21-public:
22- TryFetchAndSendIterate(Session *session_arg, bool is_transactional_arg) :
23- unary_function<plugin::QueryCache *, bool>(),
24- session(session_arg), is_transactional(is_transactional_arg) { }
25-
26- inline result_type operator()(argument_type handler)
27- {
28- if (handler->tryFetchAndSend(session, is_transactional))
29- {
30- errmsg_printf(ERRMSG_LVL_ERROR,
31- _("qcache plugin '%s' try_fetch_and_send() failed"),
32- handler->getName().c_str());
33- return true;
34- }
35- return false;
36- }
37-};
38-
39-class SetIterate
40- : public unary_function<plugin::QueryCache *, bool>
41-{
42- Session *session;
43- bool is_transactional;
44-public:
45- SetIterate(Session *session_arg, bool is_transactional_arg) :
46- unary_function<plugin::QueryCache *, bool>(),
47- session(session_arg), is_transactional(is_transactional_arg) { }
48-
49- inline result_type operator()(argument_type handler)
50- {
51-
52- if (handler->set(session, is_transactional))
53- {
54- errmsg_printf(ERRMSG_LVL_ERROR, _("qcache plugin '%s' set() failed"),
55- handler->getName().c_str());
56- return true;
57- }
58- return false;
59- }
60-};
61-
62-class InvalidateTableIterate
63- : public unary_function<plugin::QueryCache *, bool>
64-{
65- Session *session;
66- bool is_transactional;
67-public:
68- InvalidateTableIterate(Session *session_arg, bool is_transactional_arg) :
69- unary_function<plugin::QueryCache *, bool>(),
70- session(session_arg), is_transactional(is_transactional_arg) { }
71-
72- inline result_type operator()(argument_type handler)
73- {
74-
75- if (handler->invalidateTable(session, is_transactional))
76- {
77- errmsg_printf(ERRMSG_LVL_ERROR,
78- _("qcache plugin '%s' invalidateTable() failed"),
79- handler->getName().c_str());
80- return true;
81- }
82- return false;
83- }
84-};
85-
86-
87-class InvalidateDbIterate
88- : public unary_function<plugin::QueryCache *, bool>
89-{
90- Session *session;
91- const char *dbname;
92- bool is_transactional;
93-public:
94- InvalidateDbIterate(Session *session_arg, const char *dbname_arg,
95- bool is_transactional_arg) :
96- unary_function<plugin::QueryCache *, bool>(),
97- session(session_arg), dbname(dbname_arg),
98- is_transactional(is_transactional_arg) { }
99-
100- inline result_type operator()(argument_type handler)
101- {
102- if (handler->invalidateDb(session, dbname, is_transactional))
103- {
104- errmsg_printf(ERRMSG_LVL_ERROR,
105- _("qcache plugin '%s' invalidateDb() failed"),
106- handler->getName().c_str());
107- return true;
108- }
109- return false;
110- }
111-};
112-
113-class FlushIterate
114- : public unary_function<plugin::QueryCache *, bool>
115-{
116- Session *session;
117-public:
118- FlushIterate(Session *session_arg) :
119+class IsCachedIterate
120+ : public unary_function<plugin::QueryCache *, bool>
121+{
122+ Session *session;
123+public:
124+ IsCachedIterate(Session* session_arg) :
125+ unary_function<plugin::QueryCache *, bool>(),
126+ session(session_arg) { }
127+
128+ inline result_type operator()(argument_type handler)
129+ {
130+ return handler->doIsCached(session);
131+ }
132+};
133+
134+bool plugin::QueryCache::isCached(Session *session)
135+{
136+ vector<plugin::QueryCache *>::iterator iter=
137+ find_if(all_query_cache.begin(), all_query_cache.end(),
138+ IsCachedIterate(session));
139+ /* If iter is == end() here, that means that all of the plugins returned
140+ * false, which in this case means they all succeeded. Since we want to
141+ * return false on success, we return the value of the two being !=
142+ */
143+ return iter != all_query_cache.end();
144+}
145+
146+
147+class SendCachedResultsetIterate
148+ : public unary_function<plugin::QueryCache *, bool>
149+{
150+ Session *session;
151+public:
152+ SendCachedResultsetIterate(Session *session_arg) :
153+ unary_function<plugin::QueryCache *, bool>(),
154+ session(session_arg) { }
155+
156+ inline result_type operator()(argument_type handler)
157+ {
158+ if (handler->doSendCachedResultset(session))
159+ return false;
160+ return true;
161+ }
162+};
163+bool plugin::QueryCache::sendCachedResultset(Session *session)
164+{
165+ vector<plugin::QueryCache *>::iterator iter=
166+ find_if(all_query_cache.begin(), all_query_cache.end(),
167+ SendCachedResultsetIterate(session));
168+ /* If iter is == end() here, that means that all of the plugins returned
169+ * false, which in this case means they all succeeded. Since we want to
170+ * return false on success, we return the value of the two being !=
171+ */
172+ return iter != all_query_cache.end();
173+}
174+
175+class PrepareResultsetIterate
176+ : public unary_function<plugin::QueryCache *, bool>
177+{
178+ Session *session;
179+public:
180+ PrepareResultsetIterate(Session *session_arg) :
181 unary_function<plugin::QueryCache *, bool>(), session(session_arg) { }
182
183 inline result_type operator()(argument_type handler)
184 {
185- if (handler->flush(session))
186- {
187- errmsg_printf(ERRMSG_LVL_ERROR, _("qcache plugin '%s' flush() failed"),
188- handler->getName().c_str());
189- return true;
190- }
191- return false;
192- }
193-};
194+ return handler->doPrepareResultset(session);
195+ }
196+};
197+bool plugin::QueryCache::prepareResultset(Session *session)
198+{
199+ vector<plugin::QueryCache *>::iterator iter=
200+ find_if(all_query_cache.begin(), all_query_cache.end(),
201+ PrepareResultsetIterate(session));
202+ /* If iter is == end() here, that means that all of the plugins returned
203+ * false, which in this case means they all succeeded. Since we want to
204+ * return false on success, we return the value of the two being !=
205+ */
206+ return iter != all_query_cache.end();
207+}
208+
209+class SetResultsetIterate
210+ : public unary_function<plugin::QueryCache *, bool>
211+{
212+ Session *session;
213+public:
214+ SetResultsetIterate(Session *session_arg) :
215+ unary_function<plugin::QueryCache *, bool>(),
216+ session(session_arg) { }
217+
218+ inline result_type operator()(argument_type handler)
219+ {
220+ return handler->doSetResultset(session);
221+ }
222+};
223+
224+bool plugin::QueryCache::setResultset(Session *session)
225+{
226+ /* Use find_if instead of foreach so that we can collect return codes */
227+ vector<plugin::QueryCache *>::iterator iter=
228+ find_if(all_query_cache.begin(), all_query_cache.end(),
229+ SetResultsetIterate(session));
230+ /* If iter is == end() here, that means that all of the plugins returned
231+ * false, which in this case means they all succeeded. Since we want to
232+ * return false on success, we return the value of the two being !=
233+ */
234+ return iter != all_query_cache.end();
235+}
236+
237+class InsertRecordIterate
238+ : public unary_function<plugin::QueryCache *, bool>
239+{
240+ Session *session;
241+ List<Item> &item;
242+public:
243+ InsertRecordIterate(Session *session_arg, List<Item> &item_arg) :
244+ unary_function<plugin::QueryCache *, bool>(),
245+ session(session_arg), item(item_arg) { }
246+
247+ inline result_type operator()(argument_type handler)
248+ {
249+ return handler->doInsertRecord(session, item);
250+ }
251+};
252+bool plugin::QueryCache::insertRecord(Session *session, List<Item> &items)
253+{
254+ /* Use find_if instead of foreach so that we can collect return codes */
255+ vector<plugin::QueryCache *>::iterator iter=
256+ find_if(all_query_cache.begin(), all_query_cache.end(),
257+ InsertRecordIterate(session, items));
258+ /* If iter is == end() here, that means that all of the plugins returned
259+ * false, which in this case means they all succeeded. Since we want to
260+ * return false on success, we return the value of the two being !=
261+ */
262+ return iter != all_query_cache.end();
263+}
264+
265+
266
267 bool plugin::QueryCache::addPlugin(plugin::QueryCache *handler)
268 {
269@@ -166,73 +189,4 @@
270 handler));
271 }
272
273-
274-bool plugin::QueryCache::tryFetchAndSendDo(Session *session,
275- bool transactional)
276-{
277- /* Use find_if instead of foreach so that we can collect return codes */
278- vector<plugin::QueryCache *>::iterator iter=
279- find_if(all_query_cache.begin(), all_query_cache.end(),
280- TryFetchAndSendIterate(session, transactional));
281- /* If iter is == end() here, that means that all of the plugins returned
282- * false, which in this case means they all succeeded. Since we want to
283- * return false on success, we return the value of the two being !=
284- */
285- return iter != all_query_cache.end();
286-}
287-
288-bool plugin::QueryCache::setDo(Session *session, bool transactional)
289-{
290- /* Use find_if instead of foreach so that we can collect return codes */
291- vector<plugin::QueryCache *>::iterator iter=
292- find_if(all_query_cache.begin(), all_query_cache.end(),
293- SetIterate(session, transactional));
294- /* If iter is == end() here, that means that all of the plugins returned
295- * false, which in this case means they all succeeded. Since we want to
296- * return false on success, we return the value of the two being !=
297- */
298- return iter != all_query_cache.end();
299-}
300-
301-bool plugin::QueryCache::invalidateTableDo(Session *session,
302- bool transactional)
303-{
304- /* Use find_if instead of foreach so that we can collect return codes */
305- vector<plugin::QueryCache *>::iterator iter=
306- find_if(all_query_cache.begin(), all_query_cache.end(),
307- InvalidateTableIterate(session, transactional));
308- /* If iter is == end() here, that means that all of the plugins returned
309- * false, which in this case means they all succeeded. Since we want to
310- * return false on success, we return the value of the two being !=
311- */
312- return iter != all_query_cache.end();
313-}
314-
315-bool plugin::QueryCache::invalidateDbDo(Session *session, const char *dbname,
316- bool transactional)
317-{
318- /* Use find_if instead of foreach so that we can collect return codes */
319- vector<plugin::QueryCache *>::iterator iter=
320- find_if(all_query_cache.begin(), all_query_cache.end(),
321- InvalidateDbIterate(session, dbname, transactional));
322- /* If iter is == end() here, that means that all of the plugins returned
323- * false, which in this case means they all succeeded. Since we want to
324- * return false on success, we return the value of the two being !=
325- */
326- return iter != all_query_cache.end();
327-}
328-
329-bool plugin::QueryCache::flushDo(Session *session)
330-{
331- /* Use find_if instead of foreach so that we can collect return codes */
332- vector<plugin::QueryCache *>::iterator iter=
333- find_if(all_query_cache.begin(), all_query_cache.end(),
334- FlushIterate(session));
335- /* If iter is == end() here, that means that all of the plugins returned
336- * false, which in this case means they all succeeded. Since we want to
337- * return false on success, we return the value of the two being !=
338- */
339- return iter != all_query_cache.end();
340-}
341-
342 } /* namespace drizzled */
343
344=== modified file 'drizzled/plugin/query_cache.h'
345--- drizzled/plugin/query_cache.h 2010-03-06 02:08:13 +0000
346+++ drizzled/plugin/query_cache.h 2010-07-12 19:31:41 +0000
347@@ -4,6 +4,7 @@
348 * Definitions required for Query Cache plugin
349 *
350 * Copyright (C) 2008 Sun Microsystems, Toru Maesaka
351+ * Copyright (C) 2010 Djellel Eddine Difallah
352 *
353 * This program is free software; you can redistribute it and/or modify
354 * it under the terms of the GNU General Public License as published by
355@@ -22,55 +23,60 @@
356 #ifndef DRIZZLED_PLUGIN_QUERY_CACHE_H
357 #define DRIZZLED_PLUGIN_QUERY_CACHE_H
358
359+#include "drizzled/plugin.h"
360 #include "drizzled/plugin/plugin.h"
361+#include <drizzled/sql_list.h>
362
363 namespace drizzled
364 {
365 class Session;
366+class select_result;
367
368 namespace plugin
369 {
370
371 /*
372 This is the API that a qcache plugin must implement.
373- it should implement each of these function pointers.
374- if a function pointer is NULL (not loaded), that's ok.
375-
376- Return:
377- false = success
378- true = failure
379 */
380+
381 class QueryCache : public Plugin
382 {
383+private:
384+
385 QueryCache();
386 QueryCache(const QueryCache &);
387 QueryCache& operator=(const QueryCache &);
388-public:
389+
390+public:
391+
392 explicit QueryCache(std::string name_arg)
393 : Plugin(name_arg, "QueryCache")
394 {}
395
396 virtual ~QueryCache() {}
397- /* Lookup the cache and transmit the data back to the client */
398- virtual bool tryFetchAndSend(Session *session,
399- bool is_transactional)= 0;
400-
401- virtual bool set(Session *session, bool is_transactional)= 0;
402- virtual bool invalidateTable(Session *session, bool is_transactional)= 0;
403- virtual bool invalidateDb(Session *session, const char *db_name,
404- bool transactional)= 0;
405- virtual bool flush(Session *session)= 0;
406+
407+ /* these are the Query Cache interface functions */
408+
409+ /* Lookup the cache and transmit the data back to the client */
410+ virtual bool doIsCached(Session* session)= 0;
411+ /* Lookup the cache and transmit the data back to the client */
412+ virtual bool doSendCachedResultset(Session *session)= 0;
413+ /* Send the current Resultset to the cache */
414+ virtual bool doSetResultset(Session *session)= 0;
415+ /* initiate a new Resultset (header) */
416+ virtual bool doPrepareResultset(Session *session)= 0;
417+ /* push a record to the current Resultset */
418+ virtual bool doInsertRecord(Session *session, List<Item> &item)= 0;
419
420 static bool addPlugin(QueryCache *handler);
421 static void removePlugin(QueryCache *handler);
422
423 /* These are the functions called by the rest of the Drizzle server */
424- static bool tryFetchAndSendDo(Session *session, bool transactional);
425- static bool setDo(Session *session, bool transactional);
426- static bool invalidateTableDo(Session *session, bool transactional);
427- static bool invalidateDbDo(Session *session, const char *db_name,
428- bool transactional);
429- static bool flushDo(Session *session);
430+ static bool isCached(Session *session);
431+ static bool sendCachedResultset(Session *session);
432+ static bool prepareResultset(Session *session);
433+ static bool setResultset(Session *session);
434+ static bool insertRecord(Session *session, List<Item> &item);
435 };
436
437 } /* namespace plugin */
438
439=== modified file 'drizzled/select_send.h'
440--- drizzled/select_send.h 2010-02-14 19:27:57 +0000
441+++ drizzled/select_send.h 2010-07-12 19:31:41 +0000
442@@ -22,6 +22,7 @@
443 #define DRIZZLED_SELECT_SEND_H
444
445 #include <drizzled/plugin/client.h>
446+#include <drizzled/plugin/query_cache.h>
447 #include <drizzled/plugin/transactional_storage_engine.h>
448
449 namespace drizzled
450@@ -111,6 +112,10 @@
451 break;
452 }
453 }
454+ /* Insert this record to the Resultset into the cache */
455+ if (session->query_cache_key != "" && session->getResultsetMessage() != NULL)
456+ plugin::QueryCache::insertRecord(session, items);
457+
458 session->sent_row_count++;
459 if (session->is_error())
460 return true;
461
462=== modified file 'drizzled/session.cc'
463--- drizzled/session.cc 2010-07-07 17:51:44 +0000
464+++ drizzled/session.cc 2010-07-12 19:31:41 +0000
465@@ -229,6 +229,9 @@
466 cleanup_done= abort_on_warning= no_warnings_for_error= false;
467 pthread_mutex_init(&LOCK_delete, MY_MUTEX_INIT_FAST);
468
469+ /* query_cache init */
470+ query_cache_key= "";
471+ resultset= NULL;
472 /* Variables with default values */
473 proc_info="login";
474 where= Session::DEFAULT_WHERE;
475@@ -1464,6 +1467,8 @@
476 {
477 /* Cleanup SQL processing state to reuse this statement in next query. */
478 lex_end(lex);
479+ query_cache_key= ""; // reset the cache key
480+ resultset= NULL;
481 }
482
483 bool Session::copy_db_to(char **p_db, size_t *p_db_length)
484
485=== modified file 'drizzled/session.h'
486--- drizzled/session.h 2010-07-07 17:51:44 +0000
487+++ drizzled/session.h 2010-07-12 19:31:41 +0000
488@@ -67,6 +67,7 @@
489 {
490 class Transaction;
491 class Statement;
492+class Resultset;
493 }
494 namespace internal
495 {
496@@ -368,6 +369,8 @@
497 */
498 std::string db;
499
500+ /* current cache key */
501+ std::string query_cache_key;
502 /**
503 Constant for Session::where initialization in the beginning of every query.
504
505@@ -1175,7 +1178,15 @@
506 {
507 return statement_message;
508 }
509-
510+
511+ /**
512+ * Returns a pointer to the current Resulset message for this
513+ * Session, or NULL if no active message.
514+ */
515+ message::Resultset *getResultsetMessage() const
516+ {
517+ return resultset;
518+ }
519 /**
520 * Sets the active transaction message used by the ReplicationServices
521 * component.
522@@ -1197,10 +1208,24 @@
523 {
524 statement_message= in_message;
525 }
526+
527+ /**
528+ * Sets the active Resultset message used by the Query Cache
529+ * plugin.
530+ *
531+ * @param[in] Pointer to the message
532+ */
533+ void setResultsetMessage(message::Resultset *in_message)
534+ {
535+ resultset= in_message;
536+ }
537+
538 private:
539 /** Pointers to memory managed by the ReplicationServices component */
540 message::Transaction *transaction_message;
541 message::Statement *statement_message;
542+ /* Pointer to the current resultset of Select query */
543+ message::Resultset *resultset;
544 plugin::EventObserverList *session_event_observers;
545
546 /* Schema observers are mapped to databases. */
547
548=== modified file 'drizzled/sql_parse.cc'
549--- drizzled/sql_parse.cc 2010-07-07 17:51:44 +0000
550+++ drizzled/sql_parse.cc 2010-07-12 19:31:41 +0000
551@@ -44,6 +44,7 @@
552
553 #include "drizzled/plugin/logging.h"
554 #include "drizzled/plugin/query_rewrite.h"
555+#include "drizzled/plugin/query_cache.h"
556 #include "drizzled/plugin/authorization.h"
557 #include "drizzled/optimizer/explain_plan.h"
558 #include "drizzled/pthread_globals.h"
559@@ -476,9 +477,7 @@
560
561 /* now we are ready to execute the statement */
562 res= lex->statement->execute();
563-
564 session->set_proc_info("query end");
565-
566 /*
567 The return value for ROW_COUNT() is "implementation dependent" if the
568 statement is not DELETE, INSERT or UPDATE, but -1 is what JDBC and ODBC
569@@ -492,7 +491,6 @@
570
571 return (res || session->is_error());
572 }
573-
574 bool execute_sqlcom_select(Session *session, TableList *all_tables)
575 {
576 LEX *lex= session->lex;
577@@ -540,7 +538,13 @@
578 {
579 if (!result && !(result= new select_send()))
580 return true;
581+
582+ /* Init the Query Cache plugin */
583+ plugin::QueryCache::prepareResultset(session);
584 res= handle_select(session, lex, result, 0);
585+ /* Send the Resultset to the cache */
586+ plugin::QueryCache::setResultset(session);
587+
588 if (result != lex->result)
589 delete result;
590 }
591@@ -715,13 +719,25 @@
592 uint64_t start_time= my_getsystime();
593 lex_start(session);
594 session->reset_for_next_command();
595-
596+ /* Check if the Query is Cached if and return true if yes
597+ * TODO the plugin has to make sure that the query is cacheble
598+ * by setting the query_safe_cache param to TRUE
599+ */
600+ bool res= true;
601+ if (plugin::QueryCache::isCached(session))
602+ {
603+ res= plugin::QueryCache::sendCachedResultset(session);
604+ }
605+ if (not res)
606+ {
607+#if defined(DEBUG)
608+ errmsg_printf(ERRMSG_LVL_DBUG,_("Results retrieved from cache"));
609+#endif /* DEBUG */
610+ return;
611+ }
612 LEX *lex= session->lex;
613-
614 Lex_input_stream lip(session, inBuf, length);
615-
616 bool err= parse_sql(session, &lip);
617-
618 if (!err)
619 {
620 {
621@@ -731,9 +747,9 @@
622 session->thread_id,
623 const_cast<const char *>(session->db.empty() ? "" : session->db.c_str()));
624 // Implement Views here --Brian
625-
626 /* Actually execute the query */
627- try {
628+ try
629+ {
630 mysql_execute_command(session);
631 }
632 catch (...)
633@@ -749,7 +765,6 @@
634 {
635 assert(session->is_error());
636 }
637-
638 lex->unit.cleanup();
639 session->set_proc_info("freeing items");
640 session->end_statement();