~drizzle-trunk/drizzle/development

575.1.5 by Monty Taylor
Moved stuff to handlerton.cc
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
 *
4
 *  Copyright (C) 2008 Sun Microsystems
5
 *
6
 *  This program is free software; you can redistribute it and/or modify
7
 *  it under the terms of the GNU General Public License as published by
8
 *  the Free Software Foundation; version 2 of the License.
9
 *
10
 *  This program is distributed in the hope that it will be useful,
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 *  GNU General Public License for more details.
14
 *
15
 *  You should have received a copy of the GNU General Public License
16
 *  along with this program; if not, write to the Free Software
17
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
 */
19
20
#include <drizzled/server_includes.h>
21
#include <drizzled/definitions.h>
22
#include <drizzled/base.h>
23
#include <drizzled/handler.h>
960.2.23 by Monty Taylor
Moved handlerton to plugin/storage_engine.h.
24
#include <drizzled/plugin/storage_engine.h>
584.1.15 by Monty Taylor
The mega-patch from hell. Renamed sql_class to session (since that's what it is) and removed it and field and table from common_includes.
25
#include <drizzled/session.h>
575.1.5 by Monty Taylor
Moved stuff to handlerton.cc
26
#include <drizzled/error.h>
27
#include <drizzled/gettext.h>
971.1.25 by Monty Taylor
Moved StorageEngine onto drizzled::Registry.
28
#include <drizzled/registry.h>
971.1.37 by Monty Taylor
Another one bites the dust.
29
#include <drizzled/unireg.h>
971.1.38 by Monty Taylor
Moved delete table.
30
#include <drizzled/data_home.h>
960.2.44 by Monty Taylor
Removed legacy_db_type.
31
#include <string>
575.1.5 by Monty Taylor
Moved stuff to handlerton.cc
32
33
#include CSTDINT_H
34
960.2.44 by Monty Taylor
Removed legacy_db_type.
35
using namespace std;
36
971.1.25 by Monty Taylor
Moved StorageEngine onto drizzled::Registry.
37
drizzled::Registry<StorageEngine *> all_engines;
575.1.5 by Monty Taylor
Moved stuff to handlerton.cc
38
971.1.22 by Monty Taylor
Moved storage engine initialization to init methods.
39
static void add_storage_engine(StorageEngine *engine)
40
{
971.1.25 by Monty Taylor
Moved StorageEngine onto drizzled::Registry.
41
  all_engines.add(engine);
971.1.22 by Monty Taylor
Moved storage engine initialization to init methods.
42
}
43
44
static void remove_storage_engine(StorageEngine *engine)
45
{
971.1.25 by Monty Taylor
Moved StorageEngine onto drizzled::Registry.
46
  all_engines.remove(engine);
971.1.22 by Monty Taylor
Moved storage engine initialization to init methods.
47
}
48
971.1.14 by Monty Taylor
Slurp around strings rather than char* for storage engine name.
49
StorageEngine::StorageEngine(const std::string name_arg,
964.1.6 by Monty Taylor
Moved savepoint stuff to protected virtual methods, moved the offset to private, and moved the logic about adding the offset to the passed-in pointer and adding the offset to the global offset inside of the class.
50
                             const std::bitset<HTON_BIT_SIZE> &flags_arg,
51
                             size_t savepoint_offset_arg,
52
                             bool support_2pc)
53
    : name(name_arg), two_phase_commit(support_2pc), enabled(true),
54
      flags(flags_arg),
55
      savepoint_offset(savepoint_alloc_size),
56
      orig_savepoint_offset(savepoint_offset_arg),
57
      slot(0)
58
{
59
  if (enabled)
60
  {
61
    savepoint_alloc_size+= orig_savepoint_offset;
62
    slot= total_ha++;
63
    if (two_phase_commit)
64
        total_ha_2pc++;
968.2.29 by Monty Taylor
First steps towards new plugin reg.
65
  }
964.1.6 by Monty Taylor
Moved savepoint stuff to protected virtual methods, moved the offset to private, and moved the logic about adding the offset to the passed-in pointer and adding the offset to the global offset inside of the class.
66
}
67
68
69
StorageEngine::~StorageEngine()
70
{
71
  savepoint_alloc_size-= orig_savepoint_offset;
72
}
73
74
960.2.35 by Monty Taylor
Fixed default value returned.
75
/* args: current_session, db, name */
960.2.38 by Monty Taylor
Removed extraneous send myself to myself argument.
76
int StorageEngine::table_exists_in_engine(Session*, const char *, const char *)
960.2.35 by Monty Taylor
Fixed default value returned.
77
{
78
  return HA_ERR_NO_SUCH_TABLE;
79
}
575.1.5 by Monty Taylor
Moved stuff to handlerton.cc
80
81
82
/**
960.2.24 by Monty Taylor
Changed handlerton to StorageEngine.
83
  Return the default storage engine StorageEngine for thread
575.1.5 by Monty Taylor
Moved stuff to handlerton.cc
84
960.2.39 by Monty Taylor
Removed more handlerton naming references.
85
  @param ha_default_storage_engine(session)
575.1.5 by Monty Taylor
Moved stuff to handlerton.cc
86
  @param session         current thread
87
88
  @return
960.2.24 by Monty Taylor
Changed handlerton to StorageEngine.
89
    pointer to StorageEngine
575.1.5 by Monty Taylor
Moved stuff to handlerton.cc
90
*/
960.2.39 by Monty Taylor
Removed more handlerton naming references.
91
StorageEngine *ha_default_storage_engine(Session *session)
575.1.5 by Monty Taylor
Moved stuff to handlerton.cc
92
{
971.1.21 by Monty Taylor
Store StorageEngine in system variables, rather than storage engine plugin.
93
  if (session->variables.storage_engine)
94
    return session->variables.storage_engine;
95
  return global_system_variables.storage_engine;
575.1.5 by Monty Taylor
Moved stuff to handlerton.cc
96
}
97
98
99
/**
960.2.24 by Monty Taylor
Changed handlerton to StorageEngine.
100
  Return the storage engine StorageEngine for the supplied name
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
101
575.1.5 by Monty Taylor
Moved stuff to handlerton.cc
102
  @param session         current thread
103
  @param name        name of storage engine
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
104
575.1.5 by Monty Taylor
Moved stuff to handlerton.cc
105
  @return
106
    pointer to storage engine plugin handle
107
*/
971.1.21 by Monty Taylor
Store StorageEngine in system variables, rather than storage engine plugin.
108
StorageEngine *ha_resolve_by_name(Session *session, const LEX_STRING *name)
575.1.5 by Monty Taylor
Moved stuff to handlerton.cc
109
{
110
971.1.25 by Monty Taylor
Moved StorageEngine onto drizzled::Registry.
111
  string find_str(name->str, name->length);
112
  transform(find_str.begin(), find_str.end(),
113
            find_str.begin(), ::tolower);
114
  string default_str("default");
115
  if (find_str == default_str)
971.1.21 by Monty Taylor
Store StorageEngine in system variables, rather than storage engine plugin.
116
    return ha_default_storage_engine(session);
117
    
971.1.25 by Monty Taylor
Moved StorageEngine onto drizzled::Registry.
118
119
  StorageEngine *engine= all_engines.find(find_str);
120
121
  if (engine && engine->is_user_selectable())
122
    return engine;
575.1.5 by Monty Taylor
Moved stuff to handlerton.cc
123
124
  return NULL;
125
}
126
127
128
handler *get_new_handler(TABLE_SHARE *share, MEM_ROOT *alloc,
960.2.38 by Monty Taylor
Removed extraneous send myself to myself argument.
129
                         StorageEngine *engine)
575.1.5 by Monty Taylor
Moved stuff to handlerton.cc
130
{
131
  handler *file;
132
964.1.3 by Monty Taylor
Refactored state into is_enabled() call.
133
  if (engine && engine->is_enabled())
575.1.5 by Monty Taylor
Moved stuff to handlerton.cc
134
  {
960.2.38 by Monty Taylor
Removed extraneous send myself to myself argument.
135
    if ((file= engine->create(share, alloc)))
575.1.5 by Monty Taylor
Moved stuff to handlerton.cc
136
      file->init();
137
    return(file);
138
  }
139
  /*
140
    Try the default table type
141
    Here the call to current_session() is ok as we call this function a lot of
142
    times but we enter this branch very seldom.
143
  */
960.2.39 by Monty Taylor
Removed more handlerton naming references.
144
  return(get_new_handler(share, alloc, ha_default_storage_engine(current_session)));
575.1.5 by Monty Taylor
Moved stuff to handlerton.cc
145
}
146
971.1.28 by Monty Taylor
Moved ha_close_connection
147
class StorageEngineCloseConnection
148
  : public unary_function<StorageEngine *, void>
149
{
150
  Session *session;
151
public:
152
  StorageEngineCloseConnection(Session *session_arg) : session(session_arg) {}
153
  /*
154
    there's no need to rollback here as all transactions must
155
    be rolled back already
156
  */
157
  inline result_type operator() (argument_type engine)
158
  {
159
    if (engine->is_enabled() && 
160
      session_get_ha_data(session, engine))
161
    engine->close_connection(session);
162
  }
163
};
164
165
/**
166
  @note
167
    don't bother to rollback here, it's done already
168
*/
169
void ha_close_connection(Session* session)
170
{
171
  for_each(all_engines.begin(), all_engines.end(),
172
           StorageEngineCloseConnection(session));
173
}
575.1.5 by Monty Taylor
Moved stuff to handlerton.cc
174
971.1.27 by Monty Taylor
Moved first storage engine plugin_foreach.
175
void ha_drop_database(char* path)
176
{
177
  for_each(all_engines.begin(), all_engines.end(),
178
           bind2nd(mem_fun(&StorageEngine::drop_database),path));
179
}
180
971.1.30 by Monty Taylor
Migrated commit_or_rollback_by_xid.
181
int ha_commit_or_rollback_by_xid(XID *xid, bool commit)
182
{
183
  vector<int> results;
184
  
185
  if (commit)
186
    transform(all_engines.begin(), all_engines.end(), results.begin(),
187
              bind2nd(mem_fun(&StorageEngine::commit_by_xid),xid));
188
  else
189
    transform(all_engines.begin(), all_engines.end(), results.begin(),
190
              bind2nd(mem_fun(&StorageEngine::rollback_by_xid),xid));
191
192
  if (find_if(results.begin(), results.end(), bind2nd(equal_to<int>(),0))
193
         == results.end())
194
    return 1;
195
  return 0;
196
}
971.1.27 by Monty Taylor
Moved first storage engine plugin_foreach.
197
971.1.31 by Monty Taylor
Killed more plugin_foreach.
198
199
/**
200
  @details
201
  This function should be called when MySQL sends rows of a SELECT result set
202
  or the EOF mark to the client. It releases a possible adaptive hash index
203
  S-latch held by session in InnoDB and also releases a possible InnoDB query
204
  FIFO ticket to enter InnoDB. To save CPU time, InnoDB allows a session to
205
  keep them over several calls of the InnoDB handler interface when a join
206
  is executed. But when we let the control to pass to the client they have
207
  to be released because if the application program uses mysql_use_result(),
208
  it may deadlock on the S-latch if the application on another connection
209
  performs another SQL query. In MySQL-4.1 this is even more important because
210
  there a connection can have several SELECT queries open at the same time.
211
212
  @param session           the thread handle of the current connection
213
214
  @return
215
    always 0
216
*/
217
int ha_release_temporary_latches(Session *session)
218
{
219
  for_each(all_engines.begin(), all_engines.end(),
220
           bind2nd(mem_fun(&StorageEngine::release_temporary_latches),session));
221
  return 0;
222
}
223
224
225
bool ha_flush_logs(StorageEngine *engine)
226
{
227
  if (engine == NULL)
228
  {
229
    if (find_if(all_engines.begin(), all_engines.end(),
230
            mem_fun(&StorageEngine::flush_logs))
231
          != all_engines.begin())
232
      return true;
233
  }
234
  else
235
  {
236
    if ((!engine->is_enabled()) ||
237
        (engine->flush_logs()))
238
      return true;
239
  }
240
  return false;
241
}
242
971.1.35 by Monty Taylor
One more plugin_foreach down.
243
/**
244
  recover() step of xa.
245
246
  @note
247
    there are three modes of operation:
248
    - automatic recover after a crash
249
    in this case commit_list != 0, tc_heuristic_recover==0
250
    all xids from commit_list are committed, others are rolled back
251
    - manual (heuristic) recover
252
    in this case commit_list==0, tc_heuristic_recover != 0
253
    DBA has explicitly specified that all prepared transactions should
254
    be committed (or rolled back).
255
    - no recovery (MySQL did not detect a crash)
256
    in this case commit_list==0, tc_heuristic_recover == 0
257
    there should be no prepared transactions in this case.
258
*/
259
class XARecover : unary_function<StorageEngine *, void>
260
{
261
  int trans_len, found_foreign_xids, found_my_xids;
262
  bool result;
263
  XID *trans_list;
264
  HASH *commit_list;
265
  bool dry_run;
266
public:
267
  XARecover(XID *trans_list_arg, int trans_len_arg,
268
            HASH *commit_list_arg, bool dry_run_arg) 
269
    : trans_len(trans_len_arg), found_foreign_xids(0), found_my_xids(0),
270
      trans_list(trans_list_arg), commit_list(commit_list_arg),
271
      dry_run(dry_run_arg)
272
  {}
273
  
274
  int getForeignXIDs()
275
  {
276
    return found_foreign_xids; 
277
  }
278
279
  int getMyXIDs()
280
  {
281
    return found_my_xids; 
282
  }
283
284
  result_type operator() (argument_type engine)
285
  {
286
  
287
    int got;
288
  
289
    if (engine->is_enabled())
290
    {
291
      while ((got= engine->recover(trans_list, trans_len)) > 0 )
292
      {
293
        errmsg_printf(ERRMSG_LVL_INFO,
294
                      _("Found %d prepared transaction(s) in %s"),
295
                      got, engine->getName().c_str());
296
        for (int i=0; i < got; i ++)
297
        {
298
          my_xid x=trans_list[i].get_my_xid();
299
          if (!x) // not "mine" - that is generated by external TM
300
          {
301
            xid_cache_insert(trans_list+i, XA_PREPARED);
302
            found_foreign_xids++;
303
            continue;
304
          }
305
          if (dry_run)
306
          {
307
            found_my_xids++;
308
            continue;
309
          }
310
          // recovery mode
311
          if (commit_list ?
312
              hash_search(commit_list, (unsigned char *)&x, sizeof(x)) != 0 :
313
              tc_heuristic_recover == TC_HEURISTIC_RECOVER_COMMIT)
314
          {
315
            engine->commit_by_xid(trans_list+i);
316
          }
317
          else
318
          {
319
            engine->rollback_by_xid(trans_list+i);
320
          }
321
        }
322
        if (got < trans_len)
323
          break;
324
      }
325
    }
326
  }
327
328
};
329
330
int ha_recover(HASH *commit_list)
331
{
332
  XID *trans_list= NULL;
333
  int trans_len= 0;
334
335
  bool dry_run= (commit_list==0 && tc_heuristic_recover==0);
336
337
  /* commit_list and tc_heuristic_recover cannot be set both */
338
  assert(commit_list==0 || tc_heuristic_recover==0);
339
340
  /* if either is set, total_ha_2pc must be set too */
341
  if (total_ha_2pc <= 1)
342
    return 0;
343
344
345
#ifndef WILL_BE_DELETED_LATER
346
347
  /*
348
    for now, only InnoDB supports 2pc. It means we can always safely
349
    rollback all pending transactions, without risking inconsistent data
350
  */
351
352
  assert(total_ha_2pc == 2); // only InnoDB and binlog
353
  tc_heuristic_recover= TC_HEURISTIC_RECOVER_ROLLBACK; // forcing ROLLBACK
354
  dry_run=false;
355
#endif
356
  for (trans_len= MAX_XID_LIST_SIZE ;
357
       trans_list==0 && trans_len > MIN_XID_LIST_SIZE; trans_len/=2)
358
  {
359
    trans_list=(XID *)malloc(trans_len*sizeof(XID));
360
  }
361
  if (!trans_list)
362
  {
363
    errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_OUTOFMEMORY), trans_len*sizeof(XID));
364
    return(1);
365
  }
