~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/statement/create_table.cc

  • Committer: Brian Aker
  • Date: 2010-01-22 00:53:13 UTC
  • Revision ID: brian@gaz-20100122005313-jmizcbcdi1lt4tcx
Revert db patch.

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() == drizzled::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 (! lex_identified_temp_table)
 
77
  {
 
78
    if (! 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 ? NO_TMP_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 (! 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 (! (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 (! 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
      {
 
177
        /*
 
178
           CREATE from SELECT give its Select_Lex for SELECT,
 
179
           and item_list belong to SELECT
 
180
         */
 
181
        res= handle_select(session, session->lex, result, 0);
 
182
        delete result;
 
183
      }
 
184
    }
 
185
    else if (! lex_identified_temp_table)
 
186
    {
 
187
      create_table= session->lex->unlink_first_table(&link_to_local);
 
188
    }
 
189
  }
 
190
  else
 
191
  {
 
192
    /* regular create */
 
193
    if (is_create_table_like)
 
194
    {
 
195
      res= mysql_create_like_table(session, 
 
196
                                   create_table, 
 
197
                                   select_tables,
 
198
                                   create_table_proto,
 
199
                                   create_info.db_type, 
 
200
                                   is_if_not_exists,
 
201
                                   is_engine_set);
 
202
    }
 
203
    else
 
204
    {
 
205
 
 
206
      for (int32_t x= 0; x < alter_info.alter_proto.added_field_size(); x++)
 
207
      {
 
208
        message::Table::Field *field= create_table_proto.add_field();
 
209
 
 
210
        *field= alter_info.alter_proto.added_field(x);
 
211
      }
 
212
 
 
213
      res= mysql_create_table(session, 
 
214
                              new_table_identifier,
 
215
                              &create_info,
 
216
                              &create_table_proto,
 
217
                              &alter_info, 
 
218
                              false, 
 
219
                              0,
 
220
                              is_if_not_exists);
 
221
    }
 
222
    if (! res)
 
223
    {
 
224
      session->my_ok();
 
225
    }
 
226
  }
 
227
 
 
228
  /*
 
229
     Release the protection against the global read lock and wake
 
230
     everyone, who might want to set a global read lock.
 
231
   */
 
232
  start_waiting_global_read_lock(session);
 
233
 
 
234
  return res;
 
235
}
 
236
 
 
237
} /* namespace drizzled */
 
238