~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/statement/create_table.cc

  • Committer: patrick crews
  • Date: 2011-02-23 17:17:25 UTC
  • mto: (2195.1.1 build)
  • mto: This revision was merged to the branch mainline in revision 2196.
  • Revision ID: gleebix@gmail.com-20110223171725-4tgewemxhsw1m7q8
Integrated randgen with dbqp.  We now have mode=randgen and a set of randgen test suites (very basic now).  Output = same as dtr : )  We also have mode=cleanup to kill any servers we have started.  Docs updates too.  Gendata utility allows us to populate test servers 

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
3
 *
4
 
 *  Copyright (C) 2009 Sun Microsystems
 
4
 *  Copyright (C) 2009 Sun Microsystems, Inc.
5
5
 *
6
6
 *  This program is free software; you can redistribute it and/or modify
7
7
 *  it under the terms of the GNU General Public License as published by
18
18
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19
19
 */
20
20
 
21
 
#include "config.h"
 
21
#include <config.h>
 
22
 
22
23
#include <drizzled/show.h>
23
24
#include <drizzled/lock.h>
24
25
#include <drizzled/session.h>
25
26
#include <drizzled/statement/create_table.h>
26
27
#include <drizzled/message.h>
27
28
#include <drizzled/identifier.h>
 
29
#include <drizzled/plugin/storage_engine.h>
 
30
#include <drizzled/select_create.h>
28
31
 
29
32
#include <iostream>
30
33
 
31
34
namespace drizzled
32
35
{
33
36
 
 
37
namespace statement {
 
38
 
 
39
CreateTable::CreateTable(Session *in_session, Table_ident *ident, bool is_temporary) :
 
40
  Statement(in_session),
 
41
  change(NULL),
 
42
  default_value(NULL),
 
43
  on_update_value(NULL),
 
44
  is_engine_set(false),
 
45
  is_create_table_like(false),
 
46
  lex_identified_temp_table(false),
 
47
  link_to_local(false),
 
48
  create_table_list(NULL)
 
49
{
 
50
  getSession()->getLex()->sql_command= SQLCOM_CREATE_TABLE;
 
51
  createTableMessage().set_name(ident->table.str, ident->table.length);
 
52
#if 0
 
53
  createTableMessage().set_schema(ident->db.str, ident->db.length);
 
54
#endif
 
55
 
 
56
  if (is_temporary)
 
57
  {
 
58
    createTableMessage().set_type(message::Table::TEMPORARY);
 
59
  }
 
60
  else
 
61
  {
 
62
    createTableMessage().set_type(message::Table::STANDARD);
 
63
  }
 
64
}
 
65
 
 
66
CreateTable::CreateTable(Session *in_session) :
 
67
  Statement(in_session),
 
68
  change(NULL),
 
69
  default_value(NULL),
 
70
  on_update_value(NULL),
 
71
  is_engine_set(false),
 
72
  is_create_table_like(false),
 
73
  lex_identified_temp_table(false),
 
74
  link_to_local(false),
 
75
  create_table_list(NULL)
 
76
{
 
77
  getSession()->getLex()->sql_command= SQLCOM_CREATE_TABLE;
 
78
}
 
79
 
 
80
} // namespace statement
 
81
 
34
82
bool statement::CreateTable::execute()
35
83
{
36
 
  TableList *first_table= (TableList *) session->lex->select_lex.table_list.first;
37
 
  TableList *all_tables= session->lex->query_tables;
 
84
  TableList *first_table= (TableList *) getSession()->getLex()->select_lex.table_list.first;
 
85
  TableList *all_tables= getSession()->getLex()->query_tables;
38
86
  assert(first_table == all_tables && first_table != 0);
39
 
  Select_Lex *select_lex= &session->lex->select_lex;
40
 
  Select_Lex_Unit *unit= &session->lex->unit;
41
87
  bool need_start_waiting= false;
42
 
  bool res= false;
43
 
  bool link_to_local= false;
44
 
  bool lex_identified_temp_table= 
45
 
    create_table_message.type() == message::Table::TEMPORARY;
 
88
  lex_identified_temp_table= createTableMessage().type() == message::Table::TEMPORARY;
 
89
 
 
90
  is_engine_set= not createTableMessage().engine().name().empty();
46
91
 
47
92
  if (is_engine_set)
48
93
  {
49
 
    create_info.db_type= 
50
 
      plugin::StorageEngine::findByName(*session, create_table_message.engine().name());
 
94
    create_info().db_type= 
 
95
      plugin::StorageEngine::findByName(*getSession(), createTableMessage().engine().name());
51
96
 
52
 
    if (create_info.db_type == NULL)
 
97
    if (create_info().db_type == NULL)
53
98
    {
54
99
      my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), 
55
 
               create_table_message.engine().name().c_str());
 
100
               createTableMessage().engine().name().c_str());
56
101
 
57
102
      return true;
58
103
    }