366
367
  if (commit_list)
368
    errmsg_printf(ERRMSG_LVL_INFO, _("Starting crash recovery..."));
369
370
371
  XARecover recover_func(trans_list, trans_len, commit_list, dry_run);
372
  for_each(all_engines.begin(), all_engines.end(), recover_func);
373
  free(trans_list);
374
 
375
  if (recover_func.getForeignXIDs())
376
    errmsg_printf(ERRMSG_LVL_WARN,
377
                  _("Found %d prepared XA transactions"),
378
                  recover_func.getForeignXIDs());
379
  if (dry_run && recover_func.getMyXIDs())
380
  {
381
    errmsg_printf(ERRMSG_LVL_ERROR,
382
                  _("Found %d prepared transactions! It means that drizzled "
383
                    "was not shut down properly last time and critical "
384
                    "recovery information (last binlog or %s file) was "
385
                    "manually deleted after a crash. You have to start "
386
                    "drizzled with the --tc-heuristic-recover switch to "
387
                    "commit or rollback pending transactions."),
388
                    recover_func.getMyXIDs(), opt_tc_log_file);
389
    return(1);
390
  }
391
  if (commit_list)
392
    errmsg_printf(ERRMSG_LVL_INFO, _("Crash recovery finished."));
393
  return(0);
