~drizzle-trunk/drizzle/development

1 by brian
clean slate
1
/* Copyright (C) 2000-2003 MySQL AB
2
3
   This program is free software; you can redistribute it and/or modify
4
   it under the terms of the GNU General Public License as published by
5
   the Free Software Foundation; version 2 of the License.
6
7
   This program is distributed in the hope that it will be useful,
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
   GNU General Public License for more details.
11
12
   You should have received a copy of the GNU General Public License
13
   along with this program; if not, write to the Free Software
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
16
17
/* create and drop of databases */
612.2.4 by Monty Taylor
Moved some defines to config.h. Stopped including config.h directly anywhere.
18
#include <drizzled/global.h>
481.1.9 by Monty Taylor
Added autoconf tests for location of cstdint and cinttypes. Use those in C++ programs now, so that we don't have to define _STDC_LIMIT_MACROS, etc by hand. Stop, in fact, defining those by hand.
19
#include CSTDINT_H
20
#include CINTTYPES_H
318 by Brian Aker
Modified sql_db to now use Google Proto buffers instead of MySQL type.
21
#include <string>
22
#include <fstream>
316 by Brian Aker
First pass of new sql_db.cc work
23
#include <drizzled/serialize/serialize.h>
318 by Brian Aker
Modified sql_db to now use Google Proto buffers instead of MySQL type.
24
using namespace std;
243.1.17 by Jay Pipes
FINAL PHASE removal of mysql_priv.h (Bye, bye my friend.)
25
#include <drizzled/server_includes.h>
212.5.13 by Monty Taylor
Moved my_sys/my_pthread/my_nosys and mysys_err to mysys.
26
#include <mysys/mysys_err.h>
212.5.38 by Monty Taylor
Moved my_dir (and removed references to a lot of places)
27
#include <mysys/my_dir.h>
549 by Monty Taylor
Took gettext.h out of header files.
28
#include <drizzled/error.h>
538 by Monty Taylor
Moved gettext.h into drizzled in anticipation of the new client lib.
29
#include <drizzled/gettext.h>
584.1.15 by Monty Taylor
The mega-patch from hell. Renamed sql_class to session (since that's what it is) and removed it and field and table from common_includes.
30
#include <mysys/hash.h>
31
#include <drizzled/session.h>
32
#include <drizzled/db.h>
33
#include <drizzled/sql_base.h>
670.2.4 by Monty Taylor
Removed more stuff from the headers.
34
#include <drizzled/lock.h>
722.4.1 by Mark Atwood
integrate errmsg plugin into sql_print_* functions
35
#include <drizzled/errmsg_print.h>
798.2.19 by Brian Aker
Converted db.cc away from using binlog
36
#include <drizzled/replicator.h>
316 by Brian Aker
First pass of new sql_db.cc work
37
822 by Brian Aker
Merge from Stewart.
38
#define MY_DB_OPT_FILE "db.opt"
1 by brian
clean slate
39
#define MAX_DROP_TABLE_Q_LEN      1024
40
461 by Monty Taylor
Removed NullS. bu-bye.
41
const char *del_exts[]= {".frm", ".BAK", ".TMD",".opt", NULL};
1 by brian
clean slate
42
static TYPELIB deletable_extentions=
43
{array_elements(del_exts)-1,"del_exts", del_exts, NULL};
44
520.1.22 by Brian Aker
Second pass of thd cleanup
45
static long mysql_rm_known_files(Session *session, MY_DIR *dirp,
584.1.15 by Monty Taylor
The mega-patch from hell. Renamed sql_class to session (since that's what it is) and removed it and field and table from common_includes.
46
                                 const char *db, const char *path,
47
                                 uint32_t level,
327.2.4 by Brian Aker
Refactoring table.h
48
                                 TableList **dropped_tables);
584.1.15 by Monty Taylor
The mega-patch from hell. Renamed sql_class to session (since that's what it is) and removed it and field and table from common_includes.
49
253 by Brian Aker
Removed final my_bool from sql_db.
50
static bool rm_dir_w_symlink(const char *org_path, bool send_error);
520.1.22 by Brian Aker
Second pass of thd cleanup
51
static void mysql_change_db_impl(Session *session,
1 by brian
clean slate
52
                                 LEX_STRING *new_db_name,
264.2.6 by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code.
53
                                 const CHARSET_INFO * const new_db_charset);
1 by brian
clean slate
54
55
56
/* Database lock hash */
57
HASH lock_db_cache;
58
pthread_mutex_t LOCK_lock_db;
811.1.2 by Stewart Smith
remove existing db.opt implementation.
59
bool dbcache_init= false;
1 by brian
clean slate
60
int creating_database= 0;  // how many database locks are made
61
62
63
/* Structure for database lock */
64
typedef struct my_dblock_st
65
{
66
  char *name;        /* Database name        */
482 by Brian Aker
Remove uint.
67
  uint32_t name_length;  /* Database length name */
1 by brian
clean slate
68
} my_dblock_t;
69
70
71
/*
72
  lock_db key.
73
*/
74
481 by Brian Aker
Remove all of uchar.
75
extern "C" unsigned char* lock_db_get_key(my_dblock_t *, size_t *, bool not_used);
1 by brian
clean slate
76
481 by Brian Aker
Remove all of uchar.
77
unsigned char* lock_db_get_key(my_dblock_t *ptr, size_t *length,
779.1.27 by Monty Taylor
Got rid of __attribute__((unused)) and the like from the .cc files.
78
                       bool )
1 by brian
clean slate
79
{
80
  *length= ptr->name_length;
481 by Brian Aker
Remove all of uchar.
81
  return (unsigned char*) ptr->name;
1 by brian
clean slate
82
}
83
84
85
/*
86
  Free lock_db hash element.
87
*/
88
89
extern "C" void lock_db_free_element(void *ptr);
90
91
void lock_db_free_element(void *ptr)
92
{
477 by Monty Taylor
Removed my_free(). It turns out that it had been def'd to ignore the flags passed to it in the second arg anyway. Gotta love that.
93
  free(ptr);
1 by brian
clean slate
94
}
95
96
97
/*
98
  Delete a database lock entry from hash.
99
*/
100
482 by Brian Aker
Remove uint.
101
void lock_db_delete(const char *name, uint32_t length)
1 by brian
clean slate
102
{
103
  my_dblock_t *opt;
104
  safe_mutex_assert_owner(&LOCK_lock_db);
105
  if ((opt= (my_dblock_t *)hash_search(&lock_db_cache,
481 by Brian Aker
Remove all of uchar.
106
                                       (const unsigned char*) name, length)))
107
    hash_delete(&lock_db_cache, (unsigned char*) opt);
1 by brian
clean slate
108
}
109
110
/*
111
  Helper function to write a query to binlog used by mysql_rm_db()
112
*/
113
798.2.19 by Brian Aker
Converted db.cc away from using binlog
114
static inline void write_to_binlog(Session *session, char *query, uint32_t query_length, char *, uint32_t)
1 by brian
clean slate
115
{
798.2.19 by Brian Aker
Converted db.cc away from using binlog
116
  (void)replicator_statement(session, query, query_length);
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
117
}
1 by brian
clean slate
118
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
119
/*
1 by brian
clean slate
120
  Initialize database option hash and locked database hash.
121
122
  SYNOPSIS
123
    my_database_names()
124
125
  NOTES
126
    Must be called before any other database function is called.
127
128
  RETURN
129
    0	ok
130
    1	Fatal error
131
*/
132
133
bool my_database_names_init(void)
134
{
253 by Brian Aker
Removed final my_bool from sql_db.
135
  bool error= false;
811.1.2 by Stewart Smith
remove existing db.opt implementation.
136
  if (!dbcache_init)
1 by brian
clean slate
137
  {
811.1.2 by Stewart Smith
remove existing db.opt implementation.
138
    dbcache_init= true;
139
    error= hash_init(&lock_db_cache, lower_case_table_names ?
1 by brian
clean slate
140
                     &my_charset_bin : system_charset_info,
141
                     32, 0, 0, (hash_get_key) lock_db_get_key,
142
                     lock_db_free_element,0);
143
144
  }
145
  return error;
146
}
147
148
/**
149
  Return default database collation.
150
520.1.22 by Brian Aker
Second pass of thd cleanup
151
  @param session     Thread context.
1 by brian
clean slate
152
  @param db_name Database name.
153
154
  @return CHARSET_INFO object. The operation always return valid character
155
    set, even if the database does not exist.
156
*/
157
520.1.22 by Brian Aker
Second pass of thd cleanup
158
const CHARSET_INFO *get_default_db_collation(Session *session, const char *db_name)
1 by brian
clean slate
159
{
160
  HA_CREATE_INFO db_info;
161
520.1.22 by Brian Aker
Second pass of thd cleanup
162
  if (session->db != NULL && strcmp(db_name, session->db) == 0)
163
    return session->db_charset;
1 by brian
clean slate
164
165
  /*
166
    db_info.default_table_charset contains valid character set
811.1.2 by Stewart Smith
remove existing db.opt implementation.
167
    (collation_server).
1 by brian
clean slate
168
  */
169
820.1.11 by Stewart Smith
re-introduce db.opt, but with parsing it from disk instead of in process cache with mutex.
170
  load_db_opt_by_name(session, db_name, &db_info);
171
1 by brian
clean slate
172
  return db_info.default_table_charset;
173
}
174
820.1.11 by Stewart Smith
re-introduce db.opt, but with parsing it from disk instead of in process cache with mutex.
175
/* path is path to database, not schema file */
176
static int write_schema_file(Session *session,
177
			     const char *path, const char *name,
178
			     HA_CREATE_INFO *create)
179
{
180
  drizzle::Schema db;
181
  char schema_file_tmp[FN_REFLEN];
182
  string schema_file(path);
183
184
  assert(path);
185
  assert(name);
186
  assert(create);
187
822 by Brian Aker
Merge from Stewart.
188
  snprintf(schema_file_tmp, FN_REFLEN, "%s%c%s.tmpXXXXXX", path, FN_LIBCHAR, MY_DB_OPT_FILE);
820.1.11 by Stewart Smith
re-introduce db.opt, but with parsing it from disk instead of in process cache with mutex.
189
190
  schema_file.append(1, FN_LIBCHAR);
822 by Brian Aker
Merge from Stewart.
191
  schema_file.append(MY_DB_OPT_FILE);
820.1.11 by Stewart Smith
re-introduce db.opt, but with parsing it from disk instead of in process cache with mutex.
192
193
  int fd= mkstemp(schema_file_tmp);
194
195
  if (fd==-1)
196
    return errno;
197
198
  if (!create->default_table_charset)
199
    create->default_table_charset= session->variables.collation_server;
200
201
  db.set_name(name);
202
  db.set_collation(create->default_table_charset->name);
203
204
  if (!db.SerializeToFileDescriptor(fd))
205
  {
206
    close(fd);
207
    unlink(schema_file_tmp);
208
    return -1;
209
  }
210
211
  if (rename(schema_file_tmp, schema_file.c_str()) == -1)
212
  {
213
    close(fd);
214
    return errno;
215
  }
216
217
  close(fd);
218
  return 0;
219
}
220
221
int load_db_opt(Session *session, const char *path, HA_CREATE_INFO *create)
222
{
223
  drizzle::Schema db;
224
  string buffer;
225
226
  memset(create, 0, sizeof(*create));
227
  create->default_table_charset= session->variables.collation_server;
228
229
  int fd= open(path, O_RDONLY);
230
231
  if (fd == -1)
232
    return errno;
233
234
  if (!db.ParseFromFileDescriptor(fd))
235
  {
236
    close(fd);
237
    return -1;
238
  }
239
  close(fd);
240
241
  buffer= db.collation();
862 by Brian Aker
Remove charset directory code.
242
  if (!(create->default_table_charset= get_charset_by_name(buffer.c_str())))
820.1.11 by Stewart Smith
re-introduce db.opt, but with parsing it from disk instead of in process cache with mutex.
243
  {
244
    errmsg_printf(ERRMSG_LVL_ERROR,
245
		  _("Error while loading database options: '%s':"),path);
246
    errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_UNKNOWN_COLLATION), buffer.c_str());
247
    create->default_table_charset= default_charset_info;
248
    return -1;
249
  }
250
251
  return 0;
252
}
253
254
int load_db_opt_by_name(Session *session, const char *db_name,
255
			HA_CREATE_INFO *db_create_info)
256
{
257
  char db_opt_path[FN_REFLEN];
258
259
  /*
260
    Pass an empty file name, and the database options file name as extension
261
    to avoid table name to file name encoding.
262
  */
263
  (void) build_table_filename(db_opt_path, sizeof(db_opt_path),
822 by Brian Aker
Merge from Stewart.
264
                              db_name, "", MY_DB_OPT_FILE, 0);
820.1.11 by Stewart Smith
re-introduce db.opt, but with parsing it from disk instead of in process cache with mutex.
265
266
  return load_db_opt(session, db_opt_path, db_create_info);
267
}
268
1 by brian
clean slate
269
270
/*
271
  Create a database
272
273
  SYNOPSIS
274
  mysql_create_db()
520.1.22 by Brian Aker
Second pass of thd cleanup
275
  session		Thread handler
1 by brian
clean slate
276
  db		Name of database to create
277
		Function assumes that this is already validated.
278
  create_info	Database create options (like character set)
279
  silent	Used by replication when internally creating a database.
280
		In this case the entry should not be logged.
281
282
  SIDE-EFFECTS
283
   1. Report back to client that command succeeded (my_ok)
284
   2. Report errors to client
285
   3. Log event to binary log
286
   (The 'silent' flags turns off 1 and 3.)
287
288
  RETURN VALUES
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
289
  false ok
290
  true  Error
1 by brian
clean slate
291
292
*/
293
520.1.22 by Brian Aker
Second pass of thd cleanup
294
int mysql_create_db(Session *session, char *db, HA_CREATE_INFO *create_info, bool silent)
1 by brian
clean slate
295
{
296
  char	 path[FN_REFLEN+16];
297
  char	 tmp_query[FN_REFLEN+16];
298
  long result= 1;
299
  int error= 0;
482 by Brian Aker
Remove uint.
300
  uint32_t create_options= create_info ? create_info->options : 0;
301
  uint32_t path_len;
1 by brian
clean slate
302
303
  /* do not create 'information_schema' db */
575.4.7 by Monty Taylor
More header cleanup.
304
  if (!my_strcasecmp(system_charset_info, db, INFORMATION_SCHEMA_NAME.c_str()))
1 by brian
clean slate
305
  {
306
    my_error(ER_DB_CREATE_EXISTS, MYF(0), db);
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
307
    return(-1);
1 by brian
clean slate
308
  }
309
310
  /*
311
    Do not create database if another thread is holding read lock.
840.1.21 by Monty Taylor
ZOMG. Renamed all the rest of the stuff in libdrizzleclient to be drizzleclient_*. I love commandline perl.
312
    Wait for global read lock before acquiring LOCK_drizzleclient_create_db.
1 by brian
clean slate
313
    After wait_if_global_read_lock() we have protection against another
840.1.21 by Monty Taylor
ZOMG. Renamed all the rest of the stuff in libdrizzleclient to be drizzleclient_*. I love commandline perl.
314
    global read lock. If we would acquire LOCK_drizzleclient_create_db first,
1 by brian
clean slate
315
    another thread could step in and get the global read lock before we
316
    reach wait_if_global_read_lock(). If this thread tries the same as we
840.1.21 by Monty Taylor
ZOMG. Renamed all the rest of the stuff in libdrizzleclient to be drizzleclient_*. I love commandline perl.
317
    (admin a db), it would then go and wait on LOCK_drizzleclient_create_db...
1 by brian
clean slate
318
    Furthermore wait_if_global_read_lock() checks if the current thread
319
    has the global read lock and refuses the operation with
320
    ER_CANT_UPDATE_WITH_READLOCK if applicable.
321
  */
520.1.22 by Brian Aker
Second pass of thd cleanup
322
  if (wait_if_global_read_lock(session, 0, 1))
1 by brian
clean slate
323
  {
324
    error= -1;
325
    goto exit2;
326
  }
327
840.1.21 by Monty Taylor
ZOMG. Renamed all the rest of the stuff in libdrizzleclient to be drizzleclient_*. I love commandline perl.
328
  pthread_mutex_lock(&LOCK_drizzleclient_create_db);
1 by brian
clean slate
329
330
  /* Check directory */
331
  path_len= build_table_filename(path, sizeof(path), db, "", "", 0);
332
  path[path_len-1]= 0;                    // Remove last '/' from path
333
820.1.11 by Stewart Smith
re-introduce db.opt, but with parsing it from disk instead of in process cache with mutex.
334
  if (mkdir(path,0777) == -1)
1 by brian
clean slate
335
  {
820.1.11 by Stewart Smith
re-introduce db.opt, but with parsing it from disk instead of in process cache with mutex.
336
    if (errno == EEXIST)
1 by brian
clean slate
337
    {
820.1.11 by Stewart Smith
re-introduce db.opt, but with parsing it from disk instead of in process cache with mutex.
338
      if (!(create_options & HA_LEX_CREATE_IF_NOT_EXISTS))
339
      {
340
	my_error(ER_DB_CREATE_EXISTS, MYF(0), db);
341
	error= -1;
342
	goto exit;
343
      }
344
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
345
			  ER_DB_CREATE_EXISTS, ER(ER_DB_CREATE_EXISTS), db);
346
      if (!silent)
836 by Brian Aker
Fixed session call from function to method.
347
	session->my_ok();
820.1.11 by Stewart Smith
re-introduce db.opt, but with parsing it from disk instead of in process cache with mutex.
348
      error= 0;
1 by brian
clean slate
349
      goto exit;
350
    }
820.1.11 by Stewart Smith
re-introduce db.opt, but with parsing it from disk instead of in process cache with mutex.
351
352
    my_error(ER_CANT_CREATE_DB, MYF(0), db, my_errno);
353
    error= -1;
1 by brian
clean slate
354
    goto exit;
355
  }
820.1.11 by Stewart Smith
re-introduce db.opt, but with parsing it from disk instead of in process cache with mutex.
356
357
  error= write_schema_file(session, path, db, create_info);
358
  if (error && error != EEXIST)
1 by brian
clean slate
359
  {
820.1.11 by Stewart Smith
re-introduce db.opt, but with parsing it from disk instead of in process cache with mutex.
360
    if (rmdir(path) >= 0)
361
    {
1 by brian
clean slate
362
      error= -1;
363
      goto exit;
364
    }
365
  }
366
367
  if (!silent)
368
  {
369
    char *query;
482 by Brian Aker
Remove uint.
370
    uint32_t query_length;
1 by brian
clean slate
371
520.1.22 by Brian Aker
Second pass of thd cleanup
372
    if (!session->query)				// Only in replication
1 by brian
clean slate
373
    {
673.2.1 by Toru Maesaka
First pass of replacing MySQL's strxmov with libc alternatives
374
      query= tmp_query;
375
      query_length= sprintf(tmp_query, "create database `%s`", db);
1 by brian
clean slate
376
    }
377
    else
378
    {
520.1.22 by Brian Aker
Second pass of thd cleanup
379
      query= 	    session->query;
380
      query_length= session->query_length;
1 by brian
clean slate
381
    }
382
798.2.19 by Brian Aker
Converted db.cc away from using binlog
383
    (void)replicator_statement(session, query, query_length);
836 by Brian Aker
Fixed session call from function to method.
384
    session->my_ok(result);
1 by brian
clean slate
385
  }
386
387
exit:
840.1.21 by Monty Taylor
ZOMG. Renamed all the rest of the stuff in libdrizzleclient to be drizzleclient_*. I love commandline perl.
388
  pthread_mutex_unlock(&LOCK_drizzleclient_create_db);
520.1.22 by Brian Aker
Second pass of thd cleanup
389
  start_waiting_global_read_lock(session);
1 by brian
clean slate
390
exit2:
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
391
  return(error);
1 by brian
clean slate
392
}
393
394
395
/* db-name is already validated when we come here */
396
520.1.22 by Brian Aker
Second pass of thd cleanup
397
bool mysql_alter_db(Session *session, const char *db, HA_CREATE_INFO *create_info)
1 by brian
clean slate
398
{
399
  long result=1;
820.1.11 by Stewart Smith
re-introduce db.opt, but with parsing it from disk instead of in process cache with mutex.
400
  int error= 0;
401
  char	 path[FN_REFLEN+16];
402
  uint32_t path_len;
1 by brian
clean slate
403
404
  /*
405
    Do not alter database if another thread is holding read lock.
840.1.21 by Monty Taylor
ZOMG. Renamed all the rest of the stuff in libdrizzleclient to be drizzleclient_*. I love commandline perl.
406
    Wait for global read lock before acquiring LOCK_drizzleclient_create_db.
1 by brian
clean slate
407
    After wait_if_global_read_lock() we have protection against another
840.1.21 by Monty Taylor
ZOMG. Renamed all the rest of the stuff in libdrizzleclient to be drizzleclient_*. I love commandline perl.
408
    global read lock. If we would acquire LOCK_drizzleclient_create_db first,
1 by brian
clean slate
409
    another thread could step in and get the global read lock before we
410
    reach wait_if_global_read_lock(). If this thread tries the same as we
840.1.21 by Monty Taylor
ZOMG. Renamed all the rest of the stuff in libdrizzleclient to be drizzleclient_*. I love commandline perl.
411
    (admin a db), it would then go and wait on LOCK_drizzleclient_create_db...
1 by brian
clean slate
412
    Furthermore wait_if_global_read_lock() checks if the current thread
413
    has the global read lock and refuses the operation with
414
    ER_CANT_UPDATE_WITH_READLOCK if applicable.
415
  */
520.1.22 by Brian Aker
Second pass of thd cleanup
416
  if ((error=wait_if_global_read_lock(session,0,1)))
811.1.2 by Stewart Smith
remove existing db.opt implementation.
417
    goto exit;
1 by brian
clean slate
418
840.1.21 by Monty Taylor
ZOMG. Renamed all the rest of the stuff in libdrizzleclient to be drizzleclient_*. I love commandline perl.
419
  pthread_mutex_lock(&LOCK_drizzleclient_create_db);
1 by brian
clean slate
420
421
  /* Change options if current database is being altered. */
820.1.11 by Stewart Smith
re-introduce db.opt, but with parsing it from disk instead of in process cache with mutex.
422
  path_len= build_table_filename(path, sizeof(path), db, "", "", 0);
423
  path[path_len-1]= 0;                    // Remove last '/' from path
424
425
  error= write_schema_file(session, path, db, create_info);
426
  if (error && error != EEXIST)
427
  {
428
    /* TODO: find some witty way of getting back an error message */
840.1.21 by Monty Taylor
ZOMG. Renamed all the rest of the stuff in libdrizzleclient to be drizzleclient_*. I love commandline perl.
429
    pthread_mutex_unlock(&LOCK_drizzleclient_create_db);
820.1.11 by Stewart Smith
re-introduce db.opt, but with parsing it from disk instead of in process cache with mutex.
430
    goto exit;
431
  }
1 by brian
clean slate
432
520.1.22 by Brian Aker
Second pass of thd cleanup
433
  if (session->db && !strcmp(session->db,db))
1 by brian
clean slate
434
  {
520.1.22 by Brian Aker
Second pass of thd cleanup
435
    session->db_charset= create_info->default_table_charset ?
1 by brian
clean slate
436
		     create_info->default_table_charset :
520.1.22 by Brian Aker
Second pass of thd cleanup
437
		     session->variables.collation_server;
438
    session->variables.collation_database= session->db_charset;
1 by brian
clean slate
439
  }
440
798.2.19 by Brian Aker
Converted db.cc away from using binlog
441
  (void)replicator_statement(session, session->query, session->query_length);
836 by Brian Aker
Fixed session call from function to method.
442
  session->my_ok(result);
1 by brian
clean slate
443
840.1.21 by Monty Taylor
ZOMG. Renamed all the rest of the stuff in libdrizzleclient to be drizzleclient_*. I love commandline perl.
444
  pthread_mutex_unlock(&LOCK_drizzleclient_create_db);
520.1.22 by Brian Aker
Second pass of thd cleanup
445
  start_waiting_global_read_lock(session);
811.1.2 by Stewart Smith
remove existing db.opt implementation.
446
exit:
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
447
  return(error);
1 by brian
clean slate
448
}
449
450
451
/*
452
  Drop all tables in a database and the database itself
453
454
  SYNOPSIS
455
    mysql_rm_db()
520.1.22 by Brian Aker
Second pass of thd cleanup
456
    session			Thread handle
1 by brian
clean slate
457
    db			Database name in the case given by user
458
		        It's already validated and set to lower case
459
                        (if needed) when we come here
460
    if_exists		Don't give error if database doesn't exists
461
    silent		Don't generate errors
462
463
  RETURN
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
464
    false ok (Database dropped)
1 by brian
clean slate
465
    ERROR Error
466
*/
467
520.1.22 by Brian Aker
Second pass of thd cleanup
468
bool mysql_rm_db(Session *session,char *db,bool if_exists, bool silent)
1 by brian
clean slate
469
{
470
  long deleted=0;
253 by Brian Aker
Removed final my_bool from sql_db.
471
  int error= false;
1 by brian
clean slate
472
  char	path[FN_REFLEN+16];
473
  MY_DIR *dirp;
482 by Brian Aker
Remove uint.
474
  uint32_t length;
327.2.4 by Brian Aker
Refactoring table.h
475
  TableList* dropped_tables= 0;
1 by brian
clean slate
476
477
  if (db && (strcmp(db, "information_schema") == 0))
478
  {
575.4.7 by Monty Taylor
More header cleanup.
479
    my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), "", "", INFORMATION_SCHEMA_NAME.c_str());
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
480
    return(true);