59
104
  }
60
105
  else /* We now get the default, place it in create_info, and put the engine name in table proto */
61
106
  {
62
 
    create_info.db_type= session->getDefaultStorageEngine();
 
107
    create_info().db_type= getSession()->getDefaultStorageEngine();
63
108
  }
64
109
 
65
110
  if (not validateCreateTableOption())
67
112
    return true;
68
113
  }
69
114
 
70
 
 
71
 
  /* If CREATE TABLE of non-temporary table, do implicit commit */
72
115
  if (not lex_identified_temp_table)
73
116
  {
74
 
    if (not session->endActiveTransaction())
 
117
    if (getSession()->inTransaction())
75
118
    {
 
119
      my_error(ER_TRANSACTIONAL_DDL_NOT_SUPPORTED, MYF(0));
76
120
      return true;
77
121
    }
78
122
  }
79
123
  /* Skip first table, which is the table we are creating */
80
 
  TableList *create_table= session->lex->unlink_first_table(&link_to_local);
81
 
  TableList *select_tables= session->lex->query_tables;
82
 
 
83
 
  drizzled::message::init(create_table_message, create_table_message.name(), create_table->getSchemaName(), create_info.db_type->getName());
84
 
 
85
 
  TableIdentifier new_table_identifier(create_table->getSchemaName(),
86
 
                                       create_table->getTableName(),
87
 
                                       create_table_message.type());
 
124
  create_table_list= getSession()->getLex()->unlink_first_table(&link_to_local);
 
125
 
 
126
  drizzled::message::table::init(createTableMessage(), createTableMessage().name(), create_table_list->getSchemaName(), create_info().db_type->getName());
 
127
 
 
128
  identifier::Table new_table_identifier(create_table_list->getSchemaName(),
 
129
                                       create_table_list->getTableName(),
 
130
                                       createTableMessage().type());
88
131
 
89
132
  if (not check(new_table_identifier))
90
133
  {
91
134
    /* put tables back for PS rexecuting */
92
 
    session->lex->link_first_table_back(create_table, link_to_local);
 
135
    getSession()->getLex()->link_first_table_back(create_table_list, link_to_local);
93
136
    return true;
94
137
  }
95
138
 
96
139
  /* Might have been updated in create_table_precheck */
97
 
  create_info.alias= create_table->alias;
 
140
  create_info().alias= create_table_list->alias;
98
141
 
99
142
  /*
100
143
     The create-select command will open and read-lock the select table
109
152
     TABLE in the same way. That way we avoid that a new table is
110
153
     created during a gobal read lock.
111
154
   */
112
 
  if (! (need_start_waiting= not session->wait_if_global_read_lock(0, 1)))
 
155
  if (! (need_start_waiting= not getSession()->wait_if_global_read_lock(0, 1)))
113
156
  {
114
157
    /* put tables back for PS rexecuting */
115
 
    session->lex->link_first_table_back(create_table, link_to_local);
 
158
    getSession()->getLex()->link_first_table_back(create_table_list, link_to_local);
116
159
    return true;
117
160
  }
118
161
 
119
 
  if (select_lex->item_list.elements)           // With select
 
162
  bool res= executeInner(new_table_identifier);
 
163
 
 
164
  /*
 
165
    Release the protection against the global read lock and wake
 
166
    everyone, who might want to set a global read lock.
 
167
  */
 
168
  getSession()->startWaitingGlobalReadLock();
 
169
 
 
170
  return res;
 
171
}
 
172
 
 
173
bool statement::CreateTable::executeInner(identifier::Table::const_reference new_table_identifier)
 