394
}
395
971.1.36 by Monty Taylor
Removed another plugin_foreach. This time, noticing that the warning was pretty useles, as it only tested whether or not you have ANY storage engines at all. :)
396
int ha_start_consistent_snapshot(Session *session)
397
{
398
  for_each(all_engines.begin(), all_engines.end(),
399
           bind2nd(mem_fun(&StorageEngine::start_consistent_snapshot),session));
400
  return 0;
401
}
402
971.1.37 by Monty Taylor
Another one bites the dust.
403
/**
404
  Ask handler if the table exists in engine.
405
  @retval
406
    HA_ERR_NO_SUCH_TABLE     Table does not exist
407
  @retval
408
    HA_ERR_TABLE_EXIST       Table exists
409
  @retval
410
    \#                  Error code
411
*/
412
413
class TableExistsInStorageEngine: public unary_function<StorageEngine *,bool>
414
{
415
  Session *session;
416
  const char *db;
417
  const char *name;
418
public:
419
  TableExistsInStorageEngine(Session *session_arg,
420
                             const char *db_arg, const char *name_arg)
421
    :session(session_arg), db(db_arg), name(name_arg) {}
422
  result_type operator() (argument_type engine)
423
  {
424
    int ret= engine->table_exists_in_engine(session, db, name);
425
    return ret == HA_ERR_TABLE_EXIST;
426
  } 
427
};
428
429
/**
430
  Call this function in order to give the handler the possiblity
431
  to ask engine if there are any new tables that should be written to disk
432
  or any dropped tables that need to be removed from disk
433
*/
434
int ha_table_exists_in_engine(Session* session,
435
                              const char* db, const char* name,
436
                              StorageEngine **engine_arg)
