~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/identifier/schema.cc

  • Committer: Prafulla Tekawade
  • Date: 2010-08-06 11:21:12 UTC
  • mto: (1711.1.21 build) (1725.1.1 build)
  • mto: This revision was merged to the branch mainline in revision 1714.
  • Revision ID: prafulla_t@users.sourceforge.net-20100806112112-7w5u0s3nx9u67nzt
Fix for Bug 586051

1. test_if_ref method which checks whether predicate is already evaluated
   due to ref/eq_ref access or not was incorrectly removing a predicate 
   that was not implicitly evaluated due to ref access (due to presence of filesort ?)
   It was field=NULL predicate.
   Such predicate should be kept and execution engine will filter out rows
   correctly. Removal of such predicate led to returning of rows which had
   NULL for join/predicate columns.
2. field COMP_OP NULL will always false for all fields except when COMP_OP
   is NULL-safe equality operator. Modified range optimizer to return zero
   row count in such cases.
   Query now does not even run. It returns zero result. As such Fix(1) is not
   required but we might hit that case in some other query (I have not tried it
   yet)
3. Fixed Field::val_str to print "NULL" for literal NULL instead of "0". It
   added lot of confusion while debugging.

Show diffs side-by-side

added added

removed removed

Lines of Context:
26
26
#include "drizzled/session.h"
27
27
#include "drizzled/current_session.h"
28
28
#include "drizzled/internal/my_sys.h"
29
 
 
30
 
#include "drizzled/util/tablename_to_filename.h"
31
 
#include "drizzled/util/backtrace.h"
 
29
#include "drizzled/data_home.h"
32
30
 
33
31
#include <algorithm>
34
32
#include <sstream>
35
33
#include <cstdio>
36
34
 
37
 
#include <boost/algorithm/string/compare.hpp>
38
 
 
39
35
using namespace std;
40
36
 
41
37
namespace drizzled
44
40
extern string drizzle_tmpdir;
45
41
extern pid_t current_pid;
46
42
 
 
43
static const char hexchars[]= "0123456789abcdef";
 
44
 
 
45
static bool tablename_to_filename(const string &from, string &to);
 
46
 
47
47
static size_t build_schema_filename(string &path, const string &db)
48
48
{
49
 
  path.append("");
 
49
  string dbbuff("");
50
50
  bool conversion_error= false;
51
51
 
52
 
  conversion_error= util::tablename_to_filename(db, path);
 
52
  conversion_error= tablename_to_filename(db, dbbuff);
53
53
  if (conversion_error)
54
54
  {
55
55
    errmsg_printf(ERRMSG_LVL_ERROR,
57
57
                    "name length restrictions."));
58
58
    return 0;
59
59
  }
 
60
   
 
61
 
 
62
  int rootdir_len= strlen(FN_ROOTDIR);
 
63
  path.append(data_home);
 
64
  ssize_t without_rootdir= path.length() - rootdir_len;
 
65
 
 
66
  /* Don't add FN_ROOTDIR if dirzzle_data_home already includes it */
 
67
  if (without_rootdir >= 0)
 
68
  {
 
69
    const char *tmp= path.c_str() + without_rootdir;
 
70
 
 
71
    if (memcmp(tmp, FN_ROOTDIR, rootdir_len) != 0)
 
72
      path.append(FN_ROOTDIR);
 
73
  }
 
74
 
 
75
  path.append(dbbuff);
60
76
 
61
77
  return path.length();
62
78
}
63
79
 
 
80
 
 
81
/*
 
82
  Translate a table name to a cursor name (WL #1324).
 
83
 
 
84
  SYNOPSIS
 
85
    tablename_to_filename()
 
86
      from                      The table name
 
87
      to                OUT     The cursor name
 
88
 
 
89
  RETURN
 
90
    true if errors happen. false on success.
 
91
*/
 
92
static bool tablename_to_filename(const string &from, string &to)
 
93
{
 
94
  
 
95
  string::const_iterator iter= from.begin();
 
96
  for (; iter != from.end(); ++iter)
 
97
  {
 
98
    if ((*iter >= '0' && *iter <= '9') ||
 
99
        (*iter >= 'A' && *iter <= 'Z') ||
 
100
        (*iter >= 'a' && *iter <= 'z') ||
 
101
/* OSX defines an extra set of high-bit and multi-byte characters
 
102
   that cannot be used on the filesystem. Instead of trying to sort
 
103
   those out, we'll just escape encode all high-bit-set chars on OSX.
 
104
   It won't really hurt anything - it'll just make some filenames ugly. */
 
105
#if !defined(TARGET_OS_OSX)
 
106
        ((unsigned char)*iter >= 128) ||
 
107
#endif
 
108
        (*iter == '_') ||
 
109
        (*iter == ' ') ||
 
110
        (*iter == '-'))
 
111
    {
 
112
      to.push_back(*iter);
 
113
      continue;
 
114
    }
 
115
   
 
116
    /* We need to escape this char in a way that can be reversed */
 
117
    to.push_back('@');
 
118
    to.push_back(hexchars[(*iter >> 4) & 15]);
 
119
    to.push_back(hexchars[(*iter) & 15]);
 
120
  }
 
121
 
 
122
  if (internal::check_if_legal_tablename(to.c_str()))
 
123
  {
 
124
    to.append("@@@");
 
125
  }
 
126
  return false;
 
127
}
 
