~ubuntu-branches/ubuntu/trusty/drizzle/trusty

« back to all changes in this revision

Viewing changes to drizzled/statement/create_table.cc

  • Committer: Bazaar Package Importer
  • Author(s): Monty Taylor
  • Date: 2010-03-18 12:12:31 UTC
  • Revision ID: james.westby@ubuntu.com-20100318121231-k6g1xe6cshbwa0f8
Tags: upstream-2010.03.1347
ImportĀ upstreamĀ versionĀ 2010.03.1347

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