437
{
438
  StorageEngine *engine= NULL;
439
440
  drizzled::Registry<StorageEngine *>::iterator iter=
441
    find_if(all_engines.begin(), all_engines.end(),
442
            TableExistsInStorageEngine(session, db, name));
443
  if (iter != all_engines.end()) 
444
  {
445
    engine= *iter;
446
  }
447
  else
448
  {
449
    /* Default way of knowing if a table exists. (checking .frm exists) */
450
451
    char path[FN_REFLEN];
452
    build_table_filename(path, sizeof(path),
453
                         db, name, "", 0);
454
    if (table_proto_exists(path)==EEXIST)
455
    {
988.1.1 by Jay Pipes
Changes libserialize to libdrizzledmessage per ML discussion. All GPB messages are now in the drizzled::message namespace.
456
      drizzled::message::Table table;
971.1.37 by Monty Taylor
Another one bites the dust.
457
      build_table_filename(path, sizeof(path),
458
                           db, name, ".dfe", 0);
459
      if(drizzle_read_table_proto(path, &table)==0)
460
      {
461
        LEX_STRING engine_name= { (char*)table.engine().name().c_str(),
462
                                 strlen(table.engine().name().c_str()) };
463
        engine= ha_resolve_by_name(session, &engine_name);
464
      }
465
    }
466
  }
467
468
  if(engine_arg)
469
    *engine_arg= engine;
470
471
  if (engine == NULL)
472
    return HA_ERR_NO_SUCH_TABLE;
473
  return HA_ERR_TABLE_EXIST;
474
}
475
971.1.38 by Monty Taylor
Moved delete table.
476
477
static const char *check_lowercase_names(handler *file, const char *path,
478
                                         char *tmp_path)
