~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/identifier/table.cc

  • Committer: Mark Atwood
  • Date: 2012-01-04 16:59:32 UTC
  • mfrom: (2478.2.3 real-key-use-catalog)
  • Revision ID: me@mark.atwood.name-20120104165932-cm0xqs4by0u3p4cy
mergeĀ lp:~stewart/drizzle/key-use-catalog

Show diffs side-by-side

added added

removed removed

Lines of Context:
42
42
 
43
43
using namespace std;
44
44
 
45
 
namespace drizzled
46
 
{
47
 
 
48
 
class Table;
 
45
namespace drizzled {
49
46
 
50
47
extern std::string drizzle_tmpdir;
51
48
extern pid_t current_pid;
52
49
 
53
50
namespace identifier {
54
 
class Schema;
55
51
 
56
52
static const char hexchars[]= "0123456789abcdef";
57
53
 
137
133
static uint32_t get_counter()
138
134
{
139
135
  boost::mutex::scoped_lock lock(counter_mutex);
140
 
  uint32_t x;
141
 
  x= ++counter;
142
 
 
143
 
  return x;
 
136
  return ++counter;
144
137
}
145
138
 
146
139
#endif
147
140
 
148
 
size_t Table::build_tmptable_filename(std::string &buffer)
149
 
{
150
 
  size_t tmpdir_length;
151
 
  ostringstream post_tmpdir_str;
152
 
 
153
 
  buffer.append(drizzle_tmpdir);
154
 
  tmpdir_length= buffer.length();
155
 
 
156
 
  post_tmpdir_str << "/" << TMP_FILE_PREFIX << current_pid;
157
 
  post_tmpdir_str << pthread_self() << "-" << get_counter();
158
 
 
159
 
  buffer.append(post_tmpdir_str.str());
160
 
 
161
 
  transform(buffer.begin() + tmpdir_length, buffer.end(), buffer.begin() + tmpdir_length, ::tolower);
162
 
 
163
 
  return buffer.length();
164
 
}
165
 
 
166
 
size_t Table::build_tmptable_filename(std::vector<char> &buffer)
167
 
{
168
 
  ostringstream post_tmpdir_str;
169
 
 
170
 
  post_tmpdir_str << drizzle_tmpdir << "/" << TMP_FILE_PREFIX << current_pid;
171
 
  post_tmpdir_str << pthread_self() << "-" << get_counter();
172
 
 
173
 
  buffer.resize(post_tmpdir_str.str().length() + 1);
174
 
  memcpy(&buffer[0], post_tmpdir_str.str().c_str(), post_tmpdir_str.str().size());
175
 
  buffer[post_tmpdir_str.str().size()]= 0;
176
 
 
177
 
  return buffer.size();
178
 
}
179
 
 
 
141
std::string Table::build_tmptable_filename()
 
142
{
 
143
  ostringstream os;
 
144
  os << "/" << TMP_FILE_PREFIX << current_pid << pthread_self() << "-" << get_counter();
 
145
  return drizzle_tmpdir + boost::to_lower_copy(os.str());
 
146
}
180
147
 
181
148
/*
182
149
  Creates path to a cursor: drizzle_data_dir/db/table.ext
210
177
    path length on success, 0 on failure
211
178
*/
212
179
 
213
 
size_t Table::build_table_filename(std::string &in_path, const std::string &in_db, const std::string &in_table_name, bool is_tmp)
 
180
std::string Table::build_table_filename(const std::string &in_db, const std::string &in_table_name, bool is_tmp)
214
181
{
215
 
  bool conversion_error= false;
216
 
 
217
 
  conversion_error= util::tablename_to_filename(in_db, in_path);
218
 
  if (conversion_error)
219
 
  {
220
 
    errmsg_printf(error::ERROR,
221
 
                  _("Schema name cannot be encoded and fit within filesystem "
222
 
                    "name length restrictions."));
223
 
    return 0;
224
 
  }
225
 
 
226
 
  in_path.append(FN_ROOTDIR);
227
 
 
228
 
  if (is_tmp) // It a conversion tmp
229
 
  {
230
 
    in_path.append(in_table_name);
231
 
  }
232
 
  else
233
 
  {
234
 
    conversion_error= util::tablename_to_filename(in_table_name, in_path);
235
 
    if (conversion_error)
236
 
    {
237
 
      errmsg_printf(error::ERROR,
238
 
                    _("Table name cannot be encoded and fit within filesystem "
239
 
                      "name length restrictions."));
240
 
      return 0;
241
 
    }
242
 
  }
243
 
   
244
 
  return in_path.length();
 
182
  string in_path= util::tablename_to_filename(in_db) + FN_LIBCHAR;
 
183
  return in_path + (is_tmp ? in_table_name : util::tablename_to_filename(in_table_name));
245
184
}
246
185
 
247
186
Table::Table(const drizzled::Table &table) :
248
 
  identifier::Schema(table.getShare()->getSchemaName()),
 
187
  identifier::Schema(str_ref(table.getShare()->getSchemaName())),
249
188
  type(table.getShare()->getTableType()),
250
189
  table_name(table.getShare()->getTableName())
251
190
{
257
196
 
258
197
void Table::init()
259
198
{
260
 
  switch (type) {
 
199
  switch (type) 
 
200
  {
261
201
  case message::Table::FUNCTION:
262
202
  case message::Table::STANDARD:
263
 
    assert(path.size() == 0);
264
 
    build_table_filename(path, getSchemaName(), table_name, false);
 
203
    assert(path.empty());
 
204
    path= build_table_filename(getSchemaName(), table_name, false);
265
205
    break;
266
206
  case message::Table::INTERNAL:
267
 
    assert(path.size() == 0);
268
 
    build_table_filename(path, getSchemaName(), table_name, true);
 
207
    assert(path.empty());
 
208
    path= build_table_filename(getSchemaName(), table_name, true);
269
209
    break;
270
210
  case message::Table::TEMPORARY:
271
211
    if (path.empty())
272
 
    {
273
 
      build_tmptable_filename(path);
274
 
    }
275
 
    break;
276
 
  }
277
 
 
278
 
  switch (type) {
279
 
  case message::Table::FUNCTION:
280
 
  case message::Table::STANDARD:
281
 
  case message::Table::INTERNAL:
282
 
    break;
283
 
  case message::Table::TEMPORARY:
284
 
    {
285
 
      size_t pos;
286
 
 
287
 
      pos= path.find("tmp/#sql");
288
 
      if (pos != std::string::npos) 
289
 
      {
290
 
        key_path= path.substr(pos);
291
 
      }
292
 
    }
293
 
    break;
294
 
  }
295
 
 
296
 
  util::insensitive_hash hasher;
297
 
  hash_value= hasher(path);
298
 
 
299
 
  std::string tb_name(getTableName());
300
 
  std::transform(tb_name.begin(), tb_name.end(), tb_name.begin(), ::tolower);
301
 
 
302
 
  key.set(getKeySize(), getSchemaName(), tb_name);
 
212
      path= build_tmptable_filename();
 
213
    break;
 
214
  }
 
215
 
 
216
  if (type == message::Table::TEMPORARY)
 
217
  {
 
218
    size_t pos= path.find("tmp/#sql");
 
219
    if (pos != std::string::npos) 
 
220
      key_path= path.substr(pos);
 
221
  }
 
222
 
 
223
  hash_value= util::insensitive_hash()(path);
 
224
  key.set(getKeySize(), getCatalogName(), getSchemaName(), boost::to_lower_copy(std::string(getTableName())));
303
225
}
304
226
 
305
227
 
310
232
 
311
233
const std::string &Table::getKeyPath() const
312
234
{
313
 
  if (key_path.empty())
314
 
    return path;
315
 
 
316
 
  return key_path;
 
235
  return key_path.empty() ? path : key_path;
317
236
}
318
237
 
319
 
void Table::getSQLPath(std::string &sql_path) const  // @todo this is just used for errors, we should find a way to optimize it
 
238
std::string Table::getSQLPath() const  // @todo this is just used for errors, we should find a way to optimize it
320
239
{
321
 
  switch (type) {
 
240
  switch (type) 
 
241
        {
322
242
  case message::Table::FUNCTION:
323
243
  case message::Table::STANDARD:
324
 
    sql_path.append(getSchemaName());
325
 
    sql_path.append(".");
326
 
    sql_path.append(table_name);
327
 
    break;
 
244
                return getSchemaName() + "." + table_name;
328
245
  case message::Table::INTERNAL:
329
 
    sql_path.append("temporary.");
330
 
    sql_path.append(table_name);
331
 
    break;
 
246
                return "temporary." + table_name;
332
247
  case message::Table::TEMPORARY:
333
 
    sql_path.append(getSchemaName());
334
 
    sql_path.append(".#");
335
 
    sql_path.append(table_name);
336
 
    break;
 
248
    return getSchemaName() + ".#" + table_name;
337
249
  }
 
250
        assert(false);
 
251
        return "<no table>";
338
252
}
339
253
 
340
254
bool Table::isValid() const
343
257
    return false;
344
258
 
345
259
  bool error= false;
346
 
  do
347
 
  {
348
 
    if (table_name.empty())
349
 
    {
350
 
      error= true;
351
 
      break;
352
 
    }
353
 
 
354
 
    if (table_name.size() > NAME_LEN)
355
 
    {
356
 
      error= true;
357
 
      break;
358
 
    }
359
 
 
360
 
    if (table_name.at(table_name.length() -1) == ' ')
361
 
    {
362
 
      error= true;
363
 
      break;
364
 
    }
365
 
 
366
 
    if (table_name.at(0) == '.')
367
 
    {
368
 
      error= true;
369
 
      break;
370
 
    }
371
 
 
372
 
    {
373
 
      const CHARSET_INFO * const cs= &my_charset_utf8mb4_general_ci;
374
 
 
375
 
      int well_formed_error;
376
 
      uint32_t res= cs->cset->well_formed_len(cs, table_name.c_str(), table_name.c_str() + table_name.length(),
377
 
                                              NAME_CHAR_LEN, &well_formed_error);
378
 
      if (well_formed_error or table_name.length() != res)
379
 
      {
380
 
        error= true;
381
 
        break;
382
 
      }
383
 
    }
384
 
  } while (0);
385
 
 
386
 
  if (error)
387
 
  {
388
 
    std::string name;
389
 
 
390
 
    getSQLPath(name);
391
 
    my_error(ER_WRONG_TABLE_NAME, MYF(0), name.c_str());
392
 
 
393
 
    return false;
394
 
  }
395
 
 
396
 
  return true;
 
260
  if (table_name.empty()
 
261
                || table_name.size() > NAME_LEN
 
262
                || table_name[table_name.length() - 1] == ' '
 
263
                || table_name[0] == '.')
 
264
  {
 
265
    error= true;
 
266
  }
 
267
        else
 
268
  {
 
269
    const charset_info_st& cs= my_charset_utf8mb4_general_ci;
 
270
    int well_formed_error;
 
271
    uint32_t res= cs.cset->well_formed_len(cs, table_name, NAME_CHAR_LEN, &well_formed_error);
 
272
    if (well_formed_error or table_name.length() != res)
 
273
      error= true;
 
274
  }
 
275
  if (not error)
 
276
                return true;
 
277
  my_error(ER_WRONG_TABLE_NAME, MYF(0), getSQLPath().c_str());
 
278
  return false;
397
279
}
398
280
 
399
 
 
400
281
void Table::copyToTableMessage(message::Table &message) const
401
282
{
402
283
  message.set_name(table_name);
403
284
  message.set_schema(getSchemaName());
404
285
}
405
286
 
406
 
void Table::Key::set(size_t resize_arg, const std::string &a, const std::string &b)
 
287
  void Table::Key::set(size_t resize_arg, const std::string &a, const std::string &b, const std::string &c)
407
288
{
408
289
  key_buffer.resize(resize_arg);
409
290
 
410
291
  std::copy(a.begin(), a.end(), key_buffer.begin());
411
292
  std::copy(b.begin(), b.end(), key_buffer.begin() + a.length() + 1);
 
293
  std::copy(c.begin(), c.end(),
 
294
            key_buffer.begin() + a.length() + 1 + b.length() + 1);
412
295
 
413
296
  util::sensitive_hash hasher;
414
297
  hash_value= hasher(key_buffer);
424
307
  return b.getHashValue();
425
308
}
426
309
 
427
 
 
428
 
std::ostream& operator<<(std::ostream& output, Table::const_reference identifier)
 
310
std::ostream& operator<<(std::ostream& output, const Table& identifier)
429
311
{
430
 
  output << "Table:(";
431
 
  output <<  identifier.getSchemaName();
432
 
  output << ", ";
433
 
  output << identifier.getTableName();
434
 
  output << ", ";
435
 
  output << message::type(identifier.getType());
436
 
  output << ", ";
437
 
  output << identifier.getPath();
438
 
  output << ", ";
439
 
  output << identifier.getHashValue();
440
 
  output << ")";
441
 
 
442
 
  return output;  // for multiple << operators.
 
312
  return output << "Table:(" <<  identifier.getSchemaName() << ", " << identifier.getTableName() << ", " << message::type(identifier.getType()) << ", " << identifier.getPath() << ", " << identifier.getHashValue() << ")";
443
313
}
444
314
 
445
315
} /* namespace identifier */