1 by brian
clean slate
481
  }
482
483
  /*
484
    Do not drop database if another thread is holding read lock.
840.1.21 by Monty Taylor
ZOMG. Renamed all the rest of the stuff in libdrizzleclient to be drizzleclient_*. I love commandline perl.
485
    Wait for global read lock before acquiring LOCK_drizzleclient_create_db.
1 by brian
clean slate
486
    After wait_if_global_read_lock() we have protection against another
840.1.21 by Monty Taylor
ZOMG. Renamed all the rest of the stuff in libdrizzleclient to be drizzleclient_*. I love commandline perl.
487
    global read lock. If we would acquire LOCK_drizzleclient_create_db first,
1 by brian
clean slate
488
    another thread could step in and get the global read lock before we
489
    reach wait_if_global_read_lock(). If this thread tries the same as we
840.1.21 by Monty Taylor
ZOMG. Renamed all the rest of the stuff in libdrizzleclient to be drizzleclient_*. I love commandline perl.
490
    (admin a db), it would then go and wait on LOCK_drizzleclient_create_db...
1 by brian
clean slate
491
    Furthermore wait_if_global_read_lock() checks if the current thread
492
    has the global read lock and refuses the operation with
493
    ER_CANT_UPDATE_WITH_READLOCK if applicable.
494
  */