479
{
480
  if (lower_case_table_names != 2 || (file->ha_table_flags() & HA_FILE_BASED))
481
    return path;
482
483
  /* Ensure that table handler get path in lower case */
484
  if (tmp_path != path)
485
    strcpy(tmp_path, path);
486
487
  /*
488
    we only should turn into lowercase database/table part
489
    so start the process after homedirectory
490
  */
491
  my_casedn_str(files_charset_info, tmp_path + drizzle_data_home_len);
492
  return tmp_path;
493
}
494
495
/**
496
  An interceptor to hijack the text of the error message without
497
  setting an error in the thread. We need the text to present it
498
  in the form of a warning to the user.
499
*/
500
501
class Ha_delete_table_error_handler: public Internal_error_handler
502
{
503
public:
504
  Ha_delete_table_error_handler() : Internal_error_handler() {}
505
  virtual bool handle_error(uint32_t sql_errno,
506
                            const char *message,
507
                            DRIZZLE_ERROR::enum_warning_level level,
508
                            Session *session);
509
  char buff[DRIZZLE_ERRMSG_SIZE];
510
};
511
512
513
bool
514
Ha_delete_table_error_handler::
515
handle_error(uint32_t ,
516
             const char *message,
517
             DRIZZLE_ERROR::enum_warning_level ,
518
             Session *)
