2
* Copyright (C) 2010 PrimeBase Technologies GmbH, Germany
4
* This program is free software; you can redistribute it and/or modify
5
* it under the terms of the GNU General Public License as published by
6
* the Free Software Foundation; version 2 of the License.
8
* This program is distributed in the hope that it will be useful,
9
* but WITHOUT ANY WARRANTY; without even the implied warranty of
10
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
* GNU General Public License for more details.
13
* You should have received a copy of the GNU General Public License
14
* along with this program; if not, write to the Free Software
15
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25
* This plugin is an example events plugin that just prints some info for
26
* the events that it is tracking.
28
set global hello_events1_enable = ON;
29
set global hello_events1_watch_databases = "x";
30
set global hello_events1_watch_tables = "x,y";
37
#include <boost/program_options.hpp>
38
#include <drizzled/module/option_map.h>
39
#include "drizzled/session.h"
40
#include "hello_events.h"
42
namespace po= boost::program_options;
43
using namespace drizzled;
44
using namespace plugin;
47
#define PLUGIN_NAME "hello_events1"
49
static bool sysvar_hello_events_enabled;
50
static HelloEvents *hello_events= NULL;
51
static string sysvar_db_list;
52
static string sysvar_table_list;
55
* Event observer positions are used to set the order in which
56
* event observers are called in the case that more than one
57
* plugin is interested in the same event. You should only specify
58
* the order if it really matters because if more than one plugin
59
* request the same calling position only the first one gets it and
60
* the others will not be registered for the event. For this reason
61
* your plugin should always provide a way to reposition the event
62
* observer to resolve such conflicts.
64
* If position matters you will always initialy ask for the first position (1)
65
* or the last position (-1) in the calling order, for example it makes no sence
66
* to initially ask to be called in position 13.
68
typedef constrained_check<uint64_t, INT32_MAX-1, 1> position_constraint;
69
typedef constrained_check<int32_t, -1, INT32_MIN+1> post_drop_constraint;
71
static position_constraint sysvar_before_write_position; // Call this event observer first.
72
static position_constraint sysvar_before_update_position;
73
static post_drop_constraint sysvar_post_drop_db_position; // I want my event observer to be called last. No reason, I just do!
76
//==================================
77
// My table event observers:
78
static bool observeBeforeInsertRecord(BeforeInsertRecordEventData &data)
83
data.session.setVariable("BEFORE_INSERT_RECORD", boost::lexical_cast<std::string>(count));
88
static void observeAfterInsertRecord(AfterInsertRecordEventData &data)
92
data.session.setVariable("AFTER_INSERT_RECORD", boost::lexical_cast<std::string>(count));
96
static bool observeBeforeDeleteRecord(BeforeDeleteRecordEventData &data)
100
data.session.setVariable("AFTER_DELETE_RECORD", boost::lexical_cast<std::string>(count));
105
static void observeAfterDeleteRecord(AfterDeleteRecordEventData &data)
109
data.session.setVariable("AFTER_DELETE_RECORD", boost::lexical_cast<std::string>(count));
113
static bool observeBeforeUpdateRecord(BeforeUpdateRecordEventData &data)
117
data.session.setVariable("BEFORE_UPDATE_RECORD", boost::lexical_cast<std::string>(count));
122
static void observeAfterUpdateRecord(AfterUpdateRecordEventData &data)
126
data.session.setVariable("AFTER_UPDATE_RECORD", boost::lexical_cast<std::string>(count));
129
//==================================
130
// My schema event observers:
131
static void observeAfterDropTable(AfterDropTableEventData &data)
135
data.session.setVariable("AFTER_DROP_TABLE", boost::lexical_cast<std::string>(count));
139
static void observeAfterRenameTable(AfterRenameTableEventData &data)
143
data.session.setVariable("AFTER_RENAME_TABLE", boost::lexical_cast<std::string>(count));
147
static void observeAfterCreateDatabase(AfterCreateDatabaseEventData &data)
151
data.session.setVariable("AFTER_CREATE_DATABASE", boost::lexical_cast<std::string>(count));
155
static void observeAfterDropDatabase(AfterDropDatabaseEventData &data)
159
data.session.setVariable("AFTER_DROP_DATABASE", boost::lexical_cast<std::string>(count));
163
static void observeConnectSession(ConnectSessionEventData &data)
167
data.session.setVariable("CONNECT_SESSION", boost::lexical_cast<std::string>(count));
171
static void observeDisconnectSession(DisconnectSessionEventData &data)
175
data.session.setVariable("DISCONNECT_SESSION", boost::lexical_cast<std::string>(count));
179
static void observeBeforeStatement(BeforeStatementEventData &data)
183
data.session.setVariable("BEFORE_STATEMENT", boost::lexical_cast<std::string>(count));
187
static void observeAfterStatement(AfterStatementEventData &data)
191
data.session.setVariable("AFTER_STATEMENT", boost::lexical_cast<std::string>(count));
194
HelloEvents::~HelloEvents()
197
//==================================
198
/* This is where I register which table events my pluggin is interested in.*/
199
void HelloEvents::registerTableEventsDo(TableShare &table_share, EventObserverList &observers)
201
if ((is_enabled == false)
202
|| !isTableInteresting(table_share.getTableName())
203
|| !isDatabaseInteresting(table_share.getSchemaName()))
206
registerEvent(observers, BEFORE_INSERT_RECORD, sysvar_before_write_position.get());
207
// I want to be called first if passible
208
registerEvent(observers, AFTER_INSERT_RECORD);
209
registerEvent(observers, BEFORE_UPDATE_RECORD, sysvar_before_update_position.get());
210
registerEvent(observers, AFTER_UPDATE_RECORD);
211
registerEvent(observers, BEFORE_DELETE_RECORD);
212
registerEvent(observers, AFTER_DELETE_RECORD);
215
//==================================
216
/* This is where I register which schema events my pluggin is interested in.*/
217
void HelloEvents::registerSchemaEventsDo(const std::string &db, EventObserverList &observers)
219
if ((is_enabled == false)
220
|| !isDatabaseInteresting(db))
223
registerEvent(observers, AFTER_DROP_TABLE);
224
registerEvent(observers, AFTER_RENAME_TABLE);
227
//==================================
228
/* This is where I register which session events my pluggin is interested in.*/
229
void HelloEvents::registerSessionEventsDo(Session &session, EventObserverList &observers)
231
if ((is_enabled == false)
232
|| !isSessionInteresting(session))
235
registerEvent(observers, AFTER_CREATE_DATABASE);
236
registerEvent(observers, AFTER_DROP_DATABASE, sysvar_post_drop_db_position.get());
237
registerEvent(observers, DISCONNECT_SESSION);
238
registerEvent(observers, CONNECT_SESSION);
239
registerEvent(observers, BEFORE_STATEMENT);
240
registerEvent(observers, AFTER_STATEMENT);
244
//==================================
245
/* The event observer.*/
246
bool HelloEvents::observeEventDo(EventData &data)
250
switch (data.event) {
251
case AFTER_DROP_TABLE:
252
observeAfterDropTable((AfterDropTableEventData &)data);
255
case AFTER_RENAME_TABLE:
256
observeAfterRenameTable((AfterRenameTableEventData &)data);
259
case BEFORE_INSERT_RECORD:
260
result = observeBeforeInsertRecord((BeforeInsertRecordEventData &)data);
263
case AFTER_INSERT_RECORD:
264
observeAfterInsertRecord((AfterInsertRecordEventData &)data);
267
case BEFORE_UPDATE_RECORD:
268
result = observeBeforeUpdateRecord((BeforeUpdateRecordEventData &)data);
271
case AFTER_UPDATE_RECORD:
272
observeAfterUpdateRecord((AfterUpdateRecordEventData &)data);
275
case BEFORE_DELETE_RECORD:
276
result = observeBeforeDeleteRecord((BeforeDeleteRecordEventData &)data);
279
case AFTER_DELETE_RECORD:
280
observeAfterDeleteRecord((AfterDeleteRecordEventData &)data);
283
case AFTER_CREATE_DATABASE:
284
observeAfterCreateDatabase((AfterCreateDatabaseEventData &)data);
287
case AFTER_DROP_DATABASE:
288
observeAfterDropDatabase((AfterDropDatabaseEventData &)data);
291
case CONNECT_SESSION:
292
observeConnectSession((ConnectSessionEventData &)data);
295
case DISCONNECT_SESSION:
296
observeDisconnectSession((DisconnectSessionEventData &)data);
299
case BEFORE_STATEMENT:
300
observeBeforeStatement((BeforeStatementEventData &)data);
303
case AFTER_STATEMENT:
304
observeAfterStatement((AfterStatementEventData &)data);
308
fprintf(stderr, "HelloEvents: Unexpected event '%s'\n", EventObserver::eventName(data.event));
315
//==================================
316
// Some custom things for my plugin:
319
/* Plugin initialization and system variables */
321
static void enable(Session*, sql_var_t)
325
if (sysvar_hello_events_enabled)
327
hello_events->enable();
331
hello_events->disable();
337
static int set_db_list(Session *, set_var *var)
339
const char *db_list= var->value->str_value.ptr();
345
hello_events->setDatabasesOfInterest(db_list);
346
sysvar_db_list.assign(db_list);
351
static int set_table_list(Session *, set_var *var)
353
const char *table_list= var->value->str_value.ptr();
354
if (table_list == NULL)
359
hello_events->setTablesOfInterest(table_list);
360
sysvar_table_list.assign(table_list);
366
static int init(module::Context &context)
368
hello_events= new HelloEvents(PLUGIN_NAME);
370
context.add(hello_events);
372
if (sysvar_hello_events_enabled)
374
hello_events->enable();
377
context.registerVariable(new sys_var_bool_ptr("enable",
378
&sysvar_hello_events_enabled,
380
context.registerVariable(new sys_var_std_string("watch_databases",
383
context.registerVariable(new sys_var_std_string("watch_tables",
386
context.registerVariable(new sys_var_constrained_value<uint64_t>("before_write_position",
387
sysvar_before_write_position));
388
context.registerVariable(new sys_var_constrained_value<uint64_t>("before_update_position",
389
sysvar_before_update_position));
390
context.registerVariable(new sys_var_constrained_value<int32_t>("post_drop_position",
391
sysvar_post_drop_db_position));
397
static void init_options(drizzled::module::option_context &context)
400
po::value<bool>(&sysvar_hello_events_enabled)->default_value(false)->zero_tokens(),
401
N_("Enable Example Events Plugin"));
402
context("watch-databases",
403
po::value<string>(&sysvar_db_list)->default_value(""),
404
N_("A comma delimited list of databases to watch"));
405
context("watch-tables",
406
po::value<string>(&sysvar_table_list)->default_value(""),
407
N_("A comma delimited list of databases to watch"));
408
context("before-write-position",
409
po::value<position_constraint>(&sysvar_before_write_position)->default_value(1),
410
N_("Before write row event observer call position"));
411
context("before-update-position",
412
po::value<position_constraint>(&sysvar_before_update_position)->default_value(1),
413
N_("Before update row event observer call position"));
414
context("post-drop-db-position",
415
po::value<post_drop_constraint>(&sysvar_post_drop_db_position)->default_value(-1),
416
N_("After drop database event observer call position"));
421
DRIZZLE_DECLARE_PLUGIN
427
N_("An example events Plugin"),
429
init, /* Plugin Init */
431
init_options /* config options */
433
DRIZZLE_DECLARE_PLUGIN_END;