520.1.22 by Brian Aker
Second pass of thd cleanup
495
  if (wait_if_global_read_lock(session, 0, 1))
1 by brian
clean slate
496
  {
497
    error= -1;
498
    goto exit2;
499
  }
500
840.1.21 by Monty Taylor
ZOMG. Renamed all the rest of the stuff in libdrizzleclient to be drizzleclient_*. I love commandline perl.
501
  pthread_mutex_lock(&LOCK_drizzleclient_create_db);
1 by brian
clean slate
502
503
  length= build_table_filename(path, sizeof(path), db, "", "", 0);
822 by Brian Aker
Merge from Stewart.
504
  strcpy(path+length, MY_DB_OPT_FILE);         // Append db option file name
820.1.11 by Stewart Smith
re-introduce db.opt, but with parsing it from disk instead of in process cache with mutex.
505
  unlink(path);
1 by brian
clean slate
506
  path[length]= '\0';				// Remove file name
507
508
  /* See if the directory exists */
509
  if (!(dirp= my_dir(path,MYF(MY_DONT_SORT))))
510
  {
511
    if (!if_exists)
512
    {
513
      error= -1;
514
      my_error(ER_DB_DROP_EXISTS, MYF(0), db);
515
      goto exit;
516
    }
517
    else
520.1.22 by Brian Aker
Second pass of thd cleanup
518
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1 by brian
clean slate
519
			  ER_DB_DROP_EXISTS, ER(ER_DB_DROP_EXISTS), db);