519
{
520
  /* Grab the error message */
521
  strncpy(buff, message, sizeof(buff)-1);
522
  return true;
523
}
524
525
526
class DeleteTableStorageEngine
527
  : public unary_function<StorageEngine *, void>
528
{
529
  Session *session;
530
  const char *path;
531
  handler **file;
532
  int *dt_error;
533
public:
534
  DeleteTableStorageEngine(Session *session_arg, const char *path_arg,
535
                           handler **file_arg, int *error_arg)
536
    : session(session_arg), path(path_arg), file(file_arg), dt_error(error_arg) {}
537
538
  result_type operator() (argument_type engine)
539
  {
540
541
    handler *tmp_file;
542
    char tmp_path[FN_REFLEN];
543
544
    if(*dt_error!=ENOENT) /* already deleted table */
545
      return;
546
547
    if (!engine)
548
      return;
549
550
    if (!engine->is_enabled())
551
      return;
552
553
    if ((tmp_file= engine->create(NULL, session->mem_root)))
554
      tmp_file->init();
555
    else
556
      return;
557
558
    path= check_lowercase_names(tmp_file, path, tmp_path);
559
    int tmp_error= tmp_file->ha_delete_table(path);
560
561
    if(tmp_error!=ENOENT)
562
    {
563
      *dt_error= tmp_error;
564
      if(*file)
565
        delete *file;
566
      *file= tmp_file;
567
      return;
568
    }
569
    else
570
      delete tmp_file;
571
    
572
    return;
573
  }
574
};
575
576
/**
577
  This should return ENOENT if the file doesn't exists.
578
  The .frm file will be deleted only if we return 0 or ENOENT
579
*/
580
int ha_delete_table(Session *session, const char *path,
581
                    const char *db, const char *alias, bool generate_warning)
