bool check_fk_parent_table_access(THD *thd,
                                  HA_CREATE_INFO *create_info,
                                  Alter_info *alter_info,
                                  const char* create_db)
{
  Key *key;
  List_iterator<Key> key_iterator(alter_info->key_list);

  while ((key= key_iterator++))
  {
    if (key->type == Key::FOREIGN_KEY)
    {
      TABLE_LIST parent_table;
      bool is_qualified_table_name;
      Foreign_key *fk_key= (Foreign_key *)key;
      LEX_CSTRING db_name;
      LEX_CSTRING table_name= { fk_key->ref_table.str,
                               fk_key->ref_table.length };
      const ulong privileges= (SELECT_ACL | INSERT_ACL | UPDATE_ACL |
                               DELETE_ACL | REFERENCES_ACL);

      // Check if tablename is valid or not.
      DBUG_ASSERT(table_name.str != NULL);
      if (check_table_name(table_name.str, table_name.length, false))
      {
        my_error(ER_WRONG_TABLE_NAME, MYF(0), table_name.str);
        return true;
      }

      if (fk_key->ref_db.str)
      {
        is_qualified_table_name= true;
        if (!(db_name.str= (char *) thd->memdup(fk_key->ref_db.str,
                                                fk_key->ref_db.length+1)))
          return true;
        db_name.length= fk_key->ref_db.length;

        // Check if database name is valid or not.
        if (check_db_name((LEX_STRING*) &db_name))
        {
          my_error(ER_WRONG_DB_NAME, MYF(0), db_name.str);
          return true;
        }
      }
      else
      {
        if (!thd->db.str)
        {
          DBUG_ASSERT(create_db);
          db_name.length= strlen(create_db);
          if (!(db_name.str= (char *) thd->memdup(create_db,
                                                  db_name.length+1)))
            return true;
          is_qualified_table_name= true;

          if (check_db_name((LEX_STRING*) &db_name))
          {
            my_error(ER_WRONG_DB_NAME, MYF(0), db_name.str);
            return true;
          }
        }
        else
        {
          if (thd->lex->copy_db_to(&db_name))
            return true;
          else
           is_qualified_table_name= false;
        }
      }

      // if lower_case_table_names is set then convert tablename to lower case.
      if (lower_case_table_names)
      {
        char *name;
        table_name.str= name= (char *) thd->memdup(fk_key->ref_table.str,
                                                   fk_key->ref_table.length+1);
        table_name.length= my_casedn_str(files_charset_info, name);
        db_name.length= my_casedn_str(files_charset_info, (char*) db_name.str);
      }

      parent_table.init_one_table(&db_name, &table_name, 0, TL_IGNORE);

      /*
       Check if user has any of the "privileges" at table level on
       "parent_table".
       Having privilege on any of the parent_table column is not
       enough so checking whether user has any of the "privileges"
       at table level only here.
      */
      if (check_some_access(thd, privileges, &parent_table) ||
          parent_table.grant.want_privilege)
      {
        if (is_qualified_table_name)
        {
          const size_t qualified_table_name_len= NAME_LEN + 1 + NAME_LEN + 1;
          char *qualified_table_name= (char *) thd->alloc(qualified_table_name_len);

          my_snprintf(qualified_table_name, qualified_table_name_len, "%s.%s",
                      db_name.str, table_name.str);
          table_name.str= qualified_table_name;
        }

        my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0),
                 "REFERENCES",
                 thd->security_ctx->priv_user,
                 thd->security_ctx->host_or_ip,
                 table_name.str);

        return true;
      }
    }
  }

  return false;
}