520
  }
521
  else
522
  {
523
    pthread_mutex_lock(&LOCK_open);
524
    remove_db_from_cache(db);
525
    pthread_mutex_unlock(&LOCK_open);
526
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
527
1 by brian
clean slate
528
    error= -1;
520.1.22 by Brian Aker
Second pass of thd cleanup
529
    if ((deleted= mysql_rm_known_files(session, dirp, db, path, 0,
1 by brian
clean slate
530
                                       &dropped_tables)) >= 0)
531
    {
532
      ha_drop_database(path);
533
      error = 0;
534
    }
535
  }
536
  if (!silent && deleted>=0)
537
  {
538
    const char *query;
308 by Brian Aker
ulong conversion
539
    uint32_t query_length;
520.1.22 by Brian Aker
Second pass of thd cleanup
540
    if (!session->query)
1 by brian
clean slate
541
    {
542
      /* The client used the old obsolete mysql_drop_db() call */
543
      query= path;
673.2.1 by Toru Maesaka
First pass of replacing MySQL's strxmov with libc alternatives
544
      query_length= sprintf(path, "drop database `%s`", db);
1 by brian
clean slate
545
    }
546
    else
547
    {
673.2.1 by Toru Maesaka
First pass of replacing MySQL's strxmov with libc alternatives
548
      query= session->query;
520.1.22 by Brian Aker
Second pass of thd cleanup
549
      query_length= session->query_length;
1 by brian
clean slate
550
    }
798.2.19 by Brian Aker
Converted db.cc away from using binlog
551
    (void)replicator_statement(session, session->query, session->query_length);
520.1.22 by Brian Aker
Second pass of thd cleanup
552
    session->clear_error();
553
    session->server_status|= SERVER_STATUS_DB_DROPPED;
836 by Brian Aker
Fixed session call from function to method.
554
    session->my_ok((uint32_t) deleted);
520.1.22 by Brian Aker
Second pass of thd cleanup
555
    session->server_status&= ~SERVER_STATUS_DB_DROPPED;
1 by brian
clean slate
556
  }