128
 
64
129
SchemaIdentifier::SchemaIdentifier(const std::string &db_arg) :
65
130
  db(db_arg),
66
131
  db_path(""),
67
 
  catalog("LOCAL")
 
132
  lower_db(db_arg)
68
133
69
 
#if 0
70
 
  string::size_type lastPos= db.find_first_of('/', 0);
71
 
 
72
 
  if (lastPos != std::string::npos) 
73
 
  {
74
 
    catalog= db.substr(0, lastPos);
75
 
    db.erase(0, lastPos + 1);
76
 
  }
77
 
#endif
78
 
 
79
 
  if (not db_arg.empty())
80
 
  {
81
 
    drizzled::build_schema_filename(db_path, db);
 
134
  std::transform(lower_db.begin(), lower_db.end(),
 
135
                 lower_db.begin(), ::tolower);
 
136
 
 
137
  if (not lower_db.empty())
 
138
  {
 
139
    drizzled::build_schema_filename(db_path, lower_db);
82
140
    assert(db_path.length()); // TODO throw exception, this is a possibility
83
141
  }
84
142
}
85
143
 
86
 
void SchemaIdentifier::getSQLPath(std::string &arg) const
 
144
const std::string &SchemaIdentifier::getSQLPath()
87
145
{
88
 
  arg.append(getSchemaName());
 
146
  return getSchemaName();
89
147
}
90
148
 
91
149
const std::string &SchemaIdentifier::getPath() const
93
151
  return db_path;
94
152
}
95
153
 
96
 
bool SchemaIdentifier::compare(const std::string &arg) const
 
154
bool SchemaIdentifier::compare(std::string arg) const
97
155
{
98
 
  return boost::iequals(arg, db);
99
 
}
 
156
  std::transform(arg.begin(), arg.end(),
 
157
                 arg.begin(), ::tolower);
100
158
 
101
 
bool SchemaIdentifier::compare(SchemaIdentifier::const_reference arg) const
102
 
{
103
 
  return boost::iequals(arg.getSchemaName(), db);
 
159
  return arg == lower_db;
104
160
}
105
161
 
106
162
bool SchemaIdentifier::isValid() const
107
163
{
108
 
  bool error= false;
109
 
 
110
 
  do
111
 
  {
112
 
    if (db.empty())
113
 
    {
114
 
      error= true;
115
 
      break;
116
 
    }
117
 
 
118
 
    if (db.size() > NAME_LEN)
119
 
    {
120
 
      error= true;
121
 
      break;
122
 
    }
123
 
 
124
 
    if (db.at(db.length() -1) == ' ')
125
 
    {
126
 
      error= true;
127
 
      break;
128
 
    }
129
 
 
130
 
    if (db.at(0) == '.')
131
 
    {
132
 
      error= true;
133
 
      break;
134
 
    }
135
 
 
136
 
    {
137
 
      const CHARSET_INFO * const cs= &my_charset_utf8mb4_general_ci;
138
 
 
139
 
      int well_formed_error;
140
 
      uint32_t res= cs->cset->well_formed_len(cs, db.c_str(), db.c_str() + db.length(),
141
 
                                              NAME_CHAR_LEN, &well_formed_error);
142
 
      if (well_formed_error or db.length() != res)
143
 
      {
144
 
        error= true;
145
 
        break;
146
 
      }
147
 
    }
148
 
  } while (0);
149
 
 
150
 
  if (error)
151
 
  {
152
 
    std::string name;
153
 
 
154
 
    getSQLPath(name);
155
 
    my_error(ER_WRONG_DB_NAME, MYF(0), name.c_str());
156
 
 
 
164
  if (lower_db.empty())
 
165
    return false;
 
166
 
 
167
  if (lower_db.size() > NAME_LEN)
 
168
    return false;
 
169
 
 
170
  if (lower_db.at(lower_db.length() -1) == ' ')
 
171
    return false;
 
172
 
 
173
  const CHARSET_INFO * const cs= &my_charset_utf8mb4_general_ci;
 
174
 
 
175
  int well_formed_error;
 
176
  uint32_t res= cs->cset->well_formed_len(cs, lower_db.c_str(), lower_db.c_str() + lower_db.length(),
 
177
                                          NAME_CHAR_LEN, &well_formed_error);
 
178
 
 
179
  if (well_formed_error)
 
180
  {
 
181
    my_error(ER_INVALID_CHARACTER_STRING, MYF(0), "identifier", lower_db.c_str());
157
182
    return false;
158
183
  }
159
184
 
 
185
  if (lower_db.length() != res)
 
186
    return false;
 
187
 
160
188
  return true;
161
189
}
162
190