~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/statement/create_table.cc

Renamed more stuff to drizzle.

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) 2009 Sun Microsystems
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
 
#include <drizzled/show.h>
23
 
#include <drizzled/lock.h>
24
 
#include <drizzled/session.h>
25
 
#include <drizzled/statement/create_table.h>
26
 
#include <drizzled/identifier.h>
27
 
 
28
 
#include <iostream>
29
 
 
30
 
namespace drizzled
31
 
{
32
 
 
33
 
bool statement::CreateTable::execute()
34
 
{
35
 
  TableList *first_table= (TableList *) session->lex->select_lex.table_list.first;
36
 
  TableList *all_tables= session->lex->query_tables;
37
 
  assert(first_table == all_tables && first_table != 0);
38
 
  Select_Lex *select_lex= &session->lex->select_lex;
39
 
  Select_Lex_Unit *unit= &session->lex->unit;
40
 
  bool need_start_waiting= false;
41
 
  bool res= false;
42
 
  bool link_to_local= false;
43
 
  bool lex_identified_temp_table= 
44
 
    create_table_message.type() == message::Table::TEMPORARY;
45
 
 
46
 
  if (is_engine_set)
47
 
  {
48
 
    create_info.db_type= 
49
 
      plugin::StorageEngine::findByName(*session, create_table_message.engine().name());
50
 
 
51
 
    if (create_info.db_type == NULL)
52
 
    {
53
 
      my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), 
54
 
               create_table_message.engine().name().c_str());
55
 
 
56
 
      return true;
57
 
    }
58
 
  }
59
 
  else /* We now get the default, place it in create_info, and put the engine name in table proto */
60
 
  {
61
 
    create_info.db_type= session->getDefaultStorageEngine();
62
 
  }
63
 
 
64
 
  if (not validateCreateTableOption())
65
 
  {
66
 
    return true;
67
 
  }
68
 
 
69
 
  /* 
70
 
    Now we set the name in our Table proto so that it will match 
71
 
    create_info.db_type.
72
 
  */
73
 
  {
74
 
    create_table_message.mutable_engine()->set_name(create_info.db_type->getName());
75
 
  }
76
 
 
77
 
 
78
 
  /* If CREATE TABLE of non-temporary table, do implicit commit */
79
 
  if (not lex_identified_temp_table)
80
 
  {
81
 
    if (not session->endActiveTransaction())
82
 
    {
83
 
      return true;
84
 
    }
85
 
  }
86
 
  /* Skip first table, which is the table we are creating */
87
 
  TableList *create_table= session->lex->unlink_first_table(&link_to_local);
88
 
  TableList *select_tables= session->lex->query_tables;
89
 
 
90
 
 
91
 
  /*
92
 
    Now that we have the engine, we can figure out the table identifier. We need the engine in order
93
 
    to determine if the table is transactional or not if it is temp.
94
 
  */
95
 
 
96
 
  create_table_message.set_schema(create_table->db);
97
 
 
98
 
  TableIdentifier new_table_identifier(create_table->db,
99
 
                                       create_table->table_name,
100
 
                                       create_table_message.type());
101
 
 
102
 
  if (create_table_precheck(new_table_identifier))
103
 
  {
104
 
    /* put tables back for PS rexecuting */
105
 
    session->lex->link_first_table_back(create_table, link_to_local);
106
 
    return true;
107
 
  }
108
 
 
109
 
  /* Might have been updated in create_table_precheck */
110
 
  create_info.alias= create_table->alias;
111
 
 
112
 
  /*
113
 
     The create-select command will open and read-lock the select table
114
 
     and then create, open and write-lock the new table. If a global
115
 
     read lock steps in, we get a deadlock. The write lock waits for
116
 
     the global read lock, while the global read lock waits for the
117
 
     select table to be closed. So we wait until the global readlock is
118
 
     gone before starting both steps. Note that
119
 
     wait_if_global_read_lock() sets a protection against a new global
120
 
     read lock when it succeeds. This needs to be released by
121
 
     start_waiting_global_read_lock(). We protect the normal CREATE
122
 
     TABLE in the same way. That way we avoid that a new table is
123
 
     created during a gobal read lock.
124
 
   */
125
 
  if (! (need_start_waiting= ! wait_if_global_read_lock(session, 0, 1)))
126
 
  {
127
 
    /* put tables back for PS rexecuting */
128
 
    session->lex->link_first_table_back(create_table, link_to_local);
129
 
    return true;
130
 
  }
131
 
 
132
 
  if (select_lex->item_list.elements)           // With select
