~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_db.cc

  • Committer: Stewart Smith
  • Date: 2008-09-15 07:13:59 UTC
  • mfrom: (383.1.21 drizzle)
  • mto: This revision was merged to the branch mainline in revision 408.
  • Revision ID: stewart@flamingspork.com-20080915071359-f8bznznyaiqrtqxa
merged

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
 
16
16
 
17
17
/* create and drop of databases */
18
 
 
19
 
#include "mysql_priv.h"
 
18
#include <string>
 
19
#include <fstream>
 
20
#include <drizzled/serialize/serialize.h>
 
21
using namespace std;
 
22
#include <drizzled/server_includes.h>
20
23
#include <mysys/mysys_err.h>
21
24
#include <mysys/my_dir.h>
22
25
#include "log.h"
 
26
#include <drizzled/drizzled_error_messages.h>
 
27
#include <libdrizzle/gettext.h>
 
28
 
23
29
 
24
30
#define MAX_DROP_TABLE_Q_LEN      1024
25
31
 
29
35
 
30
36
static long mysql_rm_known_files(THD *thd, MY_DIR *dirp,
31
37
                                 const char *db, const char *path, uint level, 
32
 
                                 TABLE_LIST **dropped_tables);
 
38
                                 TableList **dropped_tables);
33
39
         
34
40
static bool rm_dir_w_symlink(const char *org_path, bool send_error);
35
41
static void mysql_change_db_impl(THD *thd,
36
42
                                 LEX_STRING *new_db_name,
37
 
                                 CHARSET_INFO *new_db_charset);
 
43
                                 const CHARSET_INFO * const new_db_charset);
38
44
 
39
45
 
40
46
/* Database lock hash */
101
107
{
102
108
  char *name;                   /* Database name                  */
103
109
  uint name_length;             /* Database length name           */
104
 
  CHARSET_INFO *charset;        /* Database default character set */
 
110
  const CHARSET_INFO *charset;  /* Database default character set */
105
111
} my_dbopt_t;
106
112
 
107
113
 
280
286
    }
281
287
    
282
288
    opt->name= tmp_name;
283
 
    strmov(opt->name, dbname);
 
289
    stpcpy(opt->name, dbname);
284
290
    opt->name_length= length;
285
291
    
286
292
    if ((error= my_hash_insert(&dboptions, (uchar*) opt)))
325
331
  1     Could not create file or write to it.  Error sent through my_error()
326
332
*/
327
333
 
328
 
static bool write_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create)
 
334
static bool write_db_opt(THD *thd, const char *path, const char *name, HA_CREATE_INFO *create)
329
335
{
330
 
  register File file;
331
 
  char buf[256]; // Should be enough for one option
332
336
  bool error= true;
 
337
  drizzle::Schema db;
 
338
 
 
339
  assert(name);
333
340
 
334
341
  if (!create->default_table_charset)
335
342
    create->default_table_charset= thd->variables.collation_server;
337
344
  if (put_dbopt(path, create))
338
345
    return 1;
339
346
 
340
 
  if ((file=my_create(path, CREATE_MODE,O_RDWR | O_TRUNC,MYF(MY_WME))) >= 0)
341
 
  {
342
 
    ulong length;
343
 
    length= (ulong) (strxnmov(buf, sizeof(buf)-1, "default-character-set=",
344
 
                              create->default_table_charset->csname,
345
 
                              "\ndefault-collation=",
346
 
                              create->default_table_charset->name,
347
 
                              "\n", NullS) - buf);
348
 
 
349
 
    /* Error is written by my_write */
350
 
    if (!my_write(file,(uchar*) buf, length, MYF(MY_NABP+MY_WME)))
351
 
      error= false;
352
 
    my_close(file,MYF(0));
353
 
  }
 
347
  db.set_name(name);
 
348
  db.set_characterset(create->default_table_charset->csname);
 
349
  db.set_collation(create->default_table_charset->name);
 
350
 
 
351
  fstream output(path, ios::out | ios::trunc | ios::binary);
 
352
  if (!db.SerializeToOstream(&output)) 
 
353
    error= false;
 
354
 
354
355
  return error;
355
356
}
356
357
 
372
373
 