174
{
 
175
  bool res= false;
 
176
  Select_Lex *select_lex= &getSession()->getLex()->select_lex;
 
177
  TableList *select_tables= getSession()->getLex()->query_tables;
 
178
 
 
179
  do 
120
180
  {
121
 
    select_result *result;
122
 
 
123
 
    select_lex->options|= SELECT_NO_UNLOCK;
124
 
    unit->set_limit(select_lex);
125
 
 
126
 
    if (not lex_identified_temp_table)
127
 
    {
128
 
      session->lex->link_first_table_back(create_table, link_to_local);
129
 
      create_table->setCreate(true);
130
 
    }
131
 
 
132
 
    if (not (res= session->openTablesLock(session->lex->query_tables)))
133
 
    {
134
 
      /*
135
 
         Is table which we are changing used somewhere in other parts
136
 
         of query
137
 
       */
 
181
    if (select_lex->item_list.elements)         // With select
 
182
    {
 
183
      Select_Lex_Unit *unit= &getSession()->getLex()->unit;
 
184
      select_result *result;
 
185
 
 
186
      select_lex->options|= SELECT_NO_UNLOCK;
 
187
      unit->set_limit(select_lex);
 
188
 
138
189
      if (not lex_identified_temp_table)
139
190
      {
140
 
        TableList *duplicate= NULL;
141
 
        create_table= session->lex->unlink_first_table(&link_to_local);
142
 
        if ((duplicate= unique_table(create_table, select_tables)))
143
 
        {
144
 
          my_error(ER_UPDATE_TABLE_USED, MYF(0), create_table->alias);
 
191
        getSession()->getLex()->link_first_table_back(create_table_list, link_to_local);
 
192
        create_table_list->setCreate(true);
 
193
      }
 
194
 
 
195
      if (not (res= getSession()->openTablesLock(getSession()->getLex()->query_tables)))
 
196
      {
 
197
        /*
 
198
          Is table which we are changing used somewhere in other parts
 
199
          of query
 
200
        */
 
201
        if (not lex_identified_temp_table)
 
202
        {
 
203
          TableList *duplicate= NULL;
 
204
          create_table_list= getSession()->getLex()->unlink_first_table(&link_to_local);
 
205
 
 
206
          if ((duplicate= unique_table(create_table_list, select_tables)))
 
207
          {
 
208
            my_error(ER_UPDATE_TABLE_USED, MYF(0), create_table_list->alias);
 
209
            /* put tables back for PS rexecuting */
 
210
            getSession()->getLex()->link_first_table_back(create_table_list, link_to_local);
 
211
 
 
212
            res= true;
 
213
            break;
 
214
          }
 
215
        }
 
216
 
 
217
        /*
 
218
          select_create is currently not re-execution friendly and
 
219
          needs to be created for every execution of a PS/SP.
 
220
        */
 
221
        if ((result= new select_create(create_table_list,
 
222
                                       getSession()->getLex()->exists(),
 
223
                                       &create_info(),
 
224
                                       createTableMessage(),
 
225
                                       &alter_info,
 
226
                                       select_lex->item_list,
 
227
                                       getSession()->getLex()->duplicates,
 
228
                                       getSession()->getLex()->ignore,
 
229
                                       select_tables,
 
230
                                       new_table_identifier)))
 
231
        {
145
232
          /*
146
 
             Release the protection against the global read lock and wake
147
 
             everyone, who might want to set a global read lock.
148
 
           */
149
 
          session->startWaitingGlobalReadLock();
150
 
          /* put tables back for PS rexecuting */
151
 
          session->lex->link_first_table_back(create_table, link_to_local);
152
 
 
153
 
          return true;
 
233
            CREATE from SELECT give its Select_Lex for SELECT,
 
234
            and item_list belong to SELECT
 
235
          */
 
236
          res= handle_select(getSession(), getSession()->getLex(), result, 0);
 
237
          delete result;
154
238
        }
155
239
      }
156
 
 
157
 
      /*
158
 
         select_create is currently not re-execution friendly and
159
 
         needs to be created for every execution of a PS/SP.
160
 
       */
161
 
      if ((result= new select_create(create_table,
162
 
                                     is_if_not_exists,
163
 
                                     &create_info,
164
 
                                     create_table_message,
165
 
                                     &alter_info,
166
 
                                     select_lex->item_list,
167
 
                                     session->lex->duplicates,
168
 
                                     session->lex->ignore,
169
 
                                     select_tables,
170
 
                                     new_table_identifier)))
 
240
      else if (not lex_identified_temp_table)
171
241
      {
172
 
        /*
173
 
           CREATE from SELECT give its Select_Lex for SELECT,
174
 
           and item_list belong to SELECT
175
 
         */
176
 
        res= handle_select(session, session->lex, result, 0);
177
 
        delete result;
 
242
        create_table_list= getSession()->getLex()->unlink_first_table(&link_to_local);
178
243
      }
179
244
    }
180
 
    else if (not lex_identified_temp_table)
181
 
    {
182
 
      create_table= session->lex->unlink_first_table(&link_to_local);
183
 
    }
184
 
  }
185
 
  else
186
 
  {
187
 
    /* regular create */
188
 
    if (is_create_table_like)
189
 
    {
190
 
      res= mysql_create_like_table(session, 
191
 
                                   new_table_identifier,
192
 
                                   create_table, 
193
 
                                   select_tables,
194
 
                                   create_table_message,
195
 
                                   is_if_not_exists,
196
 
                                   is_engine_set);
197
 
    }
198
245
    else
199
246
    {
200
 
 
201
 
      for (int32_t x= 0; x < alter_info.alter_proto.added_field_size(); x++)
202
 
      {
203
 
        message::Table::Field *field= create_table_message.add_field();
204
 
 
205
 
        *field= alter_info.alter_proto.added_field(x);
206
 
      }
207
 
 
208
 
      res= mysql_create_table(session, 
209
 
                              new_table_identifier,
210
 
                              &create_info,
211
 
                              create_table_message,
212
 
                              &alter_info, 
213
 
                              false, 
214
 
                              0,
215
 
                              is_if_not_exists);
216
 
    }
217
 
 
218
 
    if (not res)
219
 
    {
220
 
      session->my_ok();
221
 
    }
222
 
  }
223
 
 
224
 
  /*
225
 
     Release the protection against the global read lock and wake
226
 
     everyone, who might want to set a global read lock.
227
 
   */
228
 
  session->startWaitingGlobalReadLock();
 
247
      /* regular create */
 
248
      if (is_create_table_like)
 
249
      {
 
250
        res= create_like_table(getSession(), 
 
251
                               new_table_identifier,
 
252
                               identifier::Table(select_tables->getSchemaName(),
 
253
                                                 select_tables->getTableName()),
 
254
                               createTableMessage(),
 
255
                               getSession()->getLex()->exists(),
 
256
                               is_engine_set);
 
257
      }
 
258
      else
 
259
      {
 
260
 
 
261
        for (int32_t x= 0; x < alter_info.alter_proto.added_field_size(); x++)
 
262
        {
 
263
          message::Table::Field *field= createTableMessage().add_field();
 
264
 
 
265
          *field= alter_info.alter_proto.added_field(x);
 
266
        }
 
267
 
 
268
        res= create_table(getSession(), 
 
269
                          new_table_identifier,
 
270
                          &create_info(),
 
271
                          createTableMessage(),
 
272
                          &alter_info, 
 
273
                          false, 
 
274
                          0,
 
275
                          getSession()->getLex()->exists());
 
276
      }
 
277
 
 
278
      if (not res)
 
279
      {
 
280
        getSession()->my_ok();
 
281
      }
 
282
    }
 
283
  } while (0);
229
284
 
230
285
  return res;
231
286
}
232
287
 
