~drizzle-trunk/drizzle/development

1100.3.65 by Padraig O'Sullivan
Extracted the CREATE TABLE command into its own class and implementation
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
 *
1999.6.1 by kalebral at gmail
update Copyright strings to a more common format to help with creating the master debian copyright file
4
 *  Copyright (C) 2009 Sun Microsystems, Inc.
1100.3.65 by Padraig O'Sullivan
Extracted the CREATE TABLE command into its own class and implementation
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>
2154.2.17 by Brian Aker
Additional removal of session
22
1100.3.65 by Padraig O'Sullivan
Extracted the CREATE TABLE command into its own class and implementation
23
#include <drizzled/show.h>
24
#include <drizzled/lock.h>
25
#include <drizzled/session.h>
26
#include <drizzled/statement/create_table.h>
1802.12.1 by Brian Aker
This solves bug lp:654905
27
#include <drizzled/message.h>
1660.1.1 by Brian Aker
Merge in move identifier work.
28
#include <drizzled/identifier.h>
2148.7.12 by Brian Aker
Merge in header fixes.
29
#include <drizzled/plugin/storage_engine.h>
2154.2.17 by Brian Aker
Additional removal of session
30
#include <drizzled/select_create.h>
2239.1.9 by Olaf van der Spek
Refactor includes
31
#include <drizzled/table_ident.h>
1245.3.3 by Stewart Smith
convert builtin table options to use key,value code in parser
32
1340.1.4 by Brian Aker
A first pass through adding a timestamp to our proto.
33
#include <iostream>
34
1130.3.12 by Monty Taylor
using namespace drizzled; to namespace drizzled { in statement/
35
namespace drizzled
36
{
1100.3.65 by Padraig O'Sullivan
Extracted the CREATE TABLE command into its own class and implementation
37
2096.1.3 by Brian Aker
Have table name added in as early as possible.
38
namespace statement {
39
40
CreateTable::CreateTable(Session *in_session, Table_ident *ident, bool is_temporary) :
41
  Statement(in_session),
42
  change(NULL),
43
  default_value(NULL),
44
  on_update_value(NULL),
45
  is_engine_set(false),
46
  is_create_table_like(false),
47
  lex_identified_temp_table(false),
48
  link_to_local(false),
49
  create_table_list(NULL)
50
{
2224.2.6 by Olaf van der Spek
Statement::set_command
51
  set_command(SQLCOM_CREATE_TABLE);
2096.1.3 by Brian Aker
Have table name added in as early as possible.
52
  createTableMessage().set_name(ident->table.str, ident->table.length);
53
#if 0
54
  createTableMessage().set_schema(ident->db.str, ident->db.length);
55
#endif
56
57
  if (is_temporary)
58
  {
59
    createTableMessage().set_type(message::Table::TEMPORARY);
60
  }
61
  else
62
  {
63
    createTableMessage().set_type(message::Table::STANDARD);
64
  }
65
}
66
67
CreateTable::CreateTable(Session *in_session) :
68
  Statement(in_session),
69
  change(NULL),
70
  default_value(NULL),
71
  on_update_value(NULL),
72
  is_engine_set(false),
73
  is_create_table_like(false),
74
  lex_identified_temp_table(false),
75
  link_to_local(false),
76
  create_table_list(NULL)
77
{
2224.2.6 by Olaf van der Spek
Statement::set_command
78
  set_command(SQLCOM_CREATE_TABLE);
2096.1.3 by Brian Aker
Have table name added in as early as possible.
79
}
80
81
} // namespace statement
82
1100.3.65 by Padraig O'Sullivan
Extracted the CREATE TABLE command into its own class and implementation
83
bool statement::CreateTable::execute()
84
{
2224.2.8 by Olaf van der Spek
Statement::lex()
85
  TableList *first_table= (TableList *) lex().select_lex.table_list.first;
86
  TableList *all_tables= lex().query_tables;
1100.3.65 by Padraig O'Sullivan
Extracted the CREATE TABLE command into its own class and implementation
87
  assert(first_table == all_tables && first_table != 0);
88
  bool need_start_waiting= false;
2029.1.2 by Brian Aker
Merge in refactor of LIKE up to its own calling pointer in the parser.
89
  lex_identified_temp_table= createTableMessage().type() == message::Table::TEMPORARY;
90
91
  is_engine_set= not createTableMessage().engine().name().empty();
1245.3.7 by Stewart Smith
error out on invalid table options
92
1222.1.3 by Brian Aker
Remove used flag for engine.
93
  if (is_engine_set)
1160.1.5 by Brian Aker
Final parser SE removal.
94
  {
2029.1.2 by Brian Aker
Merge in refactor of LIKE up to its own calling pointer in the parser.
95
    create_info().db_type= 
2227.4.2 by Olaf van der Spek
Statement::session()
96
      plugin::StorageEngine::findByName(session(), createTableMessage().engine().name());
1160.1.5 by Brian Aker
Final parser SE removal.
97
2029.1.2 by Brian Aker
Merge in refactor of LIKE up to its own calling pointer in the parser.
98
    if (create_info().db_type == NULL)
1160.1.5 by Brian Aker
Final parser SE removal.
99
    {
100
      my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), 
2029.1.2 by Brian Aker
Merge in refactor of LIKE up to its own calling pointer in the parser.
101
               createTableMessage().engine().name().c_str());
1160.1.5 by Brian Aker
Final parser SE removal.
102
103
      return true;
104
    }
105
  }
106
  else /* We now get the default, place it in create_info, and put the engine name in table proto */
107
  {
2227.4.1 by Olaf van der Spek
Statement::session()
108
    create_info().db_type= session().getDefaultStorageEngine();
1160.1.5 by Brian Aker
Final parser SE removal.
109
  }
110
1502.1.30 by Brian Aker
First pass on cleanup of Stewart's patch, plus re-engineer to make it work a
111
  if (not validateCreateTableOption())
112
  {
113
    return true;
114
  }
1172.1.1 by Brian Aker
Add in support for ENGINE= in create table like.
115
1320.1.8 by Brian Aker
Temporary fix for allowing engines to say "don't do this".
116
  if (not lex_identified_temp_table)
1100.3.65 by Padraig O'Sullivan
Extracted the CREATE TABLE command into its own class and implementation
117
  {
2227.4.1 by Olaf van der Spek
Statement::session()
118
    if (session().inTransaction())
1100.3.65 by Padraig O'Sullivan
Extracted the CREATE TABLE command into its own class and implementation
119
    {
1890.2.1 by Stewart Smith
add error message for Transactional DDL not being supported. Throw it in CREATE TABLE instead of implicit commit.
120
      my_error(ER_TRANSACTIONAL_DDL_NOT_SUPPORTED, MYF(0));
1100.3.65 by Padraig O'Sullivan
Extracted the CREATE TABLE command into its own class and implementation
121
      return true;
122
    }
123
  }
124
  /* Skip first table, which is the table we are creating */
2224.2.8 by Olaf van der Spek
Statement::lex()
125
  create_table_list= lex().unlink_first_table(&link_to_local);
1128.2.3 by Brian Aker
Remove create_info from global
126
2067.3.1 by Brian Aker
Merge with trunk.
127
  drizzled::message::table::init(createTableMessage(), createTableMessage().name(), create_table_list->getSchemaName(), create_info().db_type->getName());
1337.2.2 by Stewart Smith
Add Schema to table message. modify alter table to correctly set a schema when running ALTER TABLE. Also update show_table_message test results to reflect the new field.
128
2087.4.2 by Brian Aker
Modify TableIdentifier to fit with the rest of the identifiers.
129
  identifier::Table new_table_identifier(create_table_list->getSchemaName(),
2026.2.1 by Monty Taylor
Renamed things prefixed mysql_ or mysqld_
130
                                       create_table_list->getTableName(),
2029.1.2 by Brian Aker
Merge in refactor of LIKE up to its own calling pointer in the parser.
131
                                       createTableMessage().type());
1223.4.1 by Brian Aker
Table Identifier patch.
132
1992.4.1 by Brian Aker
Update code for testing identifiers/table/schema name correctness.
133
  if (not check(new_table_identifier))
1100.3.67 by Padraig O'Sullivan
Various small style cleanups.
134
  {
135
    /* put tables back for PS rexecuting */
2224.2.8 by Olaf van der Spek
Statement::lex()
136
    lex().link_first_table_back(create_table_list, link_to_local);
1100.3.67 by Padraig O'Sullivan
Various small style cleanups.
137
    return true;
138
  }
1100.3.65 by Padraig O'Sullivan
Extracted the CREATE TABLE command into its own class and implementation
139
140
  /* Might have been updated in create_table_precheck */
2029.1.2 by Brian Aker
Merge in refactor of LIKE up to its own calling pointer in the parser.
141
  create_info().alias= create_table_list->alias;
1100.3.65 by Padraig O'Sullivan
Extracted the CREATE TABLE command into its own class and implementation
142
143
  /*
144
     The create-select command will open and read-lock the select table
145
     and then create, open and write-lock the new table. If a global
146
     read lock steps in, we get a deadlock. The write lock waits for
147
     the global read lock, while the global read lock waits for the
148
     select table to be closed. So we wait until the global readlock is
149
     gone before starting both steps. Note that
150
     wait_if_global_read_lock() sets a protection against a new global
151
     read lock when it succeeds. This needs to be released by
152
     start_waiting_global_read_lock(). We protect the normal CREATE
153
     TABLE in the same way. That way we avoid that a new table is
154
     created during a gobal read lock.
155
   */
2227.4.1 by Olaf van der Spek
Statement::session()
156
  if (! (need_start_waiting= not session().wait_if_global_read_lock(0, 1)))
1100.3.65 by Padraig O'Sullivan
Extracted the CREATE TABLE command into its own class and implementation
157
  {
1100.3.67 by Padraig O'Sullivan
Various small style cleanups.
158
    /* put tables back for PS rexecuting */
2224.2.8 by Olaf van der Spek
Statement::lex()
159
    lex().link_first_table_back(create_table_list, link_to_local);
1100.3.67 by Padraig O'Sullivan
Various small style cleanups.
160
    return true;
1100.3.65 by Padraig O'Sullivan
Extracted the CREATE TABLE command into its own class and implementation
161
  }
1172.1.1 by Brian Aker
Add in support for ENGINE= in create table like.
162
2029.1.1 by Brian Aker
Merge in first pass.
163
  bool res= executeInner(new_table_identifier);
164
165
  /*
166
    Release the protection against the global read lock and wake
167
    everyone, who might want to set a global read lock.
168
  */
2227.4.1 by Olaf van der Spek
Statement::session()
169
  session().startWaitingGlobalReadLock();
2029.1.1 by Brian Aker
Merge in first pass.
170
171
  return res;
172
}
173
2087.4.2 by Brian Aker
Modify TableIdentifier to fit with the rest of the identifiers.
174
bool statement::CreateTable::executeInner(identifier::Table::const_reference new_table_identifier)
2029.1.1 by Brian Aker
Merge in first pass.
175
{
176
  bool res= false;
2224.2.8 by Olaf van der Spek
Statement::lex()
177
  Select_Lex *select_lex= &lex().select_lex;
178
  TableList *select_tables= lex().query_tables;
2029.1.1 by Brian Aker
Merge in first pass.
179
2079.3.1 by Brian Aker
Rework the CREATE TABLE LIKE call.
180
  do 
181
  {
2183.2.20 by Olaf van der Spek
Use List::size()
182
    if (select_lex->item_list.size())		// With select
2029.1.1 by Brian Aker
Merge in first pass.
183
    {
2224.2.8 by Olaf van der Spek
Statement::lex()
184
      Select_Lex_Unit *unit= &lex().unit;
2029.1.1 by Brian Aker
Merge in first pass.
185
      select_result *result;
186
187
      select_lex->options|= SELECT_NO_UNLOCK;
188
      unit->set_limit(select_lex);
189
1340.1.1 by Brian Aker
Length usage of identifier down the tree.
190
      if (not lex_identified_temp_table)
1100.3.65 by Padraig O'Sullivan
Extracted the CREATE TABLE command into its own class and implementation
191
      {
2224.2.8 by Olaf van der Spek
Statement::lex()
192
        lex().link_first_table_back(create_table_list, link_to_local);
2029.1.1 by Brian Aker
Merge in first pass.
193
        create_table_list->setCreate(true);
194
      }
195
2227.4.1 by Olaf van der Spek
Statement::session()
196
      if (not (res= session().openTablesLock(lex().query_tables)))
2029.1.1 by Brian Aker
Merge in first pass.
197
      {
198
        /*
199
          Is table which we are changing used somewhere in other parts
200
          of query
201
        */
202
        if (not lex_identified_temp_table)
203
        {
204
          TableList *duplicate= NULL;
2224.2.8 by Olaf van der Spek
Statement::lex()
205
          create_table_list= lex().unlink_first_table(&link_to_local);
2029.1.1 by Brian Aker
Merge in first pass.
206
207
          if ((duplicate= unique_table(create_table_list, select_tables)))
208
          {
209
            my_error(ER_UPDATE_TABLE_USED, MYF(0), create_table_list->alias);
210
            /* put tables back for PS rexecuting */
2224.2.8 by Olaf van der Spek
Statement::lex()
211
            lex().link_first_table_back(create_table_list, link_to_local);
2029.1.1 by Brian Aker
Merge in first pass.
212
213
            res= true;
214
            break;
215
          }
216
        }
217
218
        /*
219
          select_create is currently not re-execution friendly and
220
          needs to be created for every execution of a PS/SP.
221
        */
222
        if ((result= new select_create(create_table_list,
2224.2.8 by Olaf van der Spek
Statement::lex()
223
                                       lex().exists(),
2029.1.2 by Brian Aker
Merge in refactor of LIKE up to its own calling pointer in the parser.
224
                                       &create_info(),
225
                                       createTableMessage(),
2029.1.1 by Brian Aker
Merge in first pass.
226
                                       &alter_info,
227
                                       select_lex->item_list,
2224.2.8 by Olaf van der Spek
Statement::lex()
228
                                       lex().duplicates,
229
                                       lex().ignore,
2029.1.1 by Brian Aker
Merge in first pass.
230
                                       select_tables,
231
                                       new_table_identifier)))
232
        {
233
          /*
234
            CREATE from SELECT give its Select_Lex for SELECT,
235
            and item_list belong to SELECT
236
          */
2227.4.2 by Olaf van der Spek
Statement::session()
237
          res= handle_select(&session(), &lex(), result, 0);
2029.1.1 by Brian Aker
Merge in first pass.
238
          delete result;
239
        }
240
      }
241
      else if (not lex_identified_temp_table)
242
      {
2224.2.8 by Olaf van der Spek
Statement::lex()
243
        create_table_list= lex().unlink_first_table(&link_to_local);
2029.1.1 by Brian Aker
Merge in first pass.
244
      }
1100.3.65 by Padraig O'Sullivan
Extracted the CREATE TABLE command into its own class and implementation
245
    }
246
    else
247
    {
2029.1.1 by Brian Aker
Merge in first pass.
248
      /* regular create */
249
      if (is_create_table_like)
250
      {
2227.4.2 by Olaf van der Spek
Statement::session()
251
        res= create_like_table(&session(), 
2029.1.1 by Brian Aker
Merge in first pass.
252
                               new_table_identifier,
2093 by Brian Aker
Merge in update so that test-run.pl runs all of test/suite and fix for
253
                               identifier::Table(select_tables->getSchemaName(),
254
                                                 select_tables->getTableName()),
2029.1.2 by Brian Aker
Merge in refactor of LIKE up to its own calling pointer in the parser.
255
                               createTableMessage(),
2224.2.8 by Olaf van der Spek
Statement::lex()
256
                               lex().exists(),
2029.1.1 by Brian Aker
Merge in first pass.
257
                               is_engine_set);
258
      }
259
      else
260
      {
261
262
        for (int32_t x= 0; x < alter_info.alter_proto.added_field_size(); x++)
263
        {
2029.1.2 by Brian Aker
Merge in refactor of LIKE up to its own calling pointer in the parser.
264
          message::Table::Field *field= createTableMessage().add_field();
2029.1.1 by Brian Aker
Merge in first pass.
265
266
          *field= alter_info.alter_proto.added_field(x);
267
        }
268
2227.4.2 by Olaf van der Spek
Statement::session()
269
        res= create_table(&session(), 
2029.1.1 by Brian Aker
Merge in first pass.
270
                          new_table_identifier,
2029.1.2 by Brian Aker
Merge in refactor of LIKE up to its own calling pointer in the parser.
271
                          &create_info(),
272
                          createTableMessage(),
2029.1.1 by Brian Aker
Merge in first pass.
273
                          &alter_info, 
274
                          false, 
275
                          0,
2224.2.8 by Olaf van der Spek
Statement::lex()
276
                          lex().exists());
2029.1.1 by Brian Aker
Merge in first pass.
277
      }
278
279
      if (not res)
280
      {
2227.4.1 by Olaf van der Spek
Statement::session()
281
        session().my_ok();
2029.1.1 by Brian Aker
Merge in first pass.
282
      }
283
    }
284
  } while (0);
1100.3.67 by Padraig O'Sullivan
Various small style cleanups.
285
1100.3.65 by Padraig O'Sullivan
Extracted the CREATE TABLE command into its own class and implementation
286
  return res;
287
}
1130.3.12 by Monty Taylor
using namespace drizzled; to namespace drizzled { in statement/
288
2087.4.2 by Brian Aker
Modify TableIdentifier to fit with the rest of the identifiers.
289
bool statement::CreateTable::check(const identifier::Table &identifier)
1992.4.1 by Brian Aker
Update code for testing identifiers/table/schema name correctness.
290
{
291
  // Check table name for validity
292
  if (not identifier.isValid())
293
    return false;
294
295
  // See if any storage engine objects to the name of the file
296
  if (not plugin::StorageEngine::canCreateTable(identifier))
297
  {
2159.2.8 by Brian Aker
Merge in fixes for error messages with privs.
298
    identifier::Schema schema_identifier= identifier;
2227.4.1 by Olaf van der Spek
Statement::session()
299
    error::access(*session().user(), schema_identifier);
1992.4.1 by Brian Aker
Update code for testing identifiers/table/schema name correctness.
300
301
    return false;
302
  }
303
304
  // Make sure the schema exists, we will do this again during the actual
305
  // create for the table.
306
  if (not plugin::StorageEngine::doesSchemaExist(identifier))
307
  {
2159.2.8 by Brian Aker
Merge in fixes for error messages with privs.
308
    identifier::Schema schema_identifier= identifier;
309
    my_error(ER_BAD_DB_ERROR, schema_identifier);
1992.4.1 by Brian Aker
Update code for testing identifiers/table/schema name correctness.
310
311
    return false;
312
  }
313
314
  return true;
315
}
316
1502.1.30 by Brian Aker
First pass on cleanup of Stewart's patch, plus re-engineer to make it work a
317
bool statement::CreateTable::validateCreateTableOption()
318
{
319
  bool rc= true;
2029.1.2 by Brian Aker
Merge in refactor of LIKE up to its own calling pointer in the parser.
320
  size_t num_engine_options= createTableMessage().engine().options_size();
1502.1.30 by Brian Aker
First pass on cleanup of Stewart's patch, plus re-engineer to make it work a
321
2029.1.2 by Brian Aker
Merge in refactor of LIKE up to its own calling pointer in the parser.
322
  assert(create_info().db_type);
1502.1.30 by Brian Aker
First pass on cleanup of Stewart's patch, plus re-engineer to make it work a
323
324
  for (size_t y= 0; y < num_engine_options; ++y)
325
  {
2029.1.2 by Brian Aker
Merge in refactor of LIKE up to its own calling pointer in the parser.
326
    bool valid= create_info().db_type->validateCreateTableOption(createTableMessage().engine().options(y).name(),
327
                                                                 createTableMessage().engine().options(y).state());
1502.1.30 by Brian Aker
First pass on cleanup of Stewart's patch, plus re-engineer to make it work a
328
329
    if (not valid)
330
    {
331
      my_error(ER_UNKNOWN_ENGINE_OPTION, MYF(0),
2029.1.2 by Brian Aker
Merge in refactor of LIKE up to its own calling pointer in the parser.
332
               createTableMessage().engine().options(y).name().c_str(),
333
               createTableMessage().engine().options(y).state().c_str());
1502.1.30 by Brian Aker
First pass on cleanup of Stewart's patch, plus re-engineer to make it work a
334
335
      rc= false;
336
    }
337
  }
338
339
  return rc;
340
}
341
1130.3.12 by Monty Taylor
using namespace drizzled; to namespace drizzled { in statement/
342
} /* namespace drizzled */
343