373
374
bool load_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create)
374
375
{
375
 
  File file;
376
 
  char buf[256];
377
376
  bool error=1;
378
 
  uint nbytes;
 
377
  drizzle::Schema db;
 
378
  string buffer;
379
379
 
380
 
  memset((char*) create, 0, sizeof(*create));
 
380
  memset(create, 0, sizeof(*create));
381
381
  create->default_table_charset= thd->variables.collation_server;
382
382
 
383
383
  /* Check if options for this database are already in the hash */
384
384
  if (!get_dbopt(path, create))
385
385
    return(0);
386
386
 
387
 
  /* Otherwise, load options from the .opt file */
388
 
  if ((file=my_open(path, O_RDONLY | O_SHARE, MYF(0))) < 0)
389
 
    goto err1;
390
 
 
391
 
  IO_CACHE cache;
392
 
  if (init_io_cache(&cache, file, IO_SIZE, READ_CACHE, 0, 0, MYF(0)))
393
 
    goto err2;
394
 
 
395
 
  while ((int) (nbytes= my_b_gets(&cache, (char*) buf, sizeof(buf))) > 0)
396
 
  {
397
 
    char *pos= buf+nbytes-1;
398
 
    /* Remove end space and control characters */
399
 
    while (pos > buf && !my_isgraph(&my_charset_latin1, pos[-1]))
400
 
      pos--;
401
 
    *pos=0;
402
 
    if ((pos= strchr(buf, '=')))
403
 
    {
404
 
      if (!strncmp(buf,"default-character-set", (pos-buf)))
405
 
      {
406
 
        /*
407
 
           Try character set name, and if it fails
408
 
           try collation name, probably it's an old
409
 
           4.1.0 db.opt file, which didn't have
410
 
           separate default-character-set and
411
 
           default-collation commands.
412
 
        */
413
 
        if (!(create->default_table_charset=
414
 
        get_charset_by_csname(pos+1, MY_CS_PRIMARY, MYF(0))) &&
415
 
            !(create->default_table_charset=
416
 
              get_charset_by_name(pos+1, MYF(0))))
417
 
        {
418
 
          sql_print_error("Error while loading database options: '%s':",path);
419
 
          sql_print_error(ER(ER_UNKNOWN_CHARACTER_SET),pos+1);
420
 
          create->default_table_charset= default_charset_info;
421
 
        }
422
 
      }
423
 
      else if (!strncmp(buf,"default-collation", (pos-buf)))
424
 
      {
425
 
        if (!(create->default_table_charset= get_charset_by_name(pos+1,
426
 
                                                           MYF(0))))
427
 
        {
428
 
          sql_print_error("Error while loading database options: '%s':",path);
429
 
          sql_print_error(ER(ER_UNKNOWN_COLLATION),pos+1);
430
 
          create->default_table_charset= default_charset_info;
431
 
        }
432
 
      }
433
 
    }
434
 
  }
 
387
  fstream input(path, ios::in | ios::binary);
 
388
  if (!input)
 
389
    goto err1;
 
390
  else if (!db.ParseFromIstream(&input))
 
391
    goto err1;
 
392
 
 
393
  buffer= db.characterset();
 
394
  if (!(create->default_table_charset= get_charset_by_csname(buffer.c_str(), MY_CS_PRIMARY, MYF(0))))
 
395
  {
 
396
    sql_print_error(_("Error while loading database options: '%s':"),path);
 
397
    sql_print_error(ER(ER_UNKNOWN_COLLATION), buffer.c_str());
 
398
    create->default_table_charset= default_charset_info;
 
399
  }
 
400
 
 
401
  buffer= db.collation();
 
402
  if (!(create->default_table_charset= get_charset_by_name(buffer.c_str(), MYF(0))))
 
403
  {
 
404
    sql_print_error(_("Error while loading database options: '%s':"),path);
 
405
    sql_print_error(ER(ER_UNKNOWN_COLLATION), buffer.c_str());
 
406
    create->default_table_charset= default_charset_info;
 
407
  }
 
408
 
435
409
  /*
436
410
    Put the loaded value into the hash.
437
411
    Note that another thread could've added the same
441
415
  */
442
416
  error= put_dbopt(path, create);
443
417
 
444
 
  end_io_cache(&cache);
445
 
err2:
446
 
  my_close(file,MYF(0));
447
418
err1:
448
419
  return(error);
449
420
}
505
476
    set, even if the database does not exist.
