~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
896.4.9 by Stewart Smith
No longer write the FRM. just use proto.
41
const char *del_exts[]= {".dfe", ".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.
971.3.2 by Eric Day
Renamed LOCK_drizzleclient_create_db to LOCK_create_db since this has nothing to do with drizzleclient. I think Monty accidently got this during the drizzleclient rename.
312
    Wait for global read lock before acquiring LOCK_create_db.
1 by brian
clean slate
313
    After wait_if_global_read_lock() we have protection against another
971.3.2 by Eric Day
Renamed LOCK_drizzleclient_create_db to LOCK_create_db since this has nothing to do with drizzleclient. I think Monty accidently got this during the drizzleclient rename.
314
    global read lock. If we would acquire LOCK_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
971.3.2 by Eric Day
Renamed LOCK_drizzleclient_create_db to LOCK_create_db since this has nothing to do with drizzleclient. I think Monty accidently got this during the drizzleclient rename.
317
    (admin a db), it would then go and wait on LOCK_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
971.3.2 by Eric Day
Renamed LOCK_drizzleclient_create_db to LOCK_create_db since this has nothing to do with drizzleclient. I think Monty accidently got this during the drizzleclient rename.
328
  pthread_mutex_lock(&LOCK_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:
971.3.2 by Eric Day
Renamed LOCK_drizzleclient_create_db to LOCK_create_db since this has nothing to do with drizzleclient. I think Monty accidently got this during the drizzleclient rename.
388
  pthread_mutex_unlock(&LOCK_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.
971.3.2 by Eric Day
Renamed LOCK_drizzleclient_create_db to LOCK_create_db since this has nothing to do with drizzleclient. I think Monty accidently got this during the drizzleclient rename.
406
    Wait for global read lock before acquiring LOCK_create_db.
1 by brian
clean slate
407
    After wait_if_global_read_lock() we have protection against another
971.3.2 by Eric Day
Renamed LOCK_drizzleclient_create_db to LOCK_create_db since this has nothing to do with drizzleclient. I think Monty accidently got this during the drizzleclient rename.
408
    global read lock. If we would acquire LOCK_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
971.3.2 by Eric Day
Renamed LOCK_drizzleclient_create_db to LOCK_create_db since this has nothing to do with drizzleclient. I think Monty accidently got this during the drizzleclient rename.
411
    (admin a db), it would then go and wait on LOCK_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
971.3.2 by Eric Day
Renamed LOCK_drizzleclient_create_db to LOCK_create_db since this has nothing to do with drizzleclient. I think Monty accidently got this during the drizzleclient rename.
419
  pthread_mutex_lock(&LOCK_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 */
971.3.2 by Eric Day
Renamed LOCK_drizzleclient_create_db to LOCK_create_db since this has nothing to do with drizzleclient. I think Monty accidently got this during the drizzleclient rename.
429
    pthread_mutex_unlock(&LOCK_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
971.3.2 by Eric Day
Renamed LOCK_drizzleclient_create_db to LOCK_create_db since this has nothing to do with drizzleclient. I think Monty accidently got this during the drizzleclient rename.
444
  pthread_mutex_unlock(&LOCK_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.
971.3.2 by Eric Day
Renamed LOCK_drizzleclient_create_db to LOCK_create_db since this has nothing to do with drizzleclient. I think Monty accidently got this during the drizzleclient rename.
485
    Wait for global read lock before acquiring LOCK_create_db.
1 by brian
clean slate
486
    After wait_if_global_read_lock() we have protection against another
971.3.2 by Eric Day
Renamed LOCK_drizzleclient_create_db to LOCK_create_db since this has nothing to do with drizzleclient. I think Monty accidently got this during the drizzleclient rename.
487
    global read lock. If we would acquire LOCK_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
971.3.2 by Eric Day
Renamed LOCK_drizzleclient_create_db to LOCK_create_db since this has nothing to do with drizzleclient. I think Monty accidently got this during the drizzleclient rename.
490
    (admin a db), it would then go and wait on LOCK_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
971.3.2 by Eric Day
Renamed LOCK_drizzleclient_create_db to LOCK_create_db since this has nothing to do with drizzleclient. I think Monty accidently got this during the drizzleclient rename.
501
  pthread_mutex_lock(&LOCK_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
      {
971.3.2 by Eric Day
Renamed LOCK_drizzleclient_create_db to LOCK_create_db since this has nothing to do with drizzleclient. I think Monty accidently got this during the drizzleclient rename.
577
        /* These DDL methods and logging protected with LOCK_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
    {
971.3.2 by Eric Day
Renamed LOCK_drizzleclient_create_db to LOCK_create_db since this has nothing to do with drizzleclient. I think Monty accidently got this during the drizzleclient rename.
590
      /* These DDL methods and logging protected with LOCK_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);
971.3.2 by Eric Day
Renamed LOCK_drizzleclient_create_db to LOCK_create_db since this has nothing to do with drizzleclient. I think Monty accidently got this during the drizzleclient rename.
604
  pthread_mutex_unlock(&LOCK_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,
896.4.9 by Stewart Smith
No longer write the FRM. just use proto.
659
                             extension, ".dfe"))
1 by brian
clean slate
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 +
1 by brian
clean slate
668
                                          strlen(file->name) + 1);
669
670
      if (!table_list)
671
        goto err;
672
      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
673
      table_list->table_name= strcpy(table_list->db, db) + db_len + 1;
398.1.10 by Monty Taylor
Actually removed VOID() this time.
674
      filename_to_tablename(file->name, table_list->table_name,
675
                            strlen(file->name) + 1);
1 by brian
clean slate
676
      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
677
      table_list->internal_tmp_table= is_prefix(file->name, TMP_FILE_PREFIX);
1 by brian
clean slate
678
      /* Link into list */
679
      (*tot_list_next)= table_list;
680
      tot_list_next= &table_list->next_local;
681
      deleted++;
682
    }
683
    else
684
    {
673.2.1 by Toru Maesaka
First pass of replacing MySQL's strxmov with libc alternatives
685
      sprintf(filePath, "%s/%s", org_path, file->name);
1 by brian
clean slate
686
      if (my_delete_with_symlink(filePath,MYF(MY_WME)))
687
      {
688
	goto err;
689
      }
690
    }
691
  }
520.1.22 by Brian Aker
Second pass of thd cleanup
692
  if (session->killed ||
590.1.7 by Stewart Smith
remove mysql_frm_type
693
      (tot_list && mysql_rm_table_part2(session, tot_list, 1, 0, 1)))
1 by brian
clean slate
694
    goto err;
695
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
696
  my_dirend(dirp);
697
1 by brian
clean slate
698
  if (dropped_tables)
699
    *dropped_tables= tot_list;
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
700
1 by brian
clean slate
701
  /*
702
    If the directory is a symbolic link, remove the link first, then
703
    remove the directory the symbolic link pointed at
704
  */
705
  if (found_other_files)
706
  {
707
    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
708
    return(-1);
1 by brian
clean slate
709
  }
710
  else
711
  {
712
    /* Don't give errors if we can't delete 'RAID' directory */
713
    if (rm_dir_w_symlink(org_path, level == 0))
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
714
      return(-1);
1 by brian
clean slate
715
  }
716
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
717
  return(deleted);
1 by brian
clean slate
718
719
err:
720
  my_dirend(dirp);
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
721
  return(-1);
1 by brian
clean slate
722
}
723
724
725
/*
726
  Remove directory with symlink
727
728
  SYNOPSIS
729
    rm_dir_w_symlink()
730
    org_path    path of derictory
731
    send_error  send errors
732
  RETURN
733
    0 OK
734
    1 ERROR
735
*/
736
253 by Brian Aker
Removed final my_bool from sql_db.
737
static bool rm_dir_w_symlink(const char *org_path, bool send_error)
1 by brian
clean slate
738
{
739
  char tmp_path[FN_REFLEN], *pos;
740
  char *path= tmp_path;
741
  unpack_filename(tmp_path, org_path);
742
#ifdef HAVE_READLINK
743
  int error;
744
  char tmp2_path[FN_REFLEN];
745
746
  /* Remove end FN_LIBCHAR as this causes problem on Linux in readlink */
376 by Brian Aker
strend remove
747
  pos= strchr(path, '\0');
1 by brian
clean slate
748
  if (pos > path && pos[-1] == FN_LIBCHAR)
749
    *--pos=0;
750
751
  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
752
    return(1);
1 by brian
clean slate
753
  if (!error)
754
  {
755
    if (my_delete(path, MYF(send_error ? MY_WME : 0)))
756
    {
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
757
      return(send_error);
1 by brian
clean slate
758
    }
759
    /* Delete directory symbolic link pointed at */
760
    path= tmp2_path;
761
  }
762
#endif
763
  /* Remove last FN_LIBCHAR to not cause a problem on OS/2 */
376 by Brian Aker
strend remove
764
  pos= strchr(path, '\0');
1 by brian
clean slate
765
766
  if (pos > path && pos[-1] == FN_LIBCHAR)
767
    *--pos=0;
768
  if (rmdir(path) < 0 && send_error)
769
  {
770
    my_error(ER_DB_DROP_RMDIR, MYF(0), path, errno);
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
771
    return(1);
1 by brian
clean slate
772
  }
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
773
  return(0);
1 by brian
clean slate
774
}
775
776
777
/**
778
  @brief Internal implementation: switch current database to a valid one.
779
520.1.22 by Brian Aker
Second pass of thd cleanup
780
  @param session            Thread context.
1 by brian
clean slate
781
  @param new_db_name    Name of the database to switch to. The function will
782
                        take ownership of the name (the caller must not free
783
                        the allocated memory). If the name is NULL, we're
784
                        going to switch to NULL db.
785
  @param new_db_charset Character set of the new database.
786
*/
787
520.1.22 by Brian Aker
Second pass of thd cleanup
788
static void mysql_change_db_impl(Session *session,
1 by brian
clean slate
789
                                 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.
790
                                 const CHARSET_INFO * const new_db_charset)
1 by brian
clean slate
791
{
520.1.21 by Brian Aker
THD -> Session rename
792
  /* 1. Change current database in Session. */
1 by brian
clean slate
793
794
  if (new_db_name == NULL)
795
  {
796
    /*
520.1.21 by Brian Aker
THD -> Session rename
797
      Session::set_db() does all the job -- it frees previous database name and
1 by brian
clean slate
798
      sets the new one.
799
    */
800
520.1.22 by Brian Aker
Second pass of thd cleanup
801
    session->set_db(NULL, 0);
1 by brian
clean slate
802
  }
575.4.7 by Monty Taylor
More header cleanup.
803
  else if (my_strcasecmp(system_charset_info, new_db_name->str,
804
                         INFORMATION_SCHEMA_NAME.c_str()) == 0)
1 by brian
clean slate
805
  {
806
    /*
520.1.21 by Brian Aker
THD -> Session rename
807
      Here we must use Session::set_db(), because we want to copy
1 by brian
clean slate
808
      INFORMATION_SCHEMA_NAME constant.
809
    */
810
575.4.7 by Monty Taylor
More header cleanup.
811
    session->set_db(INFORMATION_SCHEMA_NAME.c_str(),
812
                    INFORMATION_SCHEMA_NAME.length());
1 by brian
clean slate
813
  }
814
  else
815
  {
816
    /*
520.1.21 by Brian Aker
THD -> Session rename
817
      Here we already have a copy of database name to be used in Session. So,
818
      we just call Session::reset_db(). Since Session::reset_db() does not releases
1 by brian
clean slate
819
      the previous database name, we should do it explicitly.
820
    */
821
520.1.22 by Brian Aker
Second pass of thd cleanup
822
    if (session->db)
823
      free(session->db);
1 by brian
clean slate
824
520.1.22 by Brian Aker
Second pass of thd cleanup
825
    session->reset_db(new_db_name->str, new_db_name->length);
1 by brian
clean slate
826
  }
827
828
  /* 3. Update db-charset environment variables. */
829
520.1.22 by Brian Aker
Second pass of thd cleanup
830
  session->db_charset= new_db_charset;
831
  session->variables.collation_database= new_db_charset;
1 by brian
clean slate
832
}
833
834
835
836
/**
837
  Backup the current database name before switch.
838
520.1.22 by Brian Aker
Second pass of thd cleanup
839
  @param[in]      session             thread handle
1 by brian
clean slate
840
  @param[in, out] saved_db_name   IN: "str" points to a buffer where to store
841
                                  the old database name, "length" contains the
842
                                  buffer size
843
                                  OUT: if the current (default) database is
844
                                  not NULL, its name is copied to the
845
                                  buffer pointed at by "str"
846
                                  and "length" is updated accordingly.
847
                                  Otherwise "str" is set to NULL and
848
                                  "length" is set to 0.
849
*/
850
520.1.22 by Brian Aker
Second pass of thd cleanup
851
static void backup_current_db_name(Session *session,
1 by brian
clean slate
852
                                   LEX_STRING *saved_db_name)
853
{
520.1.22 by Brian Aker
Second pass of thd cleanup
854
  if (!session->db)
1 by brian
clean slate
855
  {
856
    /* No current (default) database selected. */
857
858
    saved_db_name->str= NULL;
859
    saved_db_name->length= 0;
860
  }
861
  else
862
  {
629.5.2 by Toru Maesaka
Second pass of replacing MySQL's strmake() with libc calls
863
    strncpy(saved_db_name->str, session->db, saved_db_name->length - 1);
520.1.22 by Brian Aker
Second pass of thd cleanup
864
    saved_db_name->length= session->db_length;
1 by brian
clean slate
865
  }
866
}
867
868
869
/**
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
870
  Return true if db1_name is equal to db2_name, false otherwise.
1 by brian
clean slate
871
872
  The function allows to compare database names according to the MySQL
873
  rules. The database names db1 and db2 are equal if:
874
     - db1 is NULL and db2 is NULL;
875
     or
876
     - db1 is not-NULL, db2 is not-NULL, db1 is equal (ignoring case) to
877
       db2 in system character set (UTF8).
878
*/
879
880
static inline bool
881
cmp_db_names(const char *db1_name,
882
             const char *db2_name)
883
{
884
  return
885
         /* db1 is NULL and db2 is NULL */
886
         (!db1_name && !db2_name) ||
887
888
         /* db1 is not-NULL, db2 is not-NULL, db1 == db2. */
889
         (db1_name && db2_name && my_strcasecmp(system_charset_info, db1_name, db2_name) == 0);
890
}
891
892
893
/**
894
  @brief Change the current database and its attributes unconditionally.
895
520.1.22 by Brian Aker
Second pass of thd cleanup
896
  @param session          thread handle
1 by brian
clean slate
897
  @param new_db_name  database name
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
898
  @param force_switch if force_switch is false, then the operation will fail if
1 by brian
clean slate
899
900
                        - new_db_name is NULL or empty;
901
902
                        - OR new database name is invalid
903
                          (check_db_name() failed);
904
905
                        - OR user has no privilege on the new database;
906
907
                        - OR new database does not exist;
908
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
909
                      if force_switch is true, then
1 by brian
clean slate
910
911
                        - if new_db_name is NULL or empty, the current
912
                          database will be NULL, @@collation_database will
913
                          be set to @@collation_server, the operation will
914
                          succeed.
915
916
                        - if new database name is invalid
917
                          (check_db_name() failed), the current database
918
                          will be NULL, @@collation_database will be set to
919
                          @@collation_server, but the operation will fail;
920
921
                        - user privileges will not be checked
520.1.21 by Brian Aker
THD -> Session rename
922
                          (Session::db_access however is updated);
1 by brian
clean slate
923
924
                          TODO: is this really the intention?
925
                                (see sp-security.test).
926
927
                        - if new database does not exist,the current database
928
                          will be NULL, @@collation_database will be set to
929
                          @@collation_server, a warning will be thrown, the
930
                          operation will succeed.
931
932
  @details The function checks that the database name corresponds to a
933
  valid and existent database, checks access rights and changes the current
934
  database with database attributes (@@collation_database session variable,
520.1.21 by Brian Aker
THD -> Session rename
935
  Session::db_access).
1 by brian
clean slate
936
937
  This function is not the only way to switch the database that is
938
  currently employed. When the replication slave thread switches the
520.1.22 by Brian Aker
Second pass of thd cleanup
939
  database before executing a query, it calls session->set_db directly.
1 by brian
clean slate
940
  However, if the query, in turn, uses a stored routine, the stored routine
941
  will use this function, even if it's run on the slave.
942
943
  This function allocates the name of the database on the system heap: this
944
  is necessary to be able to uniformly change the database from any module
945
  of the server. Up to 5.0 different modules were using different memory to
946
  store the name of the database, and this led to memory corruption:
947
  a stack pointer set by Stored Procedures was used by replication after
948
  the stack address was long gone.
949
950
  @return Operation status
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
951
    @retval false Success
952
    @retval true  Error
1 by brian
clean slate
953
*/
954
520.1.22 by Brian Aker
Second pass of thd cleanup
955
bool mysql_change_db(Session *session, const LEX_STRING *new_db_name, bool force_switch)
1 by brian
clean slate
956
{
957
  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.
958
  const CHARSET_INFO *db_default_cl;
1 by brian
clean slate
959
960
  if (new_db_name == NULL ||
961
      new_db_name->length == 0)
962
  {
963
    if (force_switch)
964
    {
965
      /*
966
        This can happen only if we're switching the current database back
967
        after loading stored program. The thing is that loading of stored
968
        program can happen when there is no current database.
969
970
        TODO: actually, new_db_name and new_db_name->str seem to be always
971
        non-NULL. In case of stored program, new_db_name->str == "" and
972
        new_db_name->length == 0.
973
      */
974
520.1.22 by Brian Aker
Second pass of thd cleanup
975
      mysql_change_db_impl(session, NULL, session->variables.collation_server);
1 by brian
clean slate
976
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
977
      return(false);
1 by brian
clean slate
978
    }
979
    else
980
    {
981
      my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
982
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
983
      return(true);
1 by brian
clean slate
984
    }
985
  }
986
987
  if (my_strcasecmp(system_charset_info, new_db_name->str,
575.4.7 by Monty Taylor
More header cleanup.
988
                    INFORMATION_SCHEMA_NAME.c_str()) == 0)
1 by brian
clean slate
989
  {
990
    /* Switch the current database to INFORMATION_SCHEMA. */
575.4.7 by Monty Taylor
More header cleanup.
991
    /* const_cast<> is safe here: mysql_change_db_impl does a copy */
992
    LEX_STRING is_name= { const_cast<char *>(INFORMATION_SCHEMA_NAME.c_str()),
993
                          INFORMATION_SCHEMA_NAME.length() };
994
    mysql_change_db_impl(session, &is_name, system_charset_info);
1 by brian
clean slate
995
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
996
    return(false);
1 by brian
clean slate
997
  }
998
999
  /*
1000
    Now we need to make a copy because check_db_name requires a
1001
    non-constant argument. Actually, it takes database file name.
1002
1003
    TODO: fix check_db_name().
1004
  */
1005
656.1.34 by Monty Taylor
Got closer...
1006
  new_db_file_name.length= new_db_name->length;
1007
  new_db_file_name.str= (char *)malloc(new_db_name->length + 1);
656.1.44 by Monty Taylor
Added some return checking.
1008
  if (new_db_file_name.str == NULL)
1009
    return(true);                             /* the error is set */
656.1.34 by Monty Taylor
Got closer...
1010
  memcpy(new_db_file_name.str, new_db_name->str, new_db_name->length);
1011
  new_db_file_name.str[new_db_name->length]= 0;
1012
1 by brian
clean slate
1013
1014
  /*
1015
    NOTE: if check_db_name() fails, we should throw an error in any case,
1016
    even if we are called from sp_head::execute().
1017
1018
    It's next to impossible however to get this error when we are called
1019
    from sp_head::execute(). But let's switch the current database to NULL
1020
    in this case to be sure.
1021
  */
1022
1023
  if (check_db_name(&new_db_file_name))
1024
  {
1025
    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.
1026
    free(new_db_file_name.str);
1 by brian
clean slate
1027
1028
    if (force_switch)
520.1.22 by Brian Aker
Second pass of thd cleanup
1029
      mysql_change_db_impl(session, NULL, session->variables.collation_server);
1 by brian
clean slate
1030
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
1031
    return(true);
1 by brian
clean slate
1032
  }
1033
1034
  if (check_db_dir_existence(new_db_file_name.str))
1035
  {
1036
    if (force_switch)
1037
    {
1038
      /* Throw a warning and free new_db_file_name. */
1039
520.1.22 by Brian Aker
Second pass of thd cleanup
1040
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1 by brian
clean slate
1041
                          ER_BAD_DB_ERROR, ER(ER_BAD_DB_ERROR),
1042
                          new_db_file_name.str);
1043
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.
1044
      free(new_db_file_name.str);
1 by brian
clean slate
1045
1046
      /* Change db to NULL. */
1047
520.1.22 by Brian Aker
Second pass of thd cleanup
1048
      mysql_change_db_impl(session, NULL, session->variables.collation_server);
1 by brian
clean slate
1049
1050
      /* The operation succeed. */
1051
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
1052
      return(false);
1 by brian
clean slate
1053
    }
1054
    else
1055
    {
1056
      /* Report an error and free new_db_file_name. */
1057
1058
      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.
1059
      free(new_db_file_name.str);
1 by brian
clean slate
1060
1061
      /* The operation failed. */
1062
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
1063
      return(true);
1 by brian
clean slate
1064
    }
1065
  }
1066
1067
  /*
520.1.21 by Brian Aker
THD -> Session rename
1068
    NOTE: in mysql_change_db_impl() new_db_file_name is assigned to Session
1069
    attributes and will be freed in Session::~Session().
1 by brian
clean slate
1070
  */
1071
520.1.22 by Brian Aker
Second pass of thd cleanup
1072
  db_default_cl= get_default_db_collation(session, new_db_file_name.str);
1 by brian
clean slate
1073
520.1.22 by Brian Aker
Second pass of thd cleanup
1074
  mysql_change_db_impl(session, &new_db_file_name, db_default_cl);
1 by brian
clean slate
1075
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
1076
  return(false);
1 by brian
clean slate
1077
}
1078
1079
1080
/**
1081
  Change the current database and its attributes if needed.
1082
520.1.22 by Brian Aker
Second pass of thd cleanup
1083
  @param          session             thread handle
1 by brian
clean slate
1084
  @param          new_db_name     database name
1085
  @param[in, out] saved_db_name   IN: "str" points to a buffer where to store
1086
                                  the old database name, "length" contains the
1087
                                  buffer size
1088
                                  OUT: if the current (default) database is
1089
                                  not NULL, its name is copied to the
1090
                                  buffer pointed at by "str"
1091
                                  and "length" is updated accordingly.
1092
                                  Otherwise "str" is set to NULL and
1093
                                  "length" is set to 0.
1094
  @param          force_switch    @see mysql_change_db()
1095
  @param[out]     cur_db_changed  out-flag to indicate whether the current
1096
                                  database has been changed (valid only if
1097
                                  the function suceeded)
1098
*/
1099
520.1.22 by Brian Aker
Second pass of thd cleanup
1100
bool mysql_opt_change_db(Session *session,
1 by brian
clean slate
1101
                         const LEX_STRING *new_db_name,
1102
                         LEX_STRING *saved_db_name,
1103
                         bool force_switch,
1104
                         bool *cur_db_changed)
1105
{
520.1.22 by Brian Aker
Second pass of thd cleanup
1106
  *cur_db_changed= !cmp_db_names(session->db, new_db_name->str);
1 by brian
clean slate
1107
1108
  if (!*cur_db_changed)
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
1109
    return false;
1 by brian
clean slate
1110
520.1.22 by Brian Aker
Second pass of thd cleanup
1111
  backup_current_db_name(session, saved_db_name);
1 by brian
clean slate
1112
520.1.22 by Brian Aker
Second pass of thd cleanup
1113
  return mysql_change_db(session, new_db_name, force_switch);
1 by brian
clean slate
1114
}
1115
1116
1117
/*
1118
  Check if there is directory for the database name.
1119
1120
  SYNOPSIS
1121
    check_db_dir_existence()
1122
    db_name   database name
1123
1124
  RETURN VALUES
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
1125
    false   There is directory for the specified database name.
1126
    true    The directory does not exist.
1 by brian
clean slate
1127
*/
1128
1129
bool check_db_dir_existence(const char *db_name)
1130
{
1131
  char db_dir_path[FN_REFLEN];
482 by Brian Aker
Remove uint.
1132
  uint32_t db_dir_path_len;
1 by brian
clean slate
1133
1134
  db_dir_path_len= build_table_filename(db_dir_path, sizeof(db_dir_path),
1135
                                        db_name, "", "", 0);
1136
1137
  if (db_dir_path_len && db_dir_path[db_dir_path_len - 1] == FN_LIBCHAR)
1138
    db_dir_path[db_dir_path_len - 1]= 0;
1139
1140
  /* Check access. */
1141
1142
  return my_access(db_dir_path, F_OK);
1143
}