~james-page/ubuntu/precise/mysql-5.5/misc-fixes

« back to all changes in this revision

Viewing changes to sql/handler.cc

  • Committer: Package Import Robot
  • Author(s): Marc Deslauriers
  • Date: 2012-06-11 07:34:33 UTC
  • mfrom: (1.1.6)
  • Revision ID: package-import@ubuntu.com-20120611073433-l9za2ni4ipp848y3
Tags: 5.5.24-0ubuntu0.12.04.1
* SECURITY UPDATE: Update to 5.5.24 to fix security issues (LP: #1011371)
  - http://dev.mysql.com/doc/refman/5.5/en/news-5-5-24.html

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
 
1
/* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
2
2
 
3
3
   This program is free software; you can redistribute it and/or modify
4
4
   it under the terms of the GNU General Public License as published by
10
10
   GNU General Public License for more details.
11
11
 
12
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 */
 
13
   along with this program; if not, write to the Free Software Foundation,
 
14
   Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
15
15
 
16
16
/** @file handler.cc
17
17
 
45
45
#include "ha_partition.h"
46
46
#endif
47
47
 
 
48
 
48
49
/*
49
50
  While we have legacy_db_type, we have this array to
50
51
  check for dups and to find handlerton from legacy_db_type.
90
91
static TYPELIB known_extensions= {0,"known_exts", NULL, NULL};
91
92
uint known_extensions_id= 0;
92
93
 
 
94
/**
 
95
  Database name that hold most of mysqld system tables.
 
96
  Current code assumes that, there exists only some
 
97
  specific "database name" designated as system database.
 
98
*/
 
99
const char* mysqld_system_database= "mysql";
 
100
 
 
101
// System tables that belong to mysqld_system_database.
 
102
st_system_tablename mysqld_system_tables[]= {
 
103
  {mysqld_system_database, "db"},
 
104
  {mysqld_system_database, "user"},
 
105
  {mysqld_system_database, "host"},
 
106
  {mysqld_system_database, "func"},
 
107
  {mysqld_system_database, "proc"},
 
108
  {mysqld_system_database, "event"},
 
109
  {mysqld_system_database, "plugin"},
 
110
  {mysqld_system_database, "servers"},
 
111
  {mysqld_system_database, "procs_priv"},
 
112
  {mysqld_system_database, "tables_priv"},
 
113
  {mysqld_system_database, "proxies_priv"},
 
114
  {mysqld_system_database, "columns_priv"},
 
115
  {mysqld_system_database, "time_zone"},
 
116
  {mysqld_system_database, "time_zone_name"},
 
117
  {mysqld_system_database, "time_zone_leap_second"},
 
118
  {mysqld_system_database, "time_zone_transition"},
 
119
  {mysqld_system_database, "time_zone_transition_type"},
 
120
  {mysqld_system_database, "help_category"},
 
121
  {mysqld_system_database, "help_keyword"},
 
122
  {mysqld_system_database, "help_relation"},
 
123
  {mysqld_system_database, "help_topic"},
 
124
  {(const char *)NULL, (const char *)NULL} /* This must be at the end */
 
125
};
 
126
 
 
127
/**
 
128
  This static pointer holds list of system databases from SQL layer and
 
129
  various SE's. The required memory is allocated once, and never freed.
 
130
*/
 
131
static const char **known_system_databases= NULL;
 
132
static const char **ha_known_system_databases();
 
133
 
 
134
// Called for each SE to get SE specific system database.
 
135
static my_bool system_databases_handlerton(THD *unused, plugin_ref plugin,
 
136
                                           void *arg);
 
137
 
 
138
// Called for each SE to check if given db.table_name is a system table.
 
139
static my_bool check_engine_system_table_handlerton(THD *unused,
 
140
                                                    plugin_ref plugin,
 
141
                                                    void *arg);
 
142
 
 
143
/**
 
144
  Structure used by SE during check for system table.
 
145
  This structure is passed to each SE handlerton and the status (OUT param)
 
146
  is collected.
 
147
*/
 
148
struct st_sys_tbl_chk_params
 
149
{
 
150
  const char *db;                             // IN param
 
151
  const char *table_name;                     // IN param
 
152
  bool is_sql_layer_system_table;             // IN param
 
153
  legacy_db_type db_type;                     // IN param
 
154
 
 
155
  enum enum_sys_tbl_chk_status
 
156
  {
 
157
    // db.table_name is not a supported system table.
 
158
    NOT_KNOWN_SYSTEM_TABLE,
 
159
    /*
 
160
      db.table_name is a system table,
 
161
      but may not be supported by SE.
 
162
    */
 
163
    KNOWN_SYSTEM_TABLE,
 
164
    /*
 
165
      db.table_name is a system table,
 
166
      and is supported by SE.
 
167
    */
 
168
    SUPPORTED_SYSTEM_TABLE
 
169
  }status;                                    // OUT param
 
170
};
93
171
 
94
172
 
95
173
static plugin_ref ha_default_plugin(THD *thd)
359
437
  SETMSG(HA_ERR_TOO_MANY_CONCURRENT_TRXS, ER_DEFAULT(ER_TOO_MANY_CONCURRENT_TRXS));
360
438
  SETMSG(HA_ERR_INDEX_COL_TOO_LONG,     ER_DEFAULT(ER_INDEX_COLUMN_TOO_LONG));
361
439
  SETMSG(HA_ERR_INDEX_CORRUPT,          ER_DEFAULT(ER_INDEX_CORRUPT));
 
440
  SETMSG(HA_ERR_TABLE_IN_FK_CHECK,      ER_DEFAULT(ER_TABLE_IN_FK_CHECK));
362
441
 
363
442
  /* Register the error messages for use with my_error(). */
364
443
  return my_error_register(get_handler_errmsgs, HA_ERR_FIRST, HA_ERR_LAST);
587
666
  */
588
667
  opt_using_transactions= total_ha>(ulong)opt_bin_log;
589
668
  savepoint_alloc_size+= sizeof(SAVEPOINT);
 
669
 
 
670
  /*
 
671
    Initialize system database name cache.
 
672
    This cache is used to do a quick check if a given
 
673
    db.tablename is a system table.
 
674
  */
 
675
  known_system_databases= ha_known_system_databases();
 
676
 
590
677
  DBUG_RETURN(error);
591
678
}
592
679
 