506
477
*/
507
478
 
508
 
CHARSET_INFO *get_default_db_collation(THD *thd, const char *db_name)
 
479
const CHARSET_INFO *get_default_db_collation(THD *thd, const char *db_name)
509
480
{
510
481
  HA_CREATE_INFO db_info;
511
482
 
599
570
      error= -1;
600
571
      goto exit;
601
572
    }
602
 
    push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
 
573
    push_warning_printf(thd, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
603
574
                        ER_DB_CREATE_EXISTS, ER(ER_DB_CREATE_EXISTS), db);
604
575
    if (!silent)
605
576
      my_ok(thd);
623
594
 
624
595
  path[path_len-1]= FN_LIBCHAR;
625
596
  strmake(path+path_len, MY_DB_OPT_FILE, sizeof(path)-path_len-1);
626
 
  if (write_db_opt(thd, path, create_info))
 
597
  if (write_db_opt(thd, path, db, create_info))
627
598
  {
628
599
    /*
629
600
      Could not create options file.
733
704
     "table name to file name" encoding.
734
705
  */
735
706
  build_table_filename(path, sizeof(path), db, "", MY_DB_OPT_FILE, 0);
736
 
  if ((error=write_db_opt(thd, path, create_info)))
 
707
  if ((error=write_db_opt(thd, path, db, create_info)))
737
708
    goto exit;
738
709
 
739
710
  /* Change options if current database is being altered. */
801
772
  char  path[FN_REFLEN+16];
802
773
  MY_DIR *dirp;
803
774
  uint length;
804
 
  TABLE_LIST* dropped_tables= 0;
 
775
  TableList* dropped_tables= 0;
805
776
 
806
777
  if (db && (strcmp(db, "information_schema") == 0))
807
778
  {
837
808
  thd->clear_current_stmt_binlog_row_based();
838
809
 
839
810
  length= build_table_filename(path, sizeof(path), db, "", "", 0);
840
 
  strmov(path+length, MY_DB_OPT_FILE);          // Append db option file name
 
811
  stpcpy(path+length, MY_DB_OPT_FILE);          // Append db option file name
841
812
  del_dbopt(path);                              // Remove dboption hash entry
842
813
  path[length]= '\0';                           // Remove file name
843
814
 
851
822
      goto exit;
852
823
    }
853
824
    else
854
 
      push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
 
825
      push_warning_printf(thd, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
855
826
                          ER_DB_DROP_EXISTS, ER(ER_DB_DROP_EXISTS), db);
856
827
  }
857
828
  else
872
843
  if (!silent && deleted>=0)
873
844
  {
874
845
    const char *query;
875
 
    ulong query_length;
 
846
    uint32_t query_length;
876
847
    if (!thd->query)
877
848
    {
878
849
      /* The client used the old obsolete mysql_drop_db() call */
903
874
    }
904
875
    thd->clear_error();
905
876
    thd->server_status|= SERVER_STATUS_DB_DROPPED;
906
 
    my_ok(thd, (ulong) deleted);
 
877
    my_ok(thd, (uint32_t) deleted);
907
878
    thd->server_status&= ~SERVER_STATUS_DB_DROPPED;
908
879
  }
909
880
  else if (mysql_bin_log.is_open())
910
881
  {
911
882
    char *query, *query_pos, *query_end, *query_data_start;
912
 
    TABLE_LIST *tbl;
 
883
    TableList *tbl;
913
884
    uint db_len;
914
885
 
915
886
    if (!(query= (char*) thd->alloc(MAX_DROP_TABLE_Q_LEN)))
916
887
      goto exit; /* not much else we can do */
917
 
    query_pos= query_data_start= strmov(query,"drop table ");
 
888
    query_pos= query_data_start= stpcpy(query,"drop table ");
918
889
    query_end= query + MAX_DROP_TABLE_Q_LEN;
919
890
    db_len= strlen(db);
920
891
 
932
903
      }
933
904
 