582
{
583
  TABLE_SHARE dummy_share;
584
  Table dummy_table;
585
  memset(&dummy_table, 0, sizeof(dummy_table));
586
  memset(&dummy_share, 0, sizeof(dummy_share));
587
588
  dummy_table.s= &dummy_share;
589
590
  int error= ENOENT;
591
  handler *file= NULL;
592
593
  for_each(all_engines.begin(), all_engines.end(),
594
           DeleteTableStorageEngine(session, path, &file, &error));
595
596
  if (error && generate_warning)
597
  {
598
    /*
599
      Because file->print_error() use my_error() to generate the error message
600
      we use an internal error handler to intercept it and store the text
601
      in a temporary buffer. Later the message will be presented to user
602
      as a warning.
603
    */
604
    Ha_delete_table_error_handler ha_delete_table_error_handler;
605
606
    /* Fill up strucutures that print_error may need */
607
    dummy_share.path.str= (char*) path;
608
    dummy_share.path.length= strlen(path);
609
    dummy_share.db.str= (char*) db;
610
    dummy_share.db.length= strlen(db);
611
    dummy_share.table_name.str= (char*) alias;
612
    dummy_share.table_name.length= strlen(alias);
613
    dummy_table.alias= alias;
614
615
616
    if(file != NULL)
617
    {
618
      file->change_table_ptr(&dummy_table, &dummy_share);
619
620
      session->push_internal_handler(&ha_delete_table_error_handler);
621
      file->print_error(error, 0);
622
623
      session->pop_internal_handler();
624
    }
625
    else
626
      error= -1; /* General form of fail. maybe bad FRM */
627
628
    /*
629
      XXX: should we convert *all* errors to warnings here?
630
      What if the error is fatal?
631
    */
632
    push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR, error,
633
                 ha_delete_table_error_handler.buff);
634
  }
635
636
  if(file)
637
    delete file;
638
639
  return error;
640
}
641
642
/**
643
  Initiates table-file and calls appropriate database-creator.
644
645
  @retval
646
   0  ok
647
  @retval
648
   1  error
649
*/
650
int ha_create_table(Session *session, const char *path,
651
                    const char *db, const char *table_name,
652
                    HA_CREATE_INFO *create_info,
653
                    bool update_create_info)