798.2.19 by Brian Aker
Converted db.cc away from using binlog
557
  else
1 by brian
clean slate
558
  {
559
    char *query, *query_pos, *query_end, *query_data_start;
327.2.4 by Brian Aker
Refactoring table.h
560
    TableList *tbl;
482 by Brian Aker
Remove uint.
561
    uint32_t db_len;
1 by brian
clean slate
562
520.1.22 by Brian Aker
Second pass of thd cleanup
563
    if (!(query= (char*) session->alloc(MAX_DROP_TABLE_Q_LEN)))
1 by brian
clean slate
564
      goto exit; /* not much else we can do */
641.4.1 by Toru Maesaka
First pass of replacing MySQL's my_stpcpy() with appropriate libc calls
565
    query_pos= query_data_start= strcpy(query,"drop table ")+11;
1 by brian
clean slate
566
    query_end= query + MAX_DROP_TABLE_Q_LEN;
567
    db_len= strlen(db);
568
569
    for (tbl= dropped_tables; tbl; tbl= tbl->next_local)
570
    {
482 by Brian Aker
Remove uint.
571
      uint32_t tbl_name_len;
1 by brian
clean slate
572
573
      /* 3 for the quotes and the comma*/
574
      tbl_name_len= strlen(tbl->table_name) + 3;
575
      if (query_pos + tbl_name_len + 1 >= query_end)
576
      {
840.1.21 by Monty Taylor
ZOMG. Renamed all the rest of the stuff in libdrizzleclient to be drizzleclient_*. I love commandline perl.
577
        /* These DDL methods and logging protected with LOCK_drizzleclient_create_db */
520.1.22 by Brian Aker
Second pass of thd cleanup
578
        write_to_binlog(session, query, query_pos -1 - query, db, db_len);
1 by brian
clean slate
579
        query_pos= query_data_start;
580
      }
581
582
      *query_pos++ = '`';
641.4.1 by Toru Maesaka
First pass of replacing MySQL's my_stpcpy() with appropriate libc calls
583
      query_pos= strcpy(query_pos,tbl->table_name) + (tbl_name_len-3);
1 by brian
clean slate
584
      *query_pos++ = '`';
585
      *query_pos++ = ',';
586
    }
587
588
    if (query_pos != query_data_start)
589
    {
840.1.21 by Monty Taylor
ZOMG. Renamed all the rest of the stuff in libdrizzleclient to be drizzleclient_*. I love commandline perl.
590
      /* These DDL methods and logging protected with LOCK_drizzleclient_create_db */
520.1.22 by Brian Aker
Second pass of thd cleanup
591
      write_to_binlog(session, query, query_pos -1 - query, db, db_len);
1 by brian
clean slate
592
    }
593
  }
594
595
exit:
596
  /*
597
    If this database was the client's selected database, we silently
598
    change the client's selected database to nothing (to have an empty
520.1.22 by Brian Aker
Second pass of thd cleanup
599
    SELECT DATABASE() in the future). For this we free() session->db and set
1 by brian
clean slate
600
    it to 0.
601
  */
520.1.22 by Brian Aker
Second pass of thd cleanup
602
  if (session->db && !strcmp(session->db, db))
603
    mysql_change_db_impl(session, NULL, session->variables.collation_server);
840.1.21 by Monty Taylor
ZOMG. Renamed all the rest of the stuff in libdrizzleclient to be drizzleclient_*. I love commandline perl.
604
  pthread_mutex_unlock(&LOCK_drizzleclient_create_db);
520.1.22 by Brian Aker
Second pass of thd cleanup
605
  start_waiting_global_read_lock(session);
1 by brian
clean slate
606
exit2:
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
607
  return(error);
1 by brian
clean slate
608
}
609
610
/*
255 by Brian Aker
Removed RAID table delete point.
611
  Removes files with known extensions plus.
520.1.22 by Brian Aker
Second pass of thd cleanup
612
  session MUST be set when calling this function!
1 by brian
clean slate
613
*/
614
520.1.22 by Brian Aker
Second pass of thd cleanup
615
static long mysql_rm_known_files(Session *session, MY_DIR *dirp, const char *db,
482 by Brian Aker
Remove uint.
616
				 const char *org_path, uint32_t level,
327.2.4 by Brian Aker
Refactoring table.h
617
                                 TableList **dropped_tables)