934
905
      *query_pos++ = '`';
935
 
      query_pos= strmov(query_pos,tbl->table_name);
 
906
      query_pos= stpcpy(query_pos,tbl->table_name);
936
907
      *query_pos++ = '`';
937
908
      *query_pos++ = ',';
938
909
    }
966
937
 
967
938
static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db,
968
939
                                 const char *org_path, uint level,
969
 
                                 TABLE_LIST **dropped_tables)
 
940
                                 TableList **dropped_tables)
970
941
{
971
942
  long deleted=0;
972
 
  ulong found_other_files=0;
 
943
  uint32_t found_other_files=0;
973
944
  char filePath[FN_REFLEN];
974
 
  TABLE_LIST *tot_list=0, **tot_list_next;
 
945
  TableList *tot_list=0, **tot_list_next;
975
946
 
976
947
  tot_list_next= &tot_list;
977
948
 
988
959
      continue;
989
960
 
990
961
    if (!(extension= strrchr(file->name, '.')))
991
 
      extension= strend(file->name);
 
962
      extension= strchr(file->name, '\0');
992
963
    if (find_type(extension, &deletable_extentions,1+2) <= 0)
993
964
    {
994
965
      if (find_type(extension, ha_known_exts(),1+2) <= 0)
1001
972
    {
1002
973
      /* Drop the table nicely */
1003
974
      *extension= 0;                    // Remove extension
1004
 
      TABLE_LIST *table_list=(TABLE_LIST*)
 
975
      TableList *table_list=(TableList*)
1005
976
                              thd->calloc(sizeof(*table_list) + 
1006
977
                                          strlen(db) + 1 +
1007
978
                                          MYSQL50_TABLE_NAME_PREFIX_LENGTH + 
1010
981
      if (!table_list)
1011
982
        goto err;
1012
983
      table_list->db= (char*) (table_list+1);
1013
 
      table_list->table_name= strmov(table_list->db, db) + 1;
 
984
      table_list->table_name= stpcpy(table_list->db, db) + 1;
1014
985
      VOID(filename_to_tablename(file->name, table_list->table_name,
1015
986
                                 MYSQL50_TABLE_NAME_PREFIX_LENGTH +
1016
987
                                 strlen(file->name) + 1));
1085
1056
  char tmp2_path[FN_REFLEN];
1086
1057
 
1087
1058
  /* Remove end FN_LIBCHAR as this causes problem on Linux in readlink */
1088
 
  pos= strend(path);
 
1059
  pos= strchr(path, '\0');
1089
1060
  if (pos > path && pos[-1] == FN_LIBCHAR)
1090
1061
    *--pos=0;
1091
1062
 
1102
1073
  }
1103
1074
#endif
1104
1075
  /* Remove last FN_LIBCHAR to not cause a problem on OS/2 */
1105
 
  pos= strend(path);
 
1076
  pos= strchr(path, '\0');
1106
1077
 
1107
1078
  if (pos > path && pos[-1] == FN_LIBCHAR)
1108
1079
    *--pos=0;
1128
1099
 
1129
1100
static void mysql_change_db_impl(THD *thd,
1130
1101
                                 LEX_STRING *new_db_name,
1131
 
                                 CHARSET_INFO *new_db_charset)
 
1102
                                 const CHARSET_INFO * const new_db_charset)
1132
1103
{
1133
1104
  /* 1. Change current database in THD. */
1134
1105
 
1293
1264
bool mysql_change_db(THD *thd, const LEX_STRING *new_db_name, bool force_switch)
1294
1265
{
1295
1266
  LEX_STRING new_db_file_name;
1296
 
  CHARSET_INFO *db_default_cl;
 
1267
  const CHARSET_INFO *db_default_cl;
1297
1268
 
1298
1269
  if (new_db_name == NULL ||
1299
1270
      new_db_name->length == 0)
1372
1343
    {
1373
1344
      /* Throw a warning and free new_db_file_name. */
1374
1345
 
1375
 
      push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
 
1346
      push_warning_printf(thd, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1376
1347
                          ER_BAD_DB_ERROR, ER(ER_BAD_DB_ERROR),
1377
1348
                          new_db_file_name.str);
1378
1349