~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/statement/execute.cc

  • Committer: Brian Aker
  • Date: 2009-02-21 00:18:15 UTC
  • Revision ID: brian@tangent.org-20090221001815-x20e8h71e984lvs1
Completion (?) of uint conversion.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* - mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
 
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
 
 *
4
 
 *  Copyright (C) 2010 Brian Aker
5
 
 *
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.
10
 
 *
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.
15
 
 *
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
19
 
 */
20
 
 
21
 
#include "config.h"
22
 
 
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"
31
 
 
32
 
namespace drizzled
33
 
{
34
 
 
35
 
void parse(drizzled::Session *session, const char *inBuf, uint32_t length);
36
 
 
37
 
namespace statement
38
 
{
39
 
 
40
 
Execute::Execute(Session *in_session,
41
 
                 drizzled::execute_string_t to_execute_arg,
42
 
                 bool is_quiet_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)
50
 
{
51
 
}
52
 
  
53
 
 
54
 
bool statement::Execute::parseVariable()
55
 
{
56
 
  if (to_execute.isVariable())
57
 
  {
58
 
    user_var_entry *var= getSession()->getVariable(to_execute, false);
59
 
 
60
 
    if (var && var->length && var->value && var->type == STRING_RESULT)
61
 
    {
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);
66
 
 
67
 
      return true;
68
 
    }
69
 
  }
70
 
 
71
 
  return false;
72
 
}
73
 
 
74
 
 
75
 
bool statement::Execute::runStatement(plugin::NullClient *client, const std::string &arg)
76
 
{
77
 
  client->pushSQL(arg);
78
 
  if (not getSession()->executeStatement())
79
 
    return true;
80
 
 
81
 
  if (getSession()->is_error())
82
 
    return true;
83
 
 
84
 
  return false;
85
 
}
86
 
 
87
 
 
88
 
bool statement::Execute::execute()
89
 
{
90
 
  bool ret= execute_shell();
91
 
 
92
 
  // We have to restore ourselves at the top for delete() to work.
93
 
  getSession()->getLex()->statement= this;
94
 
 
95
 
  return ret;
96
 
}
97
 
 
98
 
 
99
 
bool statement::Execute::execute_shell()
100
 
{
101
 
  if (to_execute.length == 0)
102
 
  {
103
 
    my_error(ER_WRONG_ARGUMENTS, MYF(0), "Invalid Variable");
104
 
    return false;
105
 
  }
106
 
 
107
 
  if (to_execute.isVariable())
108
 
  {
109
 
    if (not parseVariable())
110
 
    {
111
 
      my_error(ER_WRONG_ARGUMENTS, MYF(0), "Invalid Variable");
112
 
      return false;
113
 
    }
114
 
  }
115
 
 
116
 
  if (is_concurrent)
117
 
  {
118
 
    if (not getSession()->isConcurrentExecuteAllowed())
119
 
    {
120
 
      my_error(ER_WRONG_ARGUMENTS, MYF(0), "A Concurrent Execution Session can not launch another session.");
121
 
      return false;
122
 
    }
123
 
 
124
 
    drizzled::Execute executer(*getSession(), should_wait);
125
 
    executer.run(to_execute.str, to_execute.length);
126
 
  }
127
 
  else // Non-concurrent run.
128
 
  {
129
 
    if (is_quiet)
130
 
    {
131
 
      plugin::Client *temp= getSession()->getClient();
132
 
      plugin::NullClient *null_client= new plugin::NullClient;
133
 
 
134
 
      getSession()->setClient(null_client);
135
 
      
136
 
      bool error_occured= false;
137
 
      bool is_savepoint= false;
138
 
      {
139
 
        std::string start_sql;
140
 
        if (getSession()->inTransaction())
141
 
        {
142
 
          // @todo Figure out something a bit more solid then this.
143
 
          start_sql.append("SAVEPOINT execute_internal_savepoint");
144
 
          is_savepoint= true;
145
 
        }
146
 
        else
147
 
        {
148
 
          start_sql.append("START TRANSACTION");
149
 
        }
150
 
 
151
 
        error_occured= runStatement(null_client, start_sql);
152
 
      }
153
 
 
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)
157
 
      {
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>("\\", ";", "\""));
161
 
 
162
 
        for (Tokenizer::iterator iter= tok.begin();
163
 
             iter != tok.end() and getSession()->getKilled() != Session::KILL_CONNECTION;
164
 
             ++iter)
165
 
        {
166
 
          if (runStatement(null_client, *iter))
167
 
          {
168
 
            error_occured= true;
169
 
            break;
170
 
          }
171
 
        }
172
 
 
173
 
        // @todo Encapsulate logic later to method
174
 
        {
175
 
          std::string final_sql;
176
 
          if (is_savepoint)
177
 
          {
178
 
            if (error_occured)
179
 
            {
180
 
              final_sql.append("ROLLBACK TO SAVEPOINT execute_internal_savepoint");
181
 
            }
182
 
            else
183
 
            {
184
 
              final_sql.append("RELEASE SAVEPOINT execute_internal_savepoint");
185
 
            }
186
 
          }
187
 
          else
188
 
          {
189
 
            if (error_occured)
190
 
            {
191
 
              final_sql.append("ROLLBACK");
192
 
            }
193
 
            else
194
 
            {
195
 
              final_sql.append("COMMIT");
196
 
            }
197
 
          }
198
 
 
199
 
          // Run the cleanup command, we currently ignore if an error occurs
200
 
          // here.
201
 
          (void)runStatement(null_client, final_sql);
202
 
        }
203
 
      }
204
 
 
205
 
      getSession()->setClient(temp);
206
 
      if (getSession()->is_error())
207
 
      {
208
 
        getSession()->clear_error(true);
209
 
      }
210
 
      else
211
 
      {
212
 
        getSession()->clearDiagnostics();
213
 
      }
214
 
 
215
 
      getSession()->my_ok();
216
 
 
217
 
      null_client->close();
218
 
      delete null_client;
219
 
    }
220
 
    else
221
 
    {
222
 
      parse(getSession(), to_execute.str, to_execute.length);
223
 
    }
224
 
  }
225
 
 
226
 
  return true;
227
 
}
228
 
 
229
 
} /* namespace statement */
230
 
} /* namespace drizzled */
231