1 by brian
clean slate
618
{
619
  long deleted=0;
308 by Brian Aker
ulong conversion
620
  uint32_t found_other_files=0;
1 by brian
clean slate
621
  char filePath[FN_REFLEN];
327.2.4 by Brian Aker
Refactoring table.h
622
  TableList *tot_list=0, **tot_list_next;
1 by brian
clean slate
623
624
  tot_list_next= &tot_list;
625
482 by Brian Aker
Remove uint.
626
  for (uint32_t idx=0 ;
895 by Brian Aker
Completion (?) of uint conversion.
627
       idx < (uint32_t) dirp->number_off_files && !session->killed ;
1 by brian
clean slate
628
       idx++)
629
  {
630
    FILEINFO *file=dirp->dir_entry+idx;
631
    char *extension;
632
633
    /* skiping . and .. */
634
    if (file->name[0] == '.' && (!file->name[1] ||
635
       (file->name[1] == '.' &&  !file->name[2])))
636
      continue;
637
638
    if (!(extension= strrchr(file->name, '.')))
376 by Brian Aker
strend remove
639
      extension= strchr(file->name, '\0');
1 by brian
clean slate
640
    if (find_type(extension, &deletable_extentions,1+2) <= 0)
641
    {
584.2.7 by Stewart Smith
rename and delete tabledefinition protobuf file
642
      /*
643
        ass ass ass.
644
645
        strange checking for magic extensions that are then deleted if
646
        not reg_ext (i.e. .frm).
647
648
        and (previously) we'd err out on drop database if files not matching
649
        engine ha_known_exts() or deletable_extensions were present.
650
651
        presumably this was to avoid deleting other user data... except if that
652
        data happened to be in files ending in .BAK, .opt or .TMD. *fun*
653
       */
654
      find_type(extension, ha_known_exts(),1+2);
1 by brian
clean slate
655
      continue;
656
    }
657
    /* just for safety we use files_charset_info */
658
    if (db && !my_strcasecmp(files_charset_info,
659
                             extension, reg_ext))
660
    {
641.4.1 by Toru Maesaka
First pass of replacing MySQL's my_stpcpy() with appropriate libc calls
661
      uint32_t db_len= strlen(db);
662
1 by brian
clean slate
663
      /* Drop the table nicely */
664
      *extension= 0;			// Remove extension
327.2.4 by Brian Aker
Refactoring table.h
665
      TableList *table_list=(TableList*)
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
666
                              session->calloc(sizeof(*table_list) +
641.4.1 by Toru Maesaka
First pass of replacing MySQL's my_stpcpy() with appropriate libc calls
667
                                          db_len + 1 +
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
668
                                          MYSQL50_TABLE_NAME_PREFIX_LENGTH +
1 by brian
clean slate
669
                                          strlen(file->name) + 1);
670
671
      if (!table_list)
672
        goto err;
673
      table_list->db= (char*) (table_list+1);
641.4.1 by Toru Maesaka
First pass of replacing MySQL's my_stpcpy() with appropriate libc calls
674
      table_list->table_name= strcpy(table_list->db, db) + db_len + 1;
398.1.10 by Monty Taylor
Actually removed VOID() this time.
675
      filename_to_tablename(file->name, table_list->table_name,
676
                            MYSQL50_TABLE_NAME_PREFIX_LENGTH +
677
                            strlen(file->name) + 1);
1 by brian
clean slate
678
      table_list->alias= table_list->table_name;	// If lower_case_table_names=2
584.2.1 by Stewart Smith
convert tmp_file_prefix to TMP_FILE_PREFIX to indicate it's a macro
679
      table_list->internal_tmp_table= is_prefix(file->name, TMP_FILE_PREFIX);
1 by brian
clean slate
680
      /* Link into list */
681
      (*tot_list_next)= table_list;
682
      tot_list_next= &table_list->next_local;
683
      deleted++;
684
    }
685
    else
686
    {
673.2.1 by Toru Maesaka
First pass of replacing MySQL's strxmov with libc alternatives
687
      sprintf(filePath, "%s/%s", org_path, file->name);
1 by brian
clean slate
688
      if (my_delete_with_symlink(filePath,MYF(MY_WME)))
689
      {
690
	goto err;
691
      }
692
    }
693
  }
520.1.22 by Brian Aker
Second pass of thd cleanup
694
  if (session->killed ||
590.1.7 by Stewart Smith
remove mysql_frm_type
695
      (tot_list && mysql_rm_table_part2(session, tot_list, 1, 0, 1)))
1 by brian
clean slate
696
    goto err;
697
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
698
  my_dirend(dirp);
699
1 by brian
clean slate
700
  if (dropped_tables)
701
    *dropped_tables= tot_list;
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
702
1 by brian
clean slate
703
  /*
704
    If the directory is a symbolic link, remove the link first, then
705
    remove the directory the symbolic link pointed at
706
  */
707
  if (found_other_files)
708
  {
709
    my_error(ER_DB_DROP_RMDIR, MYF(0), org_path, EEXIST);
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
710
    return(-1);
1 by brian
clean slate
711
  }
712
  else
713
  {
714
    /* Don't give errors if we can't delete 'RAID' directory */
715
    if (rm_dir_w_symlink(org_path, level == 0))
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
716
      return(-1);
1 by brian
clean slate
717
  }
718
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
719
  return(deleted);
1 by brian
clean slate
720
721
err:
722
  my_dirend(dirp);
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
723
  return(-1);
1 by brian
clean slate
724
}
725
726
727
/*
728
  Remove directory with symlink
729
730
  SYNOPSIS
731
    rm_dir_w_symlink()
732
    org_path    path of derictory
733
    send_error  send errors
734
  RETURN
735
    0 OK
736
    1 ERROR
737
*/
738
253 by Brian Aker
Removed final my_bool from sql_db.
739
static bool rm_dir_w_symlink(const char *org_path, bool send_error)
1 by brian
clean slate
740
{
741
  char tmp_path[FN_REFLEN], *pos;
742
  char *path= tmp_path;
743
  unpack_filename(tmp_path, org_path);
744
#ifdef HAVE_READLINK
745
  int error;
746
  char tmp2_path[FN_REFLEN];
747
748
  /* Remove end FN_LIBCHAR as this causes problem on Linux in readlink */
376 by Brian Aker
strend remove
749
  pos= strchr(path, '\0');
1 by brian
clean slate
750
  if (pos > path && pos[-1] == FN_LIBCHAR)
751
    *--pos=0;
752
753
  if ((error= my_readlink(tmp2_path, path, MYF(MY_WME))) < 0)
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
754
    return(1);
1 by brian
clean slate
755
  if (!error)
756
  {
757
    if (my_delete(path, MYF(send_error ? MY_WME : 0)))
758
    {
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
759
      return(send_error);
1 by brian
clean slate
760
    }
761
    /* Delete directory symbolic link pointed at */
762
    path= tmp2_path;
763
  }
764
#endif
765
  /* Remove last FN_LIBCHAR to not cause a problem on OS/2 */
376 by Brian Aker
strend remove
766
  pos= strchr(path, '\0');
1 by brian
clean slate
767
768
  if (pos > path && pos[-1] == FN_LIBCHAR)
769
    *--pos=0;
770
  if (rmdir(path) < 0 && send_error)
771
  {
772
    my_error(ER_DB_DROP_RMDIR, MYF(0), path, errno);
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
773
    return(1);
1 by brian
clean slate
774
  }
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
775
  return(0);
1 by brian
clean slate
776
}
777
778
779
/**
780
  @brief Internal implementation: switch current database to a valid one.
781
520.1.22 by Brian Aker
Second pass of thd cleanup
782
  @param session            Thread context.
1 by brian
clean slate
783
  @param new_db_name    Name of the database to switch to. The function will
784
                        take ownership of the name (the caller must not free
785
                        the allocated memory). If the name is NULL, we're
786
                        going to switch to NULL db.
787
  @param new_db_charset Character set of the new database.
788
*/
789
520.1.22 by Brian Aker
Second pass of thd cleanup
790
static void mysql_change_db_impl(Session *session,
1 by brian
clean slate
791
                                 LEX_STRING *new_db_name,
264.2.6 by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code.
792
                                 const CHARSET_INFO * const new_db_charset)