233
 
bool statement::CreateTable::check(const TableIdentifier &identifier)
 
288
bool statement::CreateTable::check(const identifier::Table &identifier)
234
289
{
235
290
  // Check table name for validity
236
291
  if (not identifier.isValid())
239
294
  // See if any storage engine objects to the name of the file
240
295
  if (not plugin::StorageEngine::canCreateTable(identifier))
241
296
  {
242
 
    my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), "", "", identifier.getSchemaName().c_str());
 
297
    identifier::Schema schema_identifier= identifier;
 
298
    error::access(*getSession()->user(), schema_identifier);
243
299
 
244
300
    return false;
245
301
  }
248
304
  // create for the table.
249
305
  if (not plugin::StorageEngine::doesSchemaExist(identifier))
250
306
  {
251
 
    my_error(ER_BAD_DB_ERROR, MYF(0), identifier.getSchemaName().c_str());
 
307
    identifier::Schema schema_identifier= identifier;
 
308
    my_error(ER_BAD_DB_ERROR, schema_identifier);
252
309
 
253
310
    return false;
254
311
  }
259
316
bool statement::CreateTable::validateCreateTableOption()
260
317
{
261
318
  bool rc= true;
262
 
  size_t num_engine_options= create_table_message.engine().options_size();
 
319
  size_t num_engine_options= createTableMessage().engine().options_size();
263
320
 
264
 
  assert(create_info.db_type);
 
321
  assert(create_info().db_type);
265
322
 
266
323
  for (size_t y= 0; y < num_engine_options; ++y)
267
324
  {
268
 
    bool valid= create_info.db_type->validateCreateTableOption(create_table_message.engine().options(y).name(),
269
 
                                                               create_table_message.engine().options(y).state());
 
325
    bool valid= create_info().db_type->validateCreateTableOption(createTableMessage().engine().options(y).name(),
 
326
                                                                 createTableMessage().engine().options(y).state());
270
327
 
271
328
    if (not valid)
272
329
    {
273
330
      my_error(ER_UNKNOWN_ENGINE_OPTION, MYF(0),
274
 
               create_table_message.engine().options(y).name().c_str(),
275
 
               create_table_message.engine().options(y).state().c_str());
 
331
               createTableMessage().engine().options(y).name().c_str(),
 
332
               createTableMessage().engine().options(y).state().c_str());
276
333
 
277
334
      rc= false;
278
335
    }