~drizzle-trunk/drizzle/development

1835.1.6 by Brian Aker
This patch returns dynamic SQL into the core (through SQL-Server syntax).
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
2173.2.1 by Monty Taylor
Fixes incorrect usage of include
21
#include <config.h>
1835.1.6 by Brian Aker
This patch returns dynamic SQL into the core (through SQL-Server syntax).
22
2173.2.1 by Monty Taylor
Fixes incorrect usage of include
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>
2234.1.4 by Olaf van der Spek
Refactor includes
31
#include <drizzled/sql_lex.h>
1835.1.6 by Brian Aker
This patch returns dynamic SQL into the core (through SQL-Server syntax).
32
2269.1.7 by Olaf van der Spek
Use util::string::ptr
33
namespace drizzled {
34
35
void parse(drizzled::Session&, const char *inBuf, uint32_t length);
36
37
namespace statement {
1835.1.6 by Brian Aker
This patch returns dynamic SQL into the core (through SQL-Server syntax).
38
1921.4.2 by Brian Aker
Adding in concurrent execute support.
39
Execute::Execute(Session *in_session,
2385.2.15 by Olaf van der Spek
Refactor
40
                 execute_string_t to_execute_arg,
1921.4.2 by Brian Aker
Adding in concurrent execute support.
41
                 bool is_quiet_arg,
1958.1.1 by Brian Aker
Fix clash in parser with wait().
42
                 bool is_concurrent_arg,
43
                 bool should_wait_arg) :
1835.1.6 by Brian Aker
This patch returns dynamic SQL into the core (through SQL-Server syntax).
44
  Statement(in_session),
1921.4.1 by Brian Aker
Adding in support for EXECUTE to have WITH NO RETURN.
45
  is_quiet(is_quiet_arg),
1921.4.2 by Brian Aker
Adding in concurrent execute support.
46
  is_concurrent(is_concurrent_arg),
1958.1.1 by Brian Aker
Fix clash in parser with wait().
47
  should_wait(should_wait_arg),
1921.4.1 by Brian Aker
Adding in support for EXECUTE to have WITH NO RETURN.
48
  to_execute(to_execute_arg)
1835.1.6 by Brian Aker
This patch returns dynamic SQL into the core (through SQL-Server syntax).
49
{
50
}
51
  
52
53
bool statement::Execute::parseVariable()
54
{
1921.4.1 by Brian Aker
Adding in support for EXECUTE to have WITH NO RETURN.
55
  if (to_execute.isVariable())
1835.1.6 by Brian Aker
This patch returns dynamic SQL into the core (through SQL-Server syntax).
56
  {
2227.4.1 by Olaf van der Spek
Statement::session()
57
    user_var_entry *var= session().getVariable(to_execute, false);
1835.1.6 by Brian Aker
This patch returns dynamic SQL into the core (through SQL-Server syntax).
58
59
    if (var && var->length && var->value && var->type == STRING_RESULT)
60
    {
2371.1.2 by Brian Aker
Remove the typedef on lexkey
61
      lex_string_t tmp_for_var;
1835.1.6 by Brian Aker
This patch returns dynamic SQL into the core (through SQL-Server syntax).
62
      tmp_for_var.str= var->value; 
63
      tmp_for_var.length= var->length; 
1921.4.4 by Brian Aker
Fix for Solaris.
64
      to_execute.set(tmp_for_var);
65
1835.1.6 by Brian Aker
This patch returns dynamic SQL into the core (through SQL-Server syntax).
66
      return true;
67
    }
68
  }
69
70
  return false;
71
}
72
1921.4.9 by Brian Aker
Added in functionality for testing transactions in execute statements.
73
74
bool statement::Execute::runStatement(plugin::NullClient *client, const std::string &arg)
75
{
76
  client->pushSQL(arg);
2227.4.1 by Olaf van der Spek
Statement::session()
77
  if (not session().executeStatement())
1921.4.9 by Brian Aker
Added in functionality for testing transactions in execute statements.
78
    return true;
79
2227.4.1 by Olaf van der Spek
Statement::session()
80
  if (session().is_error())
1921.4.9 by Brian Aker
Added in functionality for testing transactions in execute statements.
81
    return true;
82
83
  return false;
84
}
85
86
1835.1.6 by Brian Aker
This patch returns dynamic SQL into the core (through SQL-Server syntax).
87
bool statement::Execute::execute()
88
{
1958.1.1 by Brian Aker
Fix clash in parser with wait().
89
  bool ret= execute_shell();
90
91
  // We have to restore ourselves at the top for delete() to work.
2224.2.8 by Olaf van der Spek
Statement::lex()
92
  lex().statement= this;
1958.1.1 by Brian Aker
Fix clash in parser with wait().
93
94
  return ret;
95
}
96
97
98
bool statement::Execute::execute_shell()
99
{
1835.1.6 by Brian Aker
This patch returns dynamic SQL into the core (through SQL-Server syntax).
100
  if (to_execute.length == 0)
101
  {
102
    my_error(ER_WRONG_ARGUMENTS, MYF(0), "Invalid Variable");
103
    return false;
104
  }
1958.1.1 by Brian Aker
Fix clash in parser with wait().
105
1921.4.1 by Brian Aker
Adding in support for EXECUTE to have WITH NO RETURN.
106
  if (to_execute.isVariable())
1835.1.6 by Brian Aker
This patch returns dynamic SQL into the core (through SQL-Server syntax).
107
  {
108
    if (not parseVariable())
109
    {
110
      my_error(ER_WRONG_ARGUMENTS, MYF(0), "Invalid Variable");
111
      return false;
112
    }
113
  }
114
1921.4.2 by Brian Aker
Adding in concurrent execute support.
115
  if (is_concurrent)
1921.4.1 by Brian Aker
Adding in support for EXECUTE to have WITH NO RETURN.
116
  {
2227.4.1 by Olaf van der Spek
Statement::session()
117
    if (not session().isConcurrentExecuteAllowed())
1921.4.2 by Brian Aker
Adding in concurrent execute support.
118
    {
119
      my_error(ER_WRONG_ARGUMENTS, MYF(0), "A Concurrent Execution Session can not launch another session.");
120
      return false;
121
    }
1958.1.1 by Brian Aker
Fix clash in parser with wait().
122
2227.4.2 by Olaf van der Spek
Statement::session()
123
    drizzled::Execute executer(session(), should_wait);
2385.2.15 by Olaf van der Spek
Refactor
124
    executer.run(to_execute);
1921.4.1 by Brian Aker
Adding in support for EXECUTE to have WITH NO RETURN.
125
  }
1976.7.2 by Brian Aker
Adding execute command to go along with main command.
126
  else // Non-concurrent run.
1921.4.1 by Brian Aker
Adding in support for EXECUTE to have WITH NO RETURN.
127
  {
1921.4.2 by Brian Aker
Adding in concurrent execute support.
128
    if (is_quiet)
129
    {
2227.4.1 by Olaf van der Spek
Statement::session()
130
      plugin::Client *temp= session().getClient();
1921.4.5 by Brian Aker
Fixing up support so that even when not using a new thread, we can execute
131
      plugin::NullClient *null_client= new plugin::NullClient;
1921.4.2 by Brian Aker
Adding in concurrent execute support.
132
2227.4.1 by Olaf van der Spek
Statement::session()
133
      session().setClient(null_client);
1921.4.9 by Brian Aker
Added in functionality for testing transactions in execute statements.
134
      
135
      bool error_occured= false;
136
      bool is_savepoint= false;
137
      {
138
        std::string start_sql;
2227.4.1 by Olaf van der Spek
Statement::session()
139
        if (session().inTransaction())
1921.4.9 by Brian Aker
Added in functionality for testing transactions in execute statements.
140
        {
141
          // @todo Figure out something a bit more solid then this.
142
          start_sql.append("SAVEPOINT execute_internal_savepoint");
143
          is_savepoint= true;
144
        }
145
        else
146
        {
147
          start_sql.append("START TRANSACTION");
148
        }
149
150
        error_occured= runStatement(null_client, start_sql);
151
      }
1921.4.2 by Brian Aker
Adding in concurrent execute support.
152
1921.4.5 by Brian Aker
Fixing up support so that even when not using a new thread, we can execute
153
      // @note this is copied from code in NULL client, all of this belongs
1921.4.9 by Brian Aker
Added in functionality for testing transactions in execute statements.
154
      // in the pluggable parser pieces.  
155
      if (not error_occured)
1921.4.5 by Brian Aker
Fixing up support so that even when not using a new thread, we can execute
156
      {
157
        typedef boost::tokenizer<boost::escaped_list_separator<char> > Tokenizer;
158
        std::string full_string(to_execute.str, to_execute.length);
159
        Tokenizer tok(full_string, boost::escaped_list_separator<char>("\\", ";", "\""));
160
161
        for (Tokenizer::iterator iter= tok.begin();
2227.4.1 by Olaf van der Spek
Statement::session()
162
             iter != tok.end() and session().getKilled() != Session::KILL_CONNECTION;
1921.4.5 by Brian Aker
Fixing up support so that even when not using a new thread, we can execute
163
             ++iter)
164
        {
1921.4.9 by Brian Aker
Added in functionality for testing transactions in execute statements.
165
          if (runStatement(null_client, *iter))
166
          {
167
            error_occured= true;
168
            break;
169
          }
170
        }
171
172
        // @todo Encapsulate logic later to method
173
        {
174
          std::string final_sql;
175
          if (is_savepoint)
176
          {
2269.1.7 by Olaf van der Spek
Use util::string::ptr
177
            final_sql.append(error_occured ? 
178
              "ROLLBACK TO SAVEPOINT execute_internal_savepoint" : 
179
              "RELEASE SAVEPOINT execute_internal_savepoint");
1921.4.9 by Brian Aker
Added in functionality for testing transactions in execute statements.
180
          }
181
          else
182
          {
2269.1.7 by Olaf van der Spek
Use util::string::ptr
183
            final_sql.append(error_occured ? "ROLLBACK" : "COMMIT");
1921.4.9 by Brian Aker
Added in functionality for testing transactions in execute statements.
184
          }
185
186
          // Run the cleanup command, we currently ignore if an error occurs
187
          // here.
188
          (void)runStatement(null_client, final_sql);
1921.4.5 by Brian Aker
Fixing up support so that even when not using a new thread, we can execute
189
        }
190
      }
1921.4.2 by Brian Aker
Adding in concurrent execute support.
191
2227.4.1 by Olaf van der Spek
Statement::session()
192
      session().setClient(temp);
193
      if (session().is_error())
1921.4.2 by Brian Aker
Adding in concurrent execute support.
194
      {
2227.4.1 by Olaf van der Spek
Statement::session()
195
        session().clear_error(true);
1921.4.5 by Brian Aker
Fixing up support so that even when not using a new thread, we can execute
196
      }
197
      else
198
      {
2227.4.1 by Olaf van der Spek
Statement::session()
199
        session().clearDiagnostics();
1921.4.5 by Brian Aker
Fixing up support so that even when not using a new thread, we can execute
200
      }
201
2227.4.1 by Olaf van der Spek
Statement::session()
202
      session().my_ok();
1921.4.5 by Brian Aker
Fixing up support so that even when not using a new thread, we can execute
203
1921.4.2 by Brian Aker
Adding in concurrent execute support.
204
      null_client->close();
205
      delete null_client;
206
    }
207
    else
208
    {
2269.1.7 by Olaf van der Spek
Use util::string::ptr
209
      parse(session(), to_execute.str, to_execute.length);
1921.4.2 by Brian Aker
Adding in concurrent execute support.
210
    }
1921.4.1 by Brian Aker
Adding in support for EXECUTE to have WITH NO RETURN.
211
  }
212
1835.1.6 by Brian Aker
This patch returns dynamic SQL into the core (through SQL-Server syntax).
213
  return true;
214
}
215
216
} /* namespace statement */
217
} /* namespace drizzled */
218