2878
2965
  case HA_ERR_UNDO_REC_TOO_BIG:
2879
2966
    textno= ER_UNDO_RECORD_TOO_BIG;
2880
2967
    break;
 
2968
  case HA_ERR_TABLE_IN_FK_CHECK:
 
2969
    textno= ER_TABLE_IN_FK_CHECK;
 
2970
    break;
2881
2971
  default:
2882
2972
    {
2883
2973
      /* The error was "unknown" to this function.
3784
3874
  DBUG_RETURN(FALSE);
3785
3875
}
3786
3876
 
 
3877
/**
 
3878
  @brief Check if a given table is a system table.
 
3879
 
 
3880
  @details The primary purpose of introducing this function is to stop system
 
3881
  tables to be created or being moved to undesired storage engines.
 
3882
 
 
3883
  @todo There is another function called is_system_table_name() used by
 
3884
        get_table_category(), which is used to set TABLE_SHARE table_category.
 
3885
        It checks only a subset of table name like proc, event and time*.
 
3886
        We cannot use below function in get_table_category(),
 
3887
        as that affects locking mechanism. If we need to
 
3888
        unify these functions, we need to fix locking issues generated.
 
3889
 
 
3890
  @param   hton                  Handlerton of new engine.
 
3891
  @param   db                    Database name.
 
3892
  @param   table_name            Table name to be checked.
 
3893
 
 
3894
  @return Operation status
 
3895
    @retval  true                If the table name is a valid system table
 
3896
                                 or if its a valid user table.
 
3897
 
 
3898
    @retval  false               If the table name is a system table name
 
3899
                                 and does not belong to engine specified
 
3900
                                 in the command.
 
3901
*/
 
3902
bool ha_check_if_supported_system_table(handlerton *hton, const char *db,
 
3903
                                        const char *table_name)
 
3904
{
 
3905
  DBUG_ENTER("ha_check_if_supported_system_table");
 
3906
  st_sys_tbl_chk_params check_params;
 
3907
  bool is_system_database= false;
 
3908
  const char **names;
 
3909
  st_system_tablename *systab;
 
3910
 
 
3911
  // Check if we have a system database name in the command.
 
3912
  DBUG_ASSERT(known_system_databases != NULL);
 
3913
  names= known_system_databases;
 
3914
  while (names && *names)
 
3915
  {
 
3916
    if (strcmp(*names, db) == 0)
 
3917
    {
 
3918
      /* Used to compare later, will be faster */
 
3919
      check_params.db= *names;
 
3920
      is_system_database= true;
 
3921
      break;
 
3922
    }
 
3923
    names++;
 
3924
  }
 
3925
  if (!is_system_database)
 
3926
    DBUG_RETURN(true); // It's a user table name.
 
3927
 
 
3928
  // Check if this is SQL layer system tables.
 
3929
  systab= mysqld_system_tables;
 
3930
  check_params.is_sql_layer_system_table= false;
 
3931
  while (systab && systab->db)
 
3932
  {
 
3933
    if (systab->db == check_params.db &&
 
3934
        strcmp(systab->tablename, table_name) == 0)
 
3935
    {
 
3936
      check_params.is_sql_layer_system_table= true;
 
3937
      break;
 
3938
    }
 
3939
    systab++;
 
3940
  }
 
3941
 
 
3942
  // Check if this is a system table and if some engine supports it.
 
3943
  check_params.status= check_params.is_sql_layer_system_table ?
 
3944
    st_sys_tbl_chk_params::KNOWN_SYSTEM_TABLE :
 
3945
    st_sys_tbl_chk_params::NOT_KNOWN_SYSTEM_TABLE;
 
3946
  check_params.db_type= hton->db_type;
 
3947
  check_params.table_name= table_name;
 
3948
  plugin_foreach(NULL, check_engine_system_table_handlerton,
 
3949
                 MYSQL_STORAGE_ENGINE_PLUGIN, &check_params);
 
3950
 
 
3951
  // SE does not support this system table.
 
3952
  if (check_params.status == st_sys_tbl_chk_params::KNOWN_SYSTEM_TABLE)
 
3953
    DBUG_RETURN(false);
 
3954
 
 
3955
  // It's a system table or a valid user table.
 
3956
  DBUG_RETURN(true);
 
3957
}
 
3958
 
 
3959
/**
 
3960
  @brief Called for each SE to check if given db, tablename is a system table.
 
3961
 
 
3962
  @details The primary purpose of introducing this function is to stop system
 
3963
  tables to be created or being moved to undesired storage engines.
 
3964
 
 
3965
  @param   unused  unused THD*
 
3966
  @param   plugin  Points to specific SE.
 
3967
  @param   arg     Is of type struct st_sys_tbl_chk_params.
 
3968
 
 
3969
  @note
 
3970
    args->status   Indicates OUT param,
 
3971
                   see struct st_sys_tbl_chk_params definition for more info.
 
3972
 
 
3973
  @return Operation status
 
3974
    @retval  true  There was a match found.
 
3975
                   This will stop doing checks with other SE's.
 
3976
 
 
3977
    @retval  false There was no match found.
 
3978
                   Other SE's will be checked to find a match.
 
3979
*/
 
3980
static my_bool check_engine_system_table_handlerton(THD *unused,
 
3981
                                                    plugin_ref plugin,
 
3982
                                                    void *arg)
 
3983
{
 
3984
  st_sys_tbl_chk_params *check_params= (st_sys_tbl_chk_params*) arg;
 
3985
  handlerton *hton= plugin_data(plugin, handlerton *);
 
3986
 
 
3987
  // Do we already know that the table is a system table?
 
3988
  if (check_params->status == st_sys_tbl_chk_params::KNOWN_SYSTEM_TABLE)
 
3989
  {
 
3990
    /*
 
3991
      If this is the same SE specified in the command, we can
 
3992
      simply ask the SE if it supports it stop the search regardless.
 
3993
    */
 
3994
    if (hton->db_type == check_params->db_type)
 
3995
    {
 
3996
      if (hton->is_supported_system_table &&
 
3997
          hton->is_supported_system_table(check_params->db,
 
3998
                                       check_params->table_name,
 
3999
                                       check_params->is_sql_layer_system_table))
 
4000
        check_params->status= st_sys_tbl_chk_params::SUPPORTED_SYSTEM_TABLE;
 
4001
      return TRUE;
 
4002
    }
 
4003
    /*
 
4004
      If this is a different SE, there is no point in asking the SE
 
4005
      since we already know it's a system table and we don't care
 
4006
      if it is supported or not.
 
4007
    */
 
4008
    return FALSE;
 
4009
  }
 
4010
 
 
4011
  /*
 
4012
    We don't yet know if the table is a system table or not.
 
4013
    We therefore must always ask the SE.
 
4014
  */
 
4015
  if (hton->is_supported_system_table &&
 
4016
      hton->is_supported_system_table(check_params->db,
 
4017
                                      check_params->table_name,
 
4018
                                      check_params->is_sql_layer_system_table))
 
4019
  {
 
4020
    /*
 
4021
      If this is the same SE specified in the command, we know it's a
 
4022
      supported system table and can stop the search.
 
4023
    */
 
4024
    if (hton->db_type == check_params->db_type)
 
4025
    {
 
4026
      check_params->status= st_sys_tbl_chk_params::SUPPORTED_SYSTEM_TABLE;
 
4027
      return TRUE;
 
4028
    }
 
4029
    else
 
4030
      check_params->status= st_sys_tbl_chk_params::KNOWN_SYSTEM_TABLE;
 
4031
  }
 
4032
 
 
4033
  return FALSE;
 
4034
}
 
4035
 
 
4036
/*
 
4037
  Prepare list of all known system database names
 
4038
  current we just have 'mysql' as system database name.
 
4039
 
 
4040
  Later ndbcluster, innodb SE's can define some new database
 
4041
  name which can store system tables specific to SE.
 
4042
*/
 
4043
const char** ha_known_system_databases(void)
 
4044
{
 
4045
  I_List<i_string> found_databases;
 
4046
  const char **databases, **database;
 
4047
 
 
4048
  // Get mysqld system database name.
 
4049
  found_databases.push_back(new i_string(mysqld_system_database));
 
4050
 
 
4051
  // Get system database names from every specific storage engine.
 
4052
  plugin_foreach(NULL, system_databases_handlerton,
 
4053
                 MYSQL_STORAGE_ENGINE_PLUGIN, &found_databases);
 
4054
 
 
4055
  int element_count= 0;
 
4056
  I_List_iterator<i_string> iter(found_databases);
 
4057
  while (iter++) element_count++;
 
4058
  databases= (const char **) my_once_alloc(sizeof(char *)*
 
4059
                                           (element_count+1),
 
4060
                                           MYF(MY_WME | MY_FAE));
 
4061
  DBUG_ASSERT(databases != NULL);
 
4062
 
 
4063
  database= databases;
 
4064
  i_string *tmp;
 
4065
  while ((tmp= found_databases.get()))
 
4066
  {
 
4067
    *database++= tmp->ptr;
 
4068
    delete tmp;
 
4069
  }
 
4070
  *database= NULL; // Last element.
 
4071
 
 
4072
  return databases;
 
4073
}
 
4074
 
 
4075
/**
 
4076
  @brief Fetch system database name specific to SE.
 
4077
 
 
4078
  @details This function is invoked by plugin_foreach() from
 
4079
           ha_known_system_databases(), for each storage engine.
 
4080
*/
 
4081
static my_bool system_databases_handlerton(THD *unused, plugin_ref plugin,
 
4082
                                           void *arg)
 
4083
{
 
4084
  I_List<i_string> *found_databases= (I_List<i_string> *) arg;
 
4085
  const char *db;
 
4086
 
 
4087
  handlerton *hton= plugin_data(plugin, handlerton *);
 
4088
  if (hton->system_database)
 
4089
  {
 
4090
    db= hton->system_database();
 
4091
    if (db)
 
4092
      found_databases->push_back(new i_string(db));
 
4093
  }
 
4094
 
 
4095
  return FALSE;
 
4096
}
 
4097
 
3787
4098
 
3788
4099
void st_ha_check_opt::init()
3789
4100
{