1 by brian
clean slate
793
{
520.1.21 by Brian Aker
THD -> Session rename
794
  /* 1. Change current database in Session. */
1 by brian
clean slate
795
796
  if (new_db_name == NULL)
797
  {
798
    /*
520.1.21 by Brian Aker
THD -> Session rename
799
      Session::set_db() does all the job -- it frees previous database name and
1 by brian
clean slate
800
      sets the new one.
801
    */
802
520.1.22 by Brian Aker
Second pass of thd cleanup
803
    session->set_db(NULL, 0);
1 by brian
clean slate
804
  }
575.4.7 by Monty Taylor
More header cleanup.
805
  else if (my_strcasecmp(system_charset_info, new_db_name->str,
806
                         INFORMATION_SCHEMA_NAME.c_str()) == 0)
1 by brian
clean slate
807
  {
808
    /*
520.1.21 by Brian Aker
THD -> Session rename
809
      Here we must use Session::set_db(), because we want to copy
1 by brian
clean slate
810
      INFORMATION_SCHEMA_NAME constant.
811
    */
812
575.4.7 by Monty Taylor
More header cleanup.
813
    session->set_db(INFORMATION_SCHEMA_NAME.c_str(),
814
                    INFORMATION_SCHEMA_NAME.length());
1 by brian
clean slate
815
  }
816
  else
817
  {
818
    /*
520.1.21 by Brian Aker
THD -> Session rename
819
      Here we already have a copy of database name to be used in Session. So,
820
      we just call Session::reset_db(). Since Session::reset_db() does not releases
1 by brian
clean slate
821
      the previous database name, we should do it explicitly.
822
    */
823
520.1.22 by Brian Aker
Second pass of thd cleanup
824
    if (session->db)
825
      free(session->db);
1 by brian
clean slate
826
520.1.22 by Brian Aker
Second pass of thd cleanup
827
    session->reset_db(new_db_name->str, new_db_name->length);
1 by brian
clean slate
828
  }
829
830
  /* 3. Update db-charset environment variables. */
831
520.1.22 by Brian Aker
Second pass of thd cleanup
832
  session->db_charset= new_db_charset;
833
  session->variables.collation_database= new_db_charset;
1 by brian
clean slate
834
}
835
836
837
838
/**
839
  Backup the current database name before switch.
840
520.1.22 by Brian Aker
Second pass of thd cleanup
841
  @param[in]      session             thread handle
1 by brian
clean slate
842
  @param[in, out] saved_db_name   IN: "str" points to a buffer where to store
843
                                  the old database name, "length" contains the
844
                                  buffer size
845
                                  OUT: if the current (default) database is
846
                                  not NULL, its name is copied to the
847
                                  buffer pointed at by "str"
848
                                  and "length" is updated accordingly.
849
                                  Otherwise "str" is set to NULL and
850
                                  "length" is set to 0.
851
*/
852
520.1.22 by Brian Aker
Second pass of thd cleanup
853
static void backup_current_db_name(Session *session,
1 by brian
clean slate
854
                                   LEX_STRING *saved_db_name)
855
{
520.1.22 by Brian Aker
Second pass of thd cleanup
856
  if (!session->db)
1 by brian
clean slate
857
  {
858
    /* No current (default) database selected. */
859
860
    saved_db_name->str= NULL;
861
    saved_db_name->length= 0;
862
  }
863
  else
864
  {
629.5.2 by Toru Maesaka
Second pass of replacing MySQL's strmake() with libc calls
865
    strncpy(saved_db_name->str, session->db, saved_db_name->length - 1);
520.1.22 by Brian Aker
Second pass of thd cleanup
866
    saved_db_name->length= session->db_length;
1 by brian
clean slate
867
  }
868
}
869
870
871
/**
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
872
  Return true if db1_name is equal to db2_name, false otherwise.
1 by brian
clean slate
873
874
  The function allows to compare database names according to the MySQL
875
  rules. The database names db1 and db2 are equal if:
876
     - db1 is NULL and db2 is NULL;
877
     or
878
     - db1 is not-NULL, db2 is not-NULL, db1 is equal (ignoring case) to
879
       db2 in system character set (UTF8).
880
*/
881
882
static inline bool
883
cmp_db_names(const char *db1_name,
884
             const char *db2_name)
885
{
886
  return
887
         /* db1 is NULL and db2 is NULL */
888
         (!db1_name && !db2_name) ||
889
890
         /* db1 is not-NULL, db2 is not-NULL, db1 == db2. */
891
         (db1_name && db2_name && my_strcasecmp(system_charset_info, db1_name, db2_name) == 0);
892
}
893
894
895
/**
896
  @brief Change the current database and its attributes unconditionally.
897
520.1.22 by Brian Aker
Second pass of thd cleanup
898
  @param session          thread handle
1 by brian
clean slate
899
  @param new_db_name  database name
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
900
  @param force_switch if force_switch is false, then the operation will fail if
1 by brian
clean slate
901
902
                        - new_db_name is NULL or empty;
903
904
                        - OR new database name is invalid
905
                          (check_db_name() failed);
906
907
                        - OR user has no privilege on the new database;
908
909
                        - OR new database does not exist;
910
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
911
                      if force_switch is true, then
1 by brian
clean slate
912
913
                        - if new_db_name is NULL or empty, the current
914
                          database will be NULL, @@collation_database will
915
                          be set to @@collation_server, the operation will
916
                          succeed.
917
918
                        - if new database name is invalid
919
                          (check_db_name() failed), the current database
920
                          will be NULL, @@collation_database will be set to
921
                          @@collation_server, but the operation will fail;
922
923
                        - user privileges will not be checked
520.1.21 by Brian Aker
THD -> Session rename
924
                          (Session::db_access however is updated);
1 by brian
clean slate
925
926
                          TODO: is this really the intention?
927
                                (see sp-security.test).
928
929
                        - if new database does not exist,the current database
930
                          will be NULL, @@collation_database will be set to
931
                          @@collation_server, a warning will be thrown, the
932
                          operation will succeed.
933
934
  @details The function checks that the database name corresponds to a
935
  valid and existent database, checks access rights and changes the current
936
  database with database attributes (@@collation_database session variable,
520.1.21 by Brian Aker
THD -> Session rename
937
  Session::db_access).
1 by brian
clean slate
938
939
  This function is not the only way to switch the database that is
940
  currently employed. When the replication slave thread switches the
520.1.22 by Brian Aker
Second pass of thd cleanup
941
  database before executing a query, it calls session->set_db directly.
1 by brian
clean slate
942
  However, if the query, in turn, uses a stored routine, the stored routine
943
  will use this function, even if it's run on the slave.
944
945
  This function allocates the name of the database on the system heap: this
946
  is necessary to be able to uniformly change the database from any module
947
  of the server. Up to 5.0 different modules were using different memory to
948
  store the name of the database, and this led to memory corruption:
949
  a stack pointer set by Stored Procedures was used by replication after
950
  the stack address was long gone.
951
952
  @return Operation status
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
953
    @retval false Success
954
    @retval true  Error
1 by brian
clean slate
955
*/
956
520.1.22 by Brian Aker
Second pass of thd cleanup
957
bool mysql_change_db(Session *session, const LEX_STRING *new_db_name, bool force_switch)
1 by brian
clean slate
958
{
959
  LEX_STRING new_db_file_name;
264.2.6 by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code.
960
  const CHARSET_INFO *db_default_cl;
1 by brian
clean slate
961
962
  if (new_db_name == NULL ||
963
      new_db_name->length == 0)
964
  {
965
    if (force_switch)
966
    {
967
      /*
968
        This can happen only if we're switching the current database back
969
        after loading stored program. The thing is that loading of stored
970
        program can happen when there is no current database.
971
972
        TODO: actually, new_db_name and new_db_name->str seem to be always
973
        non-NULL. In case of stored program, new_db_name->str == "" and
974
        new_db_name->length == 0.
975
      */
976
520.1.22 by Brian Aker
Second pass of thd cleanup
977
      mysql_change_db_impl(session, NULL, session->variables.collation_server);
1 by brian
clean slate
978
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
979
      return(false);
1 by brian
clean slate
980
    }
981
    else
982
    {
983
      my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
984
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
985
      return(true);
1 by brian
clean slate
986
    }
987
  }
988
989
  if (my_strcasecmp(system_charset_info, new_db_name->str,
575.4.7 by Monty Taylor
More header cleanup.
990
                    INFORMATION_SCHEMA_NAME.c_str()) == 0)
1 by brian
clean slate
991
  {
992
    /* Switch the current database to INFORMATION_SCHEMA. */
575.4.7 by Monty Taylor
More header cleanup.
993
    /* const_cast<> is safe here: mysql_change_db_impl does a copy */
994
    LEX_STRING is_name= { const_cast<char *>(INFORMATION_SCHEMA_NAME.c_str()),
995
                          INFORMATION_SCHEMA_NAME.length() };
996
    mysql_change_db_impl(session, &is_name, system_charset_info);
1 by brian
clean slate
997
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
998
    return(false);
1 by brian
clean slate
999
  }
1000
1001
  /*
1002
    Now we need to make a copy because check_db_name requires a
1003
    non-constant argument. Actually, it takes database file name.
1004
1005
    TODO: fix check_db_name().
1006
  */
1007
656.1.34 by Monty Taylor
Got closer...
1008
  new_db_file_name.length= new_db_name->length;
1009
  new_db_file_name.str= (char *)malloc(new_db_name->length + 1);
656.1.44 by Monty Taylor
Added some return checking.
1010
  if (new_db_file_name.str == NULL)
1011
    return(true);                             /* the error is set */
656.1.34 by Monty Taylor
Got closer...
1012
  memcpy(new_db_file_name.str, new_db_name->str, new_db_name->length);
1013
  new_db_file_name.str[new_db_name->length]= 0;
1014
1 by brian
clean slate
1015
1016
  /*
1017
    NOTE: if check_db_name() fails, we should throw an error in any case,
1018
    even if we are called from sp_head::execute().
1019
1020
    It's next to impossible however to get this error when we are called
1021
    from sp_head::execute(). But let's switch the current database to NULL
1022
    in this case to be sure.
1023
  */
1024
1025
  if (check_db_name(&new_db_file_name))
1026
  {
1027
    my_error(ER_WRONG_DB_NAME, MYF(0), new_db_file_name.str);
477 by Monty Taylor
Removed my_free(). It turns out that it had been def'd to ignore the flags passed to it in the second arg anyway. Gotta love that.
1028
    free(new_db_file_name.str);
1 by brian
clean slate
1029
1030
    if (force_switch)
520.1.22 by Brian Aker
Second pass of thd cleanup
1031
      mysql_change_db_impl(session, NULL, session->variables.collation_server);
1 by brian
clean slate
1032
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
1033
    return(true);
1 by brian
clean slate
1034
  }
1035
1036
  if (check_db_dir_existence(new_db_file_name.str))
1037
  {
1038
    if (force_switch)
1039
    {
1040
      /* Throw a warning and free new_db_file_name. */
1041
520.1.22 by Brian Aker
Second pass of thd cleanup
1042
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1 by brian
clean slate
1043
                          ER_BAD_DB_ERROR, ER(ER_BAD_DB_ERROR),
1044
                          new_db_file_name.str);
1045
477 by Monty Taylor
Removed my_free(). It turns out that it had been def'd to ignore the flags passed to it in the second arg anyway. Gotta love that.
1046
      free(new_db_file_name.str);
1 by brian
clean slate
1047
1048
      /* Change db to NULL. */
1049
520.1.22 by Brian Aker
Second pass of thd cleanup
1050
      mysql_change_db_impl(session, NULL, session->variables.collation_server);
1 by brian
clean slate
1051
1052
      /* The operation succeed. */
1053
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
1054
      return(false);
1 by brian
clean slate
1055
    }
1056
    else
1057
    {
1058
      /* Report an error and free new_db_file_name. */
1059
1060
      my_error(ER_BAD_DB_ERROR, MYF(0), new_db_file_name.str);
477 by Monty Taylor
Removed my_free(). It turns out that it had been def'd to ignore the flags passed to it in the second arg anyway. Gotta love that.
1061
      free(new_db_file_name.str);
1 by brian
clean slate
1062
1063
      /* The operation failed. */
1064
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
1065
      return(true);
1 by brian
clean slate
1066
    }
1067
  }
