~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/db.cc

  • Committer: Brian Aker
  • Date: 2010-01-22 00:53:13 UTC
  • Revision ID: brian@gaz-20100122005313-jmizcbcdi1lt4tcx
Revert db patch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
59
59
static long mysql_rm_known_files(Session *session, CachedDirectory &dirp,
60
60
                                 const string &db, const char *path,
61
61
                                 TableList **dropped_tables);
 
62
static void mysql_change_db_impl(Session *session, LEX_STRING *new_db_name);
62
63
 
63
64
/**
64
65
  Return default database collation.
100
101
}
101
102
 
102
103
/* path is path to database, not schema file */
103
 
static int write_schema_file(const DatabasePathName &path, const message::Schema &db)
 
104
static int write_schema_file(const char *path, const message::Schema &db)
104
105
{
105
106
  char schema_file_tmp[FN_REFLEN];
106
 
  string schema_file(path.to_string());
 
107
  string schema_file(path);
107
108
 
108
 
  snprintf(schema_file_tmp, FN_REFLEN, "%s%c%s.tmpXXXXXX", path.to_string().c_str(), FN_LIBCHAR, MY_DB_OPT_FILE);
 
109
  snprintf(schema_file_tmp, FN_REFLEN, "%s%c%s.tmpXXXXXX", path, FN_LIBCHAR, MY_DB_OPT_FILE);
109
110
 
110
111
  schema_file.append(1, FN_LIBCHAR);
111
112
  schema_file.append(MY_DB_OPT_FILE);
182
183
 
183
184
*/
184
185
 
185
 
bool mysql_create_db(Session *session, const NormalisedDatabaseName &database_name, message::Schema *schema_message, bool is_if_not_exists)
 
186
bool mysql_create_db(Session *session, const char *db, drizzled::message::Schema *schema_message, bool is_if_not_exists)
186
187
{
187
188
  ReplicationServices &replication_services= ReplicationServices::singleton();
188
189
  long result= 1;
189
190
  int error_erno;
190
191
  bool error= false;
191
 
  DatabasePathName database_path(database_name);
192
192
 
193
193
  /* do not create 'information_schema' db */
194
 
  if (!my_strcasecmp(system_charset_info, database_name.to_string().c_str(), INFORMATION_SCHEMA_NAME.c_str()))
 
194
  if (!my_strcasecmp(system_charset_info, db, INFORMATION_SCHEMA_NAME.c_str()))
195
195
  {
196
 
    my_error(ER_DB_CREATE_EXISTS, MYF(0), database_name.to_string().c_str());
 
196
    my_error(ER_DB_CREATE_EXISTS, MYF(0), db);
197
197
    return(-1);
198
198
  }
199
199
 
200
 
  assert(database_name.isValid());
201
 
  schema_message->set_name(database_name.to_string());
 
200
  schema_message->set_name(db);
202
201
 
203
202
  /*
204
203
    Do not create database if another thread is holding read lock.
220
219
 
221
220
  pthread_mutex_lock(&LOCK_create_db);
222
221
 
223
 
  if (mkdir(database_path.to_string().c_str(),0777) == -1)
 
222
  /* check directory */
 
223
  char   path[FN_REFLEN+16];
 
224
  uint32_t path_len;
 
225
  path_len= build_table_filename(path, sizeof(path), db, "", false);
 
226
  path[path_len-1]= 0;                    // remove last '/' from path
 
227
 
 
228
  if (mkdir(path, 0777) == -1)
224
229
  {
225
230
    if (errno == EEXIST)
226
231
    {
227
232
      if (! is_if_not_exists)
228
233
      {
229
 
        my_error(ER_DB_CREATE_EXISTS, MYF(0), database_name.to_string().c_str());
 
234
        my_error(ER_DB_CREATE_EXISTS, MYF(0), path);
230
235
        error= true;
231
236
        goto exit;
232
237
      }
233
238
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
234
239
                          ER_DB_CREATE_EXISTS, ER(ER_DB_CREATE_EXISTS),
235
 
                          database_name.to_string().c_str());
 
240
                          path);
236
241
      session->my_ok();
237
242
      error= false;
238
243
      goto exit;
239
244
    }
240
245
 
241
 
    my_error(ER_CANT_CREATE_DB, MYF(0), database_name.to_string().c_str(), errno);
 
246
    my_error(ER_CANT_CREATE_DB, MYF(0), path, errno);
242
247
    error= true;
243
248
    goto exit;
244
249
  }
245
250
 
246
 
  error_erno= write_schema_file(database_path, *schema_message);
 
251
  error_erno= write_schema_file(path, *schema_message);
247
252
  if (error_erno && error_erno != EEXIST)
