~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/statement/create_table.cc

  • Committer: Brian Aker
  • Date: 2009-10-01 22:56:26 UTC
  • mto: (1154.1.1 staging)
  • mto: This revision was merged to the branch mainline in revision 1155.
  • Revision ID: brian@gaz-20091001225626-sb1pdykpxlnkheaj
Remove Factory/make scheduler work like everything else.

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 <drizzled/server_includes.h>
 
22
#include <drizzled/show.h>
 
23
#include <drizzled/lock.h>
 
24
#include <drizzled/session.h>
 
25
#include <drizzled/statement/create_table.h>
 
26
 
 
27
using namespace drizzled;
 
28
 
 
29
bool statement::CreateTable::execute()
 
30
{
 
31
  TableList *first_table= (TableList *) session->lex->select_lex.table_list.first;
 
32
  TableList *all_tables= session->lex->query_tables;
 
33
  assert(first_table == all_tables && first_table != 0);
 
34
  Select_Lex *select_lex= &session->lex->select_lex;
 
35
  Select_Lex_Unit *unit= &session->lex->unit;
 
36
  bool need_start_waiting= false;
 
37
  bool res= false;
 
38
  bool link_to_local= false;
 
39
 
 
40
  /* If CREATE TABLE of non-temporary table, do implicit commit */
 
41
  if (! (create_info.options & HA_LEX_CREATE_TMP_TABLE))
 
42
  {
 
43
    if (! session->endActiveTransaction())
 
44
    {
 
45
      return true;
 
46
    }
 
47
  }
 
48
  /* Skip first table, which is the table we are creating */
 
49
  TableList *create_table= session->lex->unlink_first_table(&link_to_local);
 
50
  TableList *select_tables= session->lex->query_tables;
 
51
 
 
52
  if (create_table_precheck(session, select_tables, create_table))
 
53
  {
 
54
    /* put tables back for PS rexecuting */
 
55
    session->lex->link_first_table_back(create_table, link_to_local);
 
56
    return true;
 
57
  }
 
58
 
 
59
  /* Might have been updated in create_table_precheck */
 
60
  create_info.alias= create_table->alias;
 
61
 
 
62
  /*
 
63
     The create-select command will open and read-lock the select table
 
64
     and then create, open and write-lock the new table. If a global
 
65
     read lock steps in, we get a deadlock. The write lock waits for
 
66
     the global read lock, while the global read lock waits for the
 
67
     select table to be closed. So we wait until the global readlock is
 
68
     gone before starting both steps. Note that
 
69
     wait_if_global_read_lock() sets a protection against a new global
 
70
     read lock when it succeeds. This needs to be released by
 
71
     start_waiting_global_read_lock(). We protect the normal CREATE
 
72
     TABLE in the same way. That way we avoid that a new table is
 
73
     created during a gobal read lock.
 
74
   */
 
75
  if (! (need_start_waiting= ! wait_if_global_read_lock(session, 0, 1)))
 
76
  {
 
77
    /* put tables back for PS rexecuting */
 
78
    session->lex->link_first_table_back(create_table, link_to_local);
 
79
    return true;
 
80
  }
 
81
  if (select_lex->item_list.elements)           // With select
 
82
  {
 
83
    select_result *result;
 
84
 
 
85
    select_lex->options|= SELECT_NO_UNLOCK;
 
86
    unit->set_limit(select_lex);
 
87
 
 
88
    if (! (create_info.options & HA_LEX_CREATE_TMP_TABLE))
 
89
    {
 
90
      session->lex->link_first_table_back(create_table, link_to_local);
 
91
      create_table->create= true;
 
92
    }
 
93
 
 
94
    if (! (res= session->openTablesLock(session->lex->query_tables)))
 
95
    {
 
96
      /*
 
97
         Is table which we are changing used somewhere in other parts
 
98
         of query
 
99
       */
 
100
      if (! (create_info.options & HA_LEX_CREATE_TMP_TABLE))
 
101
      {
 
102
        TableList *duplicate= NULL;
 
103
        create_table= session->lex->unlink_first_table(&link_to_local);
 
104
        if ((duplicate= unique_table(session, create_table, select_tables, 0)))
 
105
        {
 
106
          my_error(ER_UPDATE_TABLE_USED, MYF(0), create_table->alias);
 
107
          /*
 
108
             Release the protection against the global read lock and wake
 
109
             everyone, who might want to set a global read lock.
 
110
           */
 
111
          start_waiting_global_read_lock(session);
 
112
          /* put tables back for PS rexecuting */
 
113
          session->lex->link_first_table_back(create_table, link_to_local);
 
114
          return true;
 
115
        }
 
116
      }
 
117
 
 
118
      /*
 
119
         select_create is currently not re-execution friendly and
 
120
         needs to be created for every execution of a PS/SP.
 
121
       */
 
122
      if ((result= new select_create(create_table,
 
123
                                     &create_info,
 
124
                                     &create_table_proto,
 
125
                                     &alter_info,
 
126
                                     select_lex->item_list,
 
127
                                     session->lex->duplicates,
 
128
                                     session->lex->ignore,
 
129
                                     select_tables)))
 
130
      {
 
131
        /*
 
132
           CREATE from SELECT give its Select_Lex for SELECT,
 
133
           and item_list belong to SELECT
 
134
         */
 
135
        res= handle_select(session, session->lex, result, 0);
 
136
        delete result;
 
137
      }
 
138
    }
 
139
    else if (! (create_info.options & HA_LEX_CREATE_TMP_TABLE))
 
140
    {
 
141
      create_table= session->lex->unlink_first_table(&link_to_local);
 
142
    }
 
143
  }
 
144
  else
 
145
  {
 
146
    /* So that CREATE TEMPORARY TABLE gets to binlog at commit/rollback */
 
147
    if (create_info.options & HA_LEX_CREATE_TMP_TABLE)
 
148
      session->options|= OPTION_KEEP_LOG;
 
149
    /* regular create */
 
150
    if (create_info.options & HA_LEX_CREATE_TABLE_LIKE)
 
151
    {
 
152
      res= mysql_create_like_table(session, 
 
153
                                   create_table, 
 
154
                                   select_tables,
 
155
                                   &create_info);
 
156
    }
 
157
    else
 
158
    {
 
159
      res= mysql_create_table(session, 
 
160
                              create_table->db,
 
161
                              create_table->table_name, 
 
162
                              &create_info,
 
163
                              &create_table_proto,
 
164
                              &alter_info, 
 
165
                              0, 
 
166
                              0);
 
167
    }
 
168
    if (! res)
 
169
    {
 
170
      session->my_ok();
 
171
    }
 
172
  }
 
173
 
 
174
  /*
 
175
     Release the protection against the global read lock and wake
 
176
     everyone, who might want to set a global read lock.
 
177
   */
 
178
  start_waiting_global_read_lock(session);
 
179
 
 
180
  return res;
 
181
}