1068
1069
  /*
520.1.21 by Brian Aker
THD -> Session rename
1070
    NOTE: in mysql_change_db_impl() new_db_file_name is assigned to Session
1071
    attributes and will be freed in Session::~Session().
1 by brian
clean slate
1072
  */
1073
520.1.22 by Brian Aker
Second pass of thd cleanup
1074
  db_default_cl= get_default_db_collation(session, new_db_file_name.str);
1 by brian
clean slate
1075
520.1.22 by Brian Aker
Second pass of thd cleanup
1076
  mysql_change_db_impl(session, &new_db_file_name, db_default_cl);
1 by brian
clean slate
1077
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
1078
  return(false);
1 by brian
clean slate
1079
}
1080
1081
1082
/**
1083
  Change the current database and its attributes if needed.
1084
520.1.22 by Brian Aker
Second pass of thd cleanup
1085
  @param          session             thread handle
1 by brian
clean slate
1086
  @param          new_db_name     database name
1087
  @param[in, out] saved_db_name   IN: "str" points to a buffer where to store
1088
                                  the old database name, "length" contains the
1089
                                  buffer size
1090
                                  OUT: if the current (default) database is
1091
                                  not NULL, its name is copied to the
1092
                                  buffer pointed at by "str"
1093
                                  and "length" is updated accordingly.
1094
                                  Otherwise "str" is set to NULL and
1095
                                  "length" is set to 0.
1096
  @param          force_switch    @see mysql_change_db()
1097
  @param[out]     cur_db_changed  out-flag to indicate whether the current
1098
                                  database has been changed (valid only if
1099
                                  the function suceeded)
1100
*/
1101
520.1.22 by Brian Aker
Second pass of thd cleanup
1102
bool mysql_opt_change_db(Session *session,
1 by brian
clean slate
1103
                         const LEX_STRING *new_db_name,
1104
                         LEX_STRING *saved_db_name,
1105
                         bool force_switch,
1106
                         bool *cur_db_changed)
1107
{
520.1.22 by Brian Aker
Second pass of thd cleanup
1108
  *cur_db_changed= !cmp_db_names(session->db, new_db_name->str);
1 by brian
clean slate
1109
1110
  if (!*cur_db_changed)
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
1111
    return false;
1 by brian
clean slate
1112
520.1.22 by Brian Aker
Second pass of thd cleanup
1113
  backup_current_db_name(session, saved_db_name);
1 by brian
clean slate
1114
520.1.22 by Brian Aker
Second pass of thd cleanup
1115
  return mysql_change_db(session, new_db_name, force_switch);
1 by brian
clean slate
1116
}
1117
1118
1119
/*
1120
  Check if there is directory for the database name.
1121
1122
  SYNOPSIS
1123
    check_db_dir_existence()
1124
    db_name   database name
1125
1126
  RETURN VALUES
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
1127
    false   There is directory for the specified database name.
1128
    true    The directory does not exist.
1 by brian
clean slate
1129
*/
1130
1131
bool check_db_dir_existence(const char *db_name)
1132
{
1133
  char db_dir_path[FN_REFLEN];
482 by Brian Aker
Remove uint.
1134
  uint32_t db_dir_path_len;
1 by brian
clean slate
1135
1136
  db_dir_path_len= build_table_filename(db_dir_path, sizeof(db_dir_path),
1137
                                        db_name, "", "", 0);
1138
1139
  if (db_dir_path_len && db_dir_path[db_dir_path_len - 1] == FN_LIBCHAR)
1140
    db_dir_path[db_dir_path_len - 1]= 0;
1141
1142
  /* Check access. */
1143
1144
  return my_access(db_dir_path, F_OK);
1145
}