133
 
  {
134
 
    select_result *result;
135
 
 
136
 
    select_lex->options|= SELECT_NO_UNLOCK;
137
 
    unit->set_limit(select_lex);
138
 
 
139
 
    if (not lex_identified_temp_table)
140
 
    {
141
 
      session->lex->link_first_table_back(create_table, link_to_local);
142
 
      create_table->setCreate(true);
143
 
    }
144
 
 
145
 
    if (not (res= session->openTablesLock(session->lex->query_tables)))
146
 
    {
147
 
      /*
148
 
         Is table which we are changing used somewhere in other parts
149
 
         of query
150
 
       */
151
 
      if (not lex_identified_temp_table)
152
 
      {
153
 
        TableList *duplicate= NULL;
154
 
        create_table= session->lex->unlink_first_table(&link_to_local);
155
 
        if ((duplicate= unique_table(create_table, select_tables)))
156
 
        {
157
 
          my_error(ER_UPDATE_TABLE_USED, MYF(0), create_table->alias);
158
 
          /*
159
 
             Release the protection against the global read lock and wake
160
 
             everyone, who might want to set a global read lock.
161
 
           */
162
 
          start_waiting_global_read_lock(session);
163
 
          /* put tables back for PS rexecuting */
164
 
          session->lex->link_first_table_back(create_table, link_to_local);
165
 
          return true;
166
 
        }
167
 
      }
168
 
 
169
 
      /*
170
 
         select_create is currently not re-execution friendly and
171
 
         needs to be created for every execution of a PS/SP.
172
 
       */
173
 
      if ((result= new select_create(create_table,
174
 
                                     is_if_not_exists,
175
 
                                     &create_info,
176
 
                                     create_table_message,
177
 
                                     &alter_info,
178
 
                                     select_lex->item_list,
179
 
                                     session->lex->duplicates,
180
 
                                     session->lex->ignore,
181
 
                                     select_tables,
182
 
                                     new_table_identifier)))
183
 
      {
184
 
        /*
185
 
           CREATE from SELECT give its Select_Lex for SELECT,
186
 
           and item_list belong to SELECT
187
 
         */
188
 
        res= handle_select(session, session->lex, result, 0);
189
 
        delete result;
190
 
      }
191
 
    }
192
 
    else if (not lex_identified_temp_table)
193
 
    {
194
 
      create_table= session->lex->unlink_first_table(&link_to_local);
195
 
    }
196
 
  }
197
 
  else
198
 
  {
199
 
    /* regular create */
200
 
    if (is_create_table_like)
201
 
    {
202
 
      res= mysql_create_like_table(session, 
203
 
                                   new_table_identifier,
204
 
                                   create_table, 
205
 
                                   select_tables,
206
 
                                   create_table_message,
207
 
                                   is_if_not_exists,
208
 
                                   is_engine_set);
209
 
    }
210
 
    else
211
 
    {
212
 
 
213
 
      for (int32_t x= 0; x < alter_info.alter_proto.added_field_size(); x++)
214
 
      {
215
 
        message::Table::Field *field= create_table_message.add_field();
216
 
 
217
 
        *field= alter_info.alter_proto.added_field(x);
218
 
      }
219
 
 
220
 
      res= mysql_create_table(session, 
221
 
                              new_table_identifier,
222
 
                              &create_info,
223
 
                              create_table_message,
224
 
                              &alter_info, 
225
 
                              false, 
226
 
                              0,
227
 
                              is_if_not_exists);
228
 
    }
229
 
 
230
 
    if (not res)
231
 
    {
232
 
      session->my_ok();
233
 
    }
234
 
  }
235
 
 
236
 
  /*
237
 
     Release the protection against the global read lock and wake
238
 
     everyone, who might want to set a global read lock.
239
 
   */
240
 
  start_waiting_global_read_lock(session);
241
 
 
242
 
  return res;
243
 
}
244
 
 
245
 
bool statement::CreateTable::validateCreateTableOption()
246
 
{
247
 
  bool rc= true;
248
 
  size_t num_engine_options= create_table_message.engine().options_size();
249
 
 
250
 
  assert(create_info.db_type);
251
 
 
252
 
  for (size_t y= 0; y < num_engine_options; ++y)
253
 
  {
254
 
    bool valid= create_info.db_type->validateCreateTableOption(create_table_message.engine().options(y).name(),
255
 
                                                               create_table_message.engine().options(y).state());
256
 
 
257
 
    if (not valid)
258
 
    {
259
 
      my_error(ER_UNKNOWN_ENGINE_OPTION, MYF(0),
260
 
               create_table_message.engine().options(y).name().c_str(),
261
 
               create_table_message.engine().options(y).state().c_str());
262
 
 
263
 
      rc= false;
264
 
    }
265
 
  }
266
 
 
267
 
  return rc;
268
 
}
269
 
 
270
 
} /* namespace drizzled */
271