24
24
/* Classes in mysql */
26
#include "drizzled/plugin.h"
26
#include <drizzled/plugin/protocol.h>
27
27
#include <drizzled/sql_locale.h>
28
#include "drizzled/resource_context.h"
29
#include <drizzled/cursor.h>
28
#include <drizzled/ha_trx_info.h>
29
#include <mysys/my_alloc.h>
30
#include <mysys/my_tree.h>
31
#include <drizzled/handler.h>
30
32
#include <drizzled/current_session.h>
31
33
#include <drizzled/sql_error.h>
32
34
#include <drizzled/file_exchange.h>
33
35
#include <drizzled/select_result_interceptor.h>
36
#include <drizzled/authentication.h>
37
#include <drizzled/db.h>
34
38
#include <drizzled/xid.h>
35
#include "drizzled/query_id.h"
36
#include "drizzled/named_savepoint.h"
37
#include "drizzled/transaction_context.h"
45
#include <drizzled/security_context.h>
46
#include <drizzled/open_tables_state.h>
48
#include <drizzled/internal_error_handler.h>
49
#include <drizzled/diagnostics_area.h>
51
#include <drizzled/plugin/authorization.h>
53
44
#define MIN_HANDSHAKE_SIZE 6
70
struct st_my_thread_var;
73
46
class Lex_input_stream;
74
47
class user_var_entry;
169
130
uint64_t bulk_insert_buff_size;
170
131
uint64_t join_buff_size;
171
132
uint32_t max_allowed_packet;
133
uint32_t myisam_stats_method;
172
134
uint64_t max_error_count;
173
135
uint64_t max_length_for_sort_data;
174
136
size_t max_sort_length;
175
137
uint64_t min_examined_row_limit;
138
uint32_t net_buffer_length;
139
uint32_t net_read_timeout;
140
uint32_t net_retry_count;
141
uint32_t net_wait_timeout;
142
uint32_t net_write_timeout;
176
143
bool optimizer_prune_level;
177
144
bool log_warnings;
145
bool engine_condition_pushdown;
179
147
uint32_t optimizer_search_depth;
148
/* A bitmap for switching optimizations on/off */
149
uint32_t optimizer_switch;
180
150
uint32_t div_precincrement;
181
151
uint64_t preload_buff_size;
182
152
uint32_t read_buff_size;
191
161
size_t range_alloc_block_size;
192
162
uint32_t query_alloc_block_size;
193
163
uint32_t query_prealloc_size;
164
uint32_t trans_alloc_block_size;
165
uint32_t trans_prealloc_size;
194
166
uint64_t group_concat_max_len;
167
/* TODO: change this to my_thread_id - but have to fix set_var first */
195
168
uint64_t pseudo_thread_id;
197
plugin::StorageEngine *storage_engine;
170
StorageEngine *storage_engine;
199
172
/* Only charset part of these variables is sensible */
200
173
const CHARSET_INFO *character_set_filesystem;
295
265
void mark_transaction_to_rollback(Session *session, bool all);
297
extern pthread_mutex_t LOCK_xid_cache;
298
extern HASH xid_cache;
302
Storage engine specific thread local data.
307
Storage engine specific thread local data.
308
Lifetime: one user connection.
312
* Resource contexts for both the "statement" and "normal"
315
* Resource context at index 0:
317
* Life time: one statement within a transaction. If @@autocommit is
318
* on, also represents the entire transaction.
320
* Resource context at index 1:
322
* Life time: one transaction within a connection.
326
* If the storage engine does not participate in a transaction,
327
* there will not be a resource context.
329
drizzled::ResourceContext resource_context[2];
331
Ha_data() :ha_ptr(NULL) {}
335
* Represents a client connection to the database server.
337
* Contains the client/server protocol object, the current statement
338
* being executed, local-to-session variables and status counters, and
339
* a host of other information.
343
* The Session class should have a vector of Statement object pointers which
344
* comprise the statements executed on the Session. Until this architectural
345
* change is done, we can forget about parallel operations inside a session.
349
* Make member variables private and have inlined accessors and setters. Hide
350
* all member variables that are not critical to non-internal operations of the
268
* Single command executed against this connection.
272
* One connection can contain a lot of simultaneously running statements,
273
* some of which could be prepared, that is, contain placeholders.
275
* To perform some action with statement we reset Session part to the state of
276
* that statement, do the action, and then save back modified state from Session
277
* to the statement. It will be changed in near future, and Statement will
278
* be used explicitly.
282
* The above comment is bullshit in Drizzle. See TODO markers on Session to
283
* completely detach the inheritance of Session from Statement.
353
class Session : public Open_tables_state
287
Statement(const Statement &rhs); /* not implemented: */
288
Statement &operator=(const Statement &rhs); /* non-copyable */
291
* List of items created in the parser for this query. Every item puts
292
* itself to the list on creation (see Item::Item() for details))
295
MEM_ROOT *mem_root; /**< Pointer to current memroot */
297
* Uniquely identifies each statement object in thread scope; change during
298
* statement lifetime.
300
* @todo should be const
357
305
MARK_COLUMNS_NONE: Means mark_used_colums is not set and no indicator to
358
306
handler of fields used is set
367
315
enum enum_mark_columns mark_used_columns;
317
LEX *lex; /**< parse tree descriptor */
319
Points to the query associated with this statement. It's const, but
320
we need to declare it char * because all table handlers are written
321
in C and need to point to it.
323
Note that (A) if we set query = NULL, we must at the same time set
324
query_length = 0, and protect the whole operation with the
325
LOCK_thread_count mutex. And (B) we are ONLY allowed to set query to a
326
non-NULL value if its previous value is NULL. We do not need to protect
327
operation (B) with any mutex. To avoid crashes in races, if we do not
328
know that session->query cannot change at the moment, one should print
329
session->query like this:
330
(1) reserve the LOCK_thread_count mutex;
331
(2) check if session->query is NULL;
332
(3) if not NULL, then print at most session->query_length characters from
333
it. We will see the query_length field as either 0, or the right value
335
Assuming that the write and read of an n-bit memory field in an n-bit
336
computer is atomic, we can avoid races in the above way.
337
This printing is needed at least in SHOW PROCESSLIST and SHOW INNODB
341
uint32_t query_length; /**< current query length */
344
Name of the current (default) database.
346
If there is the current (default) database, "db" contains its name. If
347
there is no current (default) database, "db" is NULL and "db_length" is
348
0. In other words, "db", "db_length" must either be NULL, or contain a
351
@note this attribute is set and alloced by the slave SQL thread (for
352
the Session of that thread); that thread is (and must remain, for now) the
353
only responsible for freeing this member.
356
uint32_t db_length; /**< Length of current schema name */
360
/* This constructor is called for backup statements */
363
Statement(LEX *lex_arg, MEM_ROOT *mem_root_arg, uint32_t id_arg)
366
mem_root(mem_root_arg),
368
mark_used_columns(MARK_COLUMNS_READ),
375
virtual ~Statement() {}
368
376
inline void* alloc(size_t size)
370
378
return alloc_root(mem_root,size);
398
406
/** Frees all items attached to this Statement */
399
407
void free_items();
401
* List of items created in the parser for this query. Every item puts
402
* itself to the list on creation (see Item::Item() for details))
405
memory::Root *mem_root; /**< Pointer to current memroot */
407
* Uniquely identifies each statement object in thread scope; change during
408
* statement lifetime.
410
* @todo should be const
413
LEX *lex; /**< parse tree descriptor */
414
/** query associated with this statement */
418
Name of the current (default) database.
420
If there is the current (default) database, "db" contains its name. If
421
there is no current (default) database, "db" is NULL and "db_length" is
422
0. In other words, "db", "db_length" must either be NULL, or contain a
425
@note this attribute is set and alloced by the slave SQL thread (for
426
the Session of that thread); that thread is (and must remain, for now) the
427
only responsible for freeing this member.
412
struct st_savepoint *prev;
415
Ha_trx_info *ha_list;
418
extern pthread_mutex_t LOCK_xid_cache;
419
extern HASH xid_cache;
421
#include <drizzled/security_context.h>
422
#include <drizzled/open_tables_state.h>
424
#include <drizzled/internal_error_handler.h>
425
#include <drizzled/diagnostics_area.h>
428
Storage engine specific thread local data.
433
Storage engine specific thread local data.
434
Lifetime: one user connection.
438
0: Life time: one statement within a transaction. If @@autocommit is
439
on, also represents the entire transaction.
440
@sa trans_register_ha()
442
1: Life time: one transaction within a connection.
443
If the storage engine does not participate in a transaction,
444
this should not be used.
445
@sa trans_register_ha()
447
Ha_trx_info ha_info[2];
449
Ha_data() :ha_ptr(NULL) {}
453
* Represents a client connection to the database server.
455
* Contains the client/server protocol object, the current statement
456
* being executed, local-to-session variables and status counters, and
457
* a host of other information.
461
* Session should NOT inherit from Statement, but rather it should have a
462
* vector of Statement object pointers which comprise the statements executed
463
* on the Session. Until this architectural change is done, we can forget
464
* about parallel operations inside a session.
468
* Make member variables private and have inlined accessors and setters. Hide
469
* all member variables that are not critical to non-internal operations of the
472
class Session :public Statement, public Open_tables_state
432
476
Constant for Session::where initialization in the beginning of every query.
437
481
static const char * const DEFAULT_WHERE;
439
memory::Root warn_root; /**< Allocation area for warnings and errors */
440
plugin::Client *client; /**< Pointer to client object */
441
plugin::Scheduler *scheduler; /**< Pointer to scheduler object */
442
void *scheduler_arg; /**< Pointer to the optional scheduler argument */
483
MEM_ROOT warn_root; /**< Allocation area for warnings and errors */
484
Protocol *protocol; /**< Pointer to the current protocol */
443
485
HASH user_vars; /**< Hash of user variables defined during the session's lifetime */
486
String packet; /**< dynamic buffer for network I/O */
487
String convert_buffer; /**< A buffer for charset conversions */
444
488
struct system_variables variables; /**< Mutable local variables local to the session */
445
489
struct system_status_var status_var; /**< Session-local status counters */
446
490
struct system_status_var *initial_status_var; /* used by show status */
456
500
char process_list_info[PROCESS_LIST_WIDTH+1];
459
* A pointer to the stack frame of the scheduler thread
503
* A pointer to the stack frame of handle_one_connection(),
460
504
* which is called first in the thread for handling a client
462
506
char *thread_stack;
465
SecurityContext security_ctx;
467
inline void checkSentry() const
469
assert(this->dbug_sentry == Session_SENTRY_MAGIC);
472
const SecurityContext& getSecurityContext() const
477
SecurityContext& getSecurityContext()
483
* Is this session viewable by the current user?
485
bool isViewable() const
487
return plugin::Authorization::isAuthorized(current_session->getSecurityContext(),
510
Some members of Session (currently 'Statement::db',
511
'query') are set and alloced by the slave SQL thread
512
(for the Session of that thread); that thread is (and must remain, for now)
513
the only responsible for freeing these 3 members. If you add members
514
here, and you add code to set them in replication, don't forget to
515
free_them_and_set_them_to_0 in replication properly. For details see
516
the 'err:' label of the handle_slave_sql() in sql/slave.cc.
518
@see handle_slave_sql
520
Security_context security_ctx;
493
523
Used in error messages to tell user in what part of MySQL we found an
502
532
chapter 'Miscellaneous functions', for functions GET_LOCK, RELEASE_LOCK.
504
534
uint32_t dbug_sentry; /**< watch for memory corruption */
505
internal::st_my_thread_var *mysys_var;
535
struct st_my_thread_var *mysys_var;
507
537
* Type of current query: COM_STMT_PREPARE, COM_QUERY, etc. Set from
508
538
* first byte of the packet in executeStatement()
510
540
enum enum_server_command command;
511
541
uint32_t file_id; /**< File ID for LOAD DATA INFILE */
512
/* @note the following three members should likely move to Client */
542
/* @note the following three members should likely move to Protocol */
543
uint32_t client_capabilities; /**< What the client supports */
544
uint16_t peer_port; /**< The remote (peer) port */
513
545
uint32_t max_client_packet_length; /**< Maximum number of bytes a client can send in a single packet */
514
546
time_t start_time;
515
547
time_t user_time;
523
555
Both of the following container points in session will be converted to an API.
527
558
/* container for handler's private per-connection data */
528
std::vector<Ha_data> ha_data;
530
Id of current query. Statement can be reused to execute several queries
531
query_id is global in context of the whole MySQL server.
532
ID is automatically generated from an atomic counter.
533
It's used in Cursor code for various purposes: to check which columns
534
from table are necessary for this select, to check if it's necessary to
535
update auto-updatable fields (like auto_increment and timestamp).
538
query_id_t warn_query_id;
540
void **getEngineData(const plugin::MonitoredInTransaction *monitored);
541
ResourceContext *getResourceContext(const plugin::MonitoredInTransaction *monitored,
559
Ha_data ha_data[MAX_HA];
561
/* container for replication data */
562
void *replication_data;
544
564
struct st_transactions {
545
std::deque<NamedSavepoint> savepoints;
546
TransactionContext all; ///< Trans since BEGIN WORK
547
TransactionContext stmt; ///< Trans for current statement
565
SAVEPOINT *savepoints;
566
Session_TRANS all; // Trans since BEGIN WORK
567
Session_TRANS stmt; // Trans for current statement
568
bool on; // see ha_enable_transaction()
548
569
XID_STATE xid_state;
572
Tables changed in transaction (that must be invalidated in query cache).
573
List contain only transactional tables, that not invalidated in query
574
cache (instead of full list of changed in transaction tables).
576
CHANGED_TableList* changed_tables;
577
MEM_ROOT mem_root; // Transaction-life memory allocation pool
582
free_root(&mem_root,MYF(MY_KEEP_PREALLOC));
586
memset(this, 0, sizeof(*this));
587
xid_state.xid.null();
588
init_sql_alloc(&mem_root, ALLOC_ROOT_MIN_BLOCK_SIZE, 0);
562
591
Field *dup_field;
563
592
sigset_t signals;
654
683
uint32_t total_warn_count;
655
684
Diagnostics_area main_da;
687
Id of current query. Statement can be reused to execute several queries
688
query_id is global in context of the whole MySQL server.
689
ID is automatically generated from mutex-protected counter.
690
It's used in handler code for various purposes: to check which columns
691
from table are necessary for this select, to check if it's necessary to
692
update auto-updatable fields (like auto_increment and timestamp).
657
696
ulong col_access;
698
#ifdef ERROR_INJECT_SUPPORT
699
ulong error_inject_value;
659
701
/* Statement id is thread-wide. This counter is used to generate ids */
660
702
uint32_t statement_id_counter;
661
703
uint32_t rand_saved_seed1;
881
906
auto_inc_intervals_forced.append(next_id, UINT64_MAX, 0);
884
Session(plugin::Client *client_arg);
909
Session(Protocol *protocol_arg);
913
Initialize memory roots necessary for query processing and (!)
914
pre-allocate memory for it. We can't do that in Session constructor because
915
there are use cases (acl_init, watcher threads,
916
killing mysqld) where it's vital to not allocate excessive and not used
917
memory. Note, that we still don't return error from init_for_queries():
918
if preallocation fails, we should notice that at the first call to
921
void init_for_queries();
887
922
void cleanup(void);
889
924
* Cleans up after query.
973
1005
bool authenticate();
978
* This will initialize the session and begin the command loop.
983
* Schedule a session to be run on the default scheduler.
988
1008
For enter_cond() / exit_cond() to work the mutex must be got before
989
1009
enter_cond(); this mutex is then released by exit_cond().
990
1010
Usage must be: lock mutex; enter_cond(); your code; exit_cond().
992
const char* enter_cond(pthread_cond_t *cond, pthread_mutex_t* mutex, const char* msg);
993
void exit_cond(const char* old_msg);
1012
inline const char* enter_cond(pthread_cond_t *cond, pthread_mutex_t* mutex, const char* msg)
1014
const char* old_msg = get_proc_info();
1015
safe_mutex_assert_owner(mutex);
1016
mysys_var->current_mutex = mutex;
1017
mysys_var->current_cond = cond;
1018
this->set_proc_info(msg);
1021
inline void exit_cond(const char* old_msg)
1024
Putting the mutex unlock in exit_cond() ensures that
1025
mysys_var->current_mutex is always unlocked _before_ mysys_var->mutex is
1026
locked (if that would not be the case, you'll get a deadlock if someone
1027
does a Session::awake() on you).
1029
pthread_mutex_unlock(mysys_var->current_mutex);
1030
pthread_mutex_lock(&mysys_var->mutex);
1031
mysys_var->current_mutex = 0;
1032
mysys_var->current_cond = 0;
1033
this->set_proc_info(old_msg);
1034
pthread_mutex_unlock(&mysys_var->mutex);
995
1036
inline time_t query_start() { return start_time; }
996
1037
inline void set_time()
1031
1072
return !lex->only_view_structure();
1074
inline void* trans_alloc(unsigned int size)
1076
return alloc_root(&transaction.mem_root,size);
1034
1079
LEX_STRING *make_lex_string(LEX_STRING *lex_str,
1035
1080
const char* str, uint32_t length,
1036
1081
bool allocate_lex_string);
1037
LEX_STRING *make_lex_string(LEX_STRING *lex_str,
1038
const std::string &str,
1039
bool allocate_lex_string);
1083
void add_changed_table(Table *table);
1084
void add_changed_table(const char *key, long key_length);
1085
CHANGED_TableList * changed_table_dup(const char *key, long key_length);
1041
1086
int send_explain_fields(select_result *result);
1043
1088
Clear the current error, if any.
1128
1173
@retval false Success
1129
1174
@retval true Out-of-memory error
1131
bool set_db(const std::string &new_db);
1176
bool set_db(const char *new_db, size_t new_db_len);
1179
Set the current database; use shallow copy of C-string.
1181
@param new_db a pointer to the new database name.
1182
@param new_db_len length of the new database name.
1184
@note This operation just sets {db, db_length}. Switching the current
1185
database usually involves other actions, like switching other database
1186
attributes including security context. In the future, this operation
1187
will be made private and more convenient interface will be provided.
1189
void reset_db(char *new_db, size_t new_db_len)
1192
db_length= new_db_len;
1134
1195
Copy the current database to the argument. Use the current arena to
1135
1196
allocate memory for a deep copy: current database may be freed after
1208
1269
return connect_microseconds;
1212
* Returns a pointer to the active Transaction message for this
1213
* Session being managed by the ReplicationServices component, or
1214
* NULL if no active message.
1216
message::Transaction *getTransactionMessage() const
1218
return transaction_message;
1222
* Returns a pointer to the active Statement message for this
1223
* Session, or NULL if no active message.
1225
message::Statement *getStatementMessage() const
1227
return statement_message;
1231
* Sets the active transaction message used by the ReplicationServices
1234
* @param[in] Pointer to the message
1236
void setTransactionMessage(message::Transaction *in_message)
1238
transaction_message= in_message;
1242
* Sets the active statement message used by the ReplicationServices
1245
* @param[in] Pointer to the message
1247
void setStatementMessage(message::Statement *in_message)
1249
statement_message= in_message;
1252
/** Pointers to memory managed by the ReplicationServices component */
1253
message::Transaction *transaction_message;
1254
message::Statement *statement_message;
1255
1273
/** Microsecond timestamp of when Session connected */
1256
1274
uint64_t connect_microseconds;
1257
1275
const char *proc_info;
1310
1328
/** A short cut for session->main_da.set_ok_status(). */
1311
inline void my_ok(ha_rows affected_rows= 0, ha_rows found_rows_arg= 0,
1312
uint64_t passed_id= 0, const char *message= NULL)
1329
inline void my_ok(ha_rows affected_rows= 0, uint64_t passed_id= 0, const char *message= NULL)
1314
main_da.set_ok_status(this, affected_rows, found_rows_arg, passed_id, message);
1331
main_da.set_ok_status(this, affected_rows, passed_id, message);
1412
1428
Table *openTable(TableList *table_list, bool *refresh, uint32_t flags= 0);
1414
1430
void unlink_open_table(Table *find);
1415
void drop_open_table(Table *table, TableIdentifier &identifier);
1431
void drop_open_table(Table *table, const char *db_name,
1432
const char *table_name);
1416
1433
void close_cached_table(Table *table);
1418
1435
/* Create a lock in the cache */
1419
1436
Table *table_cache_insert_placeholder(const char *key, uint32_t key_length);
1420
bool lock_table_name_if_not_cached(TableIdentifier &identifier, Table **table);
1421
bool lock_table_name_if_not_cached(const char *db,
1437
bool lock_table_name_if_not_cached(const char *db,
1422
1438
const char *table_name, Table **table);
1424
typedef drizzled::hash_map<std::string, message::Table> TableMessageCache;
1425
TableMessageCache table_message_cache;
1427
bool storeTableMessage(TableIdentifier &identifier, message::Table &table_message);
1428
bool removeTableMessage(TableIdentifier &identifier);
1429
bool getTableMessage(TableIdentifier &identifier, message::Table &table_message);
1430
bool doesTableMessageExist(TableIdentifier &identifier);
1431
bool renameTableMessage(TableIdentifier &from, TableIdentifier &to);
1433
1440
/* Work with temporary tables */
1434
1441
Table *find_temporary_table(TableList *table_list);
1435
1442
Table *find_temporary_table(const char *db, const char *table_name);
1436
Table *find_temporary_table(TableIdentifier &identifier);
1438
void doGetTableNames(CachedDirectory &directory,
1439
SchemaIdentifier &schema_identifier,
1440
std::set<std::string>& set_of_names);
1441
void doGetTableNames(SchemaIdentifier &schema_identifier,
1442
std::set<std::string>& set_of_names);
1444
void doGetTableIdentifiers(CachedDirectory &directory,
1445
SchemaIdentifier &schema_identifier,
1446
TableIdentifiers &set_of_identifiers);
1447
void doGetTableIdentifiers(SchemaIdentifier &schema_identifier,
1448
TableIdentifiers &set_of_identifiers);
1450
int doGetTableDefinition(drizzled::TableIdentifier &identifier,
1451
message::Table &table_proto);
1452
bool doDoesTableExist(TableIdentifier &identifier);
1454
1443
void close_temporary_tables();
1455
void close_temporary_table(Table *table);
1456
// The method below just handles the de-allocation of the table. In
1457
// a better memory type world, this would not be needed.
1459
void nukeTable(Table *table);
1462
void dumpTemporaryTableNames(const char *id);
1444
void close_temporary_table(Table *table, bool free_share, bool delete_table);
1445
void close_temporary(Table *table, bool free_share, bool delete_table);
1463
1446
int drop_temporary_table(TableList *table_list);
1464
bool rm_temporary_table(plugin::StorageEngine *base, TableIdentifier &identifier);
1465
bool rm_temporary_table(TableIdentifier &identifier);
1466
Table *open_temporary_table(TableIdentifier &identifier,
1467
bool link_in_list= true);
1447
bool rm_temporary_table(StorageEngine *base, char *path);
1448
Table *open_temporary_table(const char *path, const char *db,
1449
const char *table_name, bool link_in_list,
1450
open_table_mode open_mode);
1469
1452
/* Reopen operations */
1470
1453
bool reopen_tables(bool get_locks, bool mark_share_as_old);
1471
1454
bool reopen_name_locked_table(TableList* table_list, bool link_in);
1474
1457
void wait_for_condition(pthread_mutex_t *mutex, pthread_cond_t *cond);
1475
1458
int setup_conds(TableList *leaves, COND **conds);
1476
1459
int lock_tables(TableList *tables, uint32_t count, bool *need_reopen);
1480
Return the default storage engine
1482
@param getDefaultStorageEngine()
1485
pointer to plugin::StorageEngine
1487
plugin::StorageEngine *getDefaultStorageEngine()
1489
if (variables.storage_engine)
1490
return variables.storage_engine;
1491
return global_system_variables.storage_engine;
1494
static void unlink(Session *session);
1500
1464
#define ESCAPE_CHARS "ntrb0ZN" // keep synchronous with READ_INFO::unescape
1502
} /* namespace drizzled */
1504
/** @TODO why is this in the middle of the file */
1505
1466
#include <drizzled/select_to_file.h>
1506
1467
#include <drizzled/select_export.h>
1507
1468
#include <drizzled/select_dump.h>
1508
1469
#include <drizzled/select_insert.h>
1509
1470
#include <drizzled/select_create.h>
1471
#include <plugin/myisam/myisam.h>
1510
1472
#include <drizzled/tmp_table_param.h>
1511
1473
#include <drizzled/select_union.h>
1512
1474
#include <drizzled/select_subselect.h>
1573
1525
static const std::bitset<CF_BIT_SIZE> CF_WRITE_LOGS_COMMAND(1 << CF_BIT_WRITE_LOGS_COMMAND);
1575
1527
/* Functions in sql_class.cc */
1576
void add_to_status(system_status_var *to_var, system_status_var *from_var);
1578
void add_diff_to_status(system_status_var *to_var, system_status_var *from_var,
1579
system_status_var *dec_var);
1581
} /* namespace drizzled */
1528
void add_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var);
1530
void add_diff_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var,
1531
STATUS_VAR *dec_var);
1583
1533
#endif /* DRIZZLED_SESSION_H */