1
/* - mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
4
* Copyright (C) 2010 Brian Aker
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23
#include "drizzled/statement/execute.h"
24
#include "drizzled/session.h"
25
#include "drizzled/execute.h"
26
#include "drizzled/user_var_entry.h"
27
#include "drizzled/plugin/listen.h"
28
#include "drizzled/plugin/client.h"
29
#include "drizzled/plugin/null_client.h"
30
#include "drizzled/plugin/client/concurrent.h"
35
void parse(drizzled::Session *session, const char *inBuf, uint32_t length);
40
Execute::Execute(Session *in_session,
41
drizzled::execute_string_t to_execute_arg,
43
bool is_concurrent_arg,
44
bool should_wait_arg) :
45
Statement(in_session),
46
is_quiet(is_quiet_arg),
47
is_concurrent(is_concurrent_arg),
48
should_wait(should_wait_arg),
49
to_execute(to_execute_arg)
54
bool statement::Execute::parseVariable()
56
if (to_execute.isVariable())
58
user_var_entry *var= getSession()->getVariable(to_execute, false);
60
if (var && var->length && var->value && var->type == STRING_RESULT)
62
LEX_STRING tmp_for_var;
63
tmp_for_var.str= var->value;
64
tmp_for_var.length= var->length;
65
to_execute.set(tmp_for_var);
75
bool statement::Execute::runStatement(plugin::NullClient *client, const std::string &arg)
78
if (not getSession()->executeStatement())
81
if (getSession()->is_error())
88
bool statement::Execute::execute()
90
bool ret= execute_shell();
92
// We have to restore ourselves at the top for delete() to work.
93
getSession()->getLex()->statement= this;
99
bool statement::Execute::execute_shell()
101
if (to_execute.length == 0)
103
my_error(ER_WRONG_ARGUMENTS, MYF(0), "Invalid Variable");
107
if (to_execute.isVariable())
109
if (not parseVariable())
111
my_error(ER_WRONG_ARGUMENTS, MYF(0), "Invalid Variable");
118
if (not getSession()->isConcurrentExecuteAllowed())
120
my_error(ER_WRONG_ARGUMENTS, MYF(0), "A Concurrent Execution Session can not launch another session.");
124
drizzled::Execute executer(*getSession(), should_wait);
125
executer.run(to_execute.str, to_execute.length);
127
else // Non-concurrent run.
131
plugin::Client *temp= getSession()->getClient();
132
plugin::NullClient *null_client= new plugin::NullClient;
134
getSession()->setClient(null_client);
136
bool error_occured= false;
137
bool is_savepoint= false;
139
std::string start_sql;
140
if (getSession()->inTransaction())
142
// @todo Figure out something a bit more solid then this.
143
start_sql.append("SAVEPOINT execute_internal_savepoint");
148
start_sql.append("START TRANSACTION");
151
error_occured= runStatement(null_client, start_sql);
154
// @note this is copied from code in NULL client, all of this belongs
155
// in the pluggable parser pieces.
156
if (not error_occured)
158
typedef boost::tokenizer<boost::escaped_list_separator<char> > Tokenizer;
159
std::string full_string(to_execute.str, to_execute.length);
160
Tokenizer tok(full_string, boost::escaped_list_separator<char>("\\", ";", "\""));
162
for (Tokenizer::iterator iter= tok.begin();
163
iter != tok.end() and getSession()->getKilled() != Session::KILL_CONNECTION;
166
if (runStatement(null_client, *iter))
173
// @todo Encapsulate logic later to method
175
std::string final_sql;
180
final_sql.append("ROLLBACK TO SAVEPOINT execute_internal_savepoint");
184
final_sql.append("RELEASE SAVEPOINT execute_internal_savepoint");
191
final_sql.append("ROLLBACK");
195
final_sql.append("COMMIT");
199
// Run the cleanup command, we currently ignore if an error occurs
201
(void)runStatement(null_client, final_sql);
205
getSession()->setClient(temp);
206
if (getSession()->is_error())
208
getSession()->clear_error(true);
212
getSession()->clearDiagnostics();
215
getSession()->my_ok();
217
null_client->close();
222
parse(getSession(), to_execute.str, to_execute.length);
229
} /* namespace statement */
230
} /* namespace drizzled */