~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/statement/execute.cc

  • Committer: Brian Aker
  • Date: 2009-10-15 00:22:33 UTC
  • mto: (1183.1.11 merge)
  • mto: This revision was merged to the branch mainline in revision 1198.
  • Revision ID: brian@gaz-20091015002233-fa4ao2mbc67wls91
First pass of information engine. OMG, ponies... is it so much easier to
deal with creating and engine.

The list table iterator though... its ass, needs to go. We should also
abstract out share. Very few engines need a custom one. Just say'in

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 mysql_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
 
      mysql_parse(getSession(), to_execute.str, to_execute.length);
223
 
    }
224
 
  }
225
 
 
226
 
  return true;
227
 
}
228
 
 
229
 
} /* namespace statement */
230
 
} /* namespace drizzled */
231