QueryState¶
#include "ThriftHandler/QueryState.h"
QueryState is a set of C++ classes that:
Consolidates information about current and past SQL queries.
Record execution time of blocks of C++ code, and log with call stack relationships.
Classes¶
- QueryStates
Manages and aggregates
QueryState
objects. E.g.DBHandler
has oneQueryStates
member variable.- QueryState
Manages the lifetime of a single query. Attributes/methods (e.g.
bool just_explain
) may be moved/added directly to this class as needed to model the state of SQL queries. As such, the development of this class can be considered ongoing, as a reflection of the ongoing development of the OmniSciDB itself. Timing of code blocks (i.e. function calls) are stored in a list ofEvent
s.- Event
Records start and stop times for the lifetime of a corresponding
Timer
object.Event
s can have parent/child relationships to model call-stack nesting.- Timer
Event
s andTimer
s are created at the same time. ATimer
object is typically instantiated with a__func__
parameter, which shows up in the logs along with the duration between its construction and destruction.- QueryStateProxy
A light-weight object that can both create and be created by
Timer
objects so that call-stack relationships between parent/childEvent
s are recorded.
Example Usage¶
In DBHandler::sql_execute()
:
// session_ptr and query_str are already set or passed into the function.
auto query_state = create_query_state(session_ptr, query_str); // Line A
auto stdlog = STDLOG(query_state); // Line B
...
foo(query_state->createQueryStateProxy()); // Line C
In foo(QueryStateProxy query_state_proxy)
:
auto timer = query_state_proxy.createTimer(__func__); // Line D
...
bar(timer.createQueryStateProxy()); // Line E
In bar(QueryStateProxy query_state_proxy)
:
auto timer = query_state_proxy.createTimer(__func__); // Line F
...
- Line A
auto query_state = create_query_state(session_ptr, query_str); // Line A
Create a new
QueryState
in theDBHandler::query_states_
member variable for the current query.- Line B
auto stdlog = STDLOG(query_state); // Line B
Connects the
QueryState
object to thestdlog
which will log theQueryState
information duringstdlog
’s destructor.- Line C
foo(query_state->createQueryStateProxy()); // Line C
To pass
QueryState
to other functions, it is preferred to generate a light-weightQueryStateProxy
object rather than pass theQueryState
reference. This is becauseTimer
objects also generateQueryStateProxy
objects to pass to other functions in order to track nested timings. Thus to avoid having redundant versions of functions that accept bothQueryState
andQueryStateProxy
types, it is preferred for members/functions to acceptQueryStateProxy
. The originalQueryState
reference is then available viaQueryStateProxy::getQueryState()
.- Line D
auto timer = query_state_proxy.createTimer(__func__); // Line D
The lifetime of
timer
is recorded and stored in the originalquery_state
object from Line A, and will appear in the logs associated with__func__ = "foo"
in this case.- Line E
bar(timer.createQueryStateProxy()); // Line E
Similar to Line C, this is how to create nested timings when invoking another function deeper in the call stack.
- Line F
auto timer = query_state_proxy.createTimer(__func__); // Line F
Similar to Line D, the created
timer
will show up nested under the previousTimer
object.
The two timer
instances above directly result in the nested log lines:
foo 140038217238272 - total time 578 ms
bar 140038217238272 - total time 578 ms
(The long integer is the thread id.) Though only a couple examples were given here, each Timer
object can
spawn any number of QueryStateProxy
instances, and vice-versa.
Summary¶
The above example demonstrates how to:
Create new
QueryState
objects and connect them withSessionInfo
andStdLog
instances.Create nested
Timer
objects usingQueryStateProxy
objects as intermediaries to model nested function calls.