~drizzle-trunk/drizzle/development

1100.3.57 by Padraig O'Sullivan
Extracted the RENAME TABLE command into its own class and implementation
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
 *
1999.6.1 by kalebral at gmail
update Copyright strings to a more common format to help with creating the master debian copyright file
4
 *  Copyright (C) 2009 Sun Microsystems, Inc.
1100.3.57 by Padraig O'Sullivan
Extracted the RENAME TABLE command into its own class and implementation
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
2173.2.1 by Monty Taylor
Fixes incorrect usage of include
21
#include <config.h>
1100.3.57 by Padraig O'Sullivan
Extracted the RENAME TABLE command into its own class and implementation
22
#include <drizzled/show.h>
23
#include <drizzled/lock.h>
24
#include <drizzled/session.h>
25
#include <drizzled/statement/rename_table.h>
2173.2.1 by Monty Taylor
Fixes incorrect usage of include
26
#include <drizzled/pthread_globals.h>
27
#include <drizzled/plugin/storage_engine.h>
2211.2.2 by David Shrewsbury
Output USE from statement transform code for RAW_SQL with an identified schema. Set schema name from Session for RENAME.
28
#include <drizzled/transaction_services.h>
2239.1.10 by Olaf van der Spek
Refactor includes
29
#include <drizzled/sql_lex.h>
2272.1.1 by Olaf van der Spek
Refactor includes
30
#include <drizzled/table/cache.h>
1100.3.57 by Padraig O'Sullivan
Extracted the RENAME TABLE command into its own class and implementation
31
2239.1.10 by Olaf van der Spek
Refactor includes
32
namespace drizzled {
1100.3.57 by Padraig O'Sullivan
Extracted the RENAME TABLE command into its own class and implementation
33
34
bool statement::RenameTable::execute()
35
{
2224.2.8 by Olaf van der Spek
Statement::lex()
36
  TableList *first_table= (TableList *) lex().select_lex.table_list.first;
37
  TableList *all_tables= lex().query_tables;
1100.3.57 by Padraig O'Sullivan
Extracted the RENAME TABLE command into its own class and implementation
38
  assert(first_table == all_tables && first_table != 0);
39
  TableList *table;
1890.2.40 by Stewart Smith
error out on RENAME TABLE inside a transaction with ER_TRANSACTIONAL_DDL_NOT_SUPPORTED
40
2227.4.1 by Olaf van der Spek
Statement::session()
41
  if (session().inTransaction())
1890.2.40 by Stewart Smith
error out on RENAME TABLE inside a transaction with ER_TRANSACTIONAL_DDL_NOT_SUPPORTED
42
  {
43
    my_error(ER_TRANSACTIONAL_DDL_NOT_SUPPORTED, MYF(0));
44
    return true;
45
  }
46
1100.3.57 by Padraig O'Sullivan
Extracted the RENAME TABLE command into its own class and implementation
47
  for (table= first_table; table; table= table->next_local->next_local)
48
  {
49
    TableList old_list, new_list;
50
    /*
51
       we do not need initialize old_list and new_list because we will
52
       come table[0] and table->next[0] there
53
     */
54
    old_list= table[0];
55
    new_list= table->next_local[0];
56
  }
57
1890.2.40 by Stewart Smith
error out on RENAME TABLE inside a transaction with ER_TRANSACTIONAL_DDL_NOT_SUPPORTED
58
  if (renameTables(first_table))
1100.3.57 by Padraig O'Sullivan
Extracted the RENAME TABLE command into its own class and implementation
59
  {
60
    return true;
61
  }
2098.4.1 by Brian Aker
Make session encapsulated.
62
1100.3.57 by Padraig O'Sullivan
Extracted the RENAME TABLE command into its own class and implementation
63
  return false;
64
}
65
66
bool statement::RenameTable::renameTables(TableList *table_list)
67
{
68
  bool error= true;
69
  TableList *ren_table= NULL;
70
71
  /*
72
    Avoid problems with a rename on a table that we have locked or
73
    if the user is trying to to do this in a transcation context
74
  */
2227.4.1 by Olaf van der Spek
Statement::session()
75
  if (session().inTransaction())
1100.3.57 by Padraig O'Sullivan
Extracted the RENAME TABLE command into its own class and implementation
76
  {
77
    my_message(ER_LOCK_OR_ACTIVE_TRANSACTION, ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
78
    return true;
79
  }
80
2227.4.1 by Olaf van der Spek
Statement::session()
81
  if (session().wait_if_global_read_lock(false, true))
1100.3.57 by Padraig O'Sullivan
Extracted the RENAME TABLE command into its own class and implementation
82
    return true;
83
1938.4.12 by Brian Aker
Merge in lock refactor, this just encapsulates.
84
  {
2275.3.1 by Olaf van der Spek
Remove table::Cache::singleton()
85
    boost::mutex::scoped_lock scopedLock(table::Cache::mutex()); /* Rename table lock for exclusive access */
1938.4.13 by Brian Aker
Merge in change to rename to encapsulate the lock.
86
2227.4.1 by Olaf van der Spek
Statement::session()
87
    if (not session().lock_table_names_exclusively(table_list))
1938.4.13 by Brian Aker
Merge in change to rename to encapsulate the lock.
88
    {
89
      error= false;
90
      ren_table= renameTablesInList(table_list, false);
91
92
      if (ren_table)
93
      {
94
        /* Rename didn't succeed;  rename back the tables in reverse order */
95
        TableList *table;
96
97
        /* Reverse the table list */
98
        table_list= reverseTableList(table_list);
99
100
        /* Find the last renamed table */
101
        for (table= table_list;
102
             table->next_local != ren_table;
103
             table= table->next_local->next_local) 
104
        { /* do nothing */ }
105
106
        table= table->next_local->next_local;		// Skip error table
107
108
        /* Revert to old names */
109
        renameTablesInList(table, true);
110
        error= true;
111
      }
112
113
      table_list->unlock_table_names();
114
    }
1938.4.12 by Brian Aker
Merge in lock refactor, this just encapsulates.
115
  }
1938.4.13 by Brian Aker
Merge in change to rename to encapsulate the lock.
116
117
  /* Lets hope this doesn't fail as the result will be messy */
118
  if (not error)
1938.4.12 by Brian Aker
Merge in lock refactor, this just encapsulates.
119
  {
2318.6.62 by Olaf van der Spek
Refactor
120
    TransactionServices::rawStatement(session(), *session().getQueryString(), *session().schema());        
2227.4.1 by Olaf van der Spek
Statement::session()
121
    session().my_ok();
1938.4.12 by Brian Aker
Merge in lock refactor, this just encapsulates.
122
  }
123
2227.4.1 by Olaf van der Spek
Statement::session()
124
  session().startWaitingGlobalReadLock();
1100.3.57 by Padraig O'Sullivan
Extracted the RENAME TABLE command into its own class and implementation
125
126
  return error;
127
}
128
129
TableList *statement::RenameTable::reverseTableList(TableList *table_list)
130
{
131
  TableList *prev= NULL;
132
133
  while (table_list)
134
  {
135
    TableList *next= table_list->next_local;
136
    table_list->next_local= prev;
137
    prev= table_list;
138
    table_list= next;
139
  }
1100.3.58 by Padraig O'Sullivan
Few style cleanups.
140
  return prev;
1100.3.57 by Padraig O'Sullivan
Extracted the RENAME TABLE command into its own class and implementation
141
}
142
143
bool statement::RenameTable::rename(TableList *ren_table,
144
                                    const char *new_db,
145
                                    const char *new_table_name,
146
                                    bool skip_error)
147
{
148
  bool rc= true;
149
  const char *new_alias, *old_alias;
150
151
  {
1874.1.2 by Brian Aker
Encapsulate table_name from table_list.
152
    old_alias= ren_table->getTableName();
1100.3.57 by Padraig O'Sullivan
Extracted the RENAME TABLE command into its own class and implementation
153
    new_alias= new_table_name;
154
  }
155
1130.1.4 by Monty Taylor
Moved StorageEngine into plugin namespace.
156
  plugin::StorageEngine *engine= NULL;
2159.2.3 by Brian Aker
Remove dead call for getTableMessage()
157
  message::table::shared_ptr table_message;
1100.3.57 by Padraig O'Sullivan
Extracted the RENAME TABLE command into its own class and implementation
158
2087.4.2 by Brian Aker
Modify TableIdentifier to fit with the rest of the identifiers.
159
  identifier::Table old_identifier(ren_table->getSchemaName(), old_alias, message::Table::STANDARD);
1100.3.57 by Padraig O'Sullivan
Extracted the RENAME TABLE command into its own class and implementation
160
2227.4.2 by Olaf van der Spek
Statement::session()
161
  if (not (table_message= plugin::StorageEngine::getTableMessage(session(), old_identifier)))
1100.3.57 by Padraig O'Sullivan
Extracted the RENAME TABLE command into its own class and implementation
162
  {
2140.1.3 by Brian Aker
Merge in error message fix for just one type of error for unknown table.
163
    my_error(ER_TABLE_UNKNOWN, old_identifier);
1100.3.57 by Padraig O'Sullivan
Extracted the RENAME TABLE command into its own class and implementation
164
    return true;
165
  }
166
2227.4.2 by Olaf van der Spek
Statement::session()
167
  engine= plugin::StorageEngine::findByName(session(), table_message->engine().name());
1100.3.57 by Padraig O'Sullivan
Extracted the RENAME TABLE command into its own class and implementation
168
2087.4.2 by Brian Aker
Modify TableIdentifier to fit with the rest of the identifiers.
169
  identifier::Table new_identifier(new_db, new_alias, message::Table::STANDARD);
2227.4.2 by Olaf van der Spek
Statement::session()
170
  if (plugin::StorageEngine::doesTableExist(session(), new_identifier))
1100.3.57 by Padraig O'Sullivan
Extracted the RENAME TABLE command into its own class and implementation
171
  {
2159.2.4 by Brian Aker
Merge in error wasteful removal.
172
    my_error(ER_TABLE_EXISTS_ERROR, new_identifier);
1100.3.58 by Padraig O'Sullivan
Few style cleanups.
173
    return 1; // This can't be skipped
1100.3.57 by Padraig O'Sullivan
Extracted the RENAME TABLE command into its own class and implementation
174
  }
175
2227.4.2 by Olaf van der Spek
Statement::session()
176
  rc= rename_table(session(), engine, old_identifier, new_identifier);
1100.3.58 by Padraig O'Sullivan
Few style cleanups.
177
  if (rc && ! skip_error)
1100.3.57 by Padraig O'Sullivan
Extracted the RENAME TABLE command into its own class and implementation
178
    return true;
179
180
  return false;
181
}
182
183
TableList *statement::RenameTable::renameTablesInList(TableList *table_list,
184
                                                      bool skip_error)
185
{
186
  TableList *ren_table, *new_table;
187
188
  for (ren_table= table_list; ren_table; ren_table= new_table->next_local)
189
  {
190
    new_table= ren_table->next_local;
1874.1.2 by Brian Aker
Encapsulate table_name from table_list.
191
    if (rename(ren_table, new_table->getSchemaName(), new_table->getTableName(), skip_error))
1100.3.61 by Padraig O'Sullivan
Various style cleanups based on code review comments from Jay.
192
      return ren_table;
1100.3.57 by Padraig O'Sullivan
Extracted the RENAME TABLE command into its own class and implementation
193
  }
194
  return 0;
1238.1.4 by Brian Aker
ICC cleanup
195
}
1130.3.12 by Monty Taylor
using namespace drizzled; to namespace drizzled { in statement/
196
197
} /* namespace drizzled */