248
253
  {
249
 
    if (rmdir(database_path.to_string().c_str()) >= 0)
 
254
    if (rmdir(path) >= 0)
250
255
    {
251
256
      error= true;
252
257
      goto exit;
268
273
 
269
274
/* db-name is already validated when we come here */
270
275
 
271
 
bool mysql_alter_db(Session *session, const NormalisedDatabaseName &database_name, message::Schema *schema_message)
 
276
bool mysql_alter_db(Session *session, const char *db, message::Schema *schema_message)
272
277
{
273
278
  ReplicationServices &replication_services= ReplicationServices::singleton();
274
279
  long result=1;
275
280
  int error= 0;
276
 
  DatabasePathName database_path(database_name);
 
281
  char   path[FN_REFLEN+16];
 
282
  uint32_t path_len;
277
283
 
278
284
  /*
279
285
    Do not alter database if another thread is holding read lock.
291
297
    goto exit;
292
298
 
293
299
  assert(schema_message);
294
 
  assert(database_name.isValid());
295
300
 
296
 
  schema_message->set_name(database_name.to_string());
 
301
  schema_message->set_name(db);
297
302
 
298
303
  pthread_mutex_lock(&LOCK_create_db);
299
304
 
300
 
  error= write_schema_file(database_path, *schema_message);
 
305
  /* Change options if current database is being altered. */
 
306
  path_len= build_table_filename(path, sizeof(path), db, "", false);
 
307
  path[path_len-1]= 0;                    // Remove last '/' from path
 
308
 
 
309
  error= write_schema_file(path, *schema_message);
301
310
  if (error && error != EEXIST)
302
311
  {
303
312
    /* TODO: find some witty way of getting back an error message */
332
341
    ERROR Error
333
342
*/
334
343
 
335
 
bool mysql_rm_db(Session *session, const NormalisedDatabaseName &database_name, bool if_exists)
 
344
bool mysql_rm_db(Session *session, char *db, bool if_exists)
336
345
{
337
346
  long deleted=0;
338
347
  int error= false;
340
349
  uint32_t length;
341
350
  TableList *dropped_tables= NULL;
342
351
 
343
 
  if (database_name.to_string().compare(INFORMATION_SCHEMA_NAME) == 0)
 
352
  if (db && (strcmp(db, "information_schema") == 0))
344
353
  {
345
354
    my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), "", "", INFORMATION_SCHEMA_NAME.c_str());
346
355
    return true;
347
356
  }
348
357
 
 
358
 
349
359
  /*
350
360
    Do not drop database if another thread is holding read lock.
351
361
    Wait for global read lock before acquiring LOCK_create_db.
366
376
  pthread_mutex_lock(&LOCK_create_db);
367
377
 
368
378
  length= build_table_filename(path, sizeof(path),
369
 
                               database_name.to_string().c_str(), "", false);
 
379
                               db, "", false);
370
380
  strcpy(path+length, MY_DB_OPT_FILE);         // Append db option file name
371
381
  unlink(path);
372
382
  path[length]= '\0';                           // Remove file name
378
388
    if (!if_exists)
379
389
    {
380
390
      error= -1;
381
 
      my_error(ER_DB_DROP_EXISTS, MYF(0), database_name.to_string().c_str());
 
391
      my_error(ER_DB_DROP_EXISTS, MYF(0), path);
382
392
      goto exit;
383
393
    }
384
394
    else
385
395
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
386
396
                          ER_DB_DROP_EXISTS, ER(ER_DB_DROP_EXISTS),
387
 
                          database_name.to_string().c_str());
 
397
                          path);
388
398
  }
389
399
  else
390
400
  {
391
401
    pthread_mutex_lock(&LOCK_open); /* After deleting database, remove all cache entries related to schema */
392
 
    remove_db_from_cache(database_name.to_string().c_str());
 
402
    remove_db_from_cache(db);
393
403
    pthread_mutex_unlock(&LOCK_open);
394
404
 
395
405
 
396
406
    error= -1;
397
 
    deleted= mysql_rm_known_files(session, dirp,
398
 
                                  database_name.to_string(),
 
407
    deleted= mysql_rm_known_files(session, dirp, db,
399
408
                                  path, &dropped_tables);
400
409
    if (deleted >= 0)
401
410
    {
430
439
      goto exit; /* not much else we can do */
431
440
    query_pos= query_data_start= strcpy(query,"drop table ")+11;
432
441
    query_end= query + MAX_DROP_TABLE_Q_LEN;
433
 
    db_len= database_name.to_string().length();
 
442
    db_len= strlen(db);
434
443
 
435
444
    ReplicationServices &replication_services= ReplicationServices::singleton();
436
445
    for (tbl= dropped_tables; tbl; tbl= tbl->next_local)
466
475
    SELECT DATABASE() in the future). For this we free() session->db and set
467
476
    it to 0.
468
477
  */
469
 
  if (! session->db.empty() && session->db.compare(database_name.to_string()) == 0)
470
 
    session->clear_db();
 
478
  if (! session->db.empty() && session->db.compare(db) == 0)
 
479
    mysql_change_db_impl(session, NULL);
471
480
  pthread_mutex_unlock(&LOCK_create_db);
472
481
  start_waiting_global_read_lock(session);
473
482
  return error;
784
793
    @retval true  Error
785
794
*/
786
795
 
787
 
bool mysql_change_db(Session *session, const NormalisedDatabaseName &normalised_database_name, bool force_switch)
 
796
bool mysql_change_db(Session *session, const LEX_STRING *new_db_name, bool force_switch)
788
797
{
 
798
  LEX_STRING new_db_file_name;
789
799
  const CHARSET_INFO *db_default_cl;
790
800
 
791
 
  if (my_strcasecmp(system_charset_info, normalised_database_name.to_string().c_str(),
 
801
  assert(new_db_name);
 
802
  assert(new_db_name->length);
 
803
 
 
804
  if (my_strcasecmp(system_charset_info, new_db_name->str,
792
805
                    INFORMATION_SCHEMA_NAME.c_str()) == 0)
793
806
  {
794
 
    NonNormalisedDatabaseName non_normalised_i_s(INFORMATION_SCHEMA_NAME);
795
 
    NormalisedDatabaseName is_name(non_normalised_i_s);
 
807
    /* Switch the current database to INFORMATION_SCHEMA. */
 
808
    /* const_cast<> is safe here: mysql_change_db_impl does a copy */
 
809
    LEX_STRING is_name= { const_cast<char *>(INFORMATION_SCHEMA_NAME.c_str()),
 
810
                          INFORMATION_SCHEMA_NAME.length() };
 
811
    mysql_change_db_impl(session, &is_name);
796
812
 
797
 
    session->set_db(is_name);
798
813
    return false;
799
814
  }
800
815
 
801
816
  /*
 
817
    Now we need to make a copy because check_db_name requires a
 
818
    non-constant argument. Actually, it takes database file name.
 
819
 
 
820
    TODO: fix check_db_name().
 
821
  */
 
822
 
 
823
  new_db_file_name.length= new_db_name->length;
 
824
  new_db_file_name.str= (char *)malloc(new_db_name->length + 1);
 
825
  if (new_db_file_name.str == NULL)
 
826
    return true;                             /* the error is set */
 
827
  memcpy(new_db_file_name.str, new_db_name->str, new_db_name->length);
 
828
  new_db_file_name.str[new_db_name->length]= 0;
 
829
 
 
830
 
 
831
  /*
802
832
    NOTE: if check_db_name() fails, we should throw an error in any case,
803
833
    even if we are called from sp_head::execute().
804
834
 
806
836
    from sp_head::execute(). But let's switch the current database to NULL
807
837
    in this case to be sure.
808
838
  */
809
 
  if (! normalised_database_name.isValid())
 
839
 
 
840
  if (check_db_name(&new_db_file_name))
810
841
  {
811
 
    my_error(ER_WRONG_DB_NAME, MYF(0),
812
 
             normalised_database_name.to_string().c_str());
 
842
    my_error(ER_WRONG_DB_NAME, MYF(0), new_db_file_name.str);
 
843
    free(new_db_file_name.str);
813
844
 
814
845
    if (force_switch)
815
 
      session->clear_db();
 
846
      mysql_change_db_impl(session, NULL);
816
847
 
817
848
    return true;
818
849
  }
819
850
 
820
 
  DatabasePathName database_path(normalised_database_name);
821
 
 
822
 
  if (! database_path.exists())
 
851
  if (check_db_dir_existence(new_db_file_name.str))
823
852
  {
824
853
    if (force_switch)
825
854
    {
827
856
 
828
857
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
829
858
                          ER_BAD_DB_ERROR, ER(ER_BAD_DB_ERROR),
830
 
                          normalised_database_name.to_string().c_str());
 
859
                          new_db_file_name.str);
 
860
 
 
861
      free(new_db_file_name.str);
831
862
 
832
863
      /* Change db to NULL. */
833
864
 
834
 
      session->clear_db();
 
865
      mysql_change_db_impl(session, NULL);
835
866
 
836
867
      /* The operation succeed. */
837
868
 
841
872
    {
842
873
      /* Report an error and free new_db_file_name. */
843
874
 
844
 
      my_error(ER_BAD_DB_ERROR, MYF(0),
845
 
               normalised_database_name.to_string().c_str());
 
875
      my_error(ER_BAD_DB_ERROR, MYF(0), new_db_file_name.str);
 
876
      free(new_db_file_name.str);
846
877
 
847
878
      /* The operation failed. */
848
879
 
850
881
    }
851
882
  }
852
883
 
853
 
  db_default_cl= get_default_db_collation(normalised_database_name.to_string().c_str());
 
884
  db_default_cl= get_default_db_collation(new_db_file_name.str);
854
885
 
855
 
  session->set_db(normalised_database_name);
 
886
  mysql_change_db_impl(session, &new_db_file_name);
 
887
  free(new_db_file_name.str);
856
888
 
857
889
  return false;
858
890
}
859
891
 
860
 
NormalisedDatabaseName::NormalisedDatabaseName(const NonNormalisedDatabaseName &dbname)
861
 
{
862
 
  const std::string &non_norm_string= dbname.to_string();
863
 
  database_name= (char*)malloc(non_norm_string.size()+1);
864
 
 
865
 
  assert(database_name); /* FIXME: should throw exception */
866
 
 
867
 
  strncpy(database_name, non_norm_string.c_str(), non_norm_string.size()+1);
868
 
 
869
 
  my_casedn_str(files_charset_info, database_name);
870
 
}
871
 
 
872
 
NormalisedDatabaseName::~NormalisedDatabaseName()
873
 
{
874
 
  free(database_name);
875
 
}
876
 
 
877
 
bool NormalisedDatabaseName::isValid() const
878
 
{
879
 
  LEX_STRING db_lexstring;
880
 
 
881
 
  db_lexstring.str= database_name;
882
 
  db_lexstring.length= strlen(database_name);
883
 
 
884
 
  if (db_lexstring.length == 0
885
 
      || db_lexstring.length > NAME_LEN
886
 
      || database_name[db_lexstring.length - 1] == ' ')
887
 
    return false;
888
 
 
889
 
  return (! check_identifier_name(&db_lexstring));
890
 
}
891
 
 
892
 
DatabasePathName::DatabasePathName(const NormalisedDatabaseName &database_name)
 
892
/*
 
893
  Check if there is directory for the database name.
 
894
 
 
895
  SYNOPSIS
 
896
    check_db_dir_existence()
 
897
    db_name   database name
 
898
 
 
899
  RETURN VALUES
 
900
    false   There is directory for the specified database name.
 
901
    true    The directory does not exist.
 
902
*/
 
903
 
 
904
bool check_db_dir_existence(const char *db_name)
893
905
{
894
906
  char db_dir_path[FN_REFLEN];
895
907
  uint32_t db_dir_path_len;
896
908
 
897
909
  db_dir_path_len= build_table_filename(db_dir_path, sizeof(db_dir_path),
898
 
                                        database_name.to_string().c_str(),
899
 
                                        "", false);
 
910
                                        db_name, "", false);
900
911
 
901
912
  if (db_dir_path_len && db_dir_path[db_dir_path_len - 1] == FN_LIBCHAR)
902
913
    db_dir_path[db_dir_path_len - 1]= 0;
903
914
 
904
 
  database_path.assign(db_dir_path);
 
915
  /* Check access. */
 
916
 
 
917
  return access(db_dir_path, F_OK);
905
918
}
906
919
 
907
 
bool DatabasePathName::exists() const
 
920
/**
 
921
  @brief Internal implementation: switch current database to a valid one.
 
922
 
 
923
  @param session            Thread context.
 
924
  @param new_db_name    Name of the database to switch to. The function will
 
925
                        take ownership of the name (the caller must not free
 
926
                        the allocated memory). If the name is NULL, we're
 
927
                        going to switch to NULL db.
 
928
  @param new_db_charset Character set of the new database.
 
929
*/
 
930
 
 
931
static void mysql_change_db_impl(Session *session, LEX_STRING *new_db_name)
908
932
{
909
 
  /* TODO: handle EIO and other fun errors */
910
 
  return access(database_path.c_str(), F_OK) == 0;
 
933
  /* 1. Change current database in Session. */
 
934
 
 
935
  if (new_db_name == NULL)
 
936
  {
 
937
    /*
 
938
      Session::set_db() does all the job -- it frees previous database name and
 
939
      sets the new one.
 
940
    */
 
941
 
 
942
    session->set_db(NULL, 0);
 
943
  }
 
944
  else
 
945
  {
 
946
    /*
 
947
      Here we already have a copy of database name to be used in Session. So,
 
948
      we just call Session::reset_db(). Since Session::reset_db() does not releases
 
949
      the previous database name, we should do it explicitly.
 
950
    */
 
951
 
 
952
    session->set_db(new_db_name->str, new_db_name->length);
 
953
  }
911
954
}