654
{
655
  int error= 1;
656
  Table table;
657
  char name_buff[FN_REFLEN];
658
  const char *name;
659
  TABLE_SHARE share;
660
661
  init_tmp_table_share(session, &share, db, 0, table_name, path);
662
  if (open_table_def(session, &share, 0) ||
663
      open_table_from_share(session, &share, "", 0, (uint32_t) READ_ALL, 0, &table,
664
                            OTM_CREATE))
665
    goto err;
666
667
  if (update_create_info)
668
    table.updateCreateInfo(create_info);
669
670
  name= check_lowercase_names(table.file, share.path.str, name_buff);
671
672
  error= table.file->ha_create(name, &table, create_info);
673
  table.closefrm(false);
674
  if (error)
675
  {
676
    sprintf(name_buff,"%s.%s",db,table_name);
677
    my_error(ER_CANT_CREATE_TABLE, MYF(ME_BELL+ME_WAITTANG), name_buff, error);
678
  }
679
err:
680
  free_table_share(&share);
681
  return(error != 0);
682
}
683
684
960.2.27 by Monty Taylor
Reworked transformed handlerton into class StorageEngine.
685
int storage_engine_finalizer(st_plugin_int *plugin)
575.1.5 by Monty Taylor
Moved stuff to handlerton.cc
686
{
960.2.27 by Monty Taylor
Reworked transformed handlerton into class StorageEngine.
687
  StorageEngine *engine= static_cast<StorageEngine *>(plugin->data);
575.1.5 by Monty Taylor
Moved stuff to handlerton.cc
688
971.1.22 by Monty Taylor
Moved storage engine initialization to init methods.
689
  remove_storage_engine(engine);
968.2.29 by Monty Taylor
First steps towards new plugin reg.
690
960.2.26 by Monty Taylor
Rename hton to engine.
691
  if (engine && plugin->plugin->deinit)
692
    (void)plugin->plugin->deinit(engine);
575.1.5 by Monty Taylor
Moved stuff to handlerton.cc
693
694
  return(0);
695
}
696
697
960.2.27 by Monty Taylor
Reworked transformed handlerton into class StorageEngine.
698
int storage_engine_initializer(st_plugin_int *plugin)
575.1.5 by Monty Taylor
Moved stuff to handlerton.cc
699
{
971.1.22 by Monty Taylor
Moved storage engine initialization to init methods.
700
  StorageEngine *engine= NULL;
575.1.5 by Monty Taylor
Moved stuff to handlerton.cc
701
702
  if (plugin->plugin->init)
703
  {
960.2.27 by Monty Taylor
Reworked transformed handlerton into class StorageEngine.
704
    if (plugin->plugin->init(&engine))
575.1.5 by Monty Taylor
Moved stuff to handlerton.cc
705
    {
960.2.27 by Monty Taylor
Reworked transformed handlerton into class StorageEngine.
706
      errmsg_printf(ERRMSG_LVL_ERROR,
707
                    _("Plugin '%s' init function returned error."),
708
                    plugin->name.str);
709
      return 1;
575.1.5 by Monty Taylor
Moved stuff to handlerton.cc
710
    }
711
  }
712
971.1.22 by Monty Taylor
Moved storage engine initialization to init methods.
713
  if (engine != NULL)
714
    add_storage_engine(engine);
575.1.5 by Monty Taylor
Moved stuff to handlerton.cc
715
960.2.27 by Monty Taylor
Reworked transformed handlerton into class StorageEngine.
716
  plugin->data= engine;
965.1.1 by Brian Aker
Refactor plugin loading to remove mask (one step closer to getting rid of
717
  plugin->isInited= true;
810 by Brian Aker
Fix for making sure I_S has good information about which plugins are
718
965.1.1 by Brian Aker
Refactor plugin loading to remove mask (one step closer to getting rid of
719
  return 0;
575.1.5 by Monty Taylor
Moved stuff to handlerton.cc
720
}
721
971.1.14 by Monty Taylor
Slurp around strings rather than char* for storage engine name.
722
const string ha_resolve_storage_engine_name(const StorageEngine *engine)
575.1.5 by Monty Taylor
Moved stuff to handlerton.cc
723
{
971.1.14 by Monty Taylor
Slurp around strings rather than char* for storage engine name.
724
  return engine == NULL ? string("UNKNOWN") : engine->getName();
575.1.5 by Monty Taylor
Moved stuff to handlerton.cc
725
}
726