~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/statement/create_table.cc

  • Committer: Brian Aker
  • Date: 2010-04-05 23:46:43 UTC
  • Revision ID: brian@gaz-20100405234643-0he3xnj902rc70r8
Fixing tests to work with PBXT.

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/table_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.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
  /* 
 
65
    Now we set the name in our Table proto so that it will match 
 
66
    create_info.db_type.
 
67
  */
 
68
  {
 
69
    message::Table::StorageEngine *protoengine;
 
70
 
 
71
    protoengine= create_table_message.mutable_engine();
 
72
    protoengine->set_name(create_info.db_type->getName());
 
73
  }
 
74
 
 
75
 
 
76
  /* If CREATE TABLE of non-temporary table, do implicit commit */
 
77
  if (not lex_identified_temp_table)
 
78
  {
 
79
    if (not session->endActiveTransaction())
 
80
    {
 
81
      return true;
 
82
    }
 
83
  }
 
84
  /* Skip first table, which is the table we are creating */
 
85
  TableList *create_table= session->lex->unlink_first_table(&link_to_local);
 
86
  TableList *select_tables= session->lex->query_tables;
 
87
 
 
88
 
 
89
  /*
 
90
    Now that we have the engine, we can figure out the table identifier. We need the engine in order
 
91
    to determine if the table is transactional or not if it is temp.
 
92
  */
 
93
 
 
94
  create_table_message.set_schema(create_table->db);
 
95
 
 
96
  TableIdentifier new_table_identifier(create_table->db,
 
97
                                       create_table->table_name,
 
98
                                       create_table_message.type());
 
99
 
 
100
  if (create_table_precheck(new_table_identifier))
 
101
  {
 
102
    /* put tables back for PS rexecuting */
 
103
    session->lex->link_first_table_back(create_table, link_to_local);
 
104
    return true;
 
105
  }
 
106
 
 
107
  /* Might have been updated in create_table_precheck */
 
108
  create_info.alias= create_table->alias;
 
109
 
 
110
  /*
 
111
     The create-select command will open and read-lock the select table
 
112
     and then create, open and write-lock the new table. If a global
 
113
     read lock steps in, we get a deadlock. The write lock waits for
 
114
     the global read lock, while the global read lock waits for the
 
115
     select table to be closed. So we wait until the global readlock is
 
116
     gone before starting both steps. Note that
 
117
     wait_if_global_read_lock() sets a protection against a new global
 
118
     read lock when it succeeds. This needs to be released by
 
119
     start_waiting_global_read_lock(). We protect the normal CREATE
 
120
     TABLE in the same way. That way we avoid that a new table is
 
121
     created during a gobal read lock.
 
122
   */
 
123
  if (! (need_start_waiting= ! wait_if_global_read_lock(session, 0, 1)))
 
124
  {
 
125
    /* put tables back for PS rexecuting */
 
126
    session->lex->link_first_table_back(create_table, link_to_local);
 
127
    return true;
 
128
  }
 
129
 
 
130
  if (select_lex->item_list.elements)           // With select
 
131
  {
 
132
    select_result *result;
 
133
 
 
134
    select_lex->options|= SELECT_NO_UNLOCK;
 
135
    unit->set_limit(select_lex);
 
136
 
 
137
    if (not lex_identified_temp_table)
 
138
    {
 
139
      session->lex->link_first_table_back(create_table, link_to_local);
 
140
      create_table->create= true;
 
141
    }
 
142
 
 
143
    if (not (res= session->openTablesLock(session->lex->query_tables)))
 
144
    {
 
145
      /*
 
146
         Is table which we are changing used somewhere in other parts
 
147
         of query
 
148
       */
 
149
      if (not lex_identified_temp_table)
 
150
      {
 
151
        TableList *duplicate= NULL;
 
152
        create_table= session->lex->unlink_first_table(&link_to_local);
 
153
        if ((duplicate= unique_table(create_table, select_tables)))
 
154
        {
 
155
          my_error(ER_UPDATE_TABLE_USED, MYF(0), create_table->alias);
 
156
          /*
 
157
             Release the protection against the global read lock and wake
 
158
             everyone, who might want to set a global read lock.
 
159
           */
 
160
          start_waiting_global_read_lock(session);
 
161
          /* put tables back for PS rexecuting */
 
162
          session->lex->link_first_table_back(create_table, link_to_local);
 
163
          return true;
 
164
        }
 
165
      }
 
166
 
 
167
      /*
 
168
         select_create is currently not re-execution friendly and
 
169
         needs to be created for every execution of a PS/SP.
 
170
       */
 
171
      if ((result= new select_create(create_table,
 
172
                                     is_if_not_exists,
 
173
                                     &create_info,
 
174
                                     create_table_message,
 
175
                                     &alter_info,
 
176
                                     select_lex->item_list,
 
177
                                     session->lex->duplicates,
 
178
                                     session->lex->ignore,
 
179
                                     select_tables,
 
180
                                     new_table_identifier)))
 
181
      {
 
182
        /*
 
183
           CREATE from SELECT give its Select_Lex for SELECT,
 
184
           and item_list belong to SELECT
 
185
         */
 
186
        res= handle_select(session, session->lex, result, 0);
 
187
        delete result;
 
188
      }
 
189
    }
 
190
    else if (not lex_identified_temp_table)
 
191
    {
 
192
      create_table= session->lex->unlink_first_table(&link_to_local);
 
193
    }
 
194
  }
 
195
  else
 
196
  {
 
197
    /* regular create */
 
198
    if (is_create_table_like)
 
199
    {
 
200
      res= mysql_create_like_table(session, 
 
201
                                   new_table_identifier,
 
202
                                   create_table, 
 
203
                                   select_tables,
 
204
                                   create_table_message,
 
205
                                   is_if_not_exists,
 
206
                                   is_engine_set);
 
207
    }
 
208
    else
 
209
    {
 
210
 
 
211
      for (int32_t x= 0; x < alter_info.alter_proto.added_field_size(); x++)
 
212
      {
 
213
        message::Table::Field *field= create_table_message.add_field();
 
214
 
 
215
        *field= alter_info.alter_proto.added_field(x);
 
216
      }
 
217
 
 
218
      res= mysql_create_table(session, 
 
219
                              new_table_identifier,
 
220
                              &create_info,
 
221
                              create_table_message,
 
222
                              &alter_info, 
 
223
                              false, 
 
224
                              0,
 
225
                              is_if_not_exists);
 
226
    }
 
227
 
 
228
    if (not res)
 
229
    {
 
230
      session->my_ok();
 
231
    }
 
232
  }
 
233
 
 
234
  /*
 
235
     Release the protection against the global read lock and wake
 
236
     everyone, who might want to set a global read lock.
 
237
   */
 
238
  start_waiting_global_read_lock(session);
 
239
 
 
240
  return res;
 
241
}
 
242
 
 
243
} /* namespace drizzled */
 
244