~posulliv/drizzle/optimizer-style-cleanup

« back to all changes in this revision

Viewing changes to plugin/innobase/handler/ha_innodb.cc

  • Committer: Padraig O'Sullivan
  • Date: 2010-04-17 01:38:47 UTC
  • mfrom: (1237.9.238 bad-staging)
  • Revision ID: osullivan.padraig@gmail.com-20100417013847-ibjioqsfbmf5yg4g
Merge trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
80
80
#include "drizzled/field/varstring.h"
81
81
#include "drizzled/field/timestamp.h"
82
82
#include "drizzled/plugin/xa_storage_engine.h"
 
83
#include "drizzled/plugin/daemon.h"
83
84
#include "drizzled/memory/multi_malloc.h"
84
85
#include "drizzled/pthread_globals.h"
85
86
#include "drizzled/named_savepoint.h"
178
179
static const long AUTOINC_NO_LOCKING = 2;
179
180
 
180
181
static long innobase_mirrored_log_groups, innobase_log_files_in_group,
181
 
        innobase_log_buffer_size,
182
 
        innobase_additional_mem_pool_size, innobase_file_io_threads,
183
 
        innobase_force_recovery, innobase_open_files,
184
 
        innobase_autoinc_lock_mode;
 
182
  innobase_log_buffer_size,
 
183
  innobase_additional_mem_pool_size, innobase_file_io_threads,
 
184
  innobase_force_recovery, innobase_open_files,
 
185
  innobase_autoinc_lock_mode;
185
186
static ulong innobase_commit_concurrency = 0;
186
187
static ulong innobase_read_io_threads;
187
188
static ulong innobase_write_io_threads;
194
195
/* The default values for the following char* start-up parameters
195
196
are determined in innobase_init below: */
196
197
 
197
 
static char*    innobase_data_home_dir                  = NULL;
198
 
static char*    innobase_data_file_path                 = NULL;
199
 
static char*    innobase_log_group_home_dir             = NULL;
200
 
static char*    innobase_file_format_name               = NULL;
201
 
static char*    innobase_change_buffering               = NULL;
 
198
static char*  innobase_data_home_dir      = NULL;
 
199
static char*  innobase_data_file_path     = NULL;
 
200
static char*  innobase_log_group_home_dir   = NULL;
 
201
static char*  innobase_file_format_name   = NULL;
 
202
static char*  innobase_change_buffering   = NULL;
202
203
 
203
204
/* Note: This variable can be set to on/off and any of the supported
204
205
file formats in the configuration file, but can only be set to any
205
206
of the supported file formats during runtime. */
206
 
static char*    innobase_file_format_check              = NULL;
 
207
static char*  innobase_file_format_check    = NULL;
207
208
 
208
209
/* The following has a misleading name: starting from 4.0.5, this also
209
210
affects Windows: */
210
 
static char*    innobase_unix_file_flush_method         = NULL;
 
211
static char*  innobase_unix_file_flush_method   = NULL;
211
212
 
212
213
/* Below we have boolean-valued start-up parameters, and their default
213
214
values */
214
215
 
215
 
static ulong    innobase_fast_shutdown                  = 1;
 
216
static ulong  innobase_fast_shutdown      = 1;
216
217
#ifdef UNIV_LOG_ARCHIVE
217
 
static my_bool  innobase_log_archive                    = FALSE;
218
 
static char*    innobase_log_arch_dir                   = NULL;
 
218
static my_bool  innobase_log_archive      = FALSE;
 
219
static char*  innobase_log_arch_dir     = NULL;
219
220
#endif /* UNIV_LOG_ARCHIVE */
220
 
static my_bool  innobase_use_doublewrite                = TRUE;
221
 
static my_bool  innobase_use_checksums                  = TRUE;
222
 
static my_bool  innobase_locks_unsafe_for_binlog        = TRUE;
223
 
static my_bool  innobase_rollback_on_timeout            = FALSE;
224
 
static my_bool  innobase_create_status_file             = FALSE;
225
 
static my_bool  innobase_stats_on_metadata              = TRUE;
226
 
 
227
 
static char*    internal_innobase_data_file_path        = NULL;
228
 
 
229
 
static char*    innodb_version_str = (char*) INNODB_VERSION_STR;
 
221
static my_bool  innobase_use_doublewrite    = TRUE;
 
222
static my_bool  innobase_use_checksums      = TRUE;
 
223
static my_bool  innobase_rollback_on_timeout    = FALSE;
 
224
static my_bool  innobase_create_status_file   = FALSE;
 
225
static my_bool  innobase_stats_on_metadata    = TRUE;
 
226
 
 
227
static char*  internal_innobase_data_file_path  = NULL;
 
228
 
 
229
static char*  innodb_version_str = (char*) INNODB_VERSION_STR;
230
230
 
231
231
/* The following counter is used to convey information to InnoDB
232
232
about server activity: in selects it is not sensible to call
233
233
srv_active_wake_master_thread after each fetch or search, we only do
234
234
it every INNOBASE_WAKE_INTERVAL'th step. */
235
235
 
236
 
#define INNOBASE_WAKE_INTERVAL  32
237
 
static ulong    innobase_active_counter = 0;
238
 
 
239
 
static hash_table_t*    innobase_open_tables;
240
 
 
241
 
#ifdef __NETWARE__      /* some special cleanup for NetWare */
 
236
#define INNOBASE_WAKE_INTERVAL  32
 
237
static ulong  innobase_active_counter = 0;
 
238
 
 
239
static hash_table_t*  innobase_open_tables;
 
240
 
 
241
#ifdef __NETWARE__  /* some special cleanup for NetWare */
242
242
bool nw_panic = FALSE;
243
243
#endif
244
244
 
245
245
/** Allowed values of innodb_change_buffering */
246
246
static const char* innobase_change_buffering_values[IBUF_USE_COUNT] = {
247
 
        "none",         /* IBUF_USE_NONE */
248
 
        "inserts"       /* IBUF_USE_INSERT */
 
247
  "none",   /* IBUF_USE_NONE */
 
248
  "inserts" /* IBUF_USE_INSERT */
249
249
};
250
250
 
251
251
/********************************************************************
255
255
  NULL
256
256
};
257
257
 
 
258
#define DEFAULT_FILE_EXTENSION ".dfe" // Deep Fried Elephant
 
259
 
258
260
static INNOBASE_SHARE *get_share(const char *table_name);
259
261
static void free_share(INNOBASE_SHARE *share);
260
262
 
261
263
class InnobaseEngine : public plugin::XaStorageEngine
262
264
{
263
265
public:
264
 
  InnobaseEngine(string name_arg) :
 
266
  explicit InnobaseEngine(string name_arg) :
265
267
    plugin::XaStorageEngine(name_arg,
266
 
                          HTON_NULL_IN_KEY |
267
 
                          HTON_CAN_INDEX_BLOBS |
268
 
                          HTON_PRIMARY_KEY_REQUIRED_FOR_POSITION |
269
 
                          HTON_PRIMARY_KEY_IN_READ_INDEX |
270
 
                          HTON_PARTIAL_COLUMN_READ |
271
 
                          HTON_TABLE_SCAN_ON_INDEX |
272
 
                          HTON_HAS_DOES_TRANSACTIONS)
 
268
                            HTON_NULL_IN_KEY |
 
269
                            HTON_CAN_INDEX_BLOBS |
 
270
                            HTON_PRIMARY_KEY_IN_READ_INDEX |
 
271
                            HTON_PARTIAL_COLUMN_READ |
 
272
                            HTON_TABLE_SCAN_ON_INDEX |
 
273
                            HTON_HAS_FOREIGN_KEYS |
 
274
                            HTON_HAS_DOES_TRANSACTIONS)
273
275
  {
274
276
    table_definition_ext= plugin::DEFAULT_DEFINITION_FILE_EXT;
275
277
    addAlias("INNOBASE");
276
278
  }
 
279
 
 
280
  virtual ~InnobaseEngine()
 
281
  {
 
282
    int err= 0;
 
283
    if (innodb_inited) {
 
284
 
 
285
      srv_fast_shutdown = (ulint) innobase_fast_shutdown;
 
286
      innodb_inited = 0;
 
287
      hash_table_free(innobase_open_tables);
 
288
      innobase_open_tables = NULL;
 
289
      if (innobase_shutdown_for_mysql() != DB_SUCCESS) {
 
290
        err = 1;
 
291
      }
 
292
      srv_free_paths_and_sizes();
 
293
      if (internal_innobase_data_file_path)
 
294
        free(internal_innobase_data_file_path);
 
295
      pthread_mutex_destroy(&innobase_share_mutex);
 
296
      pthread_mutex_destroy(&prepare_commit_mutex);
 
297
      pthread_mutex_destroy(&commit_threads_m);
 
298
      pthread_mutex_destroy(&commit_cond_m);
 
299
      pthread_cond_destroy(&commit_cond);
 
300
    }
 
301
  }
 
302
 
277
303
private:
278
304
  virtual int doStartTransaction(Session *session, start_transaction_option_t options);
279
305
  virtual void doStartStatement(Session *session);
283
309
  int
284
310
  close_connection(
285
311
/*======================*/
286
 
                        /* out: 0 or error number */
287
 
        Session*        session);       /* in: handle to the MySQL thread of the user
288
 
                        whose resources should be free'd */
 
312
      /* out: 0 or error number */
 
313
  Session*  session); /* in: handle to the MySQL thread of the user
 
314
      whose resources should be free'd */
289
315
 
290
316
  virtual int doSetSavepoint(Session* session,
291
317
                                 drizzled::NamedSavepoint &savepoint);
310
336
  int
311
337
  doXaPrepare(
312
338
  /*================*/
313
 
                        /* out: 0 or error number */
314
 
        Session*        session,        /* in: handle to the MySQL thread of the user
315
 
                        whose XA transaction should be prepared */
316
 
        bool    all);   /* in: TRUE - commit transaction
317
 
                        FALSE - the current SQL statement ended */
 
339
        /* out: 0 or error number */
 
340
    Session*  session,  /* in: handle to the MySQL thread of the user
 
341
        whose XA transaction should be prepared */
 
342
    bool  all); /* in: TRUE - commit transaction
 
343
        FALSE - the current SQL statement ended */
318
344
  /***********************************************************************
319
345
  This function is used to recover X/Open XA distributed transactions   */
320
346
  virtual
321
347
  int
322
348
  doXaRecover(
323
349
  /*================*/
324
 
                                /* out: number of prepared transactions
325
 
                                stored in xid_list */
326
 
        ::drizzled::XID*        xid_list,       /* in/out: prepared transactions */
327
 
        size_t len);            /* in: number of slots in xid_list */
 
350
          /* out: number of prepared transactions
 
351
          stored in xid_list */
 
352
    ::drizzled::XID*  xid_list, /* in/out: prepared transactions */
 
353
    size_t len);    /* in: number of slots in xid_list */
328
354
  /***********************************************************************
329
355
  This function is used to commit one X/Open XA distributed transaction
330
356
  which is in the prepared state */
332
358
  int
333
359
  doXaCommitXid(
334
360
  /*===================*/
335
 
                        /* out: 0 or error number */
336
 
        ::drizzled::XID*        xid);   /* in: X/Open XA transaction identification */
 
361
        /* out: 0 or error number */
 
362
    ::drizzled::XID*  xid); /* in: X/Open XA transaction identification */
337
363
  /***********************************************************************
338
364
  This function is used to rollback one X/Open XA distributed transaction
339
365
  which is in the prepared state */
341
367
  int
342
368
  doXaRollbackXid(
343
369
  /*=====================*/
344
 
                        /* out: 0 or error number */
345
 
        ::drizzled::XID *xid);  /* in: X/Open XA transaction identification */
 
370
        /* out: 0 or error number */
 
371
    ::drizzled::XID *xid);  /* in: X/Open XA transaction identification */
346
372
 
347
373
  virtual Cursor *create(TableShare &table,
348
374
                         memory::Root *mem_root)
355
381
  bool
356
382
  doDropSchema(
357
383
  /*===================*/
358
 
                        /* out: error number */
359
 
        const std::string       &schema_name);  /* in: database path; inside InnoDB the name
360
 
                        of the last directory in the path is used as
361
 
                        the database name: for example, in 'mysql/data/test'
362
 
                        the database name is 'test' */
 
384
        /* out: error number */
 
385
    SchemaIdentifier  &identifier); /* in: database path; inside InnoDB the name
 
386
        of the last directory in the path is used as
 
387
        the database name: for example, in 'mysql/data/test'
 
388
        the database name is 'test' */
363
389
 
364
390
  /********************************************************************
365
391
  Flushes InnoDB logs to disk and makes a checkpoint. Really, a commit flushes
368
394
  bool
369
395
  flush_logs();
370
396
  /*================*/
371
 
                                /* out: TRUE if error */
 
397
          /* out: TRUE if error */
372
398
  
373
399
  /****************************************************************************
374
400
  Implements the SHOW INNODB STATUS command. Sends the output of the InnoDB
377
403
  bool
378
404
  show_status(
379
405
  /*===============*/
380
 
        Session*        session,        /* in: the MySQL query thread of the caller */
381
 
        stat_print_fn *stat_print,
382
 
        enum ha_stat_type stat_type);
 
406
    Session*  session,  /* in: the MySQL query thread of the caller */
 
407
    stat_print_fn *stat_print,
 
408
  enum ha_stat_type stat_type);
383
409
 
384
410
  virtual
385
411
  int
386
412
  doReleaseTemporaryLatches(
387
413
  /*===============================*/
388
 
                                /* out: 0 */
389
 
        Session*                session);       /* in: MySQL thread */
 
414
        /* out: 0 */
 
415
  Session*    session); /* in: MySQL thread */
390
416
 
391
417
 
392
418
  const char** bas_ext() const {
393
 
        return(ha_innobase_exts);
 
419
  return(ha_innobase_exts);
394
420
  }
395
421
 
396
 
  UNIV_INTERN int doCreateTable(Session *session,
397
 
                                const char *table_name,
398
 
                                Table& form,
 
422
  UNIV_INTERN int doCreateTable(Session &session,
 
423
                                Table &form,
 
424
                                drizzled::TableIdentifier &identifier,
399
425
                                message::Table&);
400
 
  UNIV_INTERN int doRenameTable(Session* session,
401
 
                                const char* from,
402
 
                                const char* to);
403
 
  UNIV_INTERN int doDropTable(Session& session, const string &table_path);
 
426
  UNIV_INTERN int doRenameTable(Session&, TableIdentifier &from, TableIdentifier &to);
 
427
  UNIV_INTERN int doDropTable(Session &session, TableIdentifier &identifier);
404
428
 
405
429
  UNIV_INTERN virtual bool get_error_message(int error, String *buf);
406
430
 
417
441
            HA_READ_RANGE |
418
442
            HA_KEYREAD_ONLY);
419
443
  }
 
444
 
 
445
  int doGetTableDefinition(drizzled::Session& session,
 
446
                           drizzled::TableIdentifier &identifier,
 
447
                           drizzled::message::Table &table_proto);
 
448
 
 
449
  void doGetTableNames(drizzled::CachedDirectory &directory,
 
450
           drizzled::SchemaIdentifier &schema_identifier,
 
451
                       std::set<std::string> &set_of_names);
 
452
 
 
453
  bool doDoesTableExist(drizzled::Session& session, drizzled::TableIdentifier &identifier);
 
454
 
 
455
  void doGetTableIdentifiers(drizzled::CachedDirectory &directory,
 
456
                             drizzled::SchemaIdentifier &schema_identifier,
 
457
                             drizzled::TableIdentifiers &set_of_identifiers);
420
458
};
421
459
 
 
460
void InnobaseEngine::doGetTableIdentifiers(drizzled::CachedDirectory &directory,
 
461
                                           drizzled::SchemaIdentifier &schema_identifier,
 
462
                                           drizzled::TableIdentifiers &set_of_identifiers)
 
463
{
 
464
  CachedDirectory::Entries entries= directory.getEntries();
 
465
 
 
466
  for (CachedDirectory::Entries::iterator entry_iter= entries.begin(); 
 
467
       entry_iter != entries.end(); ++entry_iter)
 
468
  {
 
469
    CachedDirectory::Entry *entry= *entry_iter;
 
470
    const string *filename= &entry->filename;
 
471
 
 
472
    assert(filename->size());
 
473
 
 
474
    const char *ext= strchr(filename->c_str(), '.');
 
475
 
 
476
    if (ext == NULL || my_strcasecmp(system_charset_info, ext, DEFAULT_FILE_EXTENSION) ||
 
477
        (filename->compare(0, strlen(TMP_FILE_PREFIX), TMP_FILE_PREFIX) == 0))
 
478
    { }
 
479
    else
 
480
    {
 
481
      char uname[NAME_LEN + 1];
 
482
      uint32_t file_name_len;
 
483
 
 
484
      file_name_len= filename_to_tablename(filename->c_str(), uname, sizeof(uname));
 
485
      // TODO: Remove need for memory copy here
 
486
      uname[file_name_len - sizeof(DEFAULT_FILE_EXTENSION) + 1]= '\0'; // Subtract ending, place NULL 
 
487
 
 
488
      set_of_identifiers.push_back(TableIdentifier(schema_identifier, uname));
 
489
    }
 
490
  }
 
491
}
 
492
 
 
493
bool InnobaseEngine::doDoesTableExist(Session&, TableIdentifier &identifier)
 
494
{
 
495
  string proto_path(identifier.getPath());
 
496
  proto_path.append(DEFAULT_FILE_EXTENSION);
 
497
 
 
498
  if (access(proto_path.c_str(), F_OK))
 
499
  {
 
500
    return false;
 
501
  }
 
502
 
 
503
  return true;
 
504
}
 
505
 
 
506
int InnobaseEngine::doGetTableDefinition(Session &,
 
507
                                         drizzled::TableIdentifier &identifier,
 
508
                                         message::Table &table_proto)
 
509
{
 
510
  string proto_path(identifier.getPath());
 
511
  proto_path.append(DEFAULT_FILE_EXTENSION);
 
512
 
 
513
  if (access(proto_path.c_str(), F_OK))
 
514
  {
 
515
    return errno;
 
516
  }
 
517
 
 
518
  if (StorageEngine::readTableFile(proto_path, table_proto))
 
519
    return EEXIST;
 
520
 
 
521
  return ENOENT;
 
522
}
 
523
 
 
524
void InnobaseEngine::doGetTableNames(CachedDirectory &directory, SchemaIdentifier&, set<string>& set_of_names)
 
525
{
 
526
  CachedDirectory::Entries entries= directory.getEntries();
 
527
 
 
528
  for (CachedDirectory::Entries::iterator entry_iter= entries.begin(); 
 
529
       entry_iter != entries.end(); ++entry_iter)
 
530
  {
 
531
    CachedDirectory::Entry *entry= *entry_iter;
 
532
    const string *filename= &entry->filename;
 
533
 
 
534
    assert(filename->size());
 
535
 
 
536
    const char *ext= strchr(filename->c_str(), '.');
 
537
 
 
538
    if (ext == NULL || my_strcasecmp(system_charset_info, ext, DEFAULT_FILE_EXTENSION) ||
 
539
        (filename->compare(0, strlen(TMP_FILE_PREFIX), TMP_FILE_PREFIX) == 0))
 
540
    { }
 
541
    else
 
542
    {
 
543
      char uname[NAME_LEN + 1];
 
544
      uint32_t file_name_len;
 
545
 
 
546
      file_name_len= filename_to_tablename(filename->c_str(), uname, sizeof(uname));
 
547
      // TODO: Remove need for memory copy here
 
548
      uname[file_name_len - sizeof(DEFAULT_FILE_EXTENSION) + 1]= '\0'; // Subtract ending, place NULL 
 
549
      set_of_names.insert(uname);
 
550
    }
 
551
  }
 
552
}
 
553
 
422
554
/** @brief Initialize the default value of innodb_commit_concurrency.
423
555
 
424
556
Once InnoDB is running, the innodb_commit_concurrency must not change
435
567
 
436
568
/************************************************************//**
437
569
Validate the file format name and return its corresponding id.
438
 
@return valid file format id */
 
570
@return valid file format id */
439
571
static
440
572
uint
441
573
innobase_file_format_name_lookup(
442
574
/*=============================*/
443
 
        const char*     format_name);           /*!< in: pointer to file format
444
 
                                                name */
 
575
  const char* format_name);   /*!< in: pointer to file format
 
576
            name */
445
577
/************************************************************//**
446
578
Validate the file format check config parameters, as a side effect it
447
579
sets the srv_check_file_format_at_startup variable.
448
 
@return true if one of  "on" or "off" */
 
580
@return true if one of  "on" or "off" */
449
581
static
450
582
bool
451
583
innobase_file_format_check_on_off(
452
584
/*==============================*/
453
 
        const char*     format_check);          /*!< in: parameter value */
 
585
  const char* format_check);    /*!< in: parameter value */
454
586
/************************************************************//**
455
587
Validate the file format check config parameters, as a side effect it
456
588
sets the srv_check_file_format_at_startup variable.
457
 
@return true if valid config value */
 
589
@return true if valid config value */
458
590
static
459
591
bool
460
592
innobase_file_format_check_validate(
461
593
/*================================*/
462
 
        const char*     format_check);          /*!< in: parameter value */
 
594
  const char* format_check);    /*!< in: parameter value */
463
595
 
464
596
static const char innobase_engine_name[]= "InnoDB";
465
597
 
466
598
/*************************************************************//**
467
599
Check for a valid value of innobase_commit_concurrency.
468
 
@return 0 for valid innodb_commit_concurrency */
 
600
@return 0 for valid innodb_commit_concurrency */
469
601
static
470
602
int
471
603
innobase_commit_concurrency_validate(
472
604
/*=================================*/
473
 
        Session*                        ,       /*!< in: thread handle */
474
 
        drizzle_sys_var*        ,       /*!< in: pointer to system
475
 
                                                variable */
476
 
        void*                           save,   /*!< out: immediate result
477
 
                                                for update function */
478
 
        drizzle_value*          value)  /*!< in: incoming string */
 
605
  Session*      , /*!< in: thread handle */
 
606
  drizzle_sys_var*  , /*!< in: pointer to system
 
607
            variable */
 
608
  void*       save, /*!< out: immediate result
 
609
            for update function */
 
610
  drizzle_value*    value)  /*!< in: incoming string */
479
611
{
480
 
        int64_t         intbuf;
481
 
        ulong           commit_concurrency;
482
 
 
483
 
        if (value->val_int(value, &intbuf)) {
484
 
                /* The value is NULL. That is invalid. */
485
 
                return(1);
486
 
        }
487
 
 
488
 
        *reinterpret_cast<ulong*>(save) = commit_concurrency
489
 
                = static_cast<ulong>(intbuf);
490
 
 
491
 
        /* Allow the value to be updated, as long as it remains zero
492
 
        or nonzero. */
493
 
        return(!(!commit_concurrency == !innobase_commit_concurrency));
 
612
  int64_t   intbuf;
 
613
  ulong   commit_concurrency;
 
614
 
 
615
  if (value->val_int(value, &intbuf)) {
 
616
    /* The value is NULL. That is invalid. */
 
617
    return(1);
 
618
  }
 
619
 
 
620
  *reinterpret_cast<ulong*>(save) = commit_concurrency
 
621
    = static_cast<ulong>(intbuf);
 
622
 
 
623
  /* Allow the value to be updated, as long as it remains zero
 
624
  or nonzero. */
 
625
  return(!(!commit_concurrency == !innobase_commit_concurrency));
494
626
}
495
627
 
496
628
static DRIZZLE_SessionVAR_BOOL(support_xa, PLUGIN_VAR_OPCMDARG,
512
644
  NULL, NULL, 50, 1, 1024 * 1024 * 1024, 0);
513
645
 
514
646
 
515
 
/***********************************************************************
516
 
Closes an InnoDB database. */
517
 
static
518
 
int
519
 
innobase_deinit(plugin::Registry &registry);
520
 
 
521
647
/*****************************************************************//**
522
648
Commits a transaction in an InnoDB database. */
523
649
static
524
650
void
525
651
innobase_commit_low(
526
652
/*================*/
527
 
        trx_t*  trx);   /*!< in: transaction handle */
 
653
  trx_t*  trx); /*!< in: transaction handle */
528
654
 
529
655
static drizzle_show_var innodb_status_variables[]= {
530
656
  {"buffer_pool_pages_data",
531
 
  (char*) &export_vars.innodb_buffer_pool_pages_data,     SHOW_LONG},
 
657
  (char*) &export_vars.innodb_buffer_pool_pages_data,   SHOW_LONG},
532
658
  {"buffer_pool_pages_dirty",
533
 
  (char*) &export_vars.innodb_buffer_pool_pages_dirty,    SHOW_LONG},
 
659
  (char*) &export_vars.innodb_buffer_pool_pages_dirty,    SHOW_LONG},
534
660
  {"buffer_pool_pages_flushed",
535
661
  (char*) &export_vars.innodb_buffer_pool_pages_flushed,  SHOW_LONG},
536
662
  {"buffer_pool_pages_free",
537
 
  (char*) &export_vars.innodb_buffer_pool_pages_free,     SHOW_LONG},
 
663
  (char*) &export_vars.innodb_buffer_pool_pages_free,   SHOW_LONG},
538
664
#ifdef UNIV_DEBUG
539
665
  {"buffer_pool_pages_latched",
540
666
  (char*) &export_vars.innodb_buffer_pool_pages_latched,  SHOW_LONG},
541
667
#endif /* UNIV_DEBUG */
542
668
  {"buffer_pool_pages_misc",
543
 
  (char*) &export_vars.innodb_buffer_pool_pages_misc,     SHOW_LONG},
 
669
  (char*) &export_vars.innodb_buffer_pool_pages_misc,   SHOW_LONG},
544
670
  {"buffer_pool_pages_total",
545
 
  (char*) &export_vars.innodb_buffer_pool_pages_total,    SHOW_LONG},
 
671
  (char*) &export_vars.innodb_buffer_pool_pages_total,    SHOW_LONG},
546
672
  {"buffer_pool_read_ahead_rnd",
547
673
  (char*) &export_vars.innodb_buffer_pool_read_ahead_rnd, SHOW_LONG},
548
674
  {"buffer_pool_read_ahead_seq",
550
676
  {"buffer_pool_read_requests",
551
677
  (char*) &export_vars.innodb_buffer_pool_read_requests,  SHOW_LONG},
552
678
  {"buffer_pool_reads",
553
 
  (char*) &export_vars.innodb_buffer_pool_reads,          SHOW_LONG},
 
679
  (char*) &export_vars.innodb_buffer_pool_reads,    SHOW_LONG},
554
680
  {"buffer_pool_wait_free",
555
 
  (char*) &export_vars.innodb_buffer_pool_wait_free,      SHOW_LONG},
 
681
  (char*) &export_vars.innodb_buffer_pool_wait_free,    SHOW_LONG},
556
682
  {"buffer_pool_write_requests",
557
683
  (char*) &export_vars.innodb_buffer_pool_write_requests, SHOW_LONG},
558
684
  {"data_fsyncs",
559
 
  (char*) &export_vars.innodb_data_fsyncs,                SHOW_LONG},
 
685
  (char*) &export_vars.innodb_data_fsyncs,      SHOW_LONG},
560
686
  {"data_pending_fsyncs",
561
 
  (char*) &export_vars.innodb_data_pending_fsyncs,        SHOW_LONG},
 
687
  (char*) &export_vars.innodb_data_pending_fsyncs,    SHOW_LONG},
562
688
  {"data_pending_reads",
563
 
  (char*) &export_vars.innodb_data_pending_reads,         SHOW_LONG},
 
689
  (char*) &export_vars.innodb_data_pending_reads,   SHOW_LONG},
564
690
  {"data_pending_writes",
565
 
  (char*) &export_vars.innodb_data_pending_writes,        SHOW_LONG},
 
691
  (char*) &export_vars.innodb_data_pending_writes,    SHOW_LONG},
566
692
  {"data_read",
567
 
  (char*) &export_vars.innodb_data_read,                  SHOW_LONG},
 
693
  (char*) &export_vars.innodb_data_read,      SHOW_LONG},
568
694
  {"data_reads",
569
 
  (char*) &export_vars.innodb_data_reads,                 SHOW_LONG},
 
695
  (char*) &export_vars.innodb_data_reads,     SHOW_LONG},
570
696
  {"data_writes",
571
 
  (char*) &export_vars.innodb_data_writes,                SHOW_LONG},
 
697
  (char*) &export_vars.innodb_data_writes,      SHOW_LONG},
572
698
  {"data_written",
573
 
  (char*) &export_vars.innodb_data_written,               SHOW_LONG},
 
699
  (char*) &export_vars.innodb_data_written,     SHOW_LONG},
574
700
  {"dblwr_pages_written",
575
 
  (char*) &export_vars.innodb_dblwr_pages_written,        SHOW_LONG},
 
701
  (char*) &export_vars.innodb_dblwr_pages_written,    SHOW_LONG},
576
702
  {"dblwr_writes",
577
 
  (char*) &export_vars.innodb_dblwr_writes,               SHOW_LONG},
 
703
  (char*) &export_vars.innodb_dblwr_writes,     SHOW_LONG},
578
704
  {"have_atomic_builtins",
579
 
  (char*) &export_vars.innodb_have_atomic_builtins,       SHOW_BOOL},
 
705
  (char*) &export_vars.innodb_have_atomic_builtins,   SHOW_BOOL},
580
706
  {"log_waits",
581
 
  (char*) &export_vars.innodb_log_waits,                  SHOW_LONG},
 
707
  (char*) &export_vars.innodb_log_waits,      SHOW_LONG},
582
708
  {"log_write_requests",
583
 
  (char*) &export_vars.innodb_log_write_requests,         SHOW_LONG},
 
709
  (char*) &export_vars.innodb_log_write_requests,   SHOW_LONG},
584
710
  {"log_writes",
585
 
  (char*) &export_vars.innodb_log_writes,                 SHOW_LONG},
 
711
  (char*) &export_vars.innodb_log_writes,     SHOW_LONG},
586
712
  {"os_log_fsyncs",
587
 
  (char*) &export_vars.innodb_os_log_fsyncs,              SHOW_LONG},
 
713
  (char*) &export_vars.innodb_os_log_fsyncs,      SHOW_LONG},
588
714
  {"os_log_pending_fsyncs",
589
 
  (char*) &export_vars.innodb_os_log_pending_fsyncs,      SHOW_LONG},
 
715
  (char*) &export_vars.innodb_os_log_pending_fsyncs,    SHOW_LONG},
590
716
  {"os_log_pending_writes",
591
 
  (char*) &export_vars.innodb_os_log_pending_writes,      SHOW_LONG},
 
717
  (char*) &export_vars.innodb_os_log_pending_writes,    SHOW_LONG},
592
718
  {"os_log_written",
593
 
  (char*) &export_vars.innodb_os_log_written,             SHOW_LONG},
 
719
  (char*) &export_vars.innodb_os_log_written,     SHOW_LONG},
594
720
  {"page_size",
595
 
  (char*) &export_vars.innodb_page_size,                  SHOW_LONG},
 
721
  (char*) &export_vars.innodb_page_size,      SHOW_LONG},
596
722
  {"pages_created",
597
 
  (char*) &export_vars.innodb_pages_created,              SHOW_LONG},
 
723
  (char*) &export_vars.innodb_pages_created,      SHOW_LONG},
598
724
  {"pages_read",
599
 
  (char*) &export_vars.innodb_pages_read,                 SHOW_LONG},
 
725
  (char*) &export_vars.innodb_pages_read,     SHOW_LONG},
600
726
  {"pages_written",
601
 
  (char*) &export_vars.innodb_pages_written,              SHOW_LONG},
 
727
  (char*) &export_vars.innodb_pages_written,      SHOW_LONG},
602
728
  {"row_lock_current_waits",
603
 
  (char*) &export_vars.innodb_row_lock_current_waits,     SHOW_LONG},
 
729
  (char*) &export_vars.innodb_row_lock_current_waits,   SHOW_LONG},
604
730
  {"row_lock_time",
605
 
  (char*) &export_vars.innodb_row_lock_time,              SHOW_LONGLONG},
 
731
  (char*) &export_vars.innodb_row_lock_time,      SHOW_LONGLONG},
606
732
  {"row_lock_time_avg",
607
 
  (char*) &export_vars.innodb_row_lock_time_avg,          SHOW_LONG},
 
733
  (char*) &export_vars.innodb_row_lock_time_avg,    SHOW_LONG},
608
734
  {"row_lock_time_max",
609
 
  (char*) &export_vars.innodb_row_lock_time_max,          SHOW_LONG},
 
735
  (char*) &export_vars.innodb_row_lock_time_max,    SHOW_LONG},
610
736
  {"row_lock_waits",
611
 
  (char*) &export_vars.innodb_row_lock_waits,             SHOW_LONG},
 
737
  (char*) &export_vars.innodb_row_lock_waits,     SHOW_LONG},
612
738
  {"rows_deleted",
613
 
  (char*) &export_vars.innodb_rows_deleted,               SHOW_LONG},
 
739
  (char*) &export_vars.innodb_rows_deleted,     SHOW_LONG},
614
740
  {"rows_inserted",
615
 
  (char*) &export_vars.innodb_rows_inserted,              SHOW_LONG},
 
741
  (char*) &export_vars.innodb_rows_inserted,      SHOW_LONG},
616
742
  {"rows_read",
617
 
  (char*) &export_vars.innodb_rows_read,                  SHOW_LONG},
 
743
  (char*) &export_vars.innodb_rows_read,      SHOW_LONG},
618
744
  {"rows_updated",
619
 
  (char*) &export_vars.innodb_rows_updated,               SHOW_LONG},
 
745
  (char*) &export_vars.innodb_rows_updated,     SHOW_LONG},
620
746
  {NULL, NULL, SHOW_LONG}
621
747
};
622
748
 
679
805
 
680
806
DRIZZLE: Note, we didn't change this name to avoid more ifdef forking 
681
807
         in non-Cursor code.
682
 
@return true if session is the replication thread */
 
808
@return true if session is the replication thread */
683
809
extern "C" UNIV_INTERN
684
810
ibool
685
811
thd_is_replication_slave_thread(
686
812
/*============================*/
687
 
        void*   )       /*!< in: thread handle (Session*) */
 
813
  void* ) /*!< in: thread handle (Session*) */
688
814
{
689
 
        return false;
 
815
  return false;
690
816
}
691
817
 
692
818
/******************************************************************//**
696
822
void
697
823
innodb_srv_conc_enter_innodb(
698
824
/*=========================*/
699
 
        trx_t*  trx)    /*!< in: transaction handle */
 
825
  trx_t*  trx)  /*!< in: transaction handle */
700
826
{
701
 
        if (UNIV_LIKELY(!srv_thread_concurrency)) {
702
 
 
703
 
                return;
704
 
        }
705
 
 
706
 
        srv_conc_enter_innodb(trx);
 
827
  if (UNIV_LIKELY(!srv_thread_concurrency)) {
 
828
 
 
829
    return;
 
830
  }
 
831
 
 
832
  srv_conc_enter_innodb(trx);
707
833
}
708
834
 
709
835
/******************************************************************//**
713
839
void
714
840
innodb_srv_conc_exit_innodb(
715
841
/*========================*/
716
 
        trx_t*  trx)    /*!< in: transaction handle */
 
842
  trx_t*  trx)  /*!< in: transaction handle */
717
843
{
718
 
        if (UNIV_LIKELY(!trx->declared_to_be_inside_innodb)) {
719
 
 
720
 
                return;
721
 
        }
722
 
 
723
 
        srv_conc_exit_innodb(trx);
 
844
  if (UNIV_LIKELY(!trx->declared_to_be_inside_innodb)) {
 
845
 
 
846
    return;
 
847
  }
 
848
 
 
849
  srv_conc_exit_innodb(trx);
724
850
}
725
851
 
726
852
/******************************************************************//**
732
858
void
733
859
innobase_release_stat_resources(
734
860
/*============================*/
735
 
        trx_t*  trx)    /*!< in: transaction object */
 
861
  trx_t*  trx)  /*!< in: transaction object */
736
862
{
737
 
        if (trx->has_search_latch) {
738
 
                trx_search_latch_release_if_reserved(trx);
739
 
        }
740
 
 
741
 
        if (trx->declared_to_be_inside_innodb) {
742
 
                /* Release our possible ticket in the FIFO */
743
 
 
744
 
                srv_conc_force_exit_innodb(trx);
745
 
        }
 
863
  if (trx->has_search_latch) {
 
864
    trx_search_latch_release_if_reserved(trx);
 
865
  }
 
866
 
 
867
  if (trx->declared_to_be_inside_innodb) {
 
868
    /* Release our possible ticket in the FIFO */
 
869
 
 
870
    srv_conc_force_exit_innodb(trx);
 
871
  }
746
872
}
747
873
 
748
874
/******************************************************************//**
753
879
 
754
880
DRIZZLE: Note, we didn't change this name to avoid more ifdef forking 
755
881
         in non-Cursor code.
756
 
@return true if non-transactional tables have been edited */
 
882
@return true if non-transactional tables have been edited */
757
883
extern "C" UNIV_INTERN
758
884
ibool
759
885
thd_has_edited_nontrans_tables(
760
886
/*===========================*/
761
 
        void*           session)        /*!< in: thread handle (Session*) */
 
887
  void*   session)  /*!< in: thread handle (Session*) */
762
888
{
763
 
        return((ibool) session_non_transactional_update((Session*) session));
 
889
  return((ibool) session_non_transactional_update((Session*) session));
764
890
}
765
891
 
766
892
/******************************************************************//**
767
893
Returns true if the thread is executing a SELECT statement.
768
 
@return true if session is executing SELECT */
 
894
@return true if session is executing SELECT */
769
895
extern "C" UNIV_INTERN
770
896
ibool
771
897
thd_is_select(
772
898
/*==========*/
773
 
        const void*     session)        /*!< in: thread handle (Session*) */
 
899
  const void* session)  /*!< in: thread handle (Session*) */
774
900
{
775
 
        return(session_sql_command((const Session*) session) == SQLCOM_SELECT);
 
901
  return(session_sql_command((const Session*) session) == SQLCOM_SELECT);
776
902
}
777
903
 
778
904
/******************************************************************//**
779
905
Returns true if the thread supports XA,
780
906
global value of innodb_supports_xa if session is NULL.
781
 
@return true if session has XA support */
 
907
@return true if session has XA support */
782
908
extern "C" UNIV_INTERN
783
909
ibool
784
910
thd_supports_xa(
785
911
/*============*/
786
 
        void*   session)        /*!< in: thread handle (Session*), or NULL to query
787
 
                                the global innodb_supports_xa */
 
912
  void* session)  /*!< in: thread handle (Session*), or NULL to query
 
913
        the global innodb_supports_xa */
788
914
{
789
 
        return(SessionVAR((Session*) session, support_xa));
 
915
  return(SessionVAR((Session*) session, support_xa));
790
916
}
791
917
 
792
918
/******************************************************************//**
793
919
Returns the lock wait timeout for the current connection.
794
 
@return the lock wait timeout, in seconds */
 
920
@return the lock wait timeout, in seconds */
795
921
extern "C" UNIV_INTERN
796
922
ulong
797
923
thd_lock_wait_timeout(
798
924
/*==================*/
799
 
        void*   session)        /*!< in: thread handle (Session*), or NULL to query
800
 
                        the global innodb_lock_wait_timeout */
 
925
  void* session)  /*!< in: thread handle (Session*), or NULL to query
 
926
      the global innodb_lock_wait_timeout */
801
927
{
802
 
        /* According to <drizzle/plugin.h>, passing session == NULL
803
 
        returns the global value of the session variable. */
804
 
        return(SessionVAR((Session*) session, lock_wait_timeout));
 
928
  /* According to <drizzle/plugin.h>, passing session == NULL
 
929
  returns the global value of the session variable. */
 
930
  return(SessionVAR((Session*) session, lock_wait_timeout));
805
931
}
806
932
 
807
933
/********************************************************************//**
808
934
Obtain the InnoDB transaction of a MySQL thread.
809
 
@return reference to transaction pointer */
 
935
@return reference to transaction pointer */
810
936
static inline
811
937
trx_t*&
812
938
session_to_trx(
813
939
/*=======*/
814
 
        Session*        session)        /*!< in: Drizzle Session */
 
940
  Session*  session)  /*!< in: Drizzle Session */
815
941
{
816
 
        return *(trx_t**) session->getEngineData(innodb_engine_ptr);
 
942
  return *(trx_t**) session->getEngineData(innodb_engine_ptr);
817
943
}
818
944
 
819
945
/********************************************************************//**
820
946
Call this function when mysqld passes control to the client. That is to
821
947
avoid deadlocks on the adaptive hash S-latch possibly held by session. For more
822
948
documentation, see Cursor.cc.
823
 
@return 0 */
 
949
@return 0 */
824
950
int
825
951
InnobaseEngine::doReleaseTemporaryLatches(
826
952
/*===============================*/
827
 
        Session*                session)        /*!< in: MySQL thread */
 
953
  Session*    session)  /*!< in: MySQL thread */
828
954
{
829
 
        trx_t*  trx;
830
 
 
831
 
        assert(this == innodb_engine_ptr);
832
 
 
833
 
        if (!innodb_inited) {
834
 
 
835
 
                return(0);
836
 
        }
837
 
 
838
 
        trx = session_to_trx(session);
839
 
 
840
 
        if (trx) {
841
 
                innobase_release_stat_resources(trx);
842
 
        }
843
 
        return(0);
 
955
  trx_t*  trx;
 
956
 
 
957
  assert(this == innodb_engine_ptr);
 
958
 
 
959
  if (!innodb_inited) {
 
960
 
 
961
    return(0);
 
962
  }
 
963
 
 
964
  trx = session_to_trx(session);
 
965
 
 
966
  if (trx) {
 
967
    innobase_release_stat_resources(trx);
 
968
  }
 
969
  return(0);
844
970
}
845
971
 
846
972
/********************************************************************//**
853
979
innobase_active_small(void)
854
980
/*=======================*/
855
981
{
856
 
        innobase_active_counter++;
 
982
  innobase_active_counter++;
857
983
 
858
 
        if ((innobase_active_counter % INNOBASE_WAKE_INTERVAL) == 0) {
859
 
                srv_active_wake_master_thread();
860
 
        }
 
984
  if ((innobase_active_counter % INNOBASE_WAKE_INTERVAL) == 0) {
 
985
    srv_active_wake_master_thread();
 
986
  }
861
987
}
862
988
 
863
989
/********************************************************************//**
864
990
Converts an InnoDB error code to a MySQL error code and also tells to MySQL
865
991
about a possible transaction rollback inside InnoDB caused by a lock wait
866
992
timeout or a deadlock.
867
 
@return MySQL error code */
 
993
@return MySQL error code */
868
994
extern "C" UNIV_INTERN
869
995
int
870
996
convert_error_code_to_mysql(
871
997
/*========================*/
872
 
        int             error,  /*!< in: InnoDB error code */
873
 
        ulint           flags,  /*!< in: InnoDB table flags, or 0 */
874
 
        Session*        session)/*!< in: user thread handle or NULL */
 
998
  int   error,  /*!< in: InnoDB error code */
 
999
  ulint   flags,  /*!< in: InnoDB table flags, or 0 */
 
1000
  Session*  session)/*!< in: user thread handle or NULL */
875
1001
{
876
 
        switch (error) {
877
 
        case DB_SUCCESS:
878
 
                return(0);
879
 
 
880
 
        case DB_ERROR:
881
 
        default:
882
 
                return(-1); /* unspecified error */
883
 
 
884
 
        case DB_DUPLICATE_KEY:
885
 
                return(HA_ERR_FOUND_DUPP_KEY);
886
 
 
887
 
        case DB_FOREIGN_DUPLICATE_KEY:
888
 
                return(HA_ERR_FOREIGN_DUPLICATE_KEY);
889
 
 
890
 
        case DB_MISSING_HISTORY:
891
 
                return(HA_ERR_TABLE_DEF_CHANGED);
892
 
 
893
 
        case DB_RECORD_NOT_FOUND:
894
 
                return(HA_ERR_NO_ACTIVE_RECORD);
895
 
 
896
 
        case DB_DEADLOCK:
897
 
                /* Since we rolled back the whole transaction, we must
898
 
                tell it also to MySQL so that MySQL knows to empty the
899
 
                cached binlog for this transaction */
 
1002
  switch (error) {
 
1003
  case DB_SUCCESS:
 
1004
    return(0);
 
1005
 
 
1006
  case DB_ERROR:
 
1007
  default:
 
1008
    return(-1); /* unspecified error */
 
1009
 
 
1010
  case DB_DUPLICATE_KEY:
 
1011
    return(HA_ERR_FOUND_DUPP_KEY);
 
1012
 
 
1013
  case DB_FOREIGN_DUPLICATE_KEY:
 
1014
    return(HA_ERR_FOREIGN_DUPLICATE_KEY);
 
1015
 
 
1016
  case DB_MISSING_HISTORY:
 
1017
    return(HA_ERR_TABLE_DEF_CHANGED);
 
1018
 
 
1019
  case DB_RECORD_NOT_FOUND:
 
1020
    return(HA_ERR_NO_ACTIVE_RECORD);
 
1021
 
 
1022
  case DB_DEADLOCK:
 
1023
    /* Since we rolled back the whole transaction, we must
 
1024
    tell it also to MySQL so that MySQL knows to empty the
 
1025
    cached binlog for this transaction */
900
1026
 
901
1027
                session_mark_transaction_to_rollback(session, TRUE);
902
1028
 
903
 
                return(HA_ERR_LOCK_DEADLOCK);
 
1029
    return(HA_ERR_LOCK_DEADLOCK);
904
1030
 
905
 
        case DB_LOCK_WAIT_TIMEOUT:
906
 
                /* Starting from 5.0.13, we let MySQL just roll back the
907
 
                latest SQL statement in a lock wait timeout. Previously, we
908
 
                rolled back the whole transaction. */
 
1031
  case DB_LOCK_WAIT_TIMEOUT:
 
1032
    /* Starting from 5.0.13, we let MySQL just roll back the
 
1033
    latest SQL statement in a lock wait timeout. Previously, we
 
1034
    rolled back the whole transaction. */
909
1035
 
910
1036
                session_mark_transaction_to_rollback(session,
911
1037
                                             (bool)row_rollback_on_timeout);
912
1038
 
913
 
                return(HA_ERR_LOCK_WAIT_TIMEOUT);
914
 
 
915
 
        case DB_NO_REFERENCED_ROW:
916
 
                return(HA_ERR_NO_REFERENCED_ROW);
917
 
 
918
 
        case DB_ROW_IS_REFERENCED:
919
 
                return(HA_ERR_ROW_IS_REFERENCED);
920
 
 
921
 
        case DB_CANNOT_ADD_CONSTRAINT:
922
 
                return(HA_ERR_CANNOT_ADD_FOREIGN);
923
 
 
924
 
        case DB_CANNOT_DROP_CONSTRAINT:
925
 
 
926
 
                return(HA_ERR_ROW_IS_REFERENCED); /* TODO: This is a bit
927
 
                                                misleading, a new MySQL error
928
 
                                                code should be introduced */
929
 
 
930
 
        case DB_COL_APPEARS_TWICE_IN_INDEX:
931
 
        case DB_CORRUPTION:
932
 
                return(HA_ERR_CRASHED);
933
 
 
934
 
        case DB_OUT_OF_FILE_SPACE:
935
 
                return(HA_ERR_RECORD_FILE_FULL);
936
 
 
937
 
        case DB_TABLE_IS_BEING_USED:
938
 
                return(HA_ERR_WRONG_COMMAND);
939
 
 
940
 
        case DB_TABLE_NOT_FOUND:
941
 
                return(HA_ERR_NO_SUCH_TABLE);
942
 
 
943
 
        case DB_TOO_BIG_RECORD:
944
 
                my_error(ER_TOO_BIG_ROWSIZE, MYF(0),
945
 
                         page_get_free_space_of_empty(flags
946
 
                                                      & DICT_TF_COMPACT) / 2);
947
 
                return(HA_ERR_TO_BIG_ROW);
948
 
 
949
 
        case DB_NO_SAVEPOINT:
950
 
                return(HA_ERR_NO_SAVEPOINT);
951
 
 
952
 
        case DB_LOCK_TABLE_FULL:
953
 
                /* Since we rolled back the whole transaction, we must
954
 
                tell it also to MySQL so that MySQL knows to empty the
955
 
                cached binlog for this transaction */
956
 
 
957
 
                session_mark_transaction_to_rollback(session, TRUE);
958
 
 
959
 
                return(HA_ERR_LOCK_TABLE_FULL);
960
 
 
961
 
        case DB_PRIMARY_KEY_IS_NULL:
962
 
                return(ER_PRIMARY_CANT_HAVE_NULL);
963
 
 
964
 
        case DB_TOO_MANY_CONCURRENT_TRXS:
965
 
 
966
 
                /* Once MySQL add the appropriate code to errmsg.txt then
967
 
                we can get rid of this #ifdef. NOTE: The code checked by
968
 
                the #ifdef is the suggested name for the error condition
969
 
                and the actual error code name could very well be different.
970
 
                This will require some monitoring, ie. the status
971
 
                of this request on our part.*/
 
1039
    return(HA_ERR_LOCK_WAIT_TIMEOUT);
 
1040
 
 
1041
  case DB_NO_REFERENCED_ROW:
 
1042
    return(HA_ERR_NO_REFERENCED_ROW);
 
1043
 
 
1044
  case DB_ROW_IS_REFERENCED:
 
1045
    return(HA_ERR_ROW_IS_REFERENCED);
 
1046
 
 
1047
  case DB_CANNOT_ADD_CONSTRAINT:
 
1048
    return(HA_ERR_CANNOT_ADD_FOREIGN);
 
1049
 
 
1050
  case DB_CANNOT_DROP_CONSTRAINT:
 
1051
 
 
1052
    return(HA_ERR_ROW_IS_REFERENCED); /* TODO: This is a bit
 
1053
            misleading, a new MySQL error
 
1054
            code should be introduced */
 
1055
 
 
1056
  case DB_COL_APPEARS_TWICE_IN_INDEX:
 
1057
  case DB_CORRUPTION:
 
1058
    return(HA_ERR_CRASHED);
 
1059
 
 
1060
  case DB_OUT_OF_FILE_SPACE:
 
1061
    return(HA_ERR_RECORD_FILE_FULL);
 
1062
 
 
1063
  case DB_TABLE_IS_BEING_USED:
 
1064
    return(HA_ERR_WRONG_COMMAND);
 
1065
 
 
1066
  case DB_TABLE_NOT_FOUND:
 
1067
    return(HA_ERR_NO_SUCH_TABLE);
 
1068
 
 
1069
  case DB_TOO_BIG_RECORD:
 
1070
    my_error(ER_TOO_BIG_ROWSIZE, MYF(0),
 
1071
       page_get_free_space_of_empty(flags
 
1072
                  & DICT_TF_COMPACT) / 2);
 
1073
    return(HA_ERR_TO_BIG_ROW);
 
1074
 
 
1075
  case DB_NO_SAVEPOINT:
 
1076
    return(HA_ERR_NO_SAVEPOINT);
 
1077
 
 
1078
  case DB_LOCK_TABLE_FULL:
 
1079
    /* Since we rolled back the whole transaction, we must
 
1080
    tell it also to MySQL so that MySQL knows to empty the
 
1081
    cached binlog for this transaction */
 
1082
 
 
1083
    session_mark_transaction_to_rollback(session, TRUE);
 
1084
 
 
1085
    return(HA_ERR_LOCK_TABLE_FULL);
 
1086
 
 
1087
  case DB_PRIMARY_KEY_IS_NULL:
 
1088
    return(ER_PRIMARY_CANT_HAVE_NULL);
 
1089
 
 
1090
  case DB_TOO_MANY_CONCURRENT_TRXS:
 
1091
 
 
1092
    /* Once MySQL add the appropriate code to errmsg.txt then
 
1093
    we can get rid of this #ifdef. NOTE: The code checked by
 
1094
    the #ifdef is the suggested name for the error condition
 
1095
    and the actual error code name could very well be different.
 
1096
    This will require some monitoring, ie. the status
 
1097
    of this request on our part.*/
972
1098
#ifdef ER_TOO_MANY_CONCURRENT_TRXS
973
 
                return(ER_TOO_MANY_CONCURRENT_TRXS);
 
1099
    return(ER_TOO_MANY_CONCURRENT_TRXS);
974
1100
#else
975
 
                return(HA_ERR_RECORD_FILE_FULL);
 
1101
    return(HA_ERR_RECORD_FILE_FULL);
976
1102
#endif
977
 
        case DB_UNSUPPORTED:
978
 
                return(HA_ERR_UNSUPPORTED);
979
 
        }
 
1103
  case DB_UNSUPPORTED:
 
1104
    return(HA_ERR_UNSUPPORTED);
 
1105
  }
980
1106
}
981
1107
 
982
1108
/*************************************************************//**
995
1121
innobase_mysql_prepare_print_arbitrary_thd(void)
996
1122
/*============================================*/
997
1123
{
998
 
        ut_ad(!mutex_own(&kernel_mutex));
999
 
        pthread_mutex_lock(&LOCK_thread_count);
 
1124
  ut_ad(!mutex_own(&kernel_mutex));
 
1125
  pthread_mutex_lock(&LOCK_thread_count);
1000
1126
}
1001
1127
 
1002
1128
/*************************************************************//**
1013
1139
innobase_mysql_end_print_arbitrary_thd(void)
1014
1140
/*========================================*/
1015
1141
{
1016
 
        ut_ad(!mutex_own(&kernel_mutex));
1017
 
        pthread_mutex_unlock(&LOCK_thread_count);
 
1142
  ut_ad(!mutex_own(&kernel_mutex));
 
1143
  pthread_mutex_unlock(&LOCK_thread_count);
1018
1144
}
1019
1145
 
1020
1146
/*************************************************************//**
1023
1149
void
1024
1150
innobase_mysql_print_thd(
1025
1151
/*=====================*/
1026
 
        FILE*   f,              /*!< in: output stream */
1027
 
        void * in_session,      /*!< in: pointer to a Drizzle Session object */
1028
 
        uint    )               /*!< in: max query length to print, or 0 to
1029
 
                                   use the default max length */
 
1152
  FILE* f,    /*!< in: output stream */
 
1153
  void * in_session,  /*!< in: pointer to a Drizzle Session object */
 
1154
  uint  )   /*!< in: max query length to print, or 0 to
 
1155
           use the default max length */
1030
1156
{
1031
1157
  Session *session= reinterpret_cast<Session *>(in_session);
1032
1158
  fprintf(f,
1040
1166
  fprintf(f,
1041
1167
          "\n%s", session->getQueryString().c_str()
1042
1168
  );
1043
 
        putc('\n', f);
 
1169
  putc('\n', f);
1044
1170
}
1045
1171
 
1046
1172
/******************************************************************//**
1049
1175
void
1050
1176
innobase_get_cset_width(
1051
1177
/*====================*/
1052
 
        ulint   cset,           /*!< in: MySQL charset-collation code */
1053
 
        ulint*  mbminlen,       /*!< out: minimum length of a char (in bytes) */
1054
 
        ulint*  mbmaxlen)       /*!< out: maximum length of a char (in bytes) */
 
1178
  ulint cset,   /*!< in: MySQL charset-collation code */
 
1179
  ulint*  mbminlen, /*!< out: minimum length of a char (in bytes) */
 
1180
  ulint*  mbmaxlen) /*!< out: maximum length of a char (in bytes) */
1055
1181
{
1056
 
        CHARSET_INFO*   cs;
1057
 
        ut_ad(cset < 256);
1058
 
        ut_ad(mbminlen);
1059
 
        ut_ad(mbmaxlen);
 
1182
  CHARSET_INFO* cs;
 
1183
  ut_ad(cset < 256);
 
1184
  ut_ad(mbminlen);
 
1185
  ut_ad(mbmaxlen);
1060
1186
 
1061
 
        cs = all_charsets[cset];
1062
 
        if (cs) {
1063
 
                *mbminlen = cs->mbminlen;
1064
 
                *mbmaxlen = cs->mbmaxlen;
1065
 
        } else {
1066
 
                ut_a(cset == 0);
1067
 
                *mbminlen = *mbmaxlen = 0;
1068
 
        }
 
1187
  cs = all_charsets[cset];
 
1188
  if (cs) {
 
1189
    *mbminlen = cs->mbminlen;
 
1190
    *mbmaxlen = cs->mbmaxlen;
 
1191
  } else {
 
1192
    ut_a(cset == 0);
 
1193
    *mbminlen = *mbmaxlen = 0;
 
1194
  }
1069
1195
}
1070
1196
 
1071
1197
/******************************************************************//**
1074
1200
void
1075
1201
innobase_convert_from_table_id(
1076
1202
/*===========================*/
1077
 
        const void*,                    /*!< in: the 'from' character set */
1078
 
        char*                   to,     /*!< out: converted identifier */
1079
 
        const char*             from,   /*!< in: identifier to convert */
1080
 
        ulint                   len)    /*!< in: length of 'to', in bytes */
 
1203
  const void*,      /*!< in: the 'from' character set */
 
1204
  char*     to, /*!< out: converted identifier */
 
1205
  const char*   from, /*!< in: identifier to convert */
 
1206
  ulint     len)  /*!< in: length of 'to', in bytes */
1081
1207
{
1082
 
        strncpy(to, from, len);
 
1208
  strncpy(to, from, len);
1083
1209
}
1084
1210
 
1085
1211
/******************************************************************//**
1088
1214
void
1089
1215
innobase_convert_from_id(
1090
1216
/*=====================*/
1091
 
        const void*,                    /*!< in: the 'from' character set */
1092
 
        char*                   to,     /*!< out: converted identifier */
1093
 
        const char*             from,   /*!< in: identifier to convert */
1094
 
        ulint                   len)    /*!< in: length of 'to', in bytes */
 
1217
  const void*,      /*!< in: the 'from' character set */
 
1218
  char*     to, /*!< out: converted identifier */
 
1219
  const char*   from, /*!< in: identifier to convert */
 
1220
  ulint     len)  /*!< in: length of 'to', in bytes */
1095
1221
{
1096
 
        strncpy(to, from, len);
 
1222
  strncpy(to, from, len);
1097
1223
}
1098
1224
 
1099
1225
/******************************************************************//**
1100
1226
Compares NUL-terminated UTF-8 strings case insensitively.
1101
 
@return 0 if a=b, <0 if a<b, >1 if a>b */
 
1227
@return 0 if a=b, <0 if a<b, >1 if a>b */
1102
1228
extern "C" UNIV_INTERN
1103
1229
int
1104
1230
innobase_strcasecmp(
1105
1231
/*================*/
1106
 
        const char*     a,      /*!< in: first string to compare */
1107
 
        const char*     b)      /*!< in: second string to compare */
 
1232
  const char* a,  /*!< in: first string to compare */
 
1233
  const char* b)  /*!< in: second string to compare */
1108
1234
{
1109
 
        return(my_strcasecmp(system_charset_info, a, b));
 
1235
  return(my_strcasecmp(system_charset_info, a, b));
1110
1236
}
1111
1237
 
1112
1238
/******************************************************************//**
1115
1241
void
1116
1242
innobase_casedn_str(
1117
1243
/*================*/
1118
 
        char*   a)      /*!< in/out: string to put in lower case */
 
1244
  char* a)  /*!< in/out: string to put in lower case */
1119
1245
{
1120
 
        my_casedn_str(system_charset_info, a);
 
1246
  my_casedn_str(system_charset_info, a);
1121
1247
}
1122
1248
 
1123
1249
/**********************************************************************//**
1124
1250
Determines the connection character set.
1125
 
@return connection character set */
 
1251
@return connection character set */
1126
1252
extern "C" UNIV_INTERN
1127
1253
const void*
1128
1254
innobase_get_charset(
1129
1255
/*=================*/
1130
 
        void*   mysql_session)  /*!< in: MySQL thread handle */
 
1256
  void* mysql_session)  /*!< in: MySQL thread handle */
1131
1257
{
1132
 
        return session_charset(static_cast<Session*>(mysql_session));
 
1258
  return session_charset(static_cast<Session*>(mysql_session));
1133
1259
}
1134
1260
 
1135
1261
extern "C" UNIV_INTERN
1136
1262
bool
1137
1263
innobase_isspace(
1138
 
        const void *cs,
1139
 
        char char_to_test)
 
1264
  const void *cs,
 
1265
  char char_to_test)
1140
1266
{
1141
 
        return my_isspace(static_cast<const CHARSET_INFO *>(cs), char_to_test);
 
1267
  return my_isspace(static_cast<const CHARSET_INFO *>(cs), char_to_test);
1142
1268
}
1143
1269
 
1144
1270
UNIV_INTERN
1146
1272
innobase_fast_mutex_init(
1147
1273
        os_fast_mutex_t*        fast_mutex)
1148
1274
{
1149
 
        return pthread_mutex_init(fast_mutex, MY_MUTEX_INIT_FAST);
 
1275
  return pthread_mutex_init(fast_mutex, MY_MUTEX_INIT_FAST);
1150
1276
}
1151
1277
 
1152
1278
#if defined (__WIN__) && defined (MYSQL_DYNAMIC_PLUGIN)
1156
1282
extern "C"
1157
1283
void __cdecl
1158
1284
_dosmaperr(
1159
 
        unsigned long); /*!< in: OS error value */
 
1285
  unsigned long); /*!< in: OS error value */
1160
1286
 
1161
1287
/*********************************************************************//**
1162
1288
Creates a temporary file.
1163
 
@return temporary file descriptor, or < 0 on error */
 
1289
@return temporary file descriptor, or < 0 on error */
1164
1290
extern "C" UNIV_INTERN
1165
1291
int
1166
1292
innobase_mysql_tmpfile(void)
1167
1293
/*========================*/
1168
1294
{
1169
 
        int     fd;                             /* handle of opened file */
1170
 
        HANDLE  osfh;                           /* OS handle of opened file */
1171
 
        char*   tmpdir;                         /* point to the directory
1172
 
                                                where to create file */
1173
 
        TCHAR   path_buf[MAX_PATH - 14];        /* buffer for tmp file path.
1174
 
                                                The length cannot be longer
1175
 
                                                than MAX_PATH - 14, or
1176
 
                                                GetTempFileName will fail. */
1177
 
        char    filename[MAX_PATH];             /* name of the tmpfile */
1178
 
        DWORD   fileaccess = GENERIC_READ       /* OS file access */
1179
 
                             | GENERIC_WRITE
1180
 
                             | DELETE;
1181
 
        DWORD   fileshare = FILE_SHARE_READ     /* OS file sharing mode */
1182
 
                            | FILE_SHARE_WRITE
1183
 
                            | FILE_SHARE_DELETE;
1184
 
        DWORD   filecreate = CREATE_ALWAYS;     /* OS method of open/create */
1185
 
        DWORD   fileattrib =                    /* OS file attribute flags */
1186
 
                             FILE_ATTRIBUTE_NORMAL
1187
 
                             | FILE_FLAG_DELETE_ON_CLOSE
1188
 
                             | FILE_ATTRIBUTE_TEMPORARY
1189
 
                             | FILE_FLAG_SEQUENTIAL_SCAN;
1190
 
 
1191
 
        tmpdir = my_tmpdir(&mysql_tmpdir_list);
1192
 
 
1193
 
        /* The tmpdir parameter can not be NULL for GetTempFileName. */
1194
 
        if (!tmpdir) {
1195
 
                uint    ret;
1196
 
 
1197
 
                /* Use GetTempPath to determine path for temporary files. */
1198
 
                ret = GetTempPath(sizeof(path_buf), path_buf);
1199
 
                if (ret > sizeof(path_buf) || (ret == 0)) {
1200
 
 
1201
 
                        _dosmaperr(GetLastError());     /* map error */
1202
 
                        return(-1);
1203
 
                }
1204
 
 
1205
 
                tmpdir = path_buf;
1206
 
        }
1207
 
 
1208
 
        /* Use GetTempFileName to generate a unique filename. */
1209
 
        if (!GetTempFileName(tmpdir, "ib", 0, filename)) {
1210
 
 
1211
 
                _dosmaperr(GetLastError());     /* map error */
1212
 
                return(-1);
1213
 
        }
1214
 
 
1215
 
        /* Open/Create the file. */
1216
 
        osfh = CreateFile(filename, fileaccess, fileshare, NULL,
1217
 
                          filecreate, fileattrib, NULL);
1218
 
        if (osfh == INVALID_HANDLE_VALUE) {
1219
 
 
1220
 
                /* open/create file failed! */
1221
 
                _dosmaperr(GetLastError());     /* map error */
1222
 
                return(-1);
1223
 
        }
1224
 
 
1225
 
        do {
1226
 
                /* Associates a CRT file descriptor with the OS file handle. */
1227
 
                fd = _open_osfhandle((intptr_t) osfh, 0);
1228
 
        } while (fd == -1 && errno == EINTR);
1229
 
 
1230
 
        if (fd == -1) {
1231
 
                /* Open failed, close the file handle. */
1232
 
 
1233
 
                _dosmaperr(GetLastError());     /* map error */
1234
 
                CloseHandle(osfh);              /* no need to check if
1235
 
                                                CloseHandle fails */
1236
 
        }
1237
 
 
1238
 
        return(fd);
 
1295
  int fd;       /* handle of opened file */
 
1296
  HANDLE  osfh;       /* OS handle of opened file */
 
1297
  char* tmpdir;       /* point to the directory
 
1298
            where to create file */
 
1299
  TCHAR path_buf[MAX_PATH - 14];  /* buffer for tmp file path.
 
1300
            The length cannot be longer
 
1301
            than MAX_PATH - 14, or
 
1302
            GetTempFileName will fail. */
 
1303
  char  filename[MAX_PATH];   /* name of the tmpfile */
 
1304
  DWORD fileaccess = GENERIC_READ /* OS file access */
 
1305
           | GENERIC_WRITE
 
1306
           | DELETE;
 
1307
  DWORD fileshare = FILE_SHARE_READ /* OS file sharing mode */
 
1308
          | FILE_SHARE_WRITE
 
1309
          | FILE_SHARE_DELETE;
 
1310
  DWORD filecreate = CREATE_ALWAYS; /* OS method of open/create */
 
1311
  DWORD fileattrib =      /* OS file attribute flags */
 
1312
           FILE_ATTRIBUTE_NORMAL
 
1313
           | FILE_FLAG_DELETE_ON_CLOSE
 
1314
           | FILE_ATTRIBUTE_TEMPORARY
 
1315
           | FILE_FLAG_SEQUENTIAL_SCAN;
 
1316
 
 
1317
  tmpdir = my_tmpdir(&mysql_tmpdir_list);
 
1318
 
 
1319
  /* The tmpdir parameter can not be NULL for GetTempFileName. */
 
1320
  if (!tmpdir) {
 
1321
    uint  ret;
 
1322
 
 
1323
    /* Use GetTempPath to determine path for temporary files. */
 
1324
    ret = GetTempPath(sizeof(path_buf), path_buf);
 
1325
    if (ret > sizeof(path_buf) || (ret == 0)) {
 
1326
 
 
1327
      _dosmaperr(GetLastError()); /* map error */
 
1328
      return(-1);
 
1329
    }
 
1330
 
 
1331
    tmpdir = path_buf;
 
1332
  }
 
1333
 
 
1334
  /* Use GetTempFileName to generate a unique filename. */
 
1335
  if (!GetTempFileName(tmpdir, "ib", 0, filename)) {
 
1336
 
 
1337
    _dosmaperr(GetLastError()); /* map error */
 
1338
    return(-1);
 
1339
  }
 
1340
 
 
1341
  /* Open/Create the file. */
 
1342
  osfh = CreateFile(filename, fileaccess, fileshare, NULL,
 
1343
        filecreate, fileattrib, NULL);
 
1344
  if (osfh == INVALID_HANDLE_VALUE) {
 
1345
 
 
1346
    /* open/create file failed! */
 
1347
    _dosmaperr(GetLastError()); /* map error */
 
1348
    return(-1);
 
1349
  }
 
1350
 
 
1351
  do {
 
1352
    /* Associates a CRT file descriptor with the OS file handle. */
 
1353
    fd = _open_osfhandle((intptr_t) osfh, 0);
 
1354
  } while (fd == -1 && errno == EINTR);
 
1355
 
 
1356
  if (fd == -1) {
 
1357
    /* Open failed, close the file handle. */
 
1358
 
 
1359
    _dosmaperr(GetLastError()); /* map error */
 
1360
    CloseHandle(osfh);    /* no need to check if
 
1361
            CloseHandle fails */
 
1362
  }
 
1363
 
 
1364
  return(fd);
1239
1365
}
1240
1366
#else
1241
1367
/*********************************************************************//**
1242
1368
Creates a temporary file.
1243
 
@return temporary file descriptor, or < 0 on error */
 
1369
@return temporary file descriptor, or < 0 on error */
1244
1370
extern "C" UNIV_INTERN
1245
1371
int
1246
1372
innobase_mysql_tmpfile(void)
1247
1373
/*========================*/
1248
1374
{
1249
 
        int     fd2 = -1;
1250
 
        int     fd = mysql_tmpfile("ib");
1251
 
        if (fd >= 0) {
1252
 
                /* Copy the file descriptor, so that the additional resources
1253
 
                allocated by create_temp_file() can be freed by invoking
1254
 
                internal::my_close().
 
1375
  int fd2 = -1;
 
1376
  int fd = mysql_tmpfile("ib");
 
1377
  if (fd >= 0) {
 
1378
    /* Copy the file descriptor, so that the additional resources
 
1379
    allocated by create_temp_file() can be freed by invoking
 
1380
    internal::my_close().
1255
1381
 
1256
 
                Because the file descriptor returned by this function
1257
 
                will be passed to fdopen(), it will be closed by invoking
1258
 
                fclose(), which in turn will invoke close() instead of
1259
 
                internal::my_close(). */
1260
 
                fd2 = dup(fd);
1261
 
                if (fd2 < 0) {
1262
 
                        errno=errno;
1263
 
                        my_error(EE_OUT_OF_FILERESOURCES,
1264
 
                                 MYF(ME_BELL+ME_WAITTANG),
1265
 
                                 "ib*", errno);
1266
 
                }
1267
 
                internal::my_close(fd, MYF(MY_WME));
1268
 
        }
1269
 
        return(fd2);
 
1382
    Because the file descriptor returned by this function
 
1383
    will be passed to fdopen(), it will be closed by invoking
 
1384
    fclose(), which in turn will invoke close() instead of
 
1385
    internal::my_close(). */
 
1386
    fd2 = dup(fd);
 
1387
    if (fd2 < 0) {
 
1388
      errno=errno;
 
1389
      my_error(EE_OUT_OF_FILERESOURCES,
 
1390
         MYF(ME_BELL+ME_WAITTANG),
 
1391
         "ib*", errno);
 
1392
    }
 
1393
    internal::my_close(fd, MYF(MY_WME));
 
1394
  }
 
1395
  return(fd2);
1270
1396
}
1271
1397
#endif /* defined (__WIN__) && defined (MYSQL_DYNAMIC_PLUGIN) */
1272
1398
 
1279
1405
The result is always NUL-terminated (provided buf_size > 0) and the
1280
1406
number of bytes that were written to "buf" is returned (including the
1281
1407
terminating NUL).
1282
 
@return number of bytes that were written */
 
1408
@return number of bytes that were written */
1283
1409
extern "C" UNIV_INTERN
1284
1410
ulint
1285
1411
innobase_raw_format(
1286
1412
/*================*/
1287
 
        const char*     data,           /*!< in: raw data */
1288
 
        ulint           data_len,       /*!< in: raw data length
1289
 
                                        in bytes */
1290
 
        ulint           ,               /*!< in: charset collation */
1291
 
        char*           buf,            /*!< out: output buffer */
1292
 
        ulint           buf_size)       /*!< in: output buffer size
1293
 
                                        in bytes */
 
1413
  const char* data,   /*!< in: raw data */
 
1414
  ulint   data_len, /*!< in: raw data length
 
1415
          in bytes */
 
1416
  ulint   ,   /*!< in: charset collation */
 
1417
  char*   buf,    /*!< out: output buffer */
 
1418
  ulint   buf_size) /*!< in: output buffer size
 
1419
          in bytes */
1294
1420
{
1295
 
        return(ut_str_sql_format(data, data_len, buf, buf_size));
 
1421
  return(ut_str_sql_format(data, data_len, buf, buf_size));
1296
1422
}
1297
1423
 
1298
1424
/*********************************************************************//**
1307
1433
Note: This function is also called with increment set to the number of
1308
1434
values we want to reserve for multi-value inserts e.g.,
1309
1435
 
1310
 
        INSERT INTO T VALUES(), (), ();
 
1436
  INSERT INTO T VALUES(), (), ();
1311
1437
 
1312
1438
innobase_next_autoinc() will be called with increment set to
1313
1439
n * 3 where autoinc_lock_mode != TRADITIONAL because we want
1314
1440
to reserve 3 values for the multi-value INSERT above.
1315
 
@return the next value */
 
1441
@return the next value */
1316
1442
static
1317
1443
uint64_t
1318
1444
innobase_next_autoinc(
1319
1445
/*==================*/
1320
 
        uint64_t        current,        /*!< in: Current value */
1321
 
        uint64_t        increment,      /*!< in: increment current by */
1322
 
        uint64_t        offset,         /*!< in: AUTOINC offset */
1323
 
        uint64_t        max_value)      /*!< in: max value for type */
 
1446
  uint64_t  current,  /*!< in: Current value */
 
1447
  uint64_t  increment,  /*!< in: increment current by */
 
1448
  uint64_t  offset,   /*!< in: AUTOINC offset */
 
1449
  uint64_t  max_value)  /*!< in: max value for type */
1324
1450
{
1325
 
        uint64_t        next_value;
1326
 
 
1327
 
        /* Should never be 0. */
1328
 
        ut_a(increment > 0);
1329
 
 
1330
 
        /* According to MySQL documentation, if the offset is greater than
1331
 
        the increment then the offset is ignored. */
1332
 
        if (offset > increment) {
1333
 
                offset = 0;
1334
 
        }
1335
 
 
1336
 
        if (max_value <= current) {
1337
 
                next_value = max_value;
1338
 
        } else if (offset <= 1) {
1339
 
                /* Offset 0 and 1 are the same, because there must be at
1340
 
                least one node in the system. */
1341
 
                if (max_value - current <= increment) {
1342
 
                        next_value = max_value;
1343
 
                } else {
1344
 
                        next_value = current + increment;
1345
 
                }
1346
 
        } else if (max_value > current) {
1347
 
                if (current > offset) {
1348
 
                        next_value = ((current - offset) / increment) + 1;
1349
 
                } else {
1350
 
                        next_value = ((offset - current) / increment) + 1;
1351
 
                }
1352
 
 
1353
 
                ut_a(increment > 0);
1354
 
                ut_a(next_value > 0);
1355
 
 
1356
 
                /* Check for multiplication overflow. */
1357
 
                if (increment > (max_value / next_value)) {
1358
 
 
1359
 
                        next_value = max_value;
1360
 
                } else {
1361
 
                        next_value *= increment;
1362
 
 
1363
 
                        ut_a(max_value >= next_value);
1364
 
 
1365
 
                        /* Check for overflow. */
1366
 
                        if (max_value - next_value <= offset) {
1367
 
                                next_value = max_value;
1368
 
                        } else {
1369
 
                                next_value += offset;
1370
 
                        }
1371
 
                }
1372
 
        } else {
1373
 
                next_value = max_value;
1374
 
        }
1375
 
 
1376
 
        ut_a(next_value <= max_value);
1377
 
 
1378
 
        return(next_value);
 
1451
  uint64_t  next_value;
 
1452
 
 
1453
  /* Should never be 0. */
 
1454
  ut_a(increment > 0);
 
1455
 
 
1456
  /* According to MySQL documentation, if the offset is greater than
 
1457
  the increment then the offset is ignored. */
 
1458
  if (offset > increment) {
 
1459
    offset = 0;
 
1460
  }
 
1461
 
 
1462
  if (max_value <= current) {
 
1463
    next_value = max_value;
 
1464
  } else if (offset <= 1) {
 
1465
    /* Offset 0 and 1 are the same, because there must be at
 
1466
    least one node in the system. */
 
1467
    if (max_value - current <= increment) {
 
1468
      next_value = max_value;
 
1469
    } else {
 
1470
      next_value = current + increment;
 
1471
    }
 
1472
  } else if (max_value > current) {
 
1473
    if (current > offset) {
 
1474
      next_value = ((current - offset) / increment) + 1;
 
1475
    } else {
 
1476
      next_value = ((offset - current) / increment) + 1;
 
1477
    }
 
1478
 
 
1479
    ut_a(increment > 0);
 
1480
    ut_a(next_value > 0);
 
1481
 
 
1482
    /* Check for multiplication overflow. */
 
1483
    if (increment > (max_value / next_value)) {
 
1484
 
 
1485
      next_value = max_value;
 
1486
    } else {
 
1487
      next_value *= increment;
 
1488
 
 
1489
      ut_a(max_value >= next_value);
 
1490
 
 
1491
      /* Check for overflow. */
 
1492
      if (max_value - next_value <= offset) {
 
1493
        next_value = max_value;
 
1494
      } else {
 
1495
        next_value += offset;
 
1496
      }
 
1497
    }
 
1498
  } else {
 
1499
    next_value = max_value;
 
1500
  }
 
1501
 
 
1502
  ut_a(next_value <= max_value);
 
1503
 
 
1504
  return(next_value);
1379
1505
}
1380
1506
 
1381
1507
/*********************************************************************//**
1384
1510
void
1385
1511
innobase_trx_init(
1386
1512
/*==============*/
1387
 
        Session*        session,        /*!< in: user thread handle */
1388
 
        trx_t*  trx)    /*!< in/out: InnoDB transaction handle */
 
1513
  Session*  session,  /*!< in: user thread handle */
 
1514
  trx_t*  trx)  /*!< in/out: InnoDB transaction handle */
1389
1515
{
1390
 
        assert(session == trx->mysql_thd);
1391
 
 
1392
 
        trx->check_foreigns = !session_test_options(
1393
 
                session, OPTION_NO_FOREIGN_KEY_CHECKS);
1394
 
 
1395
 
        trx->check_unique_secondary = !session_test_options(
1396
 
                session, OPTION_RELAXED_UNIQUE_CHECKS);
1397
 
 
1398
 
        return;
 
1516
  assert(session == trx->mysql_thd);
 
1517
 
 
1518
  trx->check_foreigns = !session_test_options(
 
1519
    session, OPTION_NO_FOREIGN_KEY_CHECKS);
 
1520
 
 
1521
  trx->check_unique_secondary = !session_test_options(
 
1522
    session, OPTION_RELAXED_UNIQUE_CHECKS);
 
1523
 
 
1524
  return;
1399
1525
}
1400
1526
 
1401
1527
/*********************************************************************//**
1402
1528
Allocates an InnoDB transaction for a MySQL Cursor object.
1403
 
@return InnoDB transaction handle */
 
1529
@return InnoDB transaction handle */
1404
1530
extern "C" UNIV_INTERN
1405
1531
trx_t*
1406
1532
innobase_trx_allocate(
1407
1533
/*==================*/
1408
 
        Session*        session)        /*!< in: user thread handle */
 
1534
  Session*  session)  /*!< in: user thread handle */
1409
1535
{
1410
 
        trx_t*  trx;
1411
 
 
1412
 
        assert(session != NULL);
1413
 
        assert(EQ_CURRENT_SESSION(session));
1414
 
 
1415
 
        trx = trx_allocate_for_mysql();
1416
 
 
1417
 
        trx->mysql_thd = session;
1418
 
        trx->mysql_query_str = session->query.c_str();
1419
 
 
1420
 
        innobase_trx_init(session, trx);
1421
 
 
1422
 
        return(trx);
 
1536
  trx_t*  trx;
 
1537
 
 
1538
  assert(session != NULL);
 
1539
  assert(EQ_CURRENT_SESSION(session));
 
1540
 
 
1541
  trx = trx_allocate_for_mysql();
 
1542
 
 
1543
  trx->mysql_thd = session;
 
1544
  trx->mysql_query_str = session->query.c_str();
 
1545
 
 
1546
  innobase_trx_init(session, trx);
 
1547
 
 
1548
  return(trx);
1423
1549
}
1424
1550
 
1425
1551
/*********************************************************************//**
1426
1552
Gets the InnoDB transaction handle for a MySQL Cursor object, creates
1427
1553
an InnoDB transaction struct if the corresponding MySQL thread struct still
1428
1554
lacks one.
1429
 
@return InnoDB transaction handle */
 
1555
@return InnoDB transaction handle */
1430
1556
static
1431
1557
trx_t*
1432
1558
check_trx_exists(
1433
1559
/*=============*/
1434
 
        Session*        session)        /*!< in: user thread handle */
 
1560
  Session*  session)  /*!< in: user thread handle */
1435
1561
{
1436
 
        trx_t*& trx = session_to_trx(session);
1437
 
 
1438
 
        ut_ad(EQ_CURRENT_SESSION(session));
1439
 
 
1440
 
        if (trx == NULL) {
1441
 
                trx = innobase_trx_allocate(session);
1442
 
        } else if (UNIV_UNLIKELY(trx->magic_n != TRX_MAGIC_N)) {
1443
 
                mem_analyze_corruption(trx);
1444
 
                ut_error;
1445
 
        }
1446
 
 
1447
 
        innobase_trx_init(session, trx);
1448
 
 
1449
 
        return(trx);
 
1562
  trx_t*& trx = session_to_trx(session);
 
1563
 
 
1564
  ut_ad(EQ_CURRENT_SESSION(session));
 
1565
 
 
1566
  if (trx == NULL) {
 
1567
    trx = innobase_trx_allocate(session);
 
1568
  } else if (UNIV_UNLIKELY(trx->magic_n != TRX_MAGIC_N)) {
 
1569
    mem_analyze_corruption(trx);
 
1570
    ut_error;
 
1571
  }
 
1572
 
 
1573
  innobase_trx_init(session, trx);
 
1574
 
 
1575
  return(trx);
1450
1576
}
1451
1577
 
1452
1578
 
1479
1605
void
1480
1606
ha_innobase::update_session(
1481
1607
/*====================*/
1482
 
        Session*        session)        /*!< in: thd to use the handle */
 
1608
  Session*  session)  /*!< in: thd to use the handle */
1483
1609
{
1484
 
        trx_t*          trx;
1485
 
 
1486
 
        trx = check_trx_exists(session);
1487
 
 
1488
 
        if (prebuilt->trx != trx) {
1489
 
 
1490
 
                row_update_prebuilt_trx(prebuilt, trx);
1491
 
        }
1492
 
 
1493
 
        user_session = session;
 
1610
  trx_t*    trx;
 
1611
 
 
1612
  trx = check_trx_exists(session);
 
1613
 
 
1614
  if (prebuilt->trx != trx) {
 
1615
 
 
1616
    row_update_prebuilt_trx(prebuilt, trx);
 
1617
  }
 
1618
 
 
1619
  user_session = session;
1494
1620
}
1495
1621
 
1496
1622
/*********************************************************************//**
1502
1628
ha_innobase::update_session()
1503
1629
/*=====================*/
1504
1630
{
1505
 
        Session*        session = ha_session();
1506
 
        ut_ad(EQ_CURRENT_SESSION(session));
1507
 
        update_session(session);
 
1631
  Session*  session = ha_session();
 
1632
  ut_ad(EQ_CURRENT_SESSION(session));
 
1633
  update_session(session);
1508
1634
}
1509
1635
 
1510
1636
/*****************************************************************//**
1511
1637
Convert an SQL identifier to the MySQL system_charset_info (UTF-8)
1512
1638
and quote it if needed.
1513
 
@return pointer to the end of buf */
 
1639
@return pointer to the end of buf */
1514
1640
static
1515
1641
char*
1516
1642
innobase_convert_identifier(
1517
1643
/*========================*/
1518
 
        char*           buf,    /*!< out: buffer for converted identifier */
1519
 
        ulint           buflen, /*!< in: length of buf, in bytes */
1520
 
        const char*     id,     /*!< in: identifier to convert */
1521
 
        ulint           idlen,  /*!< in: length of id, in bytes */
1522
 
        void*           session,/*!< in: MySQL connection thread, or NULL */
1523
 
        ibool           file_id)/*!< in: TRUE=id is a table or database name;
1524
 
                                FALSE=id is an UTF-8 string */
 
1644
  char*   buf,  /*!< out: buffer for converted identifier */
 
1645
  ulint   buflen, /*!< in: length of buf, in bytes */
 
1646
  const char* id, /*!< in: identifier to convert */
 
1647
  ulint   idlen,  /*!< in: length of id, in bytes */
 
1648
  void*   session,/*!< in: MySQL connection thread, or NULL */
 
1649
  ibool   file_id)/*!< in: TRUE=id is a table or database name;
 
1650
        FALSE=id is an UTF-8 string */
1525
1651
{
1526
 
        char nz[NAME_LEN + 1];
1527
 
        char nz2[NAME_LEN + 1 + sizeof srv_mysql50_table_name_prefix];
1528
 
 
1529
 
        const char*     s       = id;
1530
 
        int             q;
1531
 
 
1532
 
        if (file_id) {
1533
 
                /* Decode the table name.  The filename_to_tablename()
1534
 
                function expects a NUL-terminated string.  The input and
1535
 
                output strings buffers must not be shared. */
1536
 
 
1537
 
                if (UNIV_UNLIKELY(idlen > (sizeof nz) - 1)) {
1538
 
                        idlen = (sizeof nz) - 1;
1539
 
                }
1540
 
 
1541
 
                memcpy(nz, id, idlen);
1542
 
                nz[idlen] = 0;
1543
 
 
1544
 
                s = nz2;
1545
 
                idlen = filename_to_tablename(nz, nz2, sizeof nz2);
1546
 
        }
1547
 
 
1548
 
        /* See if the identifier needs to be quoted. */
1549
 
        if (UNIV_UNLIKELY(!session)) {
1550
 
                q = '"';
1551
 
        } else {
1552
 
                q = get_quote_char_for_identifier();
1553
 
        }
1554
 
 
1555
 
        if (q == EOF) {
1556
 
                if (UNIV_UNLIKELY(idlen > buflen)) {
1557
 
                        idlen = buflen;
1558
 
                }
1559
 
                memcpy(buf, s, idlen);
1560
 
                return(buf + idlen);
1561
 
        }
1562
 
 
1563
 
        /* Quote the identifier. */
1564
 
        if (buflen < 2) {
1565
 
                return(buf);
1566
 
        }
1567
 
 
1568
 
        *buf++ = q;
1569
 
        buflen--;
1570
 
 
1571
 
        for (; idlen; idlen--) {
1572
 
                int     c = *s++;
1573
 
                if (UNIV_UNLIKELY(c == q)) {
1574
 
                        if (UNIV_UNLIKELY(buflen < 3)) {
1575
 
                                break;
1576
 
                        }
1577
 
 
1578
 
                        *buf++ = c;
1579
 
                        *buf++ = c;
1580
 
                        buflen -= 2;
1581
 
                } else {
1582
 
                        if (UNIV_UNLIKELY(buflen < 2)) {
1583
 
                                break;
1584
 
                        }
1585
 
 
1586
 
                        *buf++ = c;
1587
 
                        buflen--;
1588
 
                }
1589
 
        }
1590
 
 
1591
 
        *buf++ = q;
1592
 
        return(buf);
 
1652
  char nz[NAME_LEN + 1];
 
1653
  char nz2[NAME_LEN + 1 + sizeof srv_mysql50_table_name_prefix];
 
1654
 
 
1655
  const char* s = id;
 
1656
  int   q;
 
1657
 
 
1658
  if (file_id) {
 
1659
    /* Decode the table name.  The filename_to_tablename()
 
1660
    function expects a NUL-terminated string.  The input and
 
1661
    output strings buffers must not be shared. */
 
1662
 
 
1663
    if (UNIV_UNLIKELY(idlen > (sizeof nz) - 1)) {
 
1664
      idlen = (sizeof nz) - 1;
 
1665
    }
 
1666
 
 
1667
    memcpy(nz, id, idlen);
 
1668
    nz[idlen] = 0;
 
1669
 
 
1670
    s = nz2;
 
1671
    idlen = filename_to_tablename(nz, nz2, sizeof nz2);
 
1672
  }
 
1673
 
 
1674
  /* See if the identifier needs to be quoted. */
 
1675
  if (UNIV_UNLIKELY(!session)) {
 
1676
    q = '"';
 
1677
  } else {
 
1678
    q = get_quote_char_for_identifier();
 
1679
  }
 
1680
 
 
1681
  if (q == EOF) {
 
1682
    if (UNIV_UNLIKELY(idlen > buflen)) {
 
1683
      idlen = buflen;
 
1684
    }
 
1685
    memcpy(buf, s, idlen);
 
1686
    return(buf + idlen);
 
1687
  }
 
1688
 
 
1689
  /* Quote the identifier. */
 
1690
  if (buflen < 2) {
 
1691
    return(buf);
 
1692
  }
 
1693
 
 
1694
  *buf++ = q;
 
1695
  buflen--;
 
1696
 
 
1697
  for (; idlen; idlen--) {
 
1698
    int c = *s++;
 
1699
    if (UNIV_UNLIKELY(c == q)) {
 
1700
      if (UNIV_UNLIKELY(buflen < 3)) {
 
1701
        break;
 
1702
      }
 
1703
 
 
1704
      *buf++ = c;
 
1705
      *buf++ = c;
 
1706
      buflen -= 2;
 
1707
    } else {
 
1708
      if (UNIV_UNLIKELY(buflen < 2)) {
 
1709
        break;
 
1710
      }
 
1711
 
 
1712
      *buf++ = c;
 
1713
      buflen--;
 
1714
    }
 
1715
  }
 
1716
 
 
1717
  *buf++ = q;
 
1718
  return(buf);
1593
1719
}
1594
1720
 
1595
1721
/*****************************************************************//**
1596
1722
Convert a table or index name to the MySQL system_charset_info (UTF-8)
1597
1723
and quote it if needed.
1598
 
@return pointer to the end of buf */
 
1724
@return pointer to the end of buf */
1599
1725
extern "C" UNIV_INTERN
1600
1726
char*
1601
1727
innobase_convert_name(
1602
1728
/*==================*/
1603
 
        char*           buf,    /*!< out: buffer for converted identifier */
1604
 
        ulint           buflen, /*!< in: length of buf, in bytes */
1605
 
        const char*     id,     /*!< in: identifier to convert */
1606
 
        ulint           idlen,  /*!< in: length of id, in bytes */
1607
 
        void*           session,/*!< in: MySQL connection thread, or NULL */
1608
 
        ibool           table_id)/*!< in: TRUE=id is a table or database name;
1609
 
                                FALSE=id is an index name */
 
1729
  char*   buf,  /*!< out: buffer for converted identifier */
 
1730
  ulint   buflen, /*!< in: length of buf, in bytes */
 
1731
  const char* id, /*!< in: identifier to convert */
 
1732
  ulint   idlen,  /*!< in: length of id, in bytes */
 
1733
  void*   session,/*!< in: MySQL connection thread, or NULL */
 
1734
  ibool   table_id)/*!< in: TRUE=id is a table or database name;
 
1735
        FALSE=id is an index name */
1610
1736
{
1611
 
        char*           s       = buf;
1612
 
        const char*     bufend  = buf + buflen;
1613
 
 
1614
 
        if (table_id) {
1615
 
                const char*     slash = (const char*) memchr(id, '/', idlen);
1616
 
                if (!slash) {
1617
 
 
1618
 
                        goto no_db_name;
1619
 
                }
1620
 
 
1621
 
                /* Print the database name and table name separately. */
1622
 
                s = innobase_convert_identifier(s, bufend - s, id, slash - id,
1623
 
                                                session, TRUE);
1624
 
                if (UNIV_LIKELY(s < bufend)) {
1625
 
                        *s++ = '.';
1626
 
                        s = innobase_convert_identifier(s, bufend - s,
1627
 
                                                        slash + 1, idlen
1628
 
                                                        - (slash - id) - 1,
1629
 
                                                        session, TRUE);
1630
 
                }
1631
 
        } else if (UNIV_UNLIKELY(*id == TEMP_INDEX_PREFIX)) {
1632
 
                /* Temporary index name (smart ALTER TABLE) */
1633
 
                const char temp_index_suffix[]= "--temporary--";
1634
 
 
1635
 
                s = innobase_convert_identifier(buf, buflen, id + 1, idlen - 1,
1636
 
                                                session, FALSE);
1637
 
                if (s - buf + (sizeof temp_index_suffix - 1) < buflen) {
1638
 
                        memcpy(s, temp_index_suffix,
1639
 
                               sizeof temp_index_suffix - 1);
1640
 
                        s += sizeof temp_index_suffix - 1;
1641
 
                }
1642
 
        } else {
 
1737
  char*   s = buf;
 
1738
  const char* bufend  = buf + buflen;
 
1739
 
 
1740
  if (table_id) {
 
1741
    const char* slash = (const char*) memchr(id, '/', idlen);
 
1742
    if (!slash) {
 
1743
 
 
1744
      goto no_db_name;
 
1745
    }
 
1746
 
 
1747
    /* Print the database name and table name separately. */
 
1748
    s = innobase_convert_identifier(s, bufend - s, id, slash - id,
 
1749
            session, TRUE);
 
1750
    if (UNIV_LIKELY(s < bufend)) {
 
1751
      *s++ = '.';
 
1752
      s = innobase_convert_identifier(s, bufend - s,
 
1753
              slash + 1, idlen
 
1754
              - (slash - id) - 1,
 
1755
              session, TRUE);
 
1756
    }
 
1757
  } else if (UNIV_UNLIKELY(*id == TEMP_INDEX_PREFIX)) {
 
1758
    /* Temporary index name (smart ALTER TABLE) */
 
1759
    const char temp_index_suffix[]= "--temporary--";
 
1760
 
 
1761
    s = innobase_convert_identifier(buf, buflen, id + 1, idlen - 1,
 
1762
            session, FALSE);
 
1763
    if (s - buf + (sizeof temp_index_suffix - 1) < buflen) {
 
1764
      memcpy(s, temp_index_suffix,
 
1765
             sizeof temp_index_suffix - 1);
 
1766
      s += sizeof temp_index_suffix - 1;
 
1767
    }
 
1768
  } else {
1643
1769
no_db_name:
1644
 
                s = innobase_convert_identifier(buf, buflen, id, idlen,
1645
 
                                                session, table_id);
1646
 
        }
 
1770
    s = innobase_convert_identifier(buf, buflen, id, idlen,
 
1771
            session, table_id);
 
1772
  }
1647
1773
 
1648
 
        return(s);
 
1774
  return(s);
1649
1775
 
1650
1776
}
1651
1777
 
1652
1778
/**********************************************************************//**
1653
1779
Determines if the currently running transaction has been interrupted.
1654
 
@return TRUE if interrupted */
 
1780
@return TRUE if interrupted */
1655
1781
extern "C" UNIV_INTERN
1656
1782
ibool
1657
1783
trx_is_interrupted(
1658
1784
/*===============*/
1659
 
        trx_t*  trx)    /*!< in: transaction */
 
1785
  trx_t*  trx)  /*!< in: transaction */
1660
1786
{
1661
 
        return(trx && trx->mysql_thd && session_killed((Session*) trx->mysql_thd));
 
1787
  return(trx && trx->mysql_thd && session_killed((Session*) trx->mysql_thd));
1662
1788
}
1663
1789
 
1664
1790
/**************************************************************//**
1668
1794
void
1669
1795
reset_template(
1670
1796
/*===========*/
1671
 
        row_prebuilt_t* prebuilt)       /*!< in/out: prebuilt struct */
 
1797
  row_prebuilt_t* prebuilt) /*!< in/out: prebuilt struct */
1672
1798
{
1673
 
        prebuilt->keep_other_fields_on_keyread = 0;
1674
 
        prebuilt->read_just_key = 0;
 
1799
  prebuilt->keep_other_fields_on_keyread = 0;
 
1800
  prebuilt->read_just_key = 0;
1675
1801
}
1676
1802
 
1677
1803
/*********************************************************************//**
1678
1804
Opens an InnoDB database.
1679
 
@return 0 on success, error code on failure */
 
1805
@return 0 on success, error code on failure */
1680
1806
static
1681
1807
int
1682
1808
innobase_init(
1683
1809
/*==========*/
1684
 
        plugin::Registry        &registry)      /*!< in: Drizzle Plugin Registry */
 
1810
  plugin::Context &context) /*!< in: Drizzle Plugin Context */
1685
1811
{
1686
 
        static char     current_dir[3];         /*!< Set if using current lib */
1687
 
        int             err;
1688
 
        bool            ret;
1689
 
        char            *default_path;
1690
 
        uint            format_id;
1691
 
 
1692
 
        innodb_engine_ptr= new InnobaseEngine(innobase_engine_name);
1693
 
 
1694
 
 
1695
 
        ut_a(DATA_MYSQL_TRUE_VARCHAR == (ulint)DRIZZLE_TYPE_VARCHAR);
 
1812
  static char current_dir[3];   /*!< Set if using current lib */
 
1813
  int   err;
 
1814
  bool    ret;
 
1815
  char    *default_path;
 
1816
  uint    format_id;
 
1817
 
 
1818
  innodb_engine_ptr= new InnobaseEngine(innobase_engine_name);
 
1819
 
 
1820
  ut_a(DATA_MYSQL_TRUE_VARCHAR == (ulint)DRIZZLE_TYPE_VARCHAR);
1696
1821
 
1697
1822
#ifdef UNIV_DEBUG
1698
 
        static const char       test_filename[] = "-@";
1699
 
        char                    test_tablename[sizeof test_filename
1700
 
                                + sizeof srv_mysql50_table_name_prefix];
1701
 
        if ((sizeof test_tablename) - 1
1702
 
                        != filename_to_tablename(test_filename, test_tablename,
1703
 
                        sizeof test_tablename)
1704
 
                        || strncmp(test_tablename,
1705
 
                        srv_mysql50_table_name_prefix,
1706
 
                        sizeof srv_mysql50_table_name_prefix)
1707
 
                        || strcmp(test_tablename
1708
 
                        + sizeof srv_mysql50_table_name_prefix,
1709
 
                        test_filename)) {
1710
 
                errmsg_printf(ERRMSG_LVL_ERROR, "tablename encoding has been changed");
1711
 
                goto error;
1712
 
        }
 
1823
  static const char test_filename[] = "-@";
 
1824
  char      test_tablename[sizeof test_filename
 
1825
        + sizeof srv_mysql50_table_name_prefix];
 
1826
  if ((sizeof test_tablename) - 1
 
1827
      != filename_to_tablename(test_filename, test_tablename,
 
1828
      sizeof test_tablename)
 
1829
      || strncmp(test_tablename,
 
1830
      srv_mysql50_table_name_prefix,
 
1831
      sizeof srv_mysql50_table_name_prefix)
 
1832
      || strcmp(test_tablename
 
1833
      + sizeof srv_mysql50_table_name_prefix,
 
1834
      test_filename)) {
 
1835
    errmsg_printf(ERRMSG_LVL_ERROR, "tablename encoding has been changed");
 
1836
    goto error;
 
1837
  }
1713
1838
#endif /* UNIV_DEBUG */
1714
1839
 
1715
 
        /* Check that values don't overflow on 32-bit systems. */
1716
 
        if (sizeof(ulint) == 4) {
1717
 
                if (innobase_buffer_pool_size > UINT32_MAX) {
1718
 
                        errmsg_printf(ERRMSG_LVL_ERROR, 
1719
 
                                "innobase_buffer_pool_size can't be over 4GB"
1720
 
                                " on 32-bit systems");
1721
 
 
1722
 
                        goto error;
1723
 
                }
1724
 
 
1725
 
                if (innobase_log_file_size > UINT32_MAX) {
1726
 
                        errmsg_printf(ERRMSG_LVL_ERROR, 
1727
 
                                "innobase_log_file_size can't be over 4GB"
1728
 
                                " on 32-bit systems");
1729
 
 
1730
 
                        goto error;
1731
 
                }
1732
 
        }
1733
 
 
1734
 
        os_innodb_umask = (ulint)internal::my_umask;
1735
 
 
1736
 
        /* First calculate the default path for innodb_data_home_dir etc.,
1737
 
        in case the user has not given any value.
1738
 
 
1739
 
        Note that when using the embedded server, the datadirectory is not
1740
 
        necessarily the current directory of this program. */
1741
 
 
1742
 
        /* It's better to use current lib, to keep paths short */
1743
 
        current_dir[0] = FN_CURLIB;
1744
 
        current_dir[1] = FN_LIBCHAR;
1745
 
        current_dir[2] = 0;
1746
 
        default_path = current_dir;
1747
 
 
1748
 
        ut_a(default_path);
1749
 
 
1750
 
        srv_set_thread_priorities = TRUE;
1751
 
        srv_query_thread_priority = QUERY_PRIOR;
1752
 
 
1753
 
        /* Set InnoDB initialization parameters according to the values
1754
 
        read from MySQL .cnf file */
1755
 
 
1756
 
        /*--------------- Data files -------------------------*/
1757
 
 
1758
 
        /* The default dir for data files is the datadir of MySQL */
1759
 
 
1760
 
        srv_data_home = (innobase_data_home_dir ? innobase_data_home_dir :
1761
 
                         default_path);
1762
 
 
1763
 
        /* Set default InnoDB data file size to 10 MB and let it be
1764
 
        auto-extending. Thus users can use InnoDB in >= 4.0 without having
1765
 
        to specify any startup options. */
1766
 
 
1767
 
        if (!innobase_data_file_path) {
1768
 
                innobase_data_file_path = (char*) "ibdata1:10M:autoextend";
1769
 
        }
1770
 
 
1771
 
        /* Since InnoDB edits the argument in the next call, we make another
1772
 
        copy of it: */
1773
 
 
1774
 
        internal_innobase_data_file_path = strdup(innobase_data_file_path);
1775
 
 
1776
 
        ret = (bool) srv_parse_data_file_paths_and_sizes(
1777
 
                internal_innobase_data_file_path);
1778
 
        if (ret == FALSE) {
1779
 
                errmsg_printf(ERRMSG_LVL_ERROR, 
1780
 
                        "InnoDB: syntax error in innodb_data_file_path");
 
1840
  /* Check that values don't overflow on 32-bit systems. */
 
1841
  if (sizeof(ulint) == 4) {
 
1842
    if (innobase_buffer_pool_size > UINT32_MAX) {
 
1843
      errmsg_printf(ERRMSG_LVL_ERROR, 
 
1844
        "innobase_buffer_pool_size can't be over 4GB"
 
1845
        " on 32-bit systems");
 
1846
 
 
1847
      goto error;
 
1848
    }
 
1849
 
 
1850
    if (innobase_log_file_size > UINT32_MAX) {
 
1851
      errmsg_printf(ERRMSG_LVL_ERROR, 
 
1852
        "innobase_log_file_size can't be over 4GB"
 
1853
        " on 32-bit systems");
 
1854
 
 
1855
      goto error;
 
1856
    }
 
1857
  }
 
1858
 
 
1859
  os_innodb_umask = (ulint)internal::my_umask;
 
1860
 
 
1861
  /* First calculate the default path for innodb_data_home_dir etc.,
 
1862
  in case the user has not given any value.
 
1863
 
 
1864
  Note that when using the embedded server, the datadirectory is not
 
1865
  necessarily the current directory of this program. */
 
1866
 
 
1867
  /* It's better to use current lib, to keep paths short */
 
1868
  current_dir[0] = FN_CURLIB;
 
1869
  current_dir[1] = FN_LIBCHAR;
 
1870
  current_dir[2] = 0;
 
1871
  default_path = current_dir;
 
1872
 
 
1873
  ut_a(default_path);
 
1874
 
 
1875
  srv_set_thread_priorities = TRUE;
 
1876
  srv_query_thread_priority = QUERY_PRIOR;
 
1877
 
 
1878
  /* Set InnoDB initialization parameters according to the values
 
1879
  read from MySQL .cnf file */
 
1880
 
 
1881
  /*--------------- Data files -------------------------*/
 
1882
 
 
1883
  /* The default dir for data files is the datadir of MySQL */
 
1884
 
 
1885
  srv_data_home = (innobase_data_home_dir ? innobase_data_home_dir :
 
1886
       default_path);
 
1887
 
 
1888
  /* Set default InnoDB data file size to 10 MB and let it be
 
1889
  auto-extending. Thus users can use InnoDB in >= 4.0 without having
 
1890
  to specify any startup options. */
 
1891
 
 
1892
  if (!innobase_data_file_path) {
 
1893
    innobase_data_file_path = (char*) "ibdata1:10M:autoextend";
 
1894
  }
 
1895
 
 
1896
  /* Since InnoDB edits the argument in the next call, we make another
 
1897
  copy of it: */
 
1898
 
 
1899
  internal_innobase_data_file_path = strdup(innobase_data_file_path);
 
1900
 
 
1901
  ret = (bool) srv_parse_data_file_paths_and_sizes(
 
1902
    internal_innobase_data_file_path);
 
1903
  if (ret == FALSE) {
 
1904
    errmsg_printf(ERRMSG_LVL_ERROR, 
 
1905
      "InnoDB: syntax error in innodb_data_file_path");
1781
1906
mem_free_and_error:
1782
 
                srv_free_paths_and_sizes();
1783
 
                if (internal_innobase_data_file_path)
1784
 
                  free(internal_innobase_data_file_path);
1785
 
                goto error;
1786
 
        }
1787
 
 
1788
 
        /* -------------- Log files ---------------------------*/
1789
 
 
1790
 
        /* The default dir for log files is the datadir of MySQL */
1791
 
 
1792
 
        if (!innobase_log_group_home_dir) {
1793
 
                innobase_log_group_home_dir = default_path;
1794
 
        }
 
1907
    srv_free_paths_and_sizes();
 
1908
    if (internal_innobase_data_file_path)
 
1909
      free(internal_innobase_data_file_path);
 
1910
    goto error;
 
1911
  }
 
1912
 
 
1913
  /* -------------- Log files ---------------------------*/
 
1914
 
 
1915
  /* The default dir for log files is the datadir of MySQL */
 
1916
 
 
1917
  if (!innobase_log_group_home_dir) {
 
1918
    innobase_log_group_home_dir = default_path;
 
1919
  }
1795
1920
 
1796
1921
#ifdef UNIV_LOG_ARCHIVE
1797
 
        /* Since innodb_log_arch_dir has no relevance under MySQL,
1798
 
        starting from 4.0.6 we always set it the same as
1799
 
        innodb_log_group_home_dir: */
1800
 
 
1801
 
        innobase_log_arch_dir = innobase_log_group_home_dir;
1802
 
 
1803
 
        srv_arch_dir = innobase_log_arch_dir;
 
1922
  /* Since innodb_log_arch_dir has no relevance under MySQL,
 
1923
  starting from 4.0.6 we always set it the same as
 
1924
  innodb_log_group_home_dir: */
 
1925
 
 
1926
  innobase_log_arch_dir = innobase_log_group_home_dir;
 
1927
 
 
1928
  srv_arch_dir = innobase_log_arch_dir;
1804
1929
#endif /* UNIG_LOG_ARCHIVE */
1805
1930
 
1806
 
        ret = (bool)
1807
 
                srv_parse_log_group_home_dirs(innobase_log_group_home_dir);
1808
 
 
1809
 
        if (ret == FALSE || innobase_mirrored_log_groups != 1) {
1810
 
          errmsg_printf(ERRMSG_LVL_ERROR, "syntax error in innodb_log_group_home_dir, or a "
1811
 
                          "wrong number of mirrored log groups");
1812
 
 
1813
 
                goto mem_free_and_error;
1814
 
        }
1815
 
 
1816
 
        /* Validate the file format by animal name */
1817
 
        if (innobase_file_format_name != NULL) {
1818
 
 
1819
 
                format_id = innobase_file_format_name_lookup(
1820
 
                        innobase_file_format_name);
1821
 
 
1822
 
                if (format_id > DICT_TF_FORMAT_MAX) {
1823
 
 
1824
 
                        errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB: wrong innodb_file_format.");
1825
 
 
1826
 
                        goto mem_free_and_error;
1827
 
                }
1828
 
        } else {
1829
 
                /* Set it to the default file format id. Though this
1830
 
                should never happen. */
1831
 
                format_id = 0;
1832
 
        }
1833
 
 
1834
 
        srv_file_format = format_id;
1835
 
 
1836
 
        /* Given the type of innobase_file_format_name we have little
1837
 
        choice but to cast away the constness from the returned name.
1838
 
        innobase_file_format_name is used in the MySQL set variable
1839
 
        interface and so can't be const. */
1840
 
 
1841
 
        innobase_file_format_name = 
1842
 
                (char*) trx_sys_file_format_id_to_name(format_id);
1843
 
 
1844
 
        /* Process innobase_file_format_check variable */
1845
 
        ut_a(innobase_file_format_check != NULL);
1846
 
 
1847
 
        /* As a side effect it will set srv_check_file_format_at_startup
1848
 
        on valid input. First we check for "on"/"off". */
1849
 
        if (!innobase_file_format_check_on_off(innobase_file_format_check)) {
1850
 
 
1851
 
                /* Did the user specify a format name that we support ?
1852
 
                As a side effect it will update the variable
1853
 
                srv_check_file_format_at_startup */
1854
 
                if (!innobase_file_format_check_validate(
1855
 
                        innobase_file_format_check)) {
1856
 
 
1857
 
                        errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB: invalid "
1858
 
                                        "innodb_file_format_check value: "
1859
 
                                        "should be either 'on' or 'off' or "
1860
 
                                        "any value up to %s or its "
1861
 
                                        "equivalent numeric id",
1862
 
                                        trx_sys_file_format_id_to_name(
1863
 
                                                DICT_TF_FORMAT_MAX));
1864
 
 
1865
 
                        goto mem_free_and_error;
1866
 
                }
1867
 
        }
1868
 
 
1869
 
        if (innobase_change_buffering) {
1870
 
                ulint   use;
1871
 
 
1872
 
                for (use = 0;
1873
 
                     use < UT_ARR_SIZE(innobase_change_buffering_values);
1874
 
                     use++) {
1875
 
                        if (!innobase_strcasecmp(
1876
 
                                    innobase_change_buffering,
1877
 
                                    innobase_change_buffering_values[use])) {
1878
 
                                ibuf_use = (ibuf_use_t) use;
1879
 
                                goto innobase_change_buffering_inited_ok;
1880
 
                        }
1881
 
                }
1882
 
 
1883
 
                errmsg_printf(ERRMSG_LVL_ERROR,
1884
 
                                "InnoDB: invalid value "
1885
 
                                "innodb_file_format_check=%s",
1886
 
                                innobase_change_buffering);
1887
 
                goto mem_free_and_error;
1888
 
        }
 
1931
  ret = (bool)
 
1932
    srv_parse_log_group_home_dirs(innobase_log_group_home_dir);
 
1933
 
 
1934
  if (ret == FALSE || innobase_mirrored_log_groups != 1) {
 
1935
    errmsg_printf(ERRMSG_LVL_ERROR, "syntax error in innodb_log_group_home_dir, or a "
 
1936
        "wrong number of mirrored log groups");
 
1937
 
 
1938
    goto mem_free_and_error;
 
1939
  }
 
1940
 
 
1941
  /* Validate the file format by animal name */
 
1942
  if (innobase_file_format_name != NULL) {
 
1943
 
 
1944
    format_id = innobase_file_format_name_lookup(
 
1945
      innobase_file_format_name);
 
1946
 
 
1947
    if (format_id > DICT_TF_FORMAT_MAX) {
 
1948
 
 
1949
      errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB: wrong innodb_file_format.");
 
1950
 
 
1951
      goto mem_free_and_error;
 
1952
    }
 
1953
  } else {
 
1954
    /* Set it to the default file format id. Though this
 
1955
    should never happen. */
 
1956
    format_id = 0;
 
1957
  }
 
1958
 
 
1959
  srv_file_format = format_id;
 
1960
 
 
1961
  /* Given the type of innobase_file_format_name we have little
 
1962
  choice but to cast away the constness from the returned name.
 
1963
  innobase_file_format_name is used in the MySQL set variable
 
1964
  interface and so can't be const. */
 
1965
 
 
1966
  innobase_file_format_name = 
 
1967
    (char*) trx_sys_file_format_id_to_name(format_id);
 
1968
 
 
1969
  /* Process innobase_file_format_check variable */
 
1970
  ut_a(innobase_file_format_check != NULL);
 
1971
 
 
1972
  /* As a side effect it will set srv_check_file_format_at_startup
 
1973
  on valid input. First we check for "on"/"off". */
 
1974
  if (!innobase_file_format_check_on_off(innobase_file_format_check)) {
 
1975
 
 
1976
    /* Did the user specify a format name that we support ?
 
1977
    As a side effect it will update the variable
 
1978
    srv_check_file_format_at_startup */
 
1979
    if (!innobase_file_format_check_validate(
 
1980
      innobase_file_format_check)) {
 
1981
 
 
1982
      errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB: invalid "
 
1983
          "innodb_file_format_check value: "
 
1984
          "should be either 'on' or 'off' or "
 
1985
          "any value up to %s or its "
 
1986
          "equivalent numeric id",
 
1987
          trx_sys_file_format_id_to_name(
 
1988
            DICT_TF_FORMAT_MAX));
 
1989
 
 
1990
      goto mem_free_and_error;
 
1991
    }
 
1992
  }
 
1993
 
 
1994
  if (innobase_change_buffering) {
 
1995
    ulint use;
 
1996
 
 
1997
    for (use = 0;
 
1998
         use < UT_ARR_SIZE(innobase_change_buffering_values);
 
1999
         use++) {
 
2000
      if (!innobase_strcasecmp(
 
2001
            innobase_change_buffering,
 
2002
            innobase_change_buffering_values[use])) {
 
2003
        ibuf_use = (ibuf_use_t) use;
 
2004
        goto innobase_change_buffering_inited_ok;
 
2005
      }
 
2006
    }
 
2007
 
 
2008
    errmsg_printf(ERRMSG_LVL_ERROR,
 
2009
        "InnoDB: invalid value "
 
2010
        "innodb_file_format_check=%s",
 
2011
        innobase_change_buffering);
 
2012
    goto mem_free_and_error;
 
2013
  }
1889
2014
 
1890
2015
innobase_change_buffering_inited_ok:
1891
 
        ut_a((ulint) ibuf_use < UT_ARR_SIZE(innobase_change_buffering_values));
1892
 
        innobase_change_buffering = (char*)
1893
 
                innobase_change_buffering_values[ibuf_use];
1894
 
 
1895
 
        /* --------------------------------------------------*/
1896
 
 
1897
 
        srv_file_flush_method_str = innobase_unix_file_flush_method;
1898
 
 
1899
 
        srv_n_log_groups = (ulint) innobase_mirrored_log_groups;
1900
 
        srv_n_log_files = (ulint) innobase_log_files_in_group;
1901
 
        srv_log_file_size = (ulint) innobase_log_file_size;
 
2016
  ut_a((ulint) ibuf_use < UT_ARR_SIZE(innobase_change_buffering_values));
 
2017
  innobase_change_buffering = (char*)
 
2018
    innobase_change_buffering_values[ibuf_use];
 
2019
 
 
2020
  /* --------------------------------------------------*/
 
2021
 
 
2022
  srv_file_flush_method_str = innobase_unix_file_flush_method;
 
2023
 
 
2024
  srv_n_log_groups = (ulint) innobase_mirrored_log_groups;
 
2025
  srv_n_log_files = (ulint) innobase_log_files_in_group;
 
2026
  srv_log_file_size = (ulint) innobase_log_file_size;
1902
2027
 
1903
2028
#ifdef UNIV_LOG_ARCHIVE
1904
 
        srv_log_archive_on = (ulint) innobase_log_archive;
 
2029
  srv_log_archive_on = (ulint) innobase_log_archive;
1905
2030
#endif /* UNIV_LOG_ARCHIVE */
1906
 
        srv_log_buffer_size = (ulint) innobase_log_buffer_size;
1907
 
 
1908
 
        srv_buf_pool_size = (ulint) innobase_buffer_pool_size;
1909
 
 
1910
 
        srv_mem_pool_size = (ulint) innobase_additional_mem_pool_size;
1911
 
 
1912
 
        srv_n_file_io_threads = (ulint) innobase_file_io_threads;
1913
 
        srv_n_read_io_threads = (ulint) innobase_read_io_threads;
1914
 
        srv_n_write_io_threads = (ulint) innobase_write_io_threads;
1915
 
 
1916
 
        srv_force_recovery = (ulint) innobase_force_recovery;
1917
 
 
1918
 
        srv_use_doublewrite_buf = (ibool) innobase_use_doublewrite;
1919
 
        srv_use_checksums = (ibool) innobase_use_checksums;
 
2031
  srv_log_buffer_size = (ulint) innobase_log_buffer_size;
 
2032
 
 
2033
  srv_buf_pool_size = (ulint) innobase_buffer_pool_size;
 
2034
 
 
2035
  srv_mem_pool_size = (ulint) innobase_additional_mem_pool_size;
 
2036
 
 
2037
  srv_n_file_io_threads = (ulint) innobase_file_io_threads;
 
2038
  srv_n_read_io_threads = (ulint) innobase_read_io_threads;
 
2039
  srv_n_write_io_threads = (ulint) innobase_write_io_threads;
 
2040
 
 
2041
  srv_force_recovery = (ulint) innobase_force_recovery;
 
2042
 
 
2043
  srv_use_doublewrite_buf = (ibool) innobase_use_doublewrite;
 
2044
  srv_use_checksums = (ibool) innobase_use_checksums;
1920
2045
 
1921
2046
#ifdef HAVE_LARGE_PAGES
1922
2047
        if ((os_use_large_pages = (ibool) my_use_large_pages))
1923
 
                os_large_page_size = (ulint) opt_large_page_size;
 
2048
    os_large_page_size = (ulint) opt_large_page_size;
1924
2049
#endif
1925
2050
 
1926
 
        row_rollback_on_timeout = (ibool) innobase_rollback_on_timeout;
1927
 
 
1928
 
        srv_locks_unsafe_for_binlog = (ibool) innobase_locks_unsafe_for_binlog;
1929
 
 
1930
 
        srv_max_n_open_files = (ulint) innobase_open_files;
1931
 
        srv_innodb_status = (ibool) innobase_create_status_file;
1932
 
 
1933
 
        srv_print_verbose_log = true;
1934
 
 
1935
 
        /* Store the default charset-collation number of this MySQL
1936
 
        installation */
1937
 
 
1938
 
        data_mysql_default_charset_coll = (ulint)default_charset_info->number;
1939
 
 
1940
 
 
1941
 
        innobase_commit_concurrency_init_default();
1942
 
 
1943
 
        /* Since we in this module access directly the fields of a trx
1944
 
        struct, and due to different headers and flags it might happen that
1945
 
        mutex_t has a different size in this module and in InnoDB
1946
 
        modules, we check at run time that the size is the same in
1947
 
        these compilation modules. */
1948
 
 
1949
 
        err = innobase_start_or_create_for_mysql();
1950
 
 
1951
 
        if (err != DB_SUCCESS) {
1952
 
                goto mem_free_and_error;
1953
 
        }
1954
 
 
1955
 
        innobase_open_tables = hash_create(200);
1956
 
        pthread_mutex_init(&innobase_share_mutex, MY_MUTEX_INIT_FAST);
1957
 
        pthread_mutex_init(&prepare_commit_mutex, MY_MUTEX_INIT_FAST);
1958
 
        pthread_mutex_init(&commit_threads_m, MY_MUTEX_INIT_FAST);
1959
 
        pthread_mutex_init(&commit_cond_m, MY_MUTEX_INIT_FAST);
1960
 
        pthread_cond_init(&commit_cond, NULL);
1961
 
        innodb_inited= 1;
 
2051
  row_rollback_on_timeout = (ibool) innobase_rollback_on_timeout;
 
2052
 
 
2053
  srv_locks_unsafe_for_binlog = (ibool) TRUE;
 
2054
 
 
2055
  srv_max_n_open_files = (ulint) innobase_open_files;
 
2056
  srv_innodb_status = (ibool) innobase_create_status_file;
 
2057
 
 
2058
  srv_print_verbose_log = true;
 
2059
 
 
2060
  /* Store the default charset-collation number of this MySQL
 
2061
  installation */
 
2062
 
 
2063
  data_mysql_default_charset_coll = (ulint)default_charset_info->number;
 
2064
 
 
2065
 
 
2066
  innobase_commit_concurrency_init_default();
 
2067
 
 
2068
  /* Since we in this module access directly the fields of a trx
 
2069
  struct, and due to different headers and flags it might happen that
 
2070
  mutex_t has a different size in this module and in InnoDB
 
2071
  modules, we check at run time that the size is the same in
 
2072
  these compilation modules. */
 
2073
 
 
2074
  err = innobase_start_or_create_for_mysql();
 
2075
 
 
2076
  if (err != DB_SUCCESS) {
 
2077
    goto mem_free_and_error;
 
2078
  }
 
2079
 
 
2080
  innobase_open_tables = hash_create(200);
 
2081
  pthread_mutex_init(&innobase_share_mutex, MY_MUTEX_INIT_FAST);
 
2082
  pthread_mutex_init(&prepare_commit_mutex, MY_MUTEX_INIT_FAST);
 
2083
  pthread_mutex_init(&commit_threads_m, MY_MUTEX_INIT_FAST);
 
2084
  pthread_mutex_init(&commit_cond_m, MY_MUTEX_INIT_FAST);
 
2085
  pthread_cond_init(&commit_cond, NULL);
 
2086
  innodb_inited= 1;
1962
2087
 
1963
2088
        status_table_function_ptr= new InnodbStatusTool;
1964
2089
 
1965
 
        registry.add(innodb_engine_ptr);
1966
 
 
1967
 
        registry.add(status_table_function_ptr);
1968
 
 
1969
 
        cmp_tool= new(std::nothrow)CmpTool(false);
1970
 
        registry.add(cmp_tool);
1971
 
 
1972
 
        cmp_reset_tool= new(std::nothrow)CmpTool(true);
1973
 
        registry.add(cmp_reset_tool);
1974
 
 
1975
 
        cmp_mem_tool= new(std::nothrow)CmpmemTool(false);
1976
 
        registry.add(cmp_mem_tool);
1977
 
 
1978
 
        cmp_mem_reset_tool= new(std::nothrow)CmpmemTool(true);
1979
 
        registry.add(cmp_mem_reset_tool);
1980
 
 
1981
 
        innodb_trx_tool= new(std::nothrow)InnodbTrxTool("INNODB_TRX");
1982
 
        registry.add(innodb_trx_tool);
1983
 
 
1984
 
        innodb_locks_tool= new(std::nothrow)InnodbTrxTool("INNODB_LOCKS");
1985
 
        registry.add(innodb_locks_tool);
1986
 
 
1987
 
        innodb_lock_waits_tool= new(std::nothrow)InnodbTrxTool("INNODB_LOCK_WAITS");
1988
 
        registry.add(innodb_lock_waits_tool);
1989
 
 
1990
 
        /* Get the current high water mark format. */
1991
 
        innobase_file_format_check = (char*) trx_sys_file_format_max_get();
1992
 
 
1993
 
        return(FALSE);
 
2090
  context.add(innodb_engine_ptr);
 
2091
 
 
2092
  context.add(status_table_function_ptr);
 
2093
 
 
2094
  cmp_tool= new(std::nothrow)CmpTool(false);
 
2095
  context.add(cmp_tool);
 
2096
 
 
2097
  cmp_reset_tool= new(std::nothrow)CmpTool(true);
 
2098
  context.add(cmp_reset_tool);
 
2099
 
 
2100
  cmp_mem_tool= new(std::nothrow)CmpmemTool(false);
 
2101
  context.add(cmp_mem_tool);
 
2102
 
 
2103
  cmp_mem_reset_tool= new(std::nothrow)CmpmemTool(true);
 
2104
  context.add(cmp_mem_reset_tool);
 
2105
 
 
2106
  innodb_trx_tool= new(std::nothrow)InnodbTrxTool("INNODB_TRX");
 
2107
  context.add(innodb_trx_tool);
 
2108
 
 
2109
  innodb_locks_tool= new(std::nothrow)InnodbTrxTool("INNODB_LOCKS");
 
2110
  context.add(innodb_locks_tool);
 
2111
 
 
2112
  innodb_lock_waits_tool= new(std::nothrow)InnodbTrxTool("INNODB_LOCK_WAITS");
 
2113
  context.add(innodb_lock_waits_tool);
 
2114
 
 
2115
  /* Get the current high water mark format. */
 
2116
  innobase_file_format_check = (char*) trx_sys_file_format_max_get();
 
2117
 
 
2118
  return(FALSE);
1994
2119
error:
1995
 
        return(TRUE);
1996
 
}
1997
 
 
1998
 
/*******************************************************************//**
1999
 
Closes an InnoDB database.
2000
 
@return TRUE if error */
2001
 
static
2002
 
int
2003
 
innobase_deinit(plugin::Registry &registry)
2004
 
{
2005
 
        int     err= 0;
2006
 
 
2007
 
        registry.remove(status_table_function_ptr);
2008
 
        delete status_table_function_ptr;
2009
 
 
2010
 
        registry.remove(cmp_tool);
2011
 
        delete cmp_tool;
2012
 
 
2013
 
        registry.remove(cmp_reset_tool);
2014
 
        delete cmp_reset_tool;
2015
 
 
2016
 
        registry.remove(cmp_mem_tool);
2017
 
        delete cmp_mem_tool;
2018
 
 
2019
 
        registry.remove(cmp_mem_reset_tool);
2020
 
        delete cmp_mem_reset_tool;
2021
 
 
2022
 
        registry.remove(innodb_trx_tool);
2023
 
        delete innodb_trx_tool;
2024
 
 
2025
 
        registry.remove(innodb_locks_tool);
2026
 
        delete innodb_locks_tool;
2027
 
 
2028
 
        registry.remove(innodb_lock_waits_tool);
2029
 
        delete innodb_lock_waits_tool;
2030
 
 
2031
 
        registry.remove(innodb_engine_ptr);
2032
 
        delete innodb_engine_ptr;
2033
 
 
2034
 
        if (innodb_inited) {
2035
 
 
2036
 
                srv_fast_shutdown = (ulint) innobase_fast_shutdown;
2037
 
                innodb_inited = 0;
2038
 
                hash_table_free(innobase_open_tables);
2039
 
                innobase_open_tables = NULL;
2040
 
                if (innobase_shutdown_for_mysql() != DB_SUCCESS) {
2041
 
                        err = 1;
2042
 
                }
2043
 
                srv_free_paths_and_sizes();
2044
 
                if (internal_innobase_data_file_path)
2045
 
                  free(internal_innobase_data_file_path);
2046
 
                pthread_mutex_destroy(&innobase_share_mutex);
2047
 
                pthread_mutex_destroy(&prepare_commit_mutex);
2048
 
                pthread_mutex_destroy(&commit_threads_m);
2049
 
                pthread_mutex_destroy(&commit_cond_m);
2050
 
                pthread_cond_destroy(&commit_cond);
2051
 
        }
2052
 
 
2053
 
        return(err);
2054
 
}
 
2120
  return(TRUE);
 
2121
}
 
2122
 
2055
2123
 
2056
2124
/****************************************************************//**
2057
2125
Flushes InnoDB logs to disk and makes a checkpoint. Really, a commit flushes
2058
2126
the logs, and the name of this function should be innobase_checkpoint.
2059
 
@return TRUE if error */
 
2127
@return TRUE if error */
2060
2128
bool
2061
2129
InnobaseEngine::flush_logs()
2062
2130
/*=====================*/
2063
2131
{
2064
 
        bool    result = 0;
2065
 
 
2066
 
        assert(this == innodb_engine_ptr);
2067
 
 
2068
 
        log_buffer_flush_to_disk();
2069
 
 
2070
 
        return(result);
 
2132
  bool  result = 0;
 
2133
 
 
2134
  assert(this == innodb_engine_ptr);
 
2135
 
 
2136
  log_buffer_flush_to_disk();
 
2137
 
 
2138
  return(result);
2071
2139
}
2072
2140
 
2073
2141
/*****************************************************************//**
2076
2144
void
2077
2145
innobase_commit_low(
2078
2146
/*================*/
2079
 
        trx_t*  trx)    /*!< in: transaction handle */
 
2147
  trx_t*  trx)  /*!< in: transaction handle */
2080
2148
{
2081
 
        if (trx->conc_state == TRX_NOT_STARTED) {
2082
 
 
2083
 
                return;
2084
 
        }
2085
 
 
2086
 
        trx_commit_for_mysql(trx);
 
2149
  if (trx->conc_state == TRX_NOT_STARTED) {
 
2150
 
 
2151
    return;
 
2152
  }
 
2153
 
 
2154
  trx_commit_for_mysql(trx);
2087
2155
}
2088
2156
 
2089
2157
/*****************************************************************//**
2091
2159
Starts a new InnoDB transaction if a transaction is not yet started. And
2092
2160
assigns a new snapshot for a consistent read if the transaction does not yet
2093
2161
have one.
2094
 
@return 0 */
 
2162
@return 0 */
2095
2163
int
2096
2164
InnobaseEngine::doStartTransaction(
2097
2165
/*====================================*/
2098
 
        Session*        session,        /*!< in: MySQL thread handle of the user for whom
2099
 
                                                 the transaction should be committed */
 
2166
  Session*  session,  /*!< in: MySQL thread handle of the user for whom
 
2167
                               the transaction should be committed */
2100
2168
  start_transaction_option_t options)
2101
2169
{
2102
 
        assert(this == innodb_engine_ptr);
2103
 
 
2104
 
        /* Create a new trx struct for session, if it does not yet have one */
2105
 
        trx_t *trx = check_trx_exists(session);
2106
 
 
2107
 
        /* This is just to play safe: release a possible FIFO ticket and
2108
 
        search latch. Since we will reserve the kernel mutex, we have to
2109
 
        release the search system latch first to obey the latching order. */
2110
 
        innobase_release_stat_resources(trx);
2111
 
 
2112
 
        /* If the transaction is not started yet, start it */
2113
 
        trx_start_if_not_started(trx);
2114
 
 
2115
 
        /* Assign a read view if the transaction does not have it yet */
 
2170
  assert(this == innodb_engine_ptr);
 
2171
 
 
2172
  /* Create a new trx struct for session, if it does not yet have one */
 
2173
  trx_t *trx = check_trx_exists(session);
 
2174
 
 
2175
  /* This is just to play safe: release a possible FIFO ticket and
 
2176
  search latch. Since we will reserve the kernel mutex, we have to
 
2177
  release the search system latch first to obey the latching order. */
 
2178
  innobase_release_stat_resources(trx);
 
2179
 
 
2180
  /* If the transaction is not started yet, start it */
 
2181
  trx_start_if_not_started(trx);
 
2182
 
 
2183
  /* Assign a read view if the transaction does not have it yet */
2116
2184
  if (options == START_TRANS_OPT_WITH_CONS_SNAPSHOT)
2117
 
          trx_assign_read_view(trx);
 
2185
    trx_assign_read_view(trx);
2118
2186
 
2119
 
        return 0;
 
2187
  return 0;
2120
2188
}
2121
2189
 
2122
2190
/*****************************************************************//**
2123
2191
Commits a transaction in an InnoDB database or marks an SQL statement
2124
2192
ended.
2125
 
@return 0 */
 
2193
@return 0 */
2126
2194
int
2127
2195
InnobaseEngine::doCommit(
2128
2196
/*============*/
2129
 
        Session*        session,        /*!< in: MySQL thread handle of the user for whom
2130
 
                        the transaction should be committed */
2131
 
        bool    all)    /*!< in:        TRUE - commit transaction
2132
 
                                FALSE - the current SQL statement ended */
 
2197
  Session*  session,  /*!< in: MySQL thread handle of the user for whom
 
2198
      the transaction should be committed */
 
2199
  bool  all)  /*!< in:  TRUE - commit transaction
 
2200
        FALSE - the current SQL statement ended */
2133
2201
{
2134
 
        trx_t*          trx;
2135
 
 
2136
 
        assert(this == innodb_engine_ptr);
2137
 
 
2138
 
        trx = check_trx_exists(session);
2139
 
 
2140
 
        /* Since we will reserve the kernel mutex, we have to release
2141
 
        the search system latch first to obey the latching order. */
2142
 
 
2143
 
        if (trx->has_search_latch) {
2144
 
                trx_search_latch_release_if_reserved(trx);
2145
 
        }
2146
 
 
2147
 
        if (all
2148
 
                || (!session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
2149
 
 
2150
 
                /* We were instructed to commit the whole transaction, or
2151
 
                this is an SQL statement end and autocommit is on */
2152
 
 
2153
 
                /* We need current binlog position for ibbackup to work.
2154
 
                Note, the position is current because of
2155
 
                prepare_commit_mutex */
 
2202
  trx_t*    trx;
 
2203
 
 
2204
  assert(this == innodb_engine_ptr);
 
2205
 
 
2206
  trx = check_trx_exists(session);
 
2207
 
 
2208
  /* Since we will reserve the kernel mutex, we have to release
 
2209
  the search system latch first to obey the latching order. */
 
2210
 
 
2211
  if (trx->has_search_latch) {
 
2212
    trx_search_latch_release_if_reserved(trx);
 
2213
  }
 
2214
 
 
2215
  if (all
 
2216
    || (!session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
 
2217
 
 
2218
    /* We were instructed to commit the whole transaction, or
 
2219
    this is an SQL statement end and autocommit is on */
 
2220
 
 
2221
    /* We need current binlog position for ibbackup to work.
 
2222
    Note, the position is current because of
 
2223
    prepare_commit_mutex */
2156
2224
retry:
2157
 
                if (innobase_commit_concurrency > 0) {
2158
 
                        pthread_mutex_lock(&commit_cond_m);
2159
 
                        commit_threads++;
 
2225
    if (innobase_commit_concurrency > 0) {
 
2226
      pthread_mutex_lock(&commit_cond_m);
 
2227
      commit_threads++;
2160
2228
 
2161
 
                        if (commit_threads > innobase_commit_concurrency) {
2162
 
                                commit_threads--;
2163
 
                                pthread_cond_wait(&commit_cond,
2164
 
                                        &commit_cond_m);
2165
 
                                pthread_mutex_unlock(&commit_cond_m);
2166
 
                                goto retry;
2167
 
                        }
2168
 
                        else {
2169
 
                                pthread_mutex_unlock(&commit_cond_m);
2170
 
                        }
2171
 
                }
 
2229
      if (commit_threads > innobase_commit_concurrency) {
 
2230
        commit_threads--;
 
2231
        pthread_cond_wait(&commit_cond,
 
2232
          &commit_cond_m);
 
2233
        pthread_mutex_unlock(&commit_cond_m);
 
2234
        goto retry;
 
2235
      }
 
2236
      else {
 
2237
        pthread_mutex_unlock(&commit_cond_m);
 
2238
      }
 
2239
    }
2172
2240
 
2173
2241
                /* Store transaction point for binlog
2174
 
                Later logic tests that this is set to _something_. We need
2175
 
                that logic to fire, even though we do not have a real name. */
2176
 
                trx->mysql_log_file_name = "UNUSED";
2177
 
                trx->mysql_log_offset = 0;
2178
 
 
2179
 
                /* Don't do write + flush right now. For group commit
2180
 
                to work we want to do the flush after releasing the
2181
 
                prepare_commit_mutex. */
2182
 
                trx->flush_log_later = TRUE;
2183
 
                innobase_commit_low(trx);
2184
 
                trx->flush_log_later = FALSE;
2185
 
 
2186
 
                if (innobase_commit_concurrency > 0) {
2187
 
                        pthread_mutex_lock(&commit_cond_m);
2188
 
                        commit_threads--;
2189
 
                        pthread_cond_signal(&commit_cond);
2190
 
                        pthread_mutex_unlock(&commit_cond_m);
2191
 
                }
2192
 
 
2193
 
                if (trx->conc_state == TRX_PREPARED) {
2194
 
 
2195
 
                        pthread_mutex_unlock(&prepare_commit_mutex);
2196
 
                }
2197
 
 
2198
 
                /* Now do a write + flush of logs. */
2199
 
                trx_commit_complete_for_mysql(trx);
2200
 
 
2201
 
        } else {
2202
 
                /* We just mark the SQL statement ended and do not do a
2203
 
                transaction commit */
2204
 
 
2205
 
                /* If we had reserved the auto-inc lock for some
2206
 
                table in this SQL statement we release it now */
2207
 
 
2208
 
                row_unlock_table_autoinc_for_mysql(trx);
2209
 
 
2210
 
                /* Store the current undo_no of the transaction so that we
2211
 
                know where to roll back if we have to roll back the next
2212
 
                SQL statement */
2213
 
 
2214
 
                trx_mark_sql_stat_end(trx);
2215
 
        }
2216
 
 
2217
 
        trx->n_autoinc_rows = 0; /* Reset the number AUTO-INC rows required */
2218
 
 
2219
 
        if (trx->declared_to_be_inside_innodb) {
2220
 
                /* Release our possible ticket in the FIFO */
2221
 
 
2222
 
                srv_conc_force_exit_innodb(trx);
2223
 
        }
2224
 
 
2225
 
        /* Tell the InnoDB server that there might be work for utility
2226
 
        threads: */
2227
 
        srv_active_wake_master_thread();
2228
 
 
2229
 
        return(0);
 
2242
    Later logic tests that this is set to _something_. We need
 
2243
    that logic to fire, even though we do not have a real name. */
 
2244
    trx->mysql_log_file_name = "UNUSED";
 
2245
    trx->mysql_log_offset = 0;
 
2246
 
 
2247
    /* Don't do write + flush right now. For group commit
 
2248
    to work we want to do the flush after releasing the
 
2249
    prepare_commit_mutex. */
 
2250
    trx->flush_log_later = TRUE;
 
2251
    innobase_commit_low(trx);
 
2252
    trx->flush_log_later = FALSE;
 
2253
 
 
2254
    if (innobase_commit_concurrency > 0) {
 
2255
      pthread_mutex_lock(&commit_cond_m);
 
2256
      commit_threads--;
 
2257
      pthread_cond_signal(&commit_cond);
 
2258
      pthread_mutex_unlock(&commit_cond_m);
 
2259
    }
 
2260
 
 
2261
    /* Now do a write + flush of logs. */
 
2262
    trx_commit_complete_for_mysql(trx);
 
2263
 
 
2264
  } else {
 
2265
    /* We just mark the SQL statement ended and do not do a
 
2266
    transaction commit */
 
2267
 
 
2268
    /* If we had reserved the auto-inc lock for some
 
2269
    table in this SQL statement we release it now */
 
2270
 
 
2271
    row_unlock_table_autoinc_for_mysql(trx);
 
2272
 
 
2273
    /* Store the current undo_no of the transaction so that we
 
2274
    know where to roll back if we have to roll back the next
 
2275
    SQL statement */
 
2276
 
 
2277
    trx_mark_sql_stat_end(trx);
 
2278
  }
 
2279
 
 
2280
  trx->n_autoinc_rows = 0; /* Reset the number AUTO-INC rows required */
 
2281
 
 
2282
  if (trx->declared_to_be_inside_innodb) {
 
2283
    /* Release our possible ticket in the FIFO */
 
2284
 
 
2285
    srv_conc_force_exit_innodb(trx);
 
2286
  }
 
2287
 
 
2288
  /* Tell the InnoDB server that there might be work for utility
 
2289
  threads: */
 
2290
  srv_active_wake_master_thread();
 
2291
 
 
2292
  return(0);
2230
2293
}
2231
2294
 
2232
2295
/*****************************************************************//**
2233
2296
Rolls back a transaction or the latest SQL statement.
2234
 
@return 0 or error number */
 
2297
@return 0 or error number */
2235
2298
int
2236
2299
InnobaseEngine::doRollback(
2237
2300
/*==============*/
2238
 
        Session*        session,/*!< in: handle to the MySQL thread of the user
2239
 
                        whose transaction should be rolled back */
2240
 
        bool    all)    /*!< in:        TRUE - commit transaction
2241
 
                                FALSE - the current SQL statement ended */
 
2301
  Session*  session,/*!< in: handle to the MySQL thread of the user
 
2302
      whose transaction should be rolled back */
 
2303
  bool  all)  /*!< in:  TRUE - commit transaction
 
2304
        FALSE - the current SQL statement ended */
2242
2305
{
2243
 
        int     error = 0;
2244
 
        trx_t*  trx;
2245
 
 
2246
 
        assert(this == innodb_engine_ptr);
2247
 
 
2248
 
        trx = check_trx_exists(session);
2249
 
 
2250
 
        /* Release a possible FIFO ticket and search latch. Since we will
2251
 
        reserve the kernel mutex, we have to release the search system latch
2252
 
        first to obey the latching order. */
2253
 
 
2254
 
        innobase_release_stat_resources(trx);
2255
 
 
2256
 
        /* If we had reserved the auto-inc lock for some table (if
2257
 
        we come here to roll back the latest SQL statement) we
2258
 
        release it now before a possibly lengthy rollback */
2259
 
 
2260
 
        row_unlock_table_autoinc_for_mysql(trx);
2261
 
 
2262
 
        if (all
2263
 
                || !session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
2264
 
 
2265
 
                error = trx_rollback_for_mysql(trx);
2266
 
        } else {
2267
 
                error = trx_rollback_last_sql_stat_for_mysql(trx);
2268
 
        }
2269
 
 
2270
 
        return(convert_error_code_to_mysql(error, 0, NULL));
 
2306
  int error = 0;
 
2307
  trx_t*  trx;
 
2308
 
 
2309
  assert(this == innodb_engine_ptr);
 
2310
 
 
2311
  trx = check_trx_exists(session);
 
2312
 
 
2313
  /* Release a possible FIFO ticket and search latch. Since we will
 
2314
  reserve the kernel mutex, we have to release the search system latch
 
2315
  first to obey the latching order. */
 
2316
 
 
2317
  innobase_release_stat_resources(trx);
 
2318
 
 
2319
  /* If we had reserved the auto-inc lock for some table (if
 
2320
  we come here to roll back the latest SQL statement) we
 
2321
  release it now before a possibly lengthy rollback */
 
2322
 
 
2323
  row_unlock_table_autoinc_for_mysql(trx);
 
2324
 
 
2325
  if (all
 
2326
    || !session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
 
2327
 
 
2328
    error = trx_rollback_for_mysql(trx);
 
2329
  } else {
 
2330
    error = trx_rollback_last_sql_stat_for_mysql(trx);
 
2331
  }
 
2332
 
 
2333
  return(convert_error_code_to_mysql(error, 0, NULL));
2271
2334
}
2272
2335
 
2273
2336
/*****************************************************************//**
2274
2337
Rolls back a transaction
2275
 
@return 0 or error number */
 
2338
@return 0 or error number */
2276
2339
static
2277
2340
int
2278
2341
innobase_rollback_trx(
2279
2342
/*==================*/
2280
 
        trx_t*  trx)    /*!< in: transaction */
 
2343
  trx_t*  trx)  /*!< in: transaction */
2281
2344
{
2282
 
        int     error = 0;
2283
 
 
2284
 
        /* Release a possible FIFO ticket and search latch. Since we will
2285
 
        reserve the kernel mutex, we have to release the search system latch
2286
 
        first to obey the latching order. */
2287
 
 
2288
 
        innobase_release_stat_resources(trx);
2289
 
 
2290
 
        /* If we had reserved the auto-inc lock for some table (if
2291
 
        we come here to roll back the latest SQL statement) we
2292
 
        release it now before a possibly lengthy rollback */
2293
 
 
2294
 
        row_unlock_table_autoinc_for_mysql(trx);
2295
 
 
2296
 
        error = trx_rollback_for_mysql(trx);
2297
 
 
2298
 
        return(convert_error_code_to_mysql(error, 0, NULL));
 
2345
  int error = 0;
 
2346
 
 
2347
  /* Release a possible FIFO ticket and search latch. Since we will
 
2348
  reserve the kernel mutex, we have to release the search system latch
 
2349
  first to obey the latching order. */
 
2350
 
 
2351
  innobase_release_stat_resources(trx);
 
2352
 
 
2353
  /* If we had reserved the auto-inc lock for some table (if
 
2354
  we come here to roll back the latest SQL statement) we
 
2355
  release it now before a possibly lengthy rollback */
 
2356
 
 
2357
  row_unlock_table_autoinc_for_mysql(trx);
 
2358
 
 
2359
  error = trx_rollback_for_mysql(trx);
 
2360
 
 
2361
  return(convert_error_code_to_mysql(error, 0, NULL));
2299
2362
}
2300
2363
 
2301
2364
/*****************************************************************//**
2305
2368
int
2306
2369
InnobaseEngine::doRollbackToSavepoint(
2307
2370
/*===========================*/
2308
 
        Session*        session,                /*!< in: handle to the MySQL thread of the user
2309
 
                                whose transaction should be rolled back */
2310
 
        drizzled::NamedSavepoint &named_savepoint)      /*!< in: savepoint data */
 
2371
  Session*  session,    /*!< in: handle to the MySQL thread of the user
 
2372
        whose transaction should be rolled back */
 
2373
  drizzled::NamedSavepoint &named_savepoint)  /*!< in: savepoint data */
2311
2374
{
2312
 
        ib_int64_t      mysql_binlog_cache_pos;
2313
 
        int             error = 0;
2314
 
        trx_t*          trx;
2315
 
 
2316
 
        assert(this == innodb_engine_ptr);
2317
 
 
2318
 
        trx = check_trx_exists(session);
2319
 
 
2320
 
        /* Release a possible FIFO ticket and search latch. Since we will
2321
 
        reserve the kernel mutex, we have to release the search system latch
2322
 
        first to obey the latching order. */
2323
 
 
2324
 
        innobase_release_stat_resources(trx);
2325
 
 
2326
 
        error= (int)trx_rollback_to_savepoint_for_mysql(trx, named_savepoint.getName().c_str(),
 
2375
  ib_int64_t  mysql_binlog_cache_pos;
 
2376
  int   error = 0;
 
2377
  trx_t*    trx;
 
2378
 
 
2379
  assert(this == innodb_engine_ptr);
 
2380
 
 
2381
  trx = check_trx_exists(session);
 
2382
 
 
2383
  /* Release a possible FIFO ticket and search latch. Since we will
 
2384
  reserve the kernel mutex, we have to release the search system latch
 
2385
  first to obey the latching order. */
 
2386
 
 
2387
  innobase_release_stat_resources(trx);
 
2388
 
 
2389
  error= (int)trx_rollback_to_savepoint_for_mysql(trx, named_savepoint.getName().c_str(),
2327
2390
                                                        &mysql_binlog_cache_pos);
2328
 
        return(convert_error_code_to_mysql(error, 0, NULL));
 
2391
  return(convert_error_code_to_mysql(error, 0, NULL));
2329
2392
}
2330
2393
 
2331
2394
/*****************************************************************//**
2335
2398
int
2336
2399
InnobaseEngine::doReleaseSavepoint(
2337
2400
/*=======================*/
2338
 
        Session*        session,                /*!< in: handle to the MySQL thread of the user
2339
 
                                whose transaction should be rolled back */
2340
 
        drizzled::NamedSavepoint &named_savepoint)      /*!< in: savepoint data */
 
2401
  Session*  session,    /*!< in: handle to the MySQL thread of the user
 
2402
        whose transaction should be rolled back */
 
2403
  drizzled::NamedSavepoint &named_savepoint)  /*!< in: savepoint data */
2341
2404
{
2342
 
        int             error = 0;
2343
 
        trx_t*          trx;
2344
 
 
2345
 
        assert(this == innodb_engine_ptr);
2346
 
 
2347
 
        trx = check_trx_exists(session);
2348
 
 
2349
 
        error = (int) trx_release_savepoint_for_mysql(trx, named_savepoint.getName().c_str());
2350
 
 
2351
 
        return(convert_error_code_to_mysql(error, 0, NULL));
 
2405
  int   error = 0;
 
2406
  trx_t*    trx;
 
2407
 
 
2408
  assert(this == innodb_engine_ptr);
 
2409
 
 
2410
  trx = check_trx_exists(session);
 
2411
 
 
2412
  error = (int) trx_release_savepoint_for_mysql(trx, named_savepoint.getName().c_str());
 
2413
 
 
2414
  return(convert_error_code_to_mysql(error, 0, NULL));
2352
2415
}
2353
2416
 
2354
2417
/*****************************************************************//**
2355
2418
Sets a transaction savepoint.
2356
 
@return always 0, that is, always succeeds */
 
2419
@return always 0, that is, always succeeds */
2357
2420
int
2358
2421
InnobaseEngine::doSetSavepoint(
2359
2422
/*===============*/
2360
 
        Session*        session,/*!< in: handle to the MySQL thread */
2361
 
        drizzled::NamedSavepoint &named_savepoint)      /*!< in: savepoint data */
 
2423
  Session*  session,/*!< in: handle to the MySQL thread */
 
2424
  drizzled::NamedSavepoint &named_savepoint)  /*!< in: savepoint data */
2362
2425
{
2363
 
        int     error = 0;
2364
 
        trx_t*  trx;
2365
 
 
2366
 
        assert(this == innodb_engine_ptr);
2367
 
 
2368
 
        /*
2369
 
          In the autocommit mode there is no sense to set a savepoint
2370
 
          (unless we are in sub-statement), so SQL layer ensures that
2371
 
          this method is never called in such situation.
2372
 
        */
2373
 
 
2374
 
        trx = check_trx_exists(session);
2375
 
 
2376
 
        /* Release a possible FIFO ticket and search latch. Since we will
2377
 
        reserve the kernel mutex, we have to release the search system latch
2378
 
        first to obey the latching order. */
2379
 
 
2380
 
        innobase_release_stat_resources(trx);
2381
 
 
2382
 
        /* cannot happen outside of transaction */
2383
 
        assert(trx->conc_state != TRX_NOT_STARTED);
2384
 
 
2385
 
        error = (int) trx_savepoint_for_mysql(trx, named_savepoint.getName().c_str(), (ib_int64_t)0);
2386
 
 
2387
 
        return(convert_error_code_to_mysql(error, 0, NULL));
 
2426
  int error = 0;
 
2427
  trx_t*  trx;
 
2428
 
 
2429
  assert(this == innodb_engine_ptr);
 
2430
 
 
2431
  /*
 
2432
    In the autocommit mode there is no sense to set a savepoint
 
2433
    (unless we are in sub-statement), so SQL layer ensures that
 
2434
    this method is never called in such situation.
 
2435
  */
 
2436
 
 
2437
  trx = check_trx_exists(session);
 
2438
 
 
2439
  /* Release a possible FIFO ticket and search latch. Since we will
 
2440
  reserve the kernel mutex, we have to release the search system latch
 
2441
  first to obey the latching order. */
 
2442
 
 
2443
  innobase_release_stat_resources(trx);
 
2444
 
 
2445
  /* cannot happen outside of transaction */
 
2446
  assert(trx->conc_state != TRX_NOT_STARTED);
 
2447
 
 
2448
  error = (int) trx_savepoint_for_mysql(trx, named_savepoint.getName().c_str(), (ib_int64_t)0);
 
2449
 
 
2450
  return(convert_error_code_to_mysql(error, 0, NULL));
2388
2451
}
2389
2452
 
2390
2453
/*****************************************************************//**
2391
2454
Frees a possible InnoDB trx object associated with the current Session.
2392
 
@return 0 or error number */
 
2455
@return 0 or error number */
2393
2456
int
2394
2457
InnobaseEngine::close_connection(
2395
2458
/*======================*/
2396
 
        Session*        session)/*!< in: handle to the MySQL thread of the user
2397
 
                        whose resources should be free'd */
 
2459
  Session*  session)/*!< in: handle to the MySQL thread of the user
 
2460
      whose resources should be free'd */
2398
2461
{
2399
 
        trx_t*  trx;
2400
 
 
2401
 
        assert(this == innodb_engine_ptr);
2402
 
        trx = session_to_trx(session);
2403
 
 
2404
 
        ut_a(trx);
 
2462
  trx_t*  trx;
 
2463
 
 
2464
  assert(this == innodb_engine_ptr);
 
2465
  trx = session_to_trx(session);
 
2466
 
 
2467
  ut_a(trx);
2405
2468
 
2406
2469
  assert(session->killed != Session::NOT_KILLED ||
2407
2470
         trx->conc_state == TRX_NOT_STARTED);
2408
2471
 
2409
2472
  /* Warn if rolling back some things... */
2410
 
        if (session->killed != Session::NOT_KILLED &&
 
2473
  if (session->killed != Session::NOT_KILLED &&
2411
2474
      trx->conc_state != TRX_NOT_STARTED &&
2412
2475
      trx->undo_no.low > 0 &&
2413
2476
      global_system_variables.log_warnings)
2419
2482
      (ulong) trx->undo_no.low);
2420
2483
  }
2421
2484
 
2422
 
        innobase_rollback_trx(trx);
2423
 
 
2424
 
        thr_local_free(trx->mysql_thread_id);
2425
 
        trx_free_for_mysql(trx);
2426
 
 
2427
 
        return(0);
 
2485
  innobase_rollback_trx(trx);
 
2486
 
 
2487
  thr_local_free(trx->mysql_thread_id);
 
2488
  trx_free_for_mysql(trx);
 
2489
 
 
2490
  return(0);
2428
2491
}
2429
2492
 
2430
2493
 
2441
2504
ha_innobase::get_row_type() const
2442
2505
/*=============================*/
2443
2506
{
2444
 
        if (prebuilt && prebuilt->table) {
2445
 
                const ulint     flags = prebuilt->table->flags;
2446
 
 
2447
 
                if (UNIV_UNLIKELY(!flags)) {
2448
 
                        return(ROW_TYPE_REDUNDANT);
2449
 
                }
2450
 
 
2451
 
                ut_ad(flags & DICT_TF_COMPACT);
2452
 
 
2453
 
                switch (flags & DICT_TF_FORMAT_MASK) {
2454
 
                case DICT_TF_FORMAT_51 << DICT_TF_FORMAT_SHIFT:
2455
 
                        return(ROW_TYPE_COMPACT);
2456
 
                case DICT_TF_FORMAT_ZIP << DICT_TF_FORMAT_SHIFT:
2457
 
                        if (flags & DICT_TF_ZSSIZE_MASK) {
2458
 
                                return(ROW_TYPE_COMPRESSED);
2459
 
                        } else {
2460
 
                                return(ROW_TYPE_DYNAMIC);
2461
 
                        }
 
2507
  if (prebuilt && prebuilt->table) {
 
2508
    const ulint flags = prebuilt->table->flags;
 
2509
 
 
2510
    if (UNIV_UNLIKELY(!flags)) {
 
2511
      return(ROW_TYPE_REDUNDANT);
 
2512
    }
 
2513
 
 
2514
    ut_ad(flags & DICT_TF_COMPACT);
 
2515
 
 
2516
    switch (flags & DICT_TF_FORMAT_MASK) {
 
2517
    case DICT_TF_FORMAT_51 << DICT_TF_FORMAT_SHIFT:
 
2518
      return(ROW_TYPE_COMPACT);
 
2519
    case DICT_TF_FORMAT_ZIP << DICT_TF_FORMAT_SHIFT:
 
2520
      if (flags & DICT_TF_ZSSIZE_MASK) {
 
2521
        return(ROW_TYPE_COMPRESSED);
 
2522
      } else {
 
2523
        return(ROW_TYPE_DYNAMIC);
 
2524
      }
2462
2525
#if DICT_TF_FORMAT_ZIP != DICT_TF_FORMAT_MAX
2463
2526
# error "DICT_TF_FORMAT_ZIP != DICT_TF_FORMAT_MAX"
2464
2527
#endif
2465
 
                }
2466
 
        }
2467
 
        ut_ad(0);
2468
 
        return(ROW_TYPE_NOT_USED);
 
2528
    }
 
2529
  }
 
2530
  ut_ad(0);
 
2531
  return(ROW_TYPE_NOT_USED);
2469
2532
}
2470
2533
 
2471
2534
 
2475
2538
const char*
2476
2539
ha_innobase::index_type(
2477
2540
/*====================*/
2478
 
        uint)
2479
 
                                /*!< out: index type */
 
2541
  uint)
 
2542
        /*!< out: index type */
2480
2543
{
2481
 
        return("BTREE");
 
2544
  return("BTREE");
2482
2545
}
2483
2546
 
2484
2547
/****************************************************************//**
2485
2548
Returns the maximum number of keys.
2486
 
@return MAX_KEY */
 
2549
@return MAX_KEY */
2487
2550
UNIV_INTERN
2488
2551
uint
2489
2552
InnobaseEngine::max_supported_keys() const
2490
2553
/*===================================*/
2491
2554
{
2492
 
        return(MAX_KEY);
 
2555
  return(MAX_KEY);
2493
2556
}
2494
2557
 
2495
2558
/****************************************************************//**
2496
2559
Returns the maximum key length.
2497
 
@return maximum supported key length, in bytes */
 
2560
@return maximum supported key length, in bytes */
2498
2561
UNIV_INTERN
2499
2562
uint32_t
2500
2563
InnobaseEngine::max_supported_key_length() const
2501
2564
/*=========================================*/
2502
2565
{
2503
 
        /* An InnoDB page must store >= 2 keys; a secondary key record
2504
 
        must also contain the primary key value: max key length is
2505
 
        therefore set to slightly less than 1 / 4 of page size which
2506
 
        is 16 kB; but currently MySQL does not work with keys whose
2507
 
        size is > MAX_KEY_LENGTH */
2508
 
        return(3500);
 
2566
  /* An InnoDB page must store >= 2 keys; a secondary key record
 
2567
  must also contain the primary key value: max key length is
 
2568
  therefore set to slightly less than 1 / 4 of page size which
 
2569
  is 16 kB; but currently MySQL does not work with keys whose
 
2570
  size is > MAX_KEY_LENGTH */
 
2571
  return(3500);
2509
2572
}
2510
2573
 
2511
2574
/****************************************************************//**
2512
2575
Returns the key map of keys that are usable for scanning.
2513
 
@return key_map_full */
 
2576
@return key_map_full */
2514
2577
UNIV_INTERN
2515
2578
const key_map*
2516
2579
ha_innobase::keys_to_use_for_scanning()
2517
2580
{
2518
 
        return(&key_map_full);
 
2581
  return(&key_map_full);
2519
2582
}
2520
2583
 
2521
2584
 
2522
2585
/****************************************************************//**
2523
2586
Determines if the primary key is clustered index.
2524
 
@return true */
 
2587
@return true */
2525
2588
UNIV_INTERN
2526
2589
bool
2527
2590
ha_innobase::primary_key_is_clustered()
2528
2591
{
2529
 
        return(true);
 
2592
  return(true);
2530
2593
}
2531
2594
 
2532
2595
/*****************************************************************//**
2538
2601
void
2539
2602
normalize_table_name(
2540
2603
/*=================*/
2541
 
        char*           norm_name,      /*!< out: normalized name as a
2542
 
                                        null-terminated string */
2543
 
        const char*     name)           /*!< in: table name string */
 
2604
  char*   norm_name,  /*!< out: normalized name as a
 
2605
          null-terminated string */
 
2606
  const char* name)   /*!< in: table name string */
2544
2607
{
2545
 
        const char*     name_ptr;
2546
 
        const char*     db_ptr;
2547
 
        const char*     ptr;
2548
 
 
2549
 
        /* Scan name from the end */
2550
 
 
2551
 
        ptr = strchr(name, '\0')-1;
2552
 
 
2553
 
        while (ptr >= name && *ptr != '\\' && *ptr != '/') {
2554
 
                ptr--;
2555
 
        }
2556
 
 
2557
 
        name_ptr = ptr + 1;
2558
 
 
2559
 
        assert(ptr > name);
2560
 
 
2561
 
        ptr--;
2562
 
 
2563
 
        while (ptr >= name && *ptr != '\\' && *ptr != '/') {
2564
 
                ptr--;
2565
 
        }
2566
 
 
2567
 
        db_ptr = ptr + 1;
2568
 
 
2569
 
        memcpy(norm_name, db_ptr, strlen(name) + 1 - (db_ptr - name));
2570
 
 
2571
 
        norm_name[name_ptr - db_ptr - 1] = '/';
 
2608
  const char* name_ptr;
 
2609
  const char* db_ptr;
 
2610
  const char* ptr;
 
2611
 
 
2612
  /* Scan name from the end */
 
2613
 
 
2614
  ptr = strchr(name, '\0')-1;
 
2615
 
 
2616
  while (ptr >= name && *ptr != '\\' && *ptr != '/') {
 
2617
    ptr--;
 
2618
  }
 
2619
 
 
2620
  name_ptr = ptr + 1;
 
2621
 
 
2622
  assert(ptr > name);
 
2623
 
 
2624
  ptr--;
 
2625
 
 
2626
  while (ptr >= name && *ptr != '\\' && *ptr != '/') {
 
2627
    ptr--;
 
2628
  }
 
2629
 
 
2630
  db_ptr = ptr + 1;
 
2631
 
 
2632
  memcpy(norm_name, db_ptr, strlen(name) + 1 - (db_ptr - name));
 
2633
 
 
2634
  norm_name[name_ptr - db_ptr - 1] = '/';
2572
2635
 
2573
2636
#ifdef __WIN__
2574
 
        innobase_casedn_str(norm_name);
 
2637
  innobase_casedn_str(norm_name);
2575
2638
#endif
2576
2639
}
2577
2640
 
2578
2641
/********************************************************************//**
2579
2642
Set the autoinc column max value. This should only be called once from
2580
2643
ha_innobase::open(). Therefore there's no need for a covering lock.
2581
 
@return DB_SUCCESS or error code */
 
2644
@return DB_SUCCESS or error code */
2582
2645
UNIV_INTERN
2583
2646
ulint
2584
2647
ha_innobase::innobase_initialize_autoinc()
2585
2648
/*======================================*/
2586
2649
{
2587
 
        dict_index_t*   index;
2588
 
        uint64_t        auto_inc;
2589
 
        const char*     col_name;
2590
 
        ulint           error;
2591
 
 
2592
 
        col_name = table->found_next_number_field->field_name;
2593
 
        index = innobase_get_index(table->s->next_number_index);
2594
 
 
2595
 
        /* Execute SELECT MAX(col_name) FROM TABLE; */
2596
 
        error = row_search_max_autoinc(index, col_name, &auto_inc);
2597
 
 
2598
 
        switch (error) {
2599
 
        case DB_SUCCESS:
2600
 
 
2601
 
                /* At the this stage we don't know the increment
2602
 
                or the offset, so use default inrement of 1. */
2603
 
                ++auto_inc;
2604
 
                break;
2605
 
 
2606
 
        case DB_RECORD_NOT_FOUND:
2607
 
                ut_print_timestamp(stderr);
2608
 
                fprintf(stderr, "  InnoDB: MySQL and InnoDB data "
2609
 
                        "dictionaries are out of sync.\n"
2610
 
                        "InnoDB: Unable to find the AUTOINC column %s in the "
2611
 
                        "InnoDB table %s.\n"
2612
 
                        "InnoDB: We set the next AUTOINC column value to the "
2613
 
                        "maximum possible value,\n"
2614
 
                        "InnoDB: in effect disabling the AUTOINC next value "
2615
 
                        "generation.\n"
2616
 
                        "InnoDB: You can either set the next AUTOINC value "
2617
 
                        "explicitly using ALTER TABLE\n"
2618
 
                        "InnoDB: or fix the data dictionary by recreating "
2619
 
                        "the table.\n",
2620
 
                        col_name, index->table->name);
2621
 
 
2622
 
                auto_inc = 0xFFFFFFFFFFFFFFFFULL;
2623
 
                break;
2624
 
 
2625
 
        default:
2626
 
                return(error);
2627
 
        }
2628
 
 
2629
 
        dict_table_autoinc_initialize(prebuilt->table, auto_inc);
2630
 
 
2631
 
        return(DB_SUCCESS);
 
2650
  dict_index_t* index;
 
2651
  uint64_t  auto_inc;
 
2652
  const char* col_name;
 
2653
  ulint   error;
 
2654
 
 
2655
  col_name = table->found_next_number_field->field_name;
 
2656
  index = innobase_get_index(table->s->next_number_index);
 
2657
 
 
2658
  /* Execute SELECT MAX(col_name) FROM TABLE; */
 
2659
  error = row_search_max_autoinc(index, col_name, &auto_inc);
 
2660
 
 
2661
  switch (error) {
 
2662
  case DB_SUCCESS:
 
2663
 
 
2664
    /* At the this stage we don't know the increment
 
2665
    or the offset, so use default inrement of 1. */
 
2666
    ++auto_inc;
 
2667
    break;
 
2668
 
 
2669
  case DB_RECORD_NOT_FOUND:
 
2670
    ut_print_timestamp(stderr);
 
2671
    fprintf(stderr, "  InnoDB: MySQL and InnoDB data "
 
2672
      "dictionaries are out of sync.\n"
 
2673
      "InnoDB: Unable to find the AUTOINC column %s in the "
 
2674
      "InnoDB table %s.\n"
 
2675
      "InnoDB: We set the next AUTOINC column value to the "
 
2676
      "maximum possible value,\n"
 
2677
      "InnoDB: in effect disabling the AUTOINC next value "
 
2678
      "generation.\n"
 
2679
      "InnoDB: You can either set the next AUTOINC value "
 
2680
      "explicitly using ALTER TABLE\n"
 
2681
      "InnoDB: or fix the data dictionary by recreating "
 
2682
      "the table.\n",
 
2683
      col_name, index->table->name);
 
2684
 
 
2685
    auto_inc = 0xFFFFFFFFFFFFFFFFULL;
 
2686
    break;
 
2687
 
 
2688
  default:
 
2689
    return(error);
 
2690
  }
 
2691
 
 
2692
  dict_table_autoinc_initialize(prebuilt->table, auto_inc);
 
2693
 
 
2694
  return(DB_SUCCESS);
2632
2695
}
2633
2696
 
2634
2697
/*****************************************************************//**
2635
2698
Creates and opens a handle to a table which already exists in an InnoDB
2636
2699
database.
2637
 
@return 1 if error, 0 if success */
 
2700
@return 1 if error, 0 if success */
2638
2701
UNIV_INTERN
2639
2702
int
2640
2703
ha_innobase::open(
2641
2704
/*==============*/
2642
 
        const char*     name,           /*!< in: table name */
2643
 
        int             mode,           /*!< in: not used */
2644
 
        uint            test_if_locked) /*!< in: not used */
 
2705
  const char* name,   /*!< in: table name */
 
2706
  int   mode,   /*!< in: not used */
 
2707
  uint    test_if_locked) /*!< in: not used */
2645
2708
{
2646
 
        dict_table_t*   ib_table;
2647
 
        char            norm_name[1000];
2648
 
        Session*                session;
2649
 
        ulint           retries = 0;
2650
 
        char*           is_part = NULL;
2651
 
 
2652
 
        UT_NOT_USED(mode);
2653
 
        UT_NOT_USED(test_if_locked);
2654
 
 
2655
 
        session = ha_session();
2656
 
 
2657
 
        /* Under some cases Drizzle seems to call this function while
2658
 
        holding btr_search_latch. This breaks the latching order as
2659
 
        we acquire dict_sys->mutex below and leads to a deadlock. */
2660
 
        if (session != NULL) {
2661
 
                getTransactionalEngine()->releaseTemporaryLatches(session);
2662
 
        }
2663
 
 
2664
 
        normalize_table_name(norm_name, name);
2665
 
 
2666
 
        user_session = NULL;
2667
 
 
2668
 
        if (!(share=get_share(name))) {
2669
 
 
2670
 
                return(1);
2671
 
        }
2672
 
 
2673
 
        /* Create buffers for packing the fields of a record. Why
2674
 
        table->stored_rec_length did not work here? Obviously, because char
2675
 
        fields when packed actually became 1 byte longer, when we also
2676
 
        stored the string length as the first byte. */
2677
 
 
2678
 
        upd_and_key_val_buff_len =
2679
 
                                table->s->stored_rec_length
2680
 
                                + table->s->max_key_length
2681
 
                                + MAX_REF_PARTS * 3;
2682
 
        if (!(unsigned char*) memory::multi_malloc(false,
2683
 
                        &upd_buff, upd_and_key_val_buff_len,
2684
 
                        &key_val_buff, upd_and_key_val_buff_len,
2685
 
                        NULL)) {
2686
 
                free_share(share);
2687
 
 
2688
 
                return(1);
2689
 
        }
2690
 
 
2691
 
        /* We look for pattern #P# to see if the table is partitioned
2692
 
        MySQL table. The retry logic for partitioned tables is a
2693
 
        workaround for http://bugs.mysql.com/bug.php?id=33349. Look
2694
 
        at support issue https://support.mysql.com/view.php?id=21080
2695
 
        for more details. */
2696
 
        is_part = strstr(norm_name, "#P#");
 
2709
  dict_table_t* ib_table;
 
2710
  char    norm_name[1000];
 
2711
  Session*    session;
 
2712
  ulint   retries = 0;
 
2713
  char*   is_part = NULL;
 
2714
 
 
2715
  UT_NOT_USED(mode);
 
2716
  UT_NOT_USED(test_if_locked);
 
2717
 
 
2718
  session = ha_session();
 
2719
 
 
2720
  /* Under some cases Drizzle seems to call this function while
 
2721
  holding btr_search_latch. This breaks the latching order as
 
2722
  we acquire dict_sys->mutex below and leads to a deadlock. */
 
2723
  if (session != NULL) {
 
2724
    getTransactionalEngine()->releaseTemporaryLatches(session);
 
2725
  }
 
2726
 
 
2727
  normalize_table_name(norm_name, name);
 
2728
 
 
2729
  user_session = NULL;
 
2730
 
 
2731
  if (!(share=get_share(name))) {
 
2732
 
 
2733
    return(1);
 
2734
  }
 
2735
 
 
2736
  /* Create buffers for packing the fields of a record. Why
 
2737
  table->stored_rec_length did not work here? Obviously, because char
 
2738
  fields when packed actually became 1 byte longer, when we also
 
2739
  stored the string length as the first byte. */
 
2740
 
 
2741
  upd_and_key_val_buff_len =
 
2742
        table->s->stored_rec_length
 
2743
        + table->s->max_key_length
 
2744
        + MAX_REF_PARTS * 3;
 
2745
  if (!(unsigned char*) memory::multi_malloc(false,
 
2746
      &upd_buff, upd_and_key_val_buff_len,
 
2747
      &key_val_buff, upd_and_key_val_buff_len,
 
2748
      NULL)) {
 
2749
    free_share(share);
 
2750
 
 
2751
    return(1);
 
2752
  }
 
2753
 
 
2754
  /* We look for pattern #P# to see if the table is partitioned
 
2755
  MySQL table. The retry logic for partitioned tables is a
 
2756
  workaround for http://bugs.mysql.com/bug.php?id=33349. Look
 
2757
  at support issue https://support.mysql.com/view.php?id=21080
 
2758
  for more details. */
 
2759
  is_part = strstr(norm_name, "#P#");
2697
2760
retry:
2698
 
        /* Get pointer to a table object in InnoDB dictionary cache */
2699
 
        ib_table = dict_table_get(norm_name, TRUE);
2700
 
        
2701
 
        if (NULL == ib_table) {
2702
 
                if (is_part && retries < 10) {
2703
 
                        ++retries;
2704
 
                        os_thread_sleep(100000);
2705
 
                        goto retry;
2706
 
                }
2707
 
 
2708
 
                if (is_part) {
2709
 
                        errmsg_printf(ERRMSG_LVL_ERROR, "Failed to open table %s after "
2710
 
                                        "%lu attemtps.\n", norm_name,
2711
 
                                        retries);
2712
 
                }
2713
 
 
2714
 
                errmsg_printf(ERRMSG_LVL_ERROR, "Cannot find or open table %s from\n"
2715
 
                                "the internal data dictionary of InnoDB "
2716
 
                                "though the .frm file for the\n"
2717
 
                                "table exists. Maybe you have deleted and "
2718
 
                                "recreated InnoDB data\n"
2719
 
                                "files but have forgotten to delete the "
2720
 
                                "corresponding .frm files\n"
2721
 
                                "of InnoDB tables, or you have moved .frm "
2722
 
                                "files to another database?\n"
2723
 
                                "or, the table contains indexes that this "
2724
 
                                "version of the engine\n"
2725
 
                                "doesn't support.\n"
2726
 
                                "See " REFMAN "innodb-troubleshooting.html\n"
2727
 
                                "how you can resolve the problem.\n",
2728
 
                                norm_name);
2729
 
                free_share(share);
2730
 
                free(upd_buff);
2731
 
                errno = ENOENT;
2732
 
 
2733
 
                return(HA_ERR_NO_SUCH_TABLE);
2734
 
        }
2735
 
 
2736
 
        if (ib_table->ibd_file_missing && !session_tablespace_op(session)) {
2737
 
                errmsg_printf(ERRMSG_LVL_ERROR, "MySQL is trying to open a table handle but "
2738
 
                                "the .ibd file for\ntable %s does not exist.\n"
2739
 
                                "Have you deleted the .ibd file from the "
2740
 
                                "database directory under\nthe MySQL datadir, "
2741
 
                                "or have you used DISCARD TABLESPACE?\n"
2742
 
                                "See " REFMAN "innodb-troubleshooting.html\n"
2743
 
                                "how you can resolve the problem.\n",
2744
 
                                norm_name);
2745
 
                free_share(share);
2746
 
                free(upd_buff);
2747
 
                errno = ENOENT;
2748
 
 
2749
 
                dict_table_decrement_handle_count(ib_table, FALSE);
2750
 
                return(HA_ERR_NO_SUCH_TABLE);
2751
 
        }
2752
 
 
2753
 
        prebuilt = row_create_prebuilt(ib_table);
2754
 
 
2755
 
        prebuilt->mysql_row_len = table->s->stored_rec_length;
2756
 
        prebuilt->default_rec = table->s->default_values;
2757
 
        ut_ad(prebuilt->default_rec);
2758
 
 
2759
 
        /* Looks like MySQL-3.23 sometimes has primary key number != 0 */
2760
 
 
2761
 
        primary_key = table->s->primary_key;
2762
 
        key_used_on_scan = primary_key;
2763
 
 
2764
 
        /* Allocate a buffer for a 'row reference'. A row reference is
2765
 
        a string of bytes of length ref_length which uniquely specifies
2766
 
        a row in our table. Note that MySQL may also compare two row
2767
 
        references for equality by doing a simple memcmp on the strings
2768
 
        of length ref_length! */
2769
 
 
2770
 
        if (!row_table_got_default_clust_index(ib_table)) {
2771
 
                if (primary_key >= MAX_KEY) {
2772
 
                  errmsg_printf(ERRMSG_LVL_ERROR, "Table %s has a primary key in InnoDB data "
2773
 
                                  "dictionary, but not in MySQL!", name);
2774
 
                }
2775
 
 
2776
 
                prebuilt->clust_index_was_generated = FALSE;
2777
 
 
2778
 
                /* MySQL allocates the buffer for ref. key_info->key_length
2779
 
                includes space for all key columns + one byte for each column
2780
 
                that may be NULL. ref_length must be as exact as possible to
2781
 
                save space, because all row reference buffers are allocated
2782
 
                based on ref_length. */
2783
 
 
2784
 
                ref_length = table->key_info[primary_key].key_length;
2785
 
        } else {
2786
 
                if (primary_key != MAX_KEY) {
2787
 
                  errmsg_printf(ERRMSG_LVL_ERROR, "Table %s has no primary key in InnoDB data "
2788
 
                                  "dictionary, but has one in MySQL! If you "
2789
 
                                  "created the table with a MySQL version < "
2790
 
                                  "3.23.54 and did not define a primary key, "
2791
 
                                  "but defined a unique key with all non-NULL "
2792
 
                                  "columns, then MySQL internally treats that "
2793
 
                                  "key as the primary key. You can fix this "
2794
 
                                  "error by dump + DROP + CREATE + reimport "
2795
 
                                  "of the table.", name);
2796
 
                }
2797
 
 
2798
 
                prebuilt->clust_index_was_generated = TRUE;
2799
 
 
2800
 
                ref_length = DATA_ROW_ID_LEN;
2801
 
 
2802
 
                /* If we automatically created the clustered index, then
2803
 
                MySQL does not know about it, and MySQL must NOT be aware
2804
 
                of the index used on scan, to make it avoid checking if we
2805
 
                update the column of the index. That is why we assert below
2806
 
                that key_used_on_scan is the undefined value MAX_KEY.
2807
 
                The column is the row id in the automatical generation case,
2808
 
                and it will never be updated anyway. */
2809
 
 
2810
 
                if (key_used_on_scan != MAX_KEY) {
2811
 
                        errmsg_printf(ERRMSG_LVL_WARN, 
2812
 
                                "Table %s key_used_on_scan is %lu even "
2813
 
                                "though there is no primary key inside "
2814
 
                                "InnoDB.", name, (ulong) key_used_on_scan);
2815
 
                }
2816
 
        }
2817
 
 
2818
 
        /* Index block size in InnoDB: used by MySQL in query optimization */
2819
 
        stats.block_size = 16 * 1024;
2820
 
 
2821
 
        /* Init table lock structure */
2822
 
        thr_lock_data_init(&share->lock,&lock,(void*) 0);
2823
 
 
2824
 
        if (prebuilt->table) {
2825
 
                /* We update the highest file format in the system table
2826
 
                space, if this table has higher file format setting. */
2827
 
 
2828
 
                trx_sys_file_format_max_upgrade(
2829
 
                        (const char**) &innobase_file_format_check,
2830
 
                        dict_table_get_format(prebuilt->table));
2831
 
        }
2832
 
 
2833
 
        info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
2834
 
 
2835
 
        /* Only if the table has an AUTOINC column. */
2836
 
        if (prebuilt->table != NULL && table->found_next_number_field != NULL) {
2837
 
                ulint   error;
2838
 
 
2839
 
                dict_table_autoinc_lock(prebuilt->table);
2840
 
 
2841
 
                /* Since a table can already be "open" in InnoDB's internal
2842
 
                data dictionary, we only init the autoinc counter once, the
2843
 
                first time the table is loaded. We can safely reuse the
2844
 
                autoinc value from a previous Drizzle open. */
2845
 
                if (dict_table_autoinc_read(prebuilt->table) == 0) {
2846
 
 
2847
 
                        error = innobase_initialize_autoinc();
2848
 
                        ut_a(error == DB_SUCCESS);
2849
 
                }
2850
 
 
2851
 
                dict_table_autoinc_unlock(prebuilt->table);
2852
 
        }
2853
 
 
2854
 
        return(0);
 
2761
  /* Get pointer to a table object in InnoDB dictionary cache */
 
2762
  ib_table = dict_table_get(norm_name, TRUE);
 
2763
  
 
2764
  if (NULL == ib_table) {
 
2765
    if (is_part && retries < 10) {
 
2766
      ++retries;
 
2767
      os_thread_sleep(100000);
 
2768
      goto retry;
 
2769
    }
 
2770
 
 
2771
    if (is_part) {
 
2772
      errmsg_printf(ERRMSG_LVL_ERROR, "Failed to open table %s after "
 
2773
          "%lu attemtps.\n", norm_name,
 
2774
          retries);
 
2775
    }
 
2776
 
 
2777
    errmsg_printf(ERRMSG_LVL_ERROR, "Cannot find or open table %s from\n"
 
2778
        "the internal data dictionary of InnoDB "
 
2779
        "though the .frm file for the\n"
 
2780
        "table exists. Maybe you have deleted and "
 
2781
        "recreated InnoDB data\n"
 
2782
        "files but have forgotten to delete the "
 
2783
        "corresponding .frm files\n"
 
2784
        "of InnoDB tables, or you have moved .frm "
 
2785
        "files to another database?\n"
 
2786
        "or, the table contains indexes that this "
 
2787
        "version of the engine\n"
 
2788
        "doesn't support.\n"
 
2789
        "See " REFMAN "innodb-troubleshooting.html\n"
 
2790
        "how you can resolve the problem.\n",
 
2791
        norm_name);
 
2792
    free_share(share);
 
2793
    free(upd_buff);
 
2794
    errno = ENOENT;
 
2795
 
 
2796
    return(HA_ERR_NO_SUCH_TABLE);
 
2797
  }
 
2798
 
 
2799
  if (ib_table->ibd_file_missing && !session_tablespace_op(session)) {
 
2800
    errmsg_printf(ERRMSG_LVL_ERROR, "MySQL is trying to open a table handle but "
 
2801
        "the .ibd file for\ntable %s does not exist.\n"
 
2802
        "Have you deleted the .ibd file from the "
 
2803
        "database directory under\nthe MySQL datadir, "
 
2804
        "or have you used DISCARD TABLESPACE?\n"
 
2805
        "See " REFMAN "innodb-troubleshooting.html\n"
 
2806
        "how you can resolve the problem.\n",
 
2807
        norm_name);
 
2808
    free_share(share);
 
2809
    free(upd_buff);
 
2810
    errno = ENOENT;
 
2811
 
 
2812
    dict_table_decrement_handle_count(ib_table, FALSE);
 
2813
    return(HA_ERR_NO_SUCH_TABLE);
 
2814
  }
 
2815
 
 
2816
  prebuilt = row_create_prebuilt(ib_table);
 
2817
 
 
2818
  prebuilt->mysql_row_len = table->s->stored_rec_length;
 
2819
  prebuilt->default_rec = table->s->default_values;
 
2820
  ut_ad(prebuilt->default_rec);
 
2821
 
 
2822
  /* Looks like MySQL-3.23 sometimes has primary key number != 0 */
 
2823
 
 
2824
  primary_key = table->s->primary_key;
 
2825
  key_used_on_scan = primary_key;
 
2826
 
 
2827
  /* Allocate a buffer for a 'row reference'. A row reference is
 
2828
  a string of bytes of length ref_length which uniquely specifies
 
2829
  a row in our table. Note that MySQL may also compare two row
 
2830
  references for equality by doing a simple memcmp on the strings
 
2831
  of length ref_length! */
 
2832
 
 
2833
  if (!row_table_got_default_clust_index(ib_table)) {
 
2834
    if (primary_key >= MAX_KEY) {
 
2835
      errmsg_printf(ERRMSG_LVL_ERROR, "Table %s has a primary key in InnoDB data "
 
2836
          "dictionary, but not in MySQL!", name);
 
2837
    }
 
2838
 
 
2839
    prebuilt->clust_index_was_generated = FALSE;
 
2840
 
 
2841
    /* MySQL allocates the buffer for ref. key_info->key_length
 
2842
    includes space for all key columns + one byte for each column
 
2843
    that may be NULL. ref_length must be as exact as possible to
 
2844
    save space, because all row reference buffers are allocated
 
2845
    based on ref_length. */
 
2846
 
 
2847
    ref_length = table->key_info[primary_key].key_length;
 
2848
  } else {
 
2849
    if (primary_key != MAX_KEY) {
 
2850
      errmsg_printf(ERRMSG_LVL_ERROR, "Table %s has no primary key in InnoDB data "
 
2851
          "dictionary, but has one in MySQL! If you "
 
2852
          "created the table with a MySQL version < "
 
2853
          "3.23.54 and did not define a primary key, "
 
2854
          "but defined a unique key with all non-NULL "
 
2855
          "columns, then MySQL internally treats that "
 
2856
          "key as the primary key. You can fix this "
 
2857
          "error by dump + DROP + CREATE + reimport "
 
2858
          "of the table.", name);
 
2859
    }
 
2860
 
 
2861
    prebuilt->clust_index_was_generated = TRUE;
 
2862
 
 
2863
    ref_length = DATA_ROW_ID_LEN;
 
2864
 
 
2865
    /* If we automatically created the clustered index, then
 
2866
    MySQL does not know about it, and MySQL must NOT be aware
 
2867
    of the index used on scan, to make it avoid checking if we
 
2868
    update the column of the index. That is why we assert below
 
2869
    that key_used_on_scan is the undefined value MAX_KEY.
 
2870
    The column is the row id in the automatical generation case,
 
2871
    and it will never be updated anyway. */
 
2872
 
 
2873
    if (key_used_on_scan != MAX_KEY) {
 
2874
      errmsg_printf(ERRMSG_LVL_WARN, 
 
2875
        "Table %s key_used_on_scan is %lu even "
 
2876
        "though there is no primary key inside "
 
2877
        "InnoDB.", name, (ulong) key_used_on_scan);
 
2878
    }
 
2879
  }
 
2880
 
 
2881
  /* Index block size in InnoDB: used by MySQL in query optimization */
 
2882
  stats.block_size = 16 * 1024;
 
2883
 
 
2884
  /* Init table lock structure */
 
2885
  thr_lock_data_init(&share->lock,&lock,(void*) 0);
 
2886
 
 
2887
  if (prebuilt->table) {
 
2888
    /* We update the highest file format in the system table
 
2889
    space, if this table has higher file format setting. */
 
2890
 
 
2891
    trx_sys_file_format_max_upgrade(
 
2892
      (const char**) &innobase_file_format_check,
 
2893
      dict_table_get_format(prebuilt->table));
 
2894
  }
 
2895
 
 
2896
  info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
 
2897
 
 
2898
  /* Only if the table has an AUTOINC column. */
 
2899
  if (prebuilt->table != NULL && table->found_next_number_field != NULL) {
 
2900
    ulint error;
 
2901
 
 
2902
    dict_table_autoinc_lock(prebuilt->table);
 
2903
 
 
2904
    /* Since a table can already be "open" in InnoDB's internal
 
2905
    data dictionary, we only init the autoinc counter once, the
 
2906
    first time the table is loaded. We can safely reuse the
 
2907
    autoinc value from a previous Drizzle open. */
 
2908
    if (dict_table_autoinc_read(prebuilt->table) == 0) {
 
2909
 
 
2910
      error = innobase_initialize_autoinc();
 
2911
      ut_a(error == DB_SUCCESS);
 
2912
    }
 
2913
 
 
2914
    dict_table_autoinc_unlock(prebuilt->table);
 
2915
  }
 
2916
 
 
2917
  return(0);
2855
2918
}
2856
2919
 
2857
2920
UNIV_INTERN
2858
2921
uint32_t
2859
2922
InnobaseEngine::max_supported_key_part_length() const
2860
2923
{
2861
 
        return(DICT_MAX_INDEX_COL_LEN - 1);
 
2924
  return(DICT_MAX_INDEX_COL_LEN - 1);
2862
2925
}
2863
2926
 
2864
2927
/******************************************************************//**
2865
2928
Closes a handle to an InnoDB table.
2866
 
@return 0 */
 
2929
@return 0 */
2867
2930
UNIV_INTERN
2868
2931
int
2869
2932
ha_innobase::close(void)
2870
2933
/*====================*/
2871
2934
{
2872
 
        Session*        session;
2873
 
 
2874
 
        session = ha_session();
2875
 
        if (session != NULL) {
2876
 
                getTransactionalEngine()->releaseTemporaryLatches(session);
2877
 
        }
2878
 
 
2879
 
        row_prebuilt_free(prebuilt, FALSE);
2880
 
 
2881
 
        free(upd_buff);
2882
 
        free_share(share);
2883
 
 
2884
 
        /* Tell InnoDB server that there might be work for
2885
 
        utility threads: */
2886
 
 
2887
 
        srv_active_wake_master_thread();
2888
 
 
2889
 
        return(0);
 
2935
  Session*  session;
 
2936
 
 
2937
  session = ha_session();
 
2938
  if (session != NULL) {
 
2939
    getTransactionalEngine()->releaseTemporaryLatches(session);
 
2940
  }
 
2941
 
 
2942
  row_prebuilt_free(prebuilt, FALSE);
 
2943
 
 
2944
  free(upd_buff);
 
2945
  free_share(share);
 
2946
 
 
2947
  /* Tell InnoDB server that there might be work for
 
2948
  utility threads: */
 
2949
 
 
2950
  srv_active_wake_master_thread();
 
2951
 
 
2952
  return(0);
2890
2953
}
2891
2954
 
2892
2955
/* The following accessor functions should really be inside MySQL code! */
2893
2956
 
2894
2957
/**************************************************************//**
2895
2958
Gets field offset for a field in a table.
2896
 
@return offset */
 
2959
@return offset */
2897
2960
static inline
2898
2961
uint
2899
2962
get_field_offset(
2900
2963
/*=============*/
2901
 
        Table*  table,  /*!< in: MySQL table object */
2902
 
        Field*  field)  /*!< in: MySQL field object */
 
2964
  Table*  table,  /*!< in: MySQL table object */
 
2965
  Field*  field)  /*!< in: MySQL field object */
2903
2966
{
2904
 
        return((uint) (field->ptr - table->record[0]));
 
2967
  return((uint) (field->ptr - table->record[0]));
2905
2968
}
2906
2969
 
2907
2970
/**************************************************************//**
2908
2971
Checks if a field in a record is SQL NULL. Uses the record format
2909
2972
information in table to track the null bit in record.
2910
 
@return 1 if NULL, 0 otherwise */
 
2973
@return 1 if NULL, 0 otherwise */
2911
2974
static inline
2912
2975
uint
2913
2976
field_in_record_is_null(
2914
2977
/*====================*/
2915
 
        Table*  table,  /*!< in: MySQL table object */
2916
 
        Field*  field,  /*!< in: MySQL field object */
2917
 
        char*   record) /*!< in: a row in MySQL format */
 
2978
  Table*  table,  /*!< in: MySQL table object */
 
2979
  Field*  field,  /*!< in: MySQL field object */
 
2980
  char* record) /*!< in: a row in MySQL format */
2918
2981
{
2919
 
        int     null_offset;
2920
 
 
2921
 
        if (!field->null_ptr) {
2922
 
 
2923
 
                return(0);
2924
 
        }
2925
 
 
2926
 
        null_offset = (uint) ((char*) field->null_ptr
2927
 
                                        - (char*) table->record[0]);
2928
 
 
2929
 
        if (record[null_offset] & field->null_bit) {
2930
 
 
2931
 
                return(1);
2932
 
        }
2933
 
 
2934
 
        return(0);
 
2982
  int null_offset;
 
2983
 
 
2984
  if (!field->null_ptr) {
 
2985
 
 
2986
    return(0);
 
2987
  }
 
2988
 
 
2989
  null_offset = (uint) ((char*) field->null_ptr
 
2990
          - (char*) table->record[0]);
 
2991
 
 
2992
  if (record[null_offset] & field->null_bit) {
 
2993
 
 
2994
    return(1);
 
2995
  }
 
2996
 
 
2997
  return(0);
2935
2998
}
2936
2999
 
2937
3000
/**************************************************************//**
2941
3004
void
2942
3005
set_field_in_record_to_null(
2943
3006
/*========================*/
2944
 
        Table*  table,  /*!< in: MySQL table object */
2945
 
        Field*  field,  /*!< in: MySQL field object */
2946
 
        char*   record) /*!< in: a row in MySQL format */
 
3007
  Table*  table,  /*!< in: MySQL table object */
 
3008
  Field*  field,  /*!< in: MySQL field object */
 
3009
  char* record) /*!< in: a row in MySQL format */
2947
3010
{
2948
 
        int     null_offset;
2949
 
 
2950
 
        null_offset = (uint) ((char*) field->null_ptr
2951
 
                                        - (char*) table->record[0]);
2952
 
 
2953
 
        record[null_offset] = record[null_offset] | field->null_bit;
 
3011
  int null_offset;
 
3012
 
 
3013
  null_offset = (uint) ((char*) field->null_ptr
 
3014
          - (char*) table->record[0]);
 
3015
 
 
3016
  record[null_offset] = record[null_offset] | field->null_bit;
2954
3017
}
2955
3018
 
2956
3019
/*************************************************************//**
2958
3021
is such that we must use MySQL code to compare them. NOTE that the prototype
2959
3022
of this function is in rem0cmp.c in InnoDB source code! If you change this
2960
3023
function, remember to update the prototype there!
2961
 
@return 1, 0, -1, if a is greater, equal, less than b, respectively */
 
3024
@return 1, 0, -1, if a is greater, equal, less than b, respectively */
2962
3025
extern "C" UNIV_INTERN
2963
3026
int
2964
3027
innobase_mysql_cmp(
2965
3028
/*===============*/
2966
 
        int             mysql_type,     /*!< in: MySQL type */
2967
 
        uint            charset_number, /*!< in: number of the charset */
2968
 
        const unsigned char* a,         /*!< in: data field */
2969
 
        unsigned int    a_length,       /*!< in: data field length,
2970
 
                                        not UNIV_SQL_NULL */
2971
 
        const unsigned char* b,         /* in: data field */
2972
 
        unsigned int    b_length);      /* in: data field length,
2973
 
                                        not UNIV_SQL_NULL */
 
3029
  int   mysql_type, /*!< in: MySQL type */
 
3030
  uint    charset_number, /*!< in: number of the charset */
 
3031
  const unsigned char* a,   /*!< in: data field */
 
3032
  unsigned int  a_length, /*!< in: data field length,
 
3033
          not UNIV_SQL_NULL */
 
3034
  const unsigned char* b,   /* in: data field */
 
3035
  unsigned int  b_length);  /* in: data field length,
 
3036
          not UNIV_SQL_NULL */
2974
3037
 
2975
3038
int
2976
3039
innobase_mysql_cmp(
2977
3040
/*===============*/
2978
 
                                        /* out: 1, 0, -1, if a is greater,
2979
 
                                        equal, less than b, respectively */
2980
 
        int             mysql_type,     /* in: MySQL type */
2981
 
        uint            charset_number, /* in: number of the charset */
2982
 
        const unsigned char* a,         /* in: data field */
2983
 
        unsigned int    a_length,       /* in: data field length,
2984
 
                                        not UNIV_SQL_NULL */
2985
 
        const unsigned char* b,         /* in: data field */
2986
 
        unsigned int    b_length)       /* in: data field length,
2987
 
                                        not UNIV_SQL_NULL */
 
3041
          /* out: 1, 0, -1, if a is greater,
 
3042
          equal, less than b, respectively */
 
3043
  int   mysql_type, /* in: MySQL type */
 
3044
  uint    charset_number, /* in: number of the charset */
 
3045
  const unsigned char* a,   /* in: data field */
 
3046
  unsigned int  a_length, /* in: data field length,
 
3047
          not UNIV_SQL_NULL */
 
3048
  const unsigned char* b,   /* in: data field */
 
3049
  unsigned int  b_length) /* in: data field length,
 
3050
          not UNIV_SQL_NULL */
2988
3051
{
2989
 
        const CHARSET_INFO*     charset;
2990
 
        enum_field_types        mysql_tp;
2991
 
        int                     ret;
2992
 
 
2993
 
        assert(a_length != UNIV_SQL_NULL);
2994
 
        assert(b_length != UNIV_SQL_NULL);
2995
 
 
2996
 
        mysql_tp = (enum_field_types) mysql_type;
2997
 
 
2998
 
        switch (mysql_tp) {
2999
 
 
3000
 
        case DRIZZLE_TYPE_BLOB:
3001
 
        case DRIZZLE_TYPE_VARCHAR:
3002
 
                /* Use the charset number to pick the right charset struct for
3003
 
                the comparison. Since the MySQL function get_charset may be
3004
 
                slow before Bar removes the mutex operation there, we first
3005
 
                look at 2 common charsets directly. */
3006
 
 
3007
 
                if (charset_number == default_charset_info->number) {
3008
 
                        charset = default_charset_info;
3009
 
                } else {
3010
 
                        charset = get_charset(charset_number);
3011
 
 
3012
 
                        if (charset == NULL) {
3013
 
                          errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB needs charset %lu for doing "
3014
 
                                          "a comparison, but MySQL cannot "
3015
 
                                          "find that charset.",
3016
 
                                          (ulong) charset_number);
3017
 
                                ut_a(0);
3018
 
                        }
3019
 
                }
3020
 
 
3021
 
                /* Starting from 4.1.3, we use strnncollsp() in comparisons of
3022
 
                non-latin1_swedish_ci strings. NOTE that the collation order
3023
 
                changes then: 'b\0\0...' is ordered BEFORE 'b  ...'. Users
3024
 
                having indexes on such data need to rebuild their tables! */
3025
 
 
3026
 
                ret = charset->coll->strnncollsp(charset,
3027
 
                                  a, a_length,
3028
 
                                                 b, b_length, 0);
3029
 
                if (ret < 0) {
3030
 
                        return(-1);
3031
 
                } else if (ret > 0) {
3032
 
                        return(1);
3033
 
                } else {
3034
 
                        return(0);
3035
 
                }
3036
 
        default:
3037
 
                ut_error;
3038
 
        }
3039
 
 
3040
 
        return(0);
 
3052
  const CHARSET_INFO* charset;
 
3053
  enum_field_types  mysql_tp;
 
3054
  int     ret;
 
3055
 
 
3056
  assert(a_length != UNIV_SQL_NULL);
 
3057
  assert(b_length != UNIV_SQL_NULL);
 
3058
 
 
3059
  mysql_tp = (enum_field_types) mysql_type;
 
3060
 
 
3061
  switch (mysql_tp) {
 
3062
 
 
3063
  case DRIZZLE_TYPE_BLOB:
 
3064
  case DRIZZLE_TYPE_VARCHAR:
 
3065
    /* Use the charset number to pick the right charset struct for
 
3066
    the comparison. Since the MySQL function get_charset may be
 
3067
    slow before Bar removes the mutex operation there, we first
 
3068
    look at 2 common charsets directly. */
 
3069
 
 
3070
    if (charset_number == default_charset_info->number) {
 
3071
      charset = default_charset_info;
 
3072
    } else {
 
3073
      charset = get_charset(charset_number);
 
3074
 
 
3075
      if (charset == NULL) {
 
3076
        errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB needs charset %lu for doing "
 
3077
            "a comparison, but MySQL cannot "
 
3078
            "find that charset.",
 
3079
            (ulong) charset_number);
 
3080
        ut_a(0);
 
3081
      }
 
3082
    }
 
3083
 
 
3084
    /* Starting from 4.1.3, we use strnncollsp() in comparisons of
 
3085
    non-latin1_swedish_ci strings. NOTE that the collation order
 
3086
    changes then: 'b\0\0...' is ordered BEFORE 'b  ...'. Users
 
3087
    having indexes on such data need to rebuild their tables! */
 
3088
 
 
3089
    ret = charset->coll->strnncollsp(charset,
 
3090
          a, a_length,
 
3091
             b, b_length, 0);
 
3092
    if (ret < 0) {
 
3093
      return(-1);
 
3094
    } else if (ret > 0) {
 
3095
      return(1);
 
3096
    } else {
 
3097
      return(0);
 
3098
    }
 
3099
  default:
 
3100
    ut_error;
 
3101
  }
 
3102
 
 
3103
  return(0);
3041
3104
}
3042
3105
 
3043
3106
/**************************************************************//**
3044
3107
Converts a MySQL type to an InnoDB type. Note that this function returns
3045
3108
the 'mtype' of InnoDB. InnoDB differentiates between MySQL's old <= 4.1
3046
3109
VARCHAR and the new true VARCHAR in >= 5.0.3 by the 'prtype'.
3047
 
@return DATA_BINARY, DATA_VARCHAR, ... */
 
3110
@return DATA_BINARY, DATA_VARCHAR, ... */
3048
3111
extern "C" UNIV_INTERN
3049
3112
ulint
3050
3113
get_innobase_type_from_mysql_type(
3051
3114
/*==============================*/
3052
 
        ulint*          unsigned_flag,  /*!< out: DATA_UNSIGNED if an
3053
 
                                        'unsigned type';
3054
 
                                        at least ENUM and SET,
3055
 
                                        and unsigned integer
3056
 
                                        types are 'unsigned types' */
3057
 
        const void*     f)              /*!< in: MySQL Field */
 
3115
  ulint*    unsigned_flag,  /*!< out: DATA_UNSIGNED if an
 
3116
          'unsigned type';
 
3117
          at least ENUM and SET,
 
3118
          and unsigned integer
 
3119
          types are 'unsigned types' */
 
3120
  const void* f)    /*!< in: MySQL Field */
3058
3121
{
3059
 
        const class Field* field = reinterpret_cast<const class Field*>(f);
3060
 
 
3061
 
        /* The following asserts try to check that the MySQL type code fits in
3062
 
        8 bits: this is used in ibuf and also when DATA_NOT_NULL is ORed to
3063
 
        the type */
3064
 
 
3065
 
        assert((ulint)DRIZZLE_TYPE_DOUBLE < 256);
3066
 
 
3067
 
        if (field->flags & UNSIGNED_FLAG) {
3068
 
 
3069
 
                *unsigned_flag = DATA_UNSIGNED;
3070
 
        } else {
3071
 
                *unsigned_flag = 0;
3072
 
        }
3073
 
 
3074
 
        if (field->real_type() == DRIZZLE_TYPE_ENUM)
3075
 
        {
3076
 
                /* MySQL has field->type() a string type for these, but the
3077
 
                data is actually internally stored as an unsigned integer
3078
 
                code! */
3079
 
 
3080
 
                *unsigned_flag = DATA_UNSIGNED; /* MySQL has its own unsigned
3081
 
                                                flag set to zero, even though
3082
 
                                                internally this is an unsigned
3083
 
                                                integer type */
3084
 
                return(DATA_INT);
3085
 
        }
3086
 
 
3087
 
        switch (field->type()) {
3088
 
                /* NOTE that we only allow string types in DATA_DRIZZLE and
3089
 
                DATA_VARDRIZZLE */
3090
 
        case DRIZZLE_TYPE_VARCHAR:    /* new >= 5.0.3 true VARCHAR */
3091
 
                if (field->binary()) {
3092
 
                        return(DATA_BINARY);
3093
 
                } else {
3094
 
                        return(DATA_VARMYSQL);
3095
 
                }
3096
 
        case DRIZZLE_TYPE_DECIMAL:
3097
 
                return(DATA_FIXBINARY);
3098
 
        case DRIZZLE_TYPE_LONG:
3099
 
        case DRIZZLE_TYPE_LONGLONG:
3100
 
        case DRIZZLE_TYPE_DATETIME:
3101
 
        case DRIZZLE_TYPE_DATE:
3102
 
        case DRIZZLE_TYPE_TIMESTAMP:
3103
 
                return(DATA_INT);
3104
 
        case DRIZZLE_TYPE_DOUBLE:
3105
 
                return(DATA_DOUBLE);
3106
 
        case DRIZZLE_TYPE_BLOB:
 
3122
  const class Field* field = reinterpret_cast<const class Field*>(f);
 
3123
 
 
3124
  /* The following asserts try to check that the MySQL type code fits in
 
3125
  8 bits: this is used in ibuf and also when DATA_NOT_NULL is ORed to
 
3126
  the type */
 
3127
 
 
3128
  assert((ulint)DRIZZLE_TYPE_DOUBLE < 256);
 
3129
 
 
3130
  if (field->flags & UNSIGNED_FLAG) {
 
3131
 
 
3132
    *unsigned_flag = DATA_UNSIGNED;
 
3133
  } else {
 
3134
    *unsigned_flag = 0;
 
3135
  }
 
3136
 
 
3137
  if (field->real_type() == DRIZZLE_TYPE_ENUM)
 
3138
  {
 
3139
    /* MySQL has field->type() a string type for these, but the
 
3140
    data is actually internally stored as an unsigned integer
 
3141
    code! */
 
3142
 
 
3143
    *unsigned_flag = DATA_UNSIGNED; /* MySQL has its own unsigned
 
3144
            flag set to zero, even though
 
3145
            internally this is an unsigned
 
3146
            integer type */
 
3147
    return(DATA_INT);
 
3148
  }
 
3149
 
 
3150
  switch (field->type()) {
 
3151
    /* NOTE that we only allow string types in DATA_DRIZZLE and
 
3152
    DATA_VARDRIZZLE */
 
3153
  case DRIZZLE_TYPE_VARCHAR:    /* new >= 5.0.3 true VARCHAR */
 
3154
    if (field->binary()) {
 
3155
      return(DATA_BINARY);
 
3156
    } else {
 
3157
      return(DATA_VARMYSQL);
 
3158
    }
 
3159
  case DRIZZLE_TYPE_DECIMAL:
 
3160
    return(DATA_FIXBINARY);
 
3161
  case DRIZZLE_TYPE_LONG:
 
3162
  case DRIZZLE_TYPE_LONGLONG:
 
3163
  case DRIZZLE_TYPE_DATETIME:
 
3164
  case DRIZZLE_TYPE_DATE:
 
3165
  case DRIZZLE_TYPE_TIMESTAMP:
 
3166
    return(DATA_INT);
 
3167
  case DRIZZLE_TYPE_DOUBLE:
 
3168
    return(DATA_DOUBLE);
 
3169
  case DRIZZLE_TYPE_BLOB:
3107
3170
                return(DATA_BLOB);
3108
 
        default:
3109
 
                ut_error;
3110
 
        }
 
3171
  default:
 
3172
    ut_error;
 
3173
  }
3111
3174
 
3112
 
        return(0);
 
3175
  return(0);
3113
3176
}
3114
3177
 
3115
3178
/*******************************************************************//**
3119
3182
void
3120
3183
innobase_write_to_2_little_endian(
3121
3184
/*==============================*/
3122
 
        byte*   buf,    /*!< in: where to store */
3123
 
        ulint   val)    /*!< in: value to write, must be < 64k */
 
3185
  byte* buf,  /*!< in: where to store */
 
3186
  ulint val)  /*!< in: value to write, must be < 64k */
3124
3187
{
3125
 
        ut_a(val < 256 * 256);
 
3188
  ut_a(val < 256 * 256);
3126
3189
 
3127
 
        buf[0] = (byte)(val & 0xFF);
3128
 
        buf[1] = (byte)(val / 256);
 
3190
  buf[0] = (byte)(val & 0xFF);
 
3191
  buf[1] = (byte)(val / 256);
3129
3192
}
3130
3193
 
3131
3194
/*******************************************************************//**
3132
3195
Reads an unsigned integer value < 64k from 2 bytes, in the little-endian
3133
3196
storage format.
3134
 
@return value */
 
3197
@return value */
3135
3198
static inline
3136
3199
uint
3137
3200
innobase_read_from_2_little_endian(
3138
3201
/*===============================*/
3139
 
        const unsigned char*    buf)    /*!< in: from where to read */
 
3202
  const unsigned char*  buf)  /*!< in: from where to read */
3140
3203
{
3141
 
        return (uint) ((ulint)(buf[0]) + 256 * ((ulint)(buf[1])));
 
3204
  return (uint) ((ulint)(buf[0]) + 256 * ((ulint)(buf[1])));
3142
3205
}
3143
3206
 
3144
3207
/*******************************************************************//**
3145
3208
Stores a key value for a row to a buffer.
3146
 
@return key value length as stored in buff */
 
3209
@return key value length as stored in buff */
3147
3210
UNIV_INTERN
3148
3211
uint
3149
3212
ha_innobase::store_key_val_for_row(
3150
3213
/*===============================*/
3151
 
        uint            keynr,  /*!< in: key number */
3152
 
        char*           buff,   /*!< in/out: buffer for the key value (in MySQL
3153
 
                                format) */
3154
 
        uint            buff_len,/*!< in: buffer length */
3155
 
        const unsigned char*    record)/*!< in: row in MySQL format */
 
3214
  uint    keynr,  /*!< in: key number */
 
3215
  char*   buff, /*!< in/out: buffer for the key value (in MySQL
 
3216
        format) */
 
3217
  uint    buff_len,/*!< in: buffer length */
 
3218
  const unsigned char*  record)/*!< in: row in MySQL format */
3156
3219
{
3157
 
        KEY*            key_info        = table->key_info + keynr;
3158
 
        KEY_PART_INFO*  key_part        = key_info->key_part;
3159
 
        KEY_PART_INFO*  end             = key_part + key_info->key_parts;
3160
 
        char*           buff_start      = buff;
3161
 
        enum_field_types mysql_type;
3162
 
        Field*          field;
3163
 
        ibool           is_null;
3164
 
 
3165
 
        /* The format for storing a key field in MySQL is the following:
3166
 
 
3167
 
        1. If the column can be NULL, then in the first byte we put 1 if the
3168
 
        field value is NULL, 0 otherwise.
3169
 
 
3170
 
        2. If the column is of a BLOB type (it must be a column prefix field
3171
 
        in this case), then we put the length of the data in the field to the
3172
 
        next 2 bytes, in the little-endian format. If the field is SQL NULL,
3173
 
        then these 2 bytes are set to 0. Note that the length of data in the
3174
 
        field is <= column prefix length.
3175
 
 
3176
 
        3. In a column prefix field, prefix_len next bytes are reserved for
3177
 
        data. In a normal field the max field length next bytes are reserved
3178
 
        for data. For a VARCHAR(n) the max field length is n. If the stored
3179
 
        value is the SQL NULL then these data bytes are set to 0.
3180
 
 
3181
 
        4. We always use a 2 byte length for a true >= 5.0.3 VARCHAR. Note that
3182
 
        in the MySQL row format, the length is stored in 1 or 2 bytes,
3183
 
        depending on the maximum allowed length. But in the MySQL key value
3184
 
        format, the length always takes 2 bytes.
3185
 
 
3186
 
        We have to zero-fill the buffer so that MySQL is able to use a
3187
 
        simple memcmp to compare two key values to determine if they are
3188
 
        equal. MySQL does this to compare contents of two 'ref' values. */
3189
 
 
3190
 
        bzero(buff, buff_len);
3191
 
 
3192
 
        for (; key_part != end; key_part++) {
3193
 
                is_null = FALSE;
3194
 
 
3195
 
                if (key_part->null_bit) {
3196
 
                        if (record[key_part->null_offset]
3197
 
                                                & key_part->null_bit) {
3198
 
                                *buff = 1;
3199
 
                                is_null = TRUE;
3200
 
                        } else {
3201
 
                                *buff = 0;
3202
 
                        }
3203
 
                        buff++;
3204
 
                }
3205
 
 
3206
 
                field = key_part->field;
3207
 
                mysql_type = field->type();
3208
 
 
3209
 
                if (mysql_type == DRIZZLE_TYPE_VARCHAR) {
3210
 
                                                /* >= 5.0.3 true VARCHAR */
3211
 
                        ulint           lenlen;
3212
 
                        ulint           len;
3213
 
                        const byte*     data;
3214
 
                        ulint           key_len;
3215
 
                        ulint           true_len;
3216
 
                        const CHARSET_INFO*     cs;
3217
 
                        int             error=0;
3218
 
 
3219
 
                        key_len = key_part->length;
3220
 
 
3221
 
                        if (is_null) {
3222
 
                                buff += key_len + 2;
3223
 
 
3224
 
                                continue;
3225
 
                        }
3226
 
                        cs = field->charset();
3227
 
 
3228
 
                        lenlen = (ulint)
3229
 
                                (((Field_varstring*)field)->length_bytes);
3230
 
 
3231
 
                        data = row_mysql_read_true_varchar(&len,
3232
 
                                (byte*) (record
3233
 
                                + (ulint)get_field_offset(table, field)),
3234
 
                                lenlen);
3235
 
 
3236
 
                        true_len = len;
3237
 
 
3238
 
                        /* For multi byte character sets we need to calculate
3239
 
                        the true length of the key */
3240
 
 
3241
 
                        if (len > 0 && cs->mbmaxlen > 1) {
3242
 
                                true_len = (ulint) cs->cset->well_formed_len(cs,
3243
 
                                                (const char *) data,
3244
 
                                                (const char *) data + len,
3245
 
                                                (uint) (key_len /
3246
 
                                                        cs->mbmaxlen),
3247
 
                                                &error);
3248
 
                        }
3249
 
 
3250
 
                        /* In a column prefix index, we may need to truncate
3251
 
                        the stored value: */
3252
 
 
3253
 
                        if (true_len > key_len) {
3254
 
                                true_len = key_len;
3255
 
                        }
3256
 
 
3257
 
                        /* The length in a key value is always stored in 2
3258
 
                        bytes */
3259
 
 
3260
 
                        row_mysql_store_true_var_len((byte*)buff, true_len, 2);
3261
 
                        buff += 2;
3262
 
 
3263
 
                        memcpy(buff, data, true_len);
3264
 
 
3265
 
                        /* Note that we always reserve the maximum possible
3266
 
                        length of the true VARCHAR in the key value, though
3267
 
                        only len first bytes after the 2 length bytes contain
3268
 
                        actual data. The rest of the space was reset to zero
3269
 
                        in the bzero() call above. */
3270
 
 
3271
 
                        buff += key_len;
3272
 
 
3273
 
                } else if (mysql_type == DRIZZLE_TYPE_BLOB) {
3274
 
 
3275
 
                        const CHARSET_INFO*     cs;
3276
 
                        ulint           key_len;
3277
 
                        ulint           true_len;
3278
 
                        int             error=0;
3279
 
                        ulint           blob_len;
3280
 
                        const byte*     blob_data;
3281
 
 
3282
 
                        ut_a(key_part->key_part_flag & HA_PART_KEY_SEG);
3283
 
 
3284
 
                        key_len = key_part->length;
3285
 
 
3286
 
                        if (is_null) {
3287
 
                                buff += key_len + 2;
3288
 
 
3289
 
                                continue;
3290
 
                        }
3291
 
 
3292
 
                        cs = field->charset();
3293
 
 
3294
 
                        blob_data = row_mysql_read_blob_ref(&blob_len,
3295
 
                                (byte*) (record
3296
 
                                + (ulint)get_field_offset(table, field)),
3297
 
                                        (ulint) field->pack_length());
3298
 
 
3299
 
                        true_len = blob_len;
3300
 
 
3301
 
                        ut_a(get_field_offset(table, field)
3302
 
                                == key_part->offset);
3303
 
 
3304
 
                        /* For multi byte character sets we need to calculate
3305
 
                        the true length of the key */
3306
 
 
3307
 
                        if (blob_len > 0 && cs->mbmaxlen > 1) {
3308
 
                                true_len = (ulint) cs->cset->well_formed_len(cs,
3309
 
                                                (const char *) blob_data,
3310
 
                                                (const char *) blob_data
3311
 
                                                        + blob_len,
3312
 
                                                (uint) (key_len /
3313
 
                                                        cs->mbmaxlen),
3314
 
                                                &error);
3315
 
                        }
3316
 
 
3317
 
                        /* All indexes on BLOB and TEXT are column prefix
3318
 
                        indexes, and we may need to truncate the data to be
3319
 
                        stored in the key value: */
3320
 
 
3321
 
                        if (true_len > key_len) {
3322
 
                                true_len = key_len;
3323
 
                        }
3324
 
 
3325
 
                        /* MySQL reserves 2 bytes for the length and the
3326
 
                        storage of the number is little-endian */
3327
 
 
3328
 
                        innobase_write_to_2_little_endian(
3329
 
                                        (byte*)buff, true_len);
3330
 
                        buff += 2;
3331
 
 
3332
 
                        memcpy(buff, blob_data, true_len);
3333
 
 
3334
 
                        /* Note that we always reserve the maximum possible
3335
 
                        length of the BLOB prefix in the key value. */
3336
 
 
3337
 
                        buff += key_len;
3338
 
                } else {
3339
 
                        /* Here we handle all other data types except the
3340
 
                        true VARCHAR, BLOB and TEXT. Note that the column
3341
 
                        value we store may be also in a column prefix
3342
 
                        index. */
3343
 
 
3344
 
                        ulint                   true_len;
3345
 
                        ulint                   key_len;
3346
 
                        const unsigned char*            src_start;
3347
 
                        enum_field_types        real_type;
3348
 
 
3349
 
                        key_len = key_part->length;
3350
 
 
3351
 
                        if (is_null) {
3352
 
                                 buff += key_len;
3353
 
 
3354
 
                                 continue;
3355
 
                        }
3356
 
 
3357
 
                        src_start = record + key_part->offset;
3358
 
                        real_type = field->real_type();
3359
 
                        true_len = key_len;
3360
 
 
3361
 
                        /* Character set for the field is defined only
3362
 
                        to fields whose type is string and real field
3363
 
                        type is not enum or set. For these fields check
3364
 
                        if character set is multi byte. */
3365
 
 
3366
 
                        memcpy(buff, src_start, true_len);
3367
 
                        buff += true_len;
3368
 
 
3369
 
                        /* Pad the unused space with spaces. Note that no
3370
 
                        padding is ever needed for UCS-2 because in MySQL,
3371
 
                        all UCS2 characters are 2 bytes, as MySQL does not
3372
 
                        support surrogate pairs, which are needed to represent
3373
 
                        characters in the range U+10000 to U+10FFFF. */
3374
 
 
3375
 
                        if (true_len < key_len) {
3376
 
                                ulint pad_len = key_len - true_len;
3377
 
                                memset(buff, ' ', pad_len);
3378
 
                                buff += pad_len;
3379
 
                        }
3380
 
                }
3381
 
        }
3382
 
 
3383
 
        ut_a(buff <= buff_start + buff_len);
3384
 
 
3385
 
        return((uint)(buff - buff_start));
 
3220
  KEY*    key_info  = table->key_info + keynr;
 
3221
  KEY_PART_INFO*  key_part  = key_info->key_part;
 
3222
  KEY_PART_INFO*  end   = key_part + key_info->key_parts;
 
3223
  char*   buff_start  = buff;
 
3224
  enum_field_types mysql_type;
 
3225
  Field*    field;
 
3226
  ibool   is_null;
 
3227
 
 
3228
  /* The format for storing a key field in MySQL is the following:
 
3229
 
 
3230
  1. If the column can be NULL, then in the first byte we put 1 if the
 
3231
  field value is NULL, 0 otherwise.
 
3232
 
 
3233
  2. If the column is of a BLOB type (it must be a column prefix field
 
3234
  in this case), then we put the length of the data in the field to the
 
3235
  next 2 bytes, in the little-endian format. If the field is SQL NULL,
 
3236
  then these 2 bytes are set to 0. Note that the length of data in the
 
3237
  field is <= column prefix length.
 
3238
 
 
3239
  3. In a column prefix field, prefix_len next bytes are reserved for
 
3240
  data. In a normal field the max field length next bytes are reserved
 
3241
  for data. For a VARCHAR(n) the max field length is n. If the stored
 
3242
  value is the SQL NULL then these data bytes are set to 0.
 
3243
 
 
3244
  4. We always use a 2 byte length for a true >= 5.0.3 VARCHAR. Note that
 
3245
  in the MySQL row format, the length is stored in 1 or 2 bytes,
 
3246
  depending on the maximum allowed length. But in the MySQL key value
 
3247
  format, the length always takes 2 bytes.
 
3248
 
 
3249
  We have to zero-fill the buffer so that MySQL is able to use a
 
3250
  simple memcmp to compare two key values to determine if they are
 
3251
  equal. MySQL does this to compare contents of two 'ref' values. */
 
3252
 
 
3253
  bzero(buff, buff_len);
 
3254
 
 
3255
  for (; key_part != end; key_part++) {
 
3256
    is_null = FALSE;
 
3257
 
 
3258
    if (key_part->null_bit) {
 
3259
      if (record[key_part->null_offset]
 
3260
            & key_part->null_bit) {
 
3261
        *buff = 1;
 
3262
        is_null = TRUE;
 
3263
      } else {
 
3264
        *buff = 0;
 
3265
      }
 
3266
      buff++;
 
3267
    }
 
3268
 
 
3269
    field = key_part->field;
 
3270
    mysql_type = field->type();
 
3271
 
 
3272
    if (mysql_type == DRIZZLE_TYPE_VARCHAR) {
 
3273
            /* >= 5.0.3 true VARCHAR */
 
3274
      ulint   lenlen;
 
3275
      ulint   len;
 
3276
      const byte* data;
 
3277
      ulint   key_len;
 
3278
      ulint   true_len;
 
3279
      const CHARSET_INFO* cs;
 
3280
      int   error=0;
 
3281
 
 
3282
      key_len = key_part->length;
 
3283
 
 
3284
      if (is_null) {
 
3285
        buff += key_len + 2;
 
3286
 
 
3287
        continue;
 
3288
      }
 
3289
      cs = field->charset();
 
3290
 
 
3291
      lenlen = (ulint)
 
3292
        (((Field_varstring*)field)->length_bytes);
 
3293
 
 
3294
      data = row_mysql_read_true_varchar(&len,
 
3295
        (byte*) (record
 
3296
        + (ulint)get_field_offset(table, field)),
 
3297
        lenlen);
 
3298
 
 
3299
      true_len = len;
 
3300
 
 
3301
      /* For multi byte character sets we need to calculate
 
3302
      the true length of the key */
 
3303
 
 
3304
      if (len > 0 && cs->mbmaxlen > 1) {
 
3305
        true_len = (ulint) cs->cset->well_formed_len(cs,
 
3306
            (const char *) data,
 
3307
            (const char *) data + len,
 
3308
                                                (uint) (key_len /
 
3309
                                                        cs->mbmaxlen),
 
3310
            &error);
 
3311
      }
 
3312
 
 
3313
      /* In a column prefix index, we may need to truncate
 
3314
      the stored value: */
 
3315
 
 
3316
      if (true_len > key_len) {
 
3317
        true_len = key_len;
 
3318
      }
 
3319
 
 
3320
      /* The length in a key value is always stored in 2
 
3321
      bytes */
 
3322
 
 
3323
      row_mysql_store_true_var_len((byte*)buff, true_len, 2);
 
3324
      buff += 2;
 
3325
 
 
3326
      memcpy(buff, data, true_len);
 
3327
 
 
3328
      /* Note that we always reserve the maximum possible
 
3329
      length of the true VARCHAR in the key value, though
 
3330
      only len first bytes after the 2 length bytes contain
 
3331
      actual data. The rest of the space was reset to zero
 
3332
      in the bzero() call above. */
 
3333
 
 
3334
      buff += key_len;
 
3335
 
 
3336
    } else if (mysql_type == DRIZZLE_TYPE_BLOB) {
 
3337
 
 
3338
      const CHARSET_INFO* cs;
 
3339
      ulint   key_len;
 
3340
      ulint   true_len;
 
3341
      int   error=0;
 
3342
      ulint   blob_len;
 
3343
      const byte* blob_data;
 
3344
 
 
3345
      ut_a(key_part->key_part_flag & HA_PART_KEY_SEG);
 
3346
 
 
3347
      key_len = key_part->length;
 
3348
 
 
3349
      if (is_null) {
 
3350
        buff += key_len + 2;
 
3351
 
 
3352
        continue;
 
3353
      }
 
3354
 
 
3355
      cs = field->charset();
 
3356
 
 
3357
      blob_data = row_mysql_read_blob_ref(&blob_len,
 
3358
        (byte*) (record
 
3359
        + (ulint)get_field_offset(table, field)),
 
3360
          (ulint) field->pack_length());
 
3361
 
 
3362
      true_len = blob_len;
 
3363
 
 
3364
      ut_a(get_field_offset(table, field)
 
3365
        == key_part->offset);
 
3366
 
 
3367
      /* For multi byte character sets we need to calculate
 
3368
      the true length of the key */
 
3369
 
 
3370
      if (blob_len > 0 && cs->mbmaxlen > 1) {
 
3371
        true_len = (ulint) cs->cset->well_formed_len(cs,
 
3372
            (const char *) blob_data,
 
3373
            (const char *) blob_data
 
3374
              + blob_len,
 
3375
                                                (uint) (key_len /
 
3376
                                                        cs->mbmaxlen),
 
3377
            &error);
 
3378
      }
 
3379
 
 
3380
      /* All indexes on BLOB and TEXT are column prefix
 
3381
      indexes, and we may need to truncate the data to be
 
3382
      stored in the key value: */
 
3383
 
 
3384
      if (true_len > key_len) {
 
3385
        true_len = key_len;
 
3386
      }
 
3387
 
 
3388
      /* MySQL reserves 2 bytes for the length and the
 
3389
      storage of the number is little-endian */
 
3390
 
 
3391
      innobase_write_to_2_little_endian(
 
3392
          (byte*)buff, true_len);
 
3393
      buff += 2;
 
3394
 
 
3395
      memcpy(buff, blob_data, true_len);
 
3396
 
 
3397
      /* Note that we always reserve the maximum possible
 
3398
      length of the BLOB prefix in the key value. */
 
3399
 
 
3400
      buff += key_len;
 
3401
    } else {
 
3402
      /* Here we handle all other data types except the
 
3403
      true VARCHAR, BLOB and TEXT. Note that the column
 
3404
      value we store may be also in a column prefix
 
3405
      index. */
 
3406
 
 
3407
      ulint     true_len;
 
3408
      ulint     key_len;
 
3409
      const unsigned char*    src_start;
 
3410
      enum_field_types  real_type;
 
3411
 
 
3412
      key_len = key_part->length;
 
3413
 
 
3414
      if (is_null) {
 
3415
         buff += key_len;
 
3416
 
 
3417
         continue;
 
3418
      }
 
3419
 
 
3420
      src_start = record + key_part->offset;
 
3421
      real_type = field->real_type();
 
3422
      true_len = key_len;
 
3423
 
 
3424
      /* Character set for the field is defined only
 
3425
      to fields whose type is string and real field
 
3426
      type is not enum or set. For these fields check
 
3427
      if character set is multi byte. */
 
3428
 
 
3429
      memcpy(buff, src_start, true_len);
 
3430
      buff += true_len;
 
3431
 
 
3432
      /* Pad the unused space with spaces. Note that no
 
3433
      padding is ever needed for UCS-2 because in MySQL,
 
3434
      all UCS2 characters are 2 bytes, as MySQL does not
 
3435
      support surrogate pairs, which are needed to represent
 
3436
      characters in the range U+10000 to U+10FFFF. */
 
3437
 
 
3438
      if (true_len < key_len) {
 
3439
        ulint pad_len = key_len - true_len;
 
3440
        memset(buff, ' ', pad_len);
 
3441
        buff += pad_len;
 
3442
      }
 
3443
    }
 
3444
  }
 
3445
 
 
3446
  ut_a(buff <= buff_start + buff_len);
 
3447
 
 
3448
  return((uint)(buff - buff_start));
3386
3449
}
3387
3450
 
3388
3451
/**************************************************************//**
3392
3455
void
3393
3456
build_template(
3394
3457
/*===========*/
3395
 
        row_prebuilt_t* prebuilt,       /*!< in/out: prebuilt struct */
3396
 
        Session*        ,               /*!< in: current user thread, used
3397
 
                                        only if templ_type is
3398
 
                                        ROW_DRIZZLE_REC_FIELDS */
3399
 
        Table*          table,          /*!< in: MySQL table */
3400
 
        uint            templ_type)     /*!< in: ROW_MYSQL_WHOLE_ROW or
3401
 
                                        ROW_DRIZZLE_REC_FIELDS */
 
3458
  row_prebuilt_t* prebuilt, /*!< in/out: prebuilt struct */
 
3459
  Session*  ,   /*!< in: current user thread, used
 
3460
          only if templ_type is
 
3461
          ROW_DRIZZLE_REC_FIELDS */
 
3462
  Table*    table,    /*!< in: MySQL table */
 
3463
  uint    templ_type) /*!< in: ROW_MYSQL_WHOLE_ROW or
 
3464
          ROW_DRIZZLE_REC_FIELDS */
3402
3465
{
3403
 
        dict_index_t*   index;
3404
 
        dict_index_t*   clust_index;
3405
 
        mysql_row_templ_t* templ;
3406
 
        Field*          field;
3407
 
        ulint           n_fields;
3408
 
        ulint           n_requested_fields      = 0;
3409
 
        ibool           fetch_all_in_key        = FALSE;
3410
 
        ibool           fetch_primary_key_cols  = FALSE;
3411
 
        ulint           i= 0;
3412
 
        /* byte offset of the end of last requested column */
3413
 
        ulint           mysql_prefix_len        = 0;
3414
 
 
3415
 
        if (prebuilt->select_lock_type == LOCK_X) {
3416
 
                /* We always retrieve the whole clustered index record if we
3417
 
                use exclusive row level locks, for example, if the read is
3418
 
                done in an UPDATE statement. */
3419
 
 
3420
 
                templ_type = ROW_MYSQL_WHOLE_ROW;
3421
 
        }
3422
 
 
3423
 
        if (templ_type == ROW_MYSQL_REC_FIELDS) {
3424
 
                if (prebuilt->hint_need_to_fetch_extra_cols
3425
 
                        == ROW_RETRIEVE_ALL_COLS) {
3426
 
 
3427
 
                        /* We know we must at least fetch all columns in the
3428
 
                        key, or all columns in the table */
3429
 
 
3430
 
                        if (prebuilt->read_just_key) {
3431
 
                                /* MySQL has instructed us that it is enough
3432
 
                                to fetch the columns in the key; looks like
3433
 
                                MySQL can set this flag also when there is
3434
 
                                only a prefix of the column in the key: in
3435
 
                                that case we retrieve the whole column from
3436
 
                                the clustered index */
3437
 
 
3438
 
                                fetch_all_in_key = TRUE;
3439
 
                        } else {
3440
 
                                templ_type = ROW_MYSQL_WHOLE_ROW;
3441
 
                        }
3442
 
                } else if (prebuilt->hint_need_to_fetch_extra_cols
3443
 
                        == ROW_RETRIEVE_PRIMARY_KEY) {
3444
 
                        /* We must at least fetch all primary key cols. Note
3445
 
                           that if the clustered index was internally generated
3446
 
                           by InnoDB on the row id (no primary key was
3447
 
                           defined), then row_search_for_mysql() will always
3448
 
                           retrieve the row id to a special buffer in the
3449
 
                           prebuilt struct. */
3450
 
 
3451
 
                        fetch_primary_key_cols = TRUE;
3452
 
                }
3453
 
        }
3454
 
 
3455
 
        clust_index = dict_table_get_first_index(prebuilt->table);
3456
 
 
3457
 
        if (templ_type == ROW_MYSQL_REC_FIELDS) {
3458
 
                index = prebuilt->index;
3459
 
        } else {
3460
 
                index = clust_index;
3461
 
        }
3462
 
 
3463
 
        if (index == clust_index) {
3464
 
                prebuilt->need_to_access_clustered = TRUE;
3465
 
        } else {
3466
 
                prebuilt->need_to_access_clustered = FALSE;
3467
 
                /* Below we check column by column if we need to access
3468
 
                the clustered index */
3469
 
        }
3470
 
 
3471
 
        n_fields = (ulint)table->s->fields; /* number of columns */
3472
 
 
3473
 
        if (!prebuilt->mysql_template) {
3474
 
                prebuilt->mysql_template = (mysql_row_templ_t*)
3475
 
                        mem_alloc(n_fields * sizeof(mysql_row_templ_t));
3476
 
        }
3477
 
 
3478
 
        prebuilt->template_type = templ_type;
3479
 
        prebuilt->null_bitmap_len = table->s->null_bytes;
3480
 
 
3481
 
        prebuilt->templ_contains_blob = FALSE;
3482
 
 
3483
 
        /* Note that in InnoDB, i is the column number. MySQL calls columns
3484
 
        'fields'. */
3485
 
        for (i = 0; i < n_fields; i++) {
3486
 
                templ = prebuilt->mysql_template + n_requested_fields;
3487
 
                field = table->field[i];
3488
 
 
3489
 
                if (UNIV_LIKELY(templ_type == ROW_MYSQL_REC_FIELDS)) {
3490
 
                        /* Decide which columns we should fetch
3491
 
                        and which we can skip. */
3492
 
                        register const ibool    index_contains_field =
3493
 
                                dict_index_contains_col_or_prefix(index, i);
3494
 
 
3495
 
                        if (!index_contains_field && prebuilt->read_just_key) {
3496
 
                                /* If this is a 'key read', we do not need
3497
 
                                columns that are not in the key */
3498
 
 
3499
 
                                goto skip_field;
3500
 
                        }
3501
 
 
3502
 
                        if (index_contains_field && fetch_all_in_key) {
3503
 
                                /* This field is needed in the query */
3504
 
 
3505
 
                                goto include_field;
3506
 
                        }
 
3466
  dict_index_t* index;
 
3467
  dict_index_t* clust_index;
 
3468
  mysql_row_templ_t* templ;
 
3469
  Field*    field;
 
3470
  ulint   n_fields;
 
3471
  ulint   n_requested_fields  = 0;
 
3472
  ibool   fetch_all_in_key  = FALSE;
 
3473
  ibool   fetch_primary_key_cols  = FALSE;
 
3474
  ulint   i= 0;
 
3475
  /* byte offset of the end of last requested column */
 
3476
  ulint   mysql_prefix_len  = 0;
 
3477
 
 
3478
  if (prebuilt->select_lock_type == LOCK_X) {
 
3479
    /* We always retrieve the whole clustered index record if we
 
3480
    use exclusive row level locks, for example, if the read is
 
3481
    done in an UPDATE statement. */
 
3482
 
 
3483
    templ_type = ROW_MYSQL_WHOLE_ROW;
 
3484
  }
 
3485
 
 
3486
  if (templ_type == ROW_MYSQL_REC_FIELDS) {
 
3487
    if (prebuilt->hint_need_to_fetch_extra_cols
 
3488
      == ROW_RETRIEVE_ALL_COLS) {
 
3489
 
 
3490
      /* We know we must at least fetch all columns in the
 
3491
      key, or all columns in the table */
 
3492
 
 
3493
      if (prebuilt->read_just_key) {
 
3494
        /* MySQL has instructed us that it is enough
 
3495
        to fetch the columns in the key; looks like
 
3496
        MySQL can set this flag also when there is
 
3497
        only a prefix of the column in the key: in
 
3498
        that case we retrieve the whole column from
 
3499
        the clustered index */
 
3500
 
 
3501
        fetch_all_in_key = TRUE;
 
3502
      } else {
 
3503
        templ_type = ROW_MYSQL_WHOLE_ROW;
 
3504
      }
 
3505
    } else if (prebuilt->hint_need_to_fetch_extra_cols
 
3506
      == ROW_RETRIEVE_PRIMARY_KEY) {
 
3507
      /* We must at least fetch all primary key cols. Note
 
3508
         that if the clustered index was internally generated
 
3509
         by InnoDB on the row id (no primary key was
 
3510
         defined), then row_search_for_mysql() will always
 
3511
         retrieve the row id to a special buffer in the
 
3512
         prebuilt struct. */
 
3513
 
 
3514
      fetch_primary_key_cols = TRUE;
 
3515
    }
 
3516
  }
 
3517
 
 
3518
  clust_index = dict_table_get_first_index(prebuilt->table);
 
3519
 
 
3520
  if (templ_type == ROW_MYSQL_REC_FIELDS) {
 
3521
    index = prebuilt->index;
 
3522
  } else {
 
3523
    index = clust_index;
 
3524
  }
 
3525
 
 
3526
  if (index == clust_index) {
 
3527
    prebuilt->need_to_access_clustered = TRUE;
 
3528
  } else {
 
3529
    prebuilt->need_to_access_clustered = FALSE;
 
3530
    /* Below we check column by column if we need to access
 
3531
    the clustered index */
 
3532
  }
 
3533
 
 
3534
  n_fields = (ulint)table->s->fields; /* number of columns */
 
3535
 
 
3536
  if (!prebuilt->mysql_template) {
 
3537
    prebuilt->mysql_template = (mysql_row_templ_t*)
 
3538
      mem_alloc(n_fields * sizeof(mysql_row_templ_t));
 
3539
  }
 
3540
 
 
3541
  prebuilt->template_type = templ_type;
 
3542
  prebuilt->null_bitmap_len = table->s->null_bytes;
 
3543
 
 
3544
  prebuilt->templ_contains_blob = FALSE;
 
3545
 
 
3546
  /* Note that in InnoDB, i is the column number. MySQL calls columns
 
3547
  'fields'. */
 
3548
  for (i = 0; i < n_fields; i++) {
 
3549
    templ = prebuilt->mysql_template + n_requested_fields;
 
3550
    field = table->field[i];
 
3551
 
 
3552
    if (UNIV_LIKELY(templ_type == ROW_MYSQL_REC_FIELDS)) {
 
3553
      /* Decide which columns we should fetch
 
3554
      and which we can skip. */
 
3555
      register const ibool  index_contains_field =
 
3556
        dict_index_contains_col_or_prefix(index, i);
 
3557
 
 
3558
      if (!index_contains_field && prebuilt->read_just_key) {
 
3559
        /* If this is a 'key read', we do not need
 
3560
        columns that are not in the key */
 
3561
 
 
3562
        goto skip_field;
 
3563
      }
 
3564
 
 
3565
      if (index_contains_field && fetch_all_in_key) {
 
3566
        /* This field is needed in the query */
 
3567
 
 
3568
        goto include_field;
 
3569
      }
3507
3570
 
3508
3571
                        if (field->isReadSet() || field->isWriteSet())
3509
 
                                /* This field is needed in the query */
3510
 
                                goto include_field;
 
3572
        /* This field is needed in the query */
 
3573
        goto include_field;
3511
3574
 
3512
3575
                        assert(table->isReadSet(i) == field->isReadSet());
3513
3576
                        assert(table->isWriteSet(i) == field->isWriteSet());
3514
3577
 
3515
 
                        if (fetch_primary_key_cols
3516
 
                                && dict_table_col_in_clustered_key(
3517
 
                                        index->table, i)) {
3518
 
                                /* This field is needed in the query */
3519
 
 
3520
 
                                goto include_field;
3521
 
                        }
3522
 
 
3523
 
                        /* This field is not needed in the query, skip it */
3524
 
 
3525
 
                        goto skip_field;
3526
 
                }
 
3578
      if (fetch_primary_key_cols
 
3579
        && dict_table_col_in_clustered_key(
 
3580
          index->table, i)) {
 
3581
        /* This field is needed in the query */
 
3582
 
 
3583
        goto include_field;
 
3584
      }
 
3585
 
 
3586
      /* This field is not needed in the query, skip it */
 
3587
 
 
3588
      goto skip_field;
 
3589
    }
3527
3590
include_field:
3528
 
                n_requested_fields++;
3529
 
 
3530
 
                templ->col_no = i;
3531
 
 
3532
 
                if (index == clust_index) {
3533
 
                        templ->rec_field_no = dict_col_get_clust_pos(
3534
 
                                &index->table->cols[i], index);
3535
 
                } else {
3536
 
                        templ->rec_field_no = dict_index_get_nth_col_pos(
3537
 
                                                                index, i);
3538
 
                }
3539
 
 
3540
 
                if (templ->rec_field_no == ULINT_UNDEFINED) {
3541
 
                        prebuilt->need_to_access_clustered = TRUE;
3542
 
                }
3543
 
 
3544
 
                if (field->null_ptr) {
3545
 
                        templ->mysql_null_byte_offset =
3546
 
                                (ulint) ((char*) field->null_ptr
3547
 
                                        - (char*) table->record[0]);
3548
 
 
3549
 
                        templ->mysql_null_bit_mask = (ulint) field->null_bit;
3550
 
                } else {
3551
 
                        templ->mysql_null_bit_mask = 0;
3552
 
                }
3553
 
 
3554
 
                templ->mysql_col_offset = (ulint)
3555
 
                                        get_field_offset(table, field);
3556
 
 
3557
 
                templ->mysql_col_len = (ulint) field->pack_length();
3558
 
                if (mysql_prefix_len < templ->mysql_col_offset
3559
 
                                + templ->mysql_col_len) {
3560
 
                        mysql_prefix_len = templ->mysql_col_offset
3561
 
                                + templ->mysql_col_len;
3562
 
                }
3563
 
                templ->type = index->table->cols[i].mtype;
3564
 
                templ->mysql_type = (ulint)field->type();
3565
 
 
3566
 
                if (templ->mysql_type == DATA_MYSQL_TRUE_VARCHAR) {
3567
 
                        templ->mysql_length_bytes = (ulint)
3568
 
                                (((Field_varstring*)field)->length_bytes);
3569
 
                }
3570
 
 
3571
 
                templ->charset = dtype_get_charset_coll(
3572
 
                        index->table->cols[i].prtype);
3573
 
                templ->mbminlen = index->table->cols[i].mbminlen;
3574
 
                templ->mbmaxlen = index->table->cols[i].mbmaxlen;
3575
 
                templ->is_unsigned = index->table->cols[i].prtype
3576
 
                                                        & DATA_UNSIGNED;
3577
 
                if (templ->type == DATA_BLOB) {
3578
 
                        prebuilt->templ_contains_blob = TRUE;
3579
 
                }
 
3591
    n_requested_fields++;
 
3592
 
 
3593
    templ->col_no = i;
 
3594
 
 
3595
    if (index == clust_index) {
 
3596
      templ->rec_field_no = dict_col_get_clust_pos(
 
3597
        &index->table->cols[i], index);
 
3598
    } else {
 
3599
      templ->rec_field_no = dict_index_get_nth_col_pos(
 
3600
                index, i);
 
3601
    }
 
3602
 
 
3603
    if (templ->rec_field_no == ULINT_UNDEFINED) {
 
3604
      prebuilt->need_to_access_clustered = TRUE;
 
3605
    }
 
3606
 
 
3607
    if (field->null_ptr) {
 
3608
      templ->mysql_null_byte_offset =
 
3609
        (ulint) ((char*) field->null_ptr
 
3610
          - (char*) table->record[0]);
 
3611
 
 
3612
      templ->mysql_null_bit_mask = (ulint) field->null_bit;
 
3613
    } else {
 
3614
      templ->mysql_null_bit_mask = 0;
 
3615
    }
 
3616
 
 
3617
    templ->mysql_col_offset = (ulint)
 
3618
          get_field_offset(table, field);
 
3619
 
 
3620
    templ->mysql_col_len = (ulint) field->pack_length();
 
3621
    if (mysql_prefix_len < templ->mysql_col_offset
 
3622
        + templ->mysql_col_len) {
 
3623
      mysql_prefix_len = templ->mysql_col_offset
 
3624
        + templ->mysql_col_len;
 
3625
    }
 
3626
    templ->type = index->table->cols[i].mtype;
 
3627
    templ->mysql_type = (ulint)field->type();
 
3628
 
 
3629
    if (templ->mysql_type == DATA_MYSQL_TRUE_VARCHAR) {
 
3630
      templ->mysql_length_bytes = (ulint)
 
3631
        (((Field_varstring*)field)->length_bytes);
 
3632
    }
 
3633
 
 
3634
    templ->charset = dtype_get_charset_coll(
 
3635
      index->table->cols[i].prtype);
 
3636
    templ->mbminlen = index->table->cols[i].mbminlen;
 
3637
    templ->mbmaxlen = index->table->cols[i].mbmaxlen;
 
3638
    templ->is_unsigned = index->table->cols[i].prtype
 
3639
              & DATA_UNSIGNED;
 
3640
    if (templ->type == DATA_BLOB) {
 
3641
      prebuilt->templ_contains_blob = TRUE;
 
3642
    }
3580
3643
skip_field:
3581
 
                ;
3582
 
        }
3583
 
 
3584
 
        prebuilt->n_template = n_requested_fields;
3585
 
        prebuilt->mysql_prefix_len = mysql_prefix_len;
3586
 
 
3587
 
        if (index != clust_index && prebuilt->need_to_access_clustered) {
3588
 
                /* Change rec_field_no's to correspond to the clustered index
3589
 
                record */
3590
 
                for (i = 0; i < n_requested_fields; i++) {
3591
 
                        templ = prebuilt->mysql_template + i;
3592
 
 
3593
 
                        templ->rec_field_no = dict_col_get_clust_pos(
3594
 
                                &index->table->cols[templ->col_no],
3595
 
                                clust_index);
3596
 
                }
3597
 
        }
 
3644
    ;
 
3645
  }
 
3646
 
 
3647
  prebuilt->n_template = n_requested_fields;
 
3648
  prebuilt->mysql_prefix_len = mysql_prefix_len;
 
3649
 
 
3650
  if (index != clust_index && prebuilt->need_to_access_clustered) {
 
3651
    /* Change rec_field_no's to correspond to the clustered index
 
3652
    record */
 
3653
    for (i = 0; i < n_requested_fields; i++) {
 
3654
      templ = prebuilt->mysql_template + i;
 
3655
 
 
3656
      templ->rec_field_no = dict_col_get_clust_pos(
 
3657
        &index->table->cols[templ->col_no],
 
3658
        clust_index);
 
3659
    }
 
3660
  }
3598
3661
}
3599
3662
 
3600
3663
/********************************************************************//**
3603
3666
uint64_t
3604
3667
ha_innobase::innobase_get_int_col_max_value(
3605
3668
/*========================================*/
3606
 
        const Field*    field)
 
3669
  const Field*  field)
3607
3670
{
3608
 
        uint64_t        max_value = 0;
3609
 
 
3610
 
        switch(field->key_type()) {
3611
 
        /* TINY */
3612
 
        case HA_KEYTYPE_BINARY:
3613
 
                max_value = 0xFFULL;
3614
 
                break;
3615
 
        /* MEDIUM */
3616
 
        case HA_KEYTYPE_UINT24:
3617
 
                max_value = 0xFFFFFFULL;
3618
 
                break;
3619
 
        /* LONG */
3620
 
        case HA_KEYTYPE_ULONG_INT:
3621
 
                max_value = 0xFFFFFFFFULL;
3622
 
                break;
3623
 
        case HA_KEYTYPE_LONG_INT:
3624
 
                max_value = 0x7FFFFFFFULL;
3625
 
                break;
3626
 
        /* BIG */
3627
 
        case HA_KEYTYPE_ULONGLONG:
3628
 
                max_value = 0xFFFFFFFFFFFFFFFFULL;
3629
 
                break;
3630
 
        case HA_KEYTYPE_LONGLONG:
3631
 
                max_value = 0x7FFFFFFFFFFFFFFFULL;
3632
 
                break;
3633
 
        case HA_KEYTYPE_DOUBLE:
3634
 
                /* We use the maximum as per IEEE754-2008 standard, 2^53 */
3635
 
                max_value = 0x20000000000000ULL;
3636
 
                break;
3637
 
        default:
3638
 
                ut_error;
3639
 
        }
3640
 
 
3641
 
        return(max_value);
 
3671
  uint64_t  max_value = 0;
 
3672
 
 
3673
  switch(field->key_type()) {
 
3674
  /* TINY */
 
3675
  case HA_KEYTYPE_BINARY:
 
3676
    max_value = 0xFFULL;
 
3677
    break;
 
3678
  /* MEDIUM */
 
3679
  case HA_KEYTYPE_UINT24:
 
3680
    max_value = 0xFFFFFFULL;
 
3681
    break;
 
3682
  /* LONG */
 
3683
  case HA_KEYTYPE_ULONG_INT:
 
3684
    max_value = 0xFFFFFFFFULL;
 
3685
    break;
 
3686
  case HA_KEYTYPE_LONG_INT:
 
3687
    max_value = 0x7FFFFFFFULL;
 
3688
    break;
 
3689
  /* BIG */
 
3690
  case HA_KEYTYPE_ULONGLONG:
 
3691
    max_value = 0xFFFFFFFFFFFFFFFFULL;
 
3692
    break;
 
3693
  case HA_KEYTYPE_LONGLONG:
 
3694
    max_value = 0x7FFFFFFFFFFFFFFFULL;
 
3695
    break;
 
3696
  case HA_KEYTYPE_DOUBLE:
 
3697
    /* We use the maximum as per IEEE754-2008 standard, 2^53 */
 
3698
    max_value = 0x20000000000000ULL;
 
3699
    break;
 
3700
  default:
 
3701
    ut_error;
 
3702
  }
 
3703
 
 
3704
  return(max_value);
3642
3705
}
3643
3706
 
3644
3707
/********************************************************************//**
3647
3710
INSERT ... SELECT type of statements, since MySQL binlog only stores the
3648
3711
min value of the autoinc interval. Once that is fixed we can get rid of
3649
3712
the special lock handling.
3650
 
@return DB_SUCCESS if all OK else error code */
 
3713
@return DB_SUCCESS if all OK else error code */
3651
3714
UNIV_INTERN
3652
3715
ulint
3653
3716
ha_innobase::innobase_lock_autoinc(void)
3654
3717
/*====================================*/
3655
3718
{
3656
 
        ulint           error = DB_SUCCESS;
3657
 
 
3658
 
        switch (innobase_autoinc_lock_mode) {
3659
 
        case AUTOINC_NO_LOCKING:
3660
 
                /* Acquire only the AUTOINC mutex. */
3661
 
                dict_table_autoinc_lock(prebuilt->table);
3662
 
                break;
3663
 
 
3664
 
        case AUTOINC_NEW_STYLE_LOCKING:
3665
 
                /* For simple (single/multi) row INSERTs, we fallback to the
3666
 
                old style only if another transaction has already acquired
3667
 
                the AUTOINC lock on behalf of a LOAD FILE or INSERT ... SELECT
3668
 
                etc. type of statement. */
3669
 
                if (session_sql_command(user_session) == SQLCOM_INSERT
3670
 
                    || session_sql_command(user_session) == SQLCOM_REPLACE) {
3671
 
                        dict_table_t*   d_table = prebuilt->table;
3672
 
 
3673
 
                        /* Acquire the AUTOINC mutex. */
3674
 
                        dict_table_autoinc_lock(d_table);
3675
 
 
3676
 
                        /* We need to check that another transaction isn't
3677
 
                        already holding the AUTOINC lock on the table. */
3678
 
                        if (d_table->n_waiting_or_granted_auto_inc_locks) {
3679
 
                                /* Release the mutex to avoid deadlocks. */
3680
 
                                dict_table_autoinc_unlock(d_table);
3681
 
                        } else {
3682
 
                                break;
3683
 
                        }
3684
 
                }
3685
 
                /* Fall through to old style locking. */
3686
 
 
3687
 
        case AUTOINC_OLD_STYLE_LOCKING:
3688
 
                error = row_lock_table_autoinc_for_mysql(prebuilt);
3689
 
 
3690
 
                if (error == DB_SUCCESS) {
3691
 
 
3692
 
                        /* Acquire the AUTOINC mutex. */
3693
 
                        dict_table_autoinc_lock(prebuilt->table);
3694
 
                }
3695
 
                break;
3696
 
 
3697
 
        default:
3698
 
                ut_error;
3699
 
        }
3700
 
 
3701
 
        return(ulong(error));
 
3719
  ulint   error = DB_SUCCESS;
 
3720
 
 
3721
  switch (innobase_autoinc_lock_mode) {
 
3722
  case AUTOINC_NO_LOCKING:
 
3723
    /* Acquire only the AUTOINC mutex. */
 
3724
    dict_table_autoinc_lock(prebuilt->table);
 
3725
    break;
 
3726
 
 
3727
  case AUTOINC_NEW_STYLE_LOCKING:
 
3728
    /* For simple (single/multi) row INSERTs, we fallback to the
 
3729
    old style only if another transaction has already acquired
 
3730
    the AUTOINC lock on behalf of a LOAD FILE or INSERT ... SELECT
 
3731
    etc. type of statement. */
 
3732
    if (session_sql_command(user_session) == SQLCOM_INSERT
 
3733
        || session_sql_command(user_session) == SQLCOM_REPLACE) {
 
3734
      dict_table_t* d_table = prebuilt->table;
 
3735
 
 
3736
      /* Acquire the AUTOINC mutex. */
 
3737
      dict_table_autoinc_lock(d_table);
 
3738
 
 
3739
      /* We need to check that another transaction isn't
 
3740
      already holding the AUTOINC lock on the table. */
 
3741
      if (d_table->n_waiting_or_granted_auto_inc_locks) {
 
3742
        /* Release the mutex to avoid deadlocks. */
 
3743
        dict_table_autoinc_unlock(d_table);
 
3744
      } else {
 
3745
        break;
 
3746
      }
 
3747
    }
 
3748
    /* Fall through to old style locking. */
 
3749
 
 
3750
  case AUTOINC_OLD_STYLE_LOCKING:
 
3751
    error = row_lock_table_autoinc_for_mysql(prebuilt);
 
3752
 
 
3753
    if (error == DB_SUCCESS) {
 
3754
 
 
3755
      /* Acquire the AUTOINC mutex. */
 
3756
      dict_table_autoinc_lock(prebuilt->table);
 
3757
    }
 
3758
    break;
 
3759
 
 
3760
  default:
 
3761
    ut_error;
 
3762
  }
 
3763
 
 
3764
  return(ulong(error));
3702
3765
}
3703
3766
 
3704
3767
/********************************************************************//**
3705
3768
Reset the autoinc value in the table.
3706
 
@return DB_SUCCESS if all went well else error code */
 
3769
@return DB_SUCCESS if all went well else error code */
3707
3770
UNIV_INTERN
3708
3771
ulint
3709
3772
ha_innobase::innobase_reset_autoinc(
3710
3773
/*================================*/
3711
 
        uint64_t        autoinc)        /*!< in: value to store */
 
3774
  uint64_t  autoinc)  /*!< in: value to store */
3712
3775
{
3713
 
        ulint           error;
3714
 
 
3715
 
        error = innobase_lock_autoinc();
3716
 
 
3717
 
        if (error == DB_SUCCESS) {
3718
 
 
3719
 
                dict_table_autoinc_initialize(prebuilt->table, autoinc);
3720
 
 
3721
 
                dict_table_autoinc_unlock(prebuilt->table);
3722
 
        }
3723
 
 
3724
 
        return(ulong(error));
 
3776
  ulint   error;
 
3777
 
 
3778
  error = innobase_lock_autoinc();
 
3779
 
 
3780
  if (error == DB_SUCCESS) {
 
3781
 
 
3782
    dict_table_autoinc_initialize(prebuilt->table, autoinc);
 
3783
 
 
3784
    dict_table_autoinc_unlock(prebuilt->table);
 
3785
  }
 
3786
 
 
3787
  return(ulong(error));
3725
3788
}
3726
3789
 
3727
3790
/********************************************************************//**
3728
3791
Store the autoinc value in the table. The autoinc value is only set if
3729
3792
it's greater than the existing autoinc value in the table.
3730
 
@return DB_SUCCESS if all went well else error code */
 
3793
@return DB_SUCCESS if all went well else error code */
3731
3794
UNIV_INTERN
3732
3795
ulint
3733
3796
ha_innobase::innobase_set_max_autoinc(
3734
3797
/*==================================*/
3735
 
        uint64_t        auto_inc)       /*!< in: value to store */
 
3798
  uint64_t  auto_inc) /*!< in: value to store */
3736
3799
{
3737
 
        ulint           error;
3738
 
 
3739
 
        error = innobase_lock_autoinc();
3740
 
 
3741
 
        if (error == DB_SUCCESS) {
3742
 
 
3743
 
                dict_table_autoinc_update_if_greater(prebuilt->table, auto_inc);
3744
 
 
3745
 
                dict_table_autoinc_unlock(prebuilt->table);
3746
 
        }
3747
 
 
3748
 
        return(ulong(error));
 
3800
  ulint   error;
 
3801
 
 
3802
  error = innobase_lock_autoinc();
 
3803
 
 
3804
  if (error == DB_SUCCESS) {
 
3805
 
 
3806
    dict_table_autoinc_update_if_greater(prebuilt->table, auto_inc);
 
3807
 
 
3808
    dict_table_autoinc_unlock(prebuilt->table);
 
3809
  }
 
3810
 
 
3811
  return(ulong(error));
3749
3812
}
3750
3813
 
3751
3814
/********************************************************************//**
3752
3815
Stores a row in an InnoDB database, to the table specified in this
3753
3816
handle.
3754
 
@return error code */
 
3817
@return error code */
3755
3818
UNIV_INTERN
3756
3819
int
3757
3820
ha_innobase::write_row(
3758
3821
/*===================*/
3759
 
        unsigned char*  record) /*!< in: a row in MySQL format */
 
3822
  unsigned char*  record) /*!< in: a row in MySQL format */
3760
3823
{
3761
 
        ulint           error = 0;
 
3824
  ulint   error = 0;
3762
3825
        int             error_result= 0;
3763
 
        ibool           auto_inc_used= FALSE;
3764
 
        ulint           sql_command;
3765
 
        trx_t*          trx = session_to_trx(user_session);
3766
 
 
3767
 
        if (prebuilt->trx != trx) {
3768
 
          errmsg_printf(ERRMSG_LVL_ERROR, "The transaction object for the table handle is at "
3769
 
                          "%p, but for the current thread it is at %p",
3770
 
                          (const void*) prebuilt->trx, (const void*) trx);
3771
 
 
3772
 
                fputs("InnoDB: Dump of 200 bytes around prebuilt: ", stderr);
3773
 
                ut_print_buf(stderr, ((const byte*)prebuilt) - 100, 200);
3774
 
                fputs("\n"
3775
 
                        "InnoDB: Dump of 200 bytes around ha_data: ",
3776
 
                        stderr);
3777
 
                ut_print_buf(stderr, ((const byte*) trx) - 100, 200);
3778
 
                putc('\n', stderr);
3779
 
                ut_error;
3780
 
        }
3781
 
 
3782
 
        ha_statistic_increment(&system_status_var::ha_write_count);
3783
 
 
3784
 
        sql_command = session_sql_command(user_session);
3785
 
 
3786
 
        if ((sql_command == SQLCOM_ALTER_TABLE
3787
 
             || sql_command == SQLCOM_CREATE_INDEX
3788
 
             || sql_command == SQLCOM_DROP_INDEX)
3789
 
            && num_write_row >= 10000) {
3790
 
                /* ALTER TABLE is COMMITted at every 10000 copied rows.
3791
 
                The IX table lock for the original table has to be re-issued.
3792
 
                As this method will be called on a temporary table where the
3793
 
                contents of the original table is being copied to, it is
3794
 
                a bit tricky to determine the source table.  The cursor
3795
 
                position in the source table need not be adjusted after the
3796
 
                intermediate COMMIT, since writes by other transactions are
3797
 
                being blocked by a MySQL table lock TL_WRITE_ALLOW_READ. */
3798
 
 
3799
 
                dict_table_t*   src_table;
3800
 
                enum lock_mode  mode;
3801
 
 
3802
 
                num_write_row = 0;
3803
 
 
3804
 
                /* Commit the transaction.  This will release the table
3805
 
                locks, so they have to be acquired again. */
3806
 
 
3807
 
                /* Altering an InnoDB table */
3808
 
                /* Get the source table. */
3809
 
                src_table = lock_get_src_table(
3810
 
                                prebuilt->trx, prebuilt->table, &mode);
3811
 
                if (!src_table) {
 
3826
  ibool   auto_inc_used= FALSE;
 
3827
  ulint   sql_command;
 
3828
  trx_t*    trx = session_to_trx(user_session);
 
3829
 
 
3830
  if (prebuilt->trx != trx) {
 
3831
    errmsg_printf(ERRMSG_LVL_ERROR, "The transaction object for the table handle is at "
 
3832
        "%p, but for the current thread it is at %p",
 
3833
        (const void*) prebuilt->trx, (const void*) trx);
 
3834
 
 
3835
    fputs("InnoDB: Dump of 200 bytes around prebuilt: ", stderr);
 
3836
    ut_print_buf(stderr, ((const byte*)prebuilt) - 100, 200);
 
3837
    fputs("\n"
 
3838
      "InnoDB: Dump of 200 bytes around ha_data: ",
 
3839
      stderr);
 
3840
    ut_print_buf(stderr, ((const byte*) trx) - 100, 200);
 
3841
    putc('\n', stderr);
 
3842
    ut_error;
 
3843
  }
 
3844
 
 
3845
  ha_statistic_increment(&system_status_var::ha_write_count);
 
3846
 
 
3847
  sql_command = session_sql_command(user_session);
 
3848
 
 
3849
  if ((sql_command == SQLCOM_ALTER_TABLE
 
3850
       || sql_command == SQLCOM_CREATE_INDEX
 
3851
       || sql_command == SQLCOM_DROP_INDEX)
 
3852
      && num_write_row >= 10000) {
 
3853
    /* ALTER TABLE is COMMITted at every 10000 copied rows.
 
3854
    The IX table lock for the original table has to be re-issued.
 
3855
    As this method will be called on a temporary table where the
 
3856
    contents of the original table is being copied to, it is
 
3857
    a bit tricky to determine the source table.  The cursor
 
3858
    position in the source table need not be adjusted after the
 
3859
    intermediate COMMIT, since writes by other transactions are
 
3860
    being blocked by a MySQL table lock TL_WRITE_ALLOW_READ. */
 
3861
 
 
3862
    dict_table_t* src_table;
 
3863
    enum lock_mode  mode;
 
3864
 
 
3865
    num_write_row = 0;
 
3866
 
 
3867
    /* Commit the transaction.  This will release the table
 
3868
    locks, so they have to be acquired again. */
 
3869
 
 
3870
    /* Altering an InnoDB table */
 
3871
    /* Get the source table. */
 
3872
    src_table = lock_get_src_table(
 
3873
        prebuilt->trx, prebuilt->table, &mode);
 
3874
    if (!src_table) {
3812
3875
no_commit:
3813
 
                        /* Unknown situation: do not commit */
3814
 
                        /*
3815
 
                        ut_print_timestamp(stderr);
3816
 
                        fprintf(stderr,
3817
 
                                "  InnoDB: ALTER TABLE is holding lock"
3818
 
                                " on %lu tables!\n",
3819
 
                                prebuilt->trx->mysql_n_tables_locked);
3820
 
                        */
3821
 
                        ;
3822
 
                } else if (src_table == prebuilt->table) {
3823
 
                        /* Source table is not in InnoDB format:
3824
 
                        no need to re-acquire locks on it. */
3825
 
 
3826
 
                        /* Altering to InnoDB format */
3827
 
                        getTransactionalEngine()->commit(user_session, 1);
3828
 
                        /* We will need an IX lock on the destination table. */
3829
 
                        prebuilt->sql_stat_start = TRUE;
3830
 
                } else {
3831
 
                        /* Ensure that there are no other table locks than
3832
 
                        LOCK_IX and LOCK_AUTO_INC on the destination table. */
3833
 
 
3834
 
                        if (!lock_is_table_exclusive(prebuilt->table,
3835
 
                                                        prebuilt->trx)) {
3836
 
                                goto no_commit;
3837
 
                        }
3838
 
 
3839
 
                        /* Commit the transaction.  This will release the table
3840
 
                        locks, so they have to be acquired again. */
3841
 
                        getTransactionalEngine()->commit(user_session, 1);
3842
 
                        /* Re-acquire the table lock on the source table. */
3843
 
                        row_lock_table_for_mysql(prebuilt, src_table, mode);
3844
 
                        /* We will need an IX lock on the destination table. */
3845
 
                        prebuilt->sql_stat_start = TRUE;
3846
 
                }
3847
 
        }
3848
 
 
3849
 
        num_write_row++;
3850
 
 
3851
 
        /* This is the case where the table has an auto-increment column */
3852
 
        if (table->next_number_field && record == table->record[0]) {
3853
 
 
3854
 
                /* Reset the error code before calling
3855
 
                innobase_get_auto_increment(). */
3856
 
                prebuilt->autoinc_error = DB_SUCCESS;
3857
 
 
3858
 
                if ((error = update_auto_increment())) {
3859
 
 
3860
 
                        /* We don't want to mask autoinc overflow errors. */
3861
 
                        if (prebuilt->autoinc_error != DB_SUCCESS) {
3862
 
                                error = (int) prebuilt->autoinc_error;
3863
 
 
3864
 
                                goto report_error;
3865
 
                        }
3866
 
 
3867
 
                        /* MySQL errors are passed straight back. */
3868
 
                        error_result = (int) error;
3869
 
                        goto func_exit;
3870
 
                }
3871
 
 
3872
 
                auto_inc_used = TRUE;
3873
 
        }
3874
 
 
3875
 
        if (prebuilt->mysql_template == NULL
3876
 
            || prebuilt->template_type != ROW_MYSQL_WHOLE_ROW) {
3877
 
 
3878
 
                /* Build the template used in converting quickly between
3879
 
                the two database formats */
3880
 
 
3881
 
                build_template(prebuilt, NULL, table,
3882
 
                               ROW_MYSQL_WHOLE_ROW);
3883
 
        }
3884
 
 
3885
 
        innodb_srv_conc_enter_innodb(prebuilt->trx);
3886
 
 
3887
 
        error = row_insert_for_mysql((byte*) record, prebuilt);
3888
 
 
3889
 
        /* Handle duplicate key errors */
3890
 
        if (auto_inc_used) {
3891
 
                ulint           err;
3892
 
                uint64_t        auto_inc;
3893
 
                uint64_t        col_max_value;
3894
 
 
3895
 
                /* Note the number of rows processed for this statement, used
3896
 
                by get_auto_increment() to determine the number of AUTO-INC
3897
 
                values to reserve. This is only useful for a mult-value INSERT
3898
 
                and is a statement level counter.*/
3899
 
                if (trx->n_autoinc_rows > 0) {
3900
 
                        --trx->n_autoinc_rows;
3901
 
                }
3902
 
 
3903
 
                /* We need the upper limit of the col type to check for
3904
 
                whether we update the table autoinc counter or not. */
3905
 
                col_max_value = innobase_get_int_col_max_value(
3906
 
                        table->next_number_field);
3907
 
 
3908
 
                /* Get the value that MySQL attempted to store in the table.*/
3909
 
                auto_inc = table->next_number_field->val_int();
3910
 
 
3911
 
                switch (error) {
3912
 
                case DB_DUPLICATE_KEY:
3913
 
 
3914
 
                        /* A REPLACE command and LOAD DATA INFILE REPLACE
3915
 
                        handle a duplicate key error themselves, but we
3916
 
                        must update the autoinc counter if we are performing
3917
 
                        those statements. */
3918
 
 
3919
 
                        switch (sql_command) {
3920
 
                        case SQLCOM_LOAD:
3921
 
                                if ((trx->duplicates
3922
 
                                    & (TRX_DUP_IGNORE | TRX_DUP_REPLACE))) {
3923
 
 
3924
 
                                        goto set_max_autoinc;
3925
 
                                }
3926
 
                                break;
3927
 
 
3928
 
                        case SQLCOM_REPLACE:
3929
 
                        case SQLCOM_INSERT_SELECT:
3930
 
                        case SQLCOM_REPLACE_SELECT:
3931
 
                                goto set_max_autoinc;
3932
 
 
3933
 
                        default:
3934
 
                                break;
3935
 
                        }
3936
 
 
3937
 
                        break;
3938
 
 
3939
 
                case DB_SUCCESS:
3940
 
                        /* If the actual value inserted is greater than
3941
 
                        the upper limit of the interval, then we try and
3942
 
                        update the table upper limit. Note: last_value
3943
 
                        will be 0 if get_auto_increment() was not called.*/
3944
 
 
3945
 
                        if (auto_inc <= col_max_value
3946
 
                            && auto_inc >= prebuilt->autoinc_last_value) {
 
3876
      /* Unknown situation: do not commit */
 
3877
      /*
 
3878
      ut_print_timestamp(stderr);
 
3879
      fprintf(stderr,
 
3880
        "  InnoDB: ALTER TABLE is holding lock"
 
3881
        " on %lu tables!\n",
 
3882
        prebuilt->trx->mysql_n_tables_locked);
 
3883
      */
 
3884
      ;
 
3885
    } else if (src_table == prebuilt->table) {
 
3886
      /* Source table is not in InnoDB format:
 
3887
      no need to re-acquire locks on it. */
 
3888
 
 
3889
      /* Altering to InnoDB format */
 
3890
      getTransactionalEngine()->commit(user_session, 1);
 
3891
      /* We will need an IX lock on the destination table. */
 
3892
      prebuilt->sql_stat_start = TRUE;
 
3893
    } else {
 
3894
      /* Ensure that there are no other table locks than
 
3895
      LOCK_IX and LOCK_AUTO_INC on the destination table. */
 
3896
 
 
3897
      if (!lock_is_table_exclusive(prebuilt->table,
 
3898
              prebuilt->trx)) {
 
3899
        goto no_commit;
 
3900
      }
 
3901
 
 
3902
      /* Commit the transaction.  This will release the table
 
3903
      locks, so they have to be acquired again. */
 
3904
      getTransactionalEngine()->commit(user_session, 1);
 
3905
      /* Re-acquire the table lock on the source table. */
 
3906
      row_lock_table_for_mysql(prebuilt, src_table, mode);
 
3907
      /* We will need an IX lock on the destination table. */
 
3908
      prebuilt->sql_stat_start = TRUE;
 
3909
    }
 
3910
  }
 
3911
 
 
3912
  num_write_row++;
 
3913
 
 
3914
  /* This is the case where the table has an auto-increment column */
 
3915
  if (table->next_number_field && record == table->record[0]) {
 
3916
 
 
3917
    /* Reset the error code before calling
 
3918
    innobase_get_auto_increment(). */
 
3919
    prebuilt->autoinc_error = DB_SUCCESS;
 
3920
 
 
3921
    if ((error = update_auto_increment())) {
 
3922
 
 
3923
      /* We don't want to mask autoinc overflow errors. */
 
3924
      if (prebuilt->autoinc_error != DB_SUCCESS) {
 
3925
        error = (int) prebuilt->autoinc_error;
 
3926
 
 
3927
        goto report_error;
 
3928
      }
 
3929
 
 
3930
      /* MySQL errors are passed straight back. */
 
3931
      error_result = (int) error;
 
3932
      goto func_exit;
 
3933
    }
 
3934
 
 
3935
    auto_inc_used = TRUE;
 
3936
  }
 
3937
 
 
3938
  if (prebuilt->mysql_template == NULL
 
3939
      || prebuilt->template_type != ROW_MYSQL_WHOLE_ROW) {
 
3940
 
 
3941
    /* Build the template used in converting quickly between
 
3942
    the two database formats */
 
3943
 
 
3944
    build_template(prebuilt, NULL, table,
 
3945
             ROW_MYSQL_WHOLE_ROW);
 
3946
  }
 
3947
 
 
3948
  innodb_srv_conc_enter_innodb(prebuilt->trx);
 
3949
 
 
3950
  error = row_insert_for_mysql((byte*) record, prebuilt);
 
3951
 
 
3952
  /* Handle duplicate key errors */
 
3953
  if (auto_inc_used) {
 
3954
    ulint   err;
 
3955
    uint64_t  auto_inc;
 
3956
    uint64_t  col_max_value;
 
3957
 
 
3958
    /* Note the number of rows processed for this statement, used
 
3959
    by get_auto_increment() to determine the number of AUTO-INC
 
3960
    values to reserve. This is only useful for a mult-value INSERT
 
3961
    and is a statement level counter.*/
 
3962
    if (trx->n_autoinc_rows > 0) {
 
3963
      --trx->n_autoinc_rows;
 
3964
    }
 
3965
 
 
3966
    /* We need the upper limit of the col type to check for
 
3967
    whether we update the table autoinc counter or not. */
 
3968
    col_max_value = innobase_get_int_col_max_value(
 
3969
      table->next_number_field);
 
3970
 
 
3971
    /* Get the value that MySQL attempted to store in the table.*/
 
3972
    auto_inc = table->next_number_field->val_int();
 
3973
 
 
3974
    switch (error) {
 
3975
    case DB_DUPLICATE_KEY:
 
3976
 
 
3977
      /* A REPLACE command and LOAD DATA INFILE REPLACE
 
3978
      handle a duplicate key error themselves, but we
 
3979
      must update the autoinc counter if we are performing
 
3980
      those statements. */
 
3981
 
 
3982
      switch (sql_command) {
 
3983
      case SQLCOM_LOAD:
 
3984
        if ((trx->duplicates
 
3985
            & (TRX_DUP_IGNORE | TRX_DUP_REPLACE))) {
 
3986
 
 
3987
          goto set_max_autoinc;
 
3988
        }
 
3989
        break;
 
3990
 
 
3991
      case SQLCOM_REPLACE:
 
3992
      case SQLCOM_INSERT_SELECT:
 
3993
      case SQLCOM_REPLACE_SELECT:
 
3994
        goto set_max_autoinc;
 
3995
 
 
3996
      default:
 
3997
        break;
 
3998
      }
 
3999
 
 
4000
      break;
 
4001
 
 
4002
    case DB_SUCCESS:
 
4003
      /* If the actual value inserted is greater than
 
4004
      the upper limit of the interval, then we try and
 
4005
      update the table upper limit. Note: last_value
 
4006
      will be 0 if get_auto_increment() was not called.*/
 
4007
 
 
4008
      if (auto_inc <= col_max_value
 
4009
          && auto_inc >= prebuilt->autoinc_last_value) {
3947
4010
set_max_autoinc:
3948
 
                                ut_a(prebuilt->autoinc_increment > 0);
3949
 
 
3950
 
                                uint64_t        need;
3951
 
                                uint64_t        offset;
3952
 
 
3953
 
                                offset = prebuilt->autoinc_offset;
3954
 
                                need = prebuilt->autoinc_increment;
3955
 
 
3956
 
                                auto_inc = innobase_next_autoinc(
3957
 
                                        auto_inc, need, offset, col_max_value);
3958
 
 
3959
 
                                err = innobase_set_max_autoinc(auto_inc);
3960
 
 
3961
 
                                if (err != DB_SUCCESS) {
3962
 
                                        error = err;
3963
 
                                }
3964
 
                        }
3965
 
                        break;
3966
 
                }
3967
 
        }
3968
 
 
3969
 
        innodb_srv_conc_exit_innodb(prebuilt->trx);
 
4011
        ut_a(prebuilt->autoinc_increment > 0);
 
4012
 
 
4013
        uint64_t  need;
 
4014
        uint64_t  offset;
 
4015
 
 
4016
        offset = prebuilt->autoinc_offset;
 
4017
        need = prebuilt->autoinc_increment;
 
4018
 
 
4019
        auto_inc = innobase_next_autoinc(
 
4020
          auto_inc, need, offset, col_max_value);
 
4021
 
 
4022
        err = innobase_set_max_autoinc(auto_inc);
 
4023
 
 
4024
        if (err != DB_SUCCESS) {
 
4025
          error = err;
 
4026
        }
 
4027
      }
 
4028
      break;
 
4029
    }
 
4030
  }
 
4031
 
 
4032
  innodb_srv_conc_exit_innodb(prebuilt->trx);
3970
4033
 
3971
4034
report_error:
3972
 
        error_result = convert_error_code_to_mysql((int) error,
3973
 
                                                   prebuilt->table->flags,
3974
 
                                                   user_session);
 
4035
  error_result = convert_error_code_to_mysql((int) error,
 
4036
               prebuilt->table->flags,
 
4037
               user_session);
3975
4038
 
3976
4039
func_exit:
3977
 
        innobase_active_small();
 
4040
  innobase_active_small();
3978
4041
 
3979
 
        return(error_result);
 
4042
  return(error_result);
3980
4043
}
3981
4044
 
3982
4045
/**********************************************************************//**
3983
4046
Checks which fields have changed in a row and stores information
3984
4047
of them to an update vector.
3985
 
@return error number or 0 */
 
4048
@return error number or 0 */
3986
4049
static
3987
4050
int
3988
4051
calc_row_difference(
3989
4052
/*================*/
3990
 
        upd_t*          uvect,          /*!< in/out: update vector */
3991
 
        unsigned char*          old_row,        /*!< in: old row in MySQL format */
3992
 
        unsigned char*          new_row,        /*!< in: new row in MySQL format */
3993
 
        Table* table,           /*!< in: table in MySQL data
3994
 
                                        dictionary */
3995
 
        unsigned char*  upd_buff,       /*!< in: buffer to use */
3996
 
        ulint           buff_len,       /*!< in: buffer length */
3997
 
        row_prebuilt_t* prebuilt,       /*!< in: InnoDB prebuilt struct */
3998
 
        Session*        )               /*!< in: user thread */
 
4053
  upd_t*    uvect,    /*!< in/out: update vector */
 
4054
  unsigned char*    old_row,  /*!< in: old row in MySQL format */
 
4055
  unsigned char*    new_row,  /*!< in: new row in MySQL format */
 
4056
  Table* table,   /*!< in: table in MySQL data
 
4057
          dictionary */
 
4058
  unsigned char*  upd_buff, /*!< in: buffer to use */
 
4059
  ulint   buff_len, /*!< in: buffer length */
 
4060
  row_prebuilt_t* prebuilt, /*!< in: InnoDB prebuilt struct */
 
4061
  Session*  )   /*!< in: user thread */
3999
4062
{
4000
 
        unsigned char*          original_upd_buff = upd_buff;
4001
 
        Field*          field;
4002
 
        enum_field_types field_mysql_type;
4003
 
        uint            n_fields;
4004
 
        ulint           o_len;
4005
 
        ulint           n_len;
4006
 
        ulint           col_pack_len;
4007
 
        const byte*     new_mysql_row_col;
4008
 
        const byte*     o_ptr;
4009
 
        const byte*     n_ptr;
4010
 
        byte*           buf;
4011
 
        upd_field_t*    ufield;
4012
 
        ulint           col_type;
4013
 
        ulint           n_changed = 0;
4014
 
        dfield_t        dfield;
4015
 
        dict_index_t*   clust_index;
4016
 
        uint            i= 0;
4017
 
 
4018
 
        n_fields = table->s->fields;
4019
 
        clust_index = dict_table_get_first_index(prebuilt->table);
4020
 
 
4021
 
        /* We use upd_buff to convert changed fields */
4022
 
        buf = (byte*) upd_buff;
4023
 
 
4024
 
        for (i = 0; i < n_fields; i++) {
4025
 
                field = table->field[i];
4026
 
 
4027
 
                o_ptr = (const byte*) old_row + get_field_offset(table, field);
4028
 
                n_ptr = (const byte*) new_row + get_field_offset(table, field);
4029
 
 
4030
 
                /* Use new_mysql_row_col and col_pack_len save the values */
4031
 
 
4032
 
                new_mysql_row_col = n_ptr;
4033
 
                col_pack_len = field->pack_length();
4034
 
 
4035
 
                o_len = col_pack_len;
4036
 
                n_len = col_pack_len;
4037
 
 
4038
 
                /* We use o_ptr and n_ptr to dig up the actual data for
4039
 
                comparison. */
4040
 
 
4041
 
                field_mysql_type = field->type();
4042
 
 
4043
 
                col_type = prebuilt->table->cols[i].mtype;
4044
 
 
4045
 
                switch (col_type) {
4046
 
 
4047
 
                case DATA_BLOB:
4048
 
                        o_ptr = row_mysql_read_blob_ref(&o_len, o_ptr, o_len);
4049
 
                        n_ptr = row_mysql_read_blob_ref(&n_len, n_ptr, n_len);
4050
 
 
4051
 
                        break;
4052
 
 
4053
 
                case DATA_VARCHAR:
4054
 
                case DATA_BINARY:
4055
 
                case DATA_VARMYSQL:
4056
 
                        if (field_mysql_type == DRIZZLE_TYPE_VARCHAR) {
4057
 
                                /* This is a >= 5.0.3 type true VARCHAR where
4058
 
                                the real payload data length is stored in
4059
 
                                1 or 2 bytes */
4060
 
 
4061
 
                                o_ptr = row_mysql_read_true_varchar(
4062
 
                                        &o_len, o_ptr,
4063
 
                                        (ulint)
4064
 
                                        (((Field_varstring*)field)->length_bytes));
4065
 
 
4066
 
                                n_ptr = row_mysql_read_true_varchar(
4067
 
                                        &n_len, n_ptr,
4068
 
                                        (ulint)
4069
 
                                        (((Field_varstring*)field)->length_bytes));
4070
 
                        }
4071
 
 
4072
 
                        break;
4073
 
                default:
4074
 
                        ;
4075
 
                }
4076
 
 
4077
 
                if (field->null_ptr) {
4078
 
                        if (field_in_record_is_null(table, field,
4079
 
                                                        (char*) old_row)) {
4080
 
                                o_len = UNIV_SQL_NULL;
4081
 
                        }
4082
 
 
4083
 
                        if (field_in_record_is_null(table, field,
4084
 
                                                        (char*) new_row)) {
4085
 
                                n_len = UNIV_SQL_NULL;
4086
 
                        }
4087
 
                }
4088
 
 
4089
 
                if (o_len != n_len || (o_len != UNIV_SQL_NULL &&
4090
 
                                        0 != memcmp(o_ptr, n_ptr, o_len))) {
4091
 
                        /* The field has changed */
4092
 
 
4093
 
                        ufield = uvect->fields + n_changed;
4094
 
 
4095
 
                        /* Let us use a dummy dfield to make the conversion
4096
 
                        from the MySQL column format to the InnoDB format */
4097
 
 
4098
 
                        dict_col_copy_type(prebuilt->table->cols + i,
4099
 
                                                     &dfield.type);
4100
 
 
4101
 
                        if (n_len != UNIV_SQL_NULL) {
4102
 
                                buf = row_mysql_store_col_in_innobase_format(
4103
 
                                        &dfield,
4104
 
                                        (byte*)buf,
4105
 
                                        TRUE,
4106
 
                                        new_mysql_row_col,
4107
 
                                        col_pack_len,
4108
 
                                        dict_table_is_comp(prebuilt->table));
4109
 
                                dfield_copy_data(&ufield->new_val, &dfield);
4110
 
                        } else {
4111
 
                                dfield_set_null(&ufield->new_val);
4112
 
                        }
4113
 
 
4114
 
                        ufield->exp = NULL;
4115
 
                        ufield->orig_len = 0;
4116
 
                        ufield->field_no = dict_col_get_clust_pos(
4117
 
                                &prebuilt->table->cols[i], clust_index);
4118
 
                        n_changed++;
4119
 
                }
4120
 
        }
4121
 
 
4122
 
        uvect->n_fields = n_changed;
4123
 
        uvect->info_bits = 0;
4124
 
 
4125
 
        ut_a(buf <= (byte*)original_upd_buff + buff_len);
4126
 
 
4127
 
        return(0);
 
4063
  unsigned char*    original_upd_buff = upd_buff;
 
4064
  Field*    field;
 
4065
  enum_field_types field_mysql_type;
 
4066
  uint    n_fields;
 
4067
  ulint   o_len;
 
4068
  ulint   n_len;
 
4069
  ulint   col_pack_len;
 
4070
  const byte* new_mysql_row_col;
 
4071
  const byte* o_ptr;
 
4072
  const byte* n_ptr;
 
4073
  byte*   buf;
 
4074
  upd_field_t*  ufield;
 
4075
  ulint   col_type;
 
4076
  ulint   n_changed = 0;
 
4077
  dfield_t  dfield;
 
4078
  dict_index_t* clust_index;
 
4079
  uint    i= 0;
 
4080
 
 
4081
  n_fields = table->s->fields;
 
4082
  clust_index = dict_table_get_first_index(prebuilt->table);
 
4083
 
 
4084
  /* We use upd_buff to convert changed fields */
 
4085
  buf = (byte*) upd_buff;
 
4086
 
 
4087
  for (i = 0; i < n_fields; i++) {
 
4088
    field = table->field[i];
 
4089
 
 
4090
    o_ptr = (const byte*) old_row + get_field_offset(table, field);
 
4091
    n_ptr = (const byte*) new_row + get_field_offset(table, field);
 
4092
 
 
4093
    /* Use new_mysql_row_col and col_pack_len save the values */
 
4094
 
 
4095
    new_mysql_row_col = n_ptr;
 
4096
    col_pack_len = field->pack_length();
 
4097
 
 
4098
    o_len = col_pack_len;
 
4099
    n_len = col_pack_len;
 
4100
 
 
4101
    /* We use o_ptr and n_ptr to dig up the actual data for
 
4102
    comparison. */
 
4103
 
 
4104
    field_mysql_type = field->type();
 
4105
 
 
4106
    col_type = prebuilt->table->cols[i].mtype;
 
4107
 
 
4108
    switch (col_type) {
 
4109
 
 
4110
    case DATA_BLOB:
 
4111
      o_ptr = row_mysql_read_blob_ref(&o_len, o_ptr, o_len);
 
4112
      n_ptr = row_mysql_read_blob_ref(&n_len, n_ptr, n_len);
 
4113
 
 
4114
      break;
 
4115
 
 
4116
    case DATA_VARCHAR:
 
4117
    case DATA_BINARY:
 
4118
    case DATA_VARMYSQL:
 
4119
      if (field_mysql_type == DRIZZLE_TYPE_VARCHAR) {
 
4120
        /* This is a >= 5.0.3 type true VARCHAR where
 
4121
        the real payload data length is stored in
 
4122
        1 or 2 bytes */
 
4123
 
 
4124
        o_ptr = row_mysql_read_true_varchar(
 
4125
          &o_len, o_ptr,
 
4126
          (ulint)
 
4127
          (((Field_varstring*)field)->length_bytes));
 
4128
 
 
4129
        n_ptr = row_mysql_read_true_varchar(
 
4130
          &n_len, n_ptr,
 
4131
          (ulint)
 
4132
          (((Field_varstring*)field)->length_bytes));
 
4133
      }
 
4134
 
 
4135
      break;
 
4136
    default:
 
4137
      ;
 
4138
    }
 
4139
 
 
4140
    if (field->null_ptr) {
 
4141
      if (field_in_record_is_null(table, field,
 
4142
              (char*) old_row)) {
 
4143
        o_len = UNIV_SQL_NULL;
 
4144
      }
 
4145
 
 
4146
      if (field_in_record_is_null(table, field,
 
4147
              (char*) new_row)) {
 
4148
        n_len = UNIV_SQL_NULL;
 
4149
      }
 
4150
    }
 
4151
 
 
4152
    if (o_len != n_len || (o_len != UNIV_SQL_NULL &&
 
4153
          0 != memcmp(o_ptr, n_ptr, o_len))) {
 
4154
      /* The field has changed */
 
4155
 
 
4156
      ufield = uvect->fields + n_changed;
 
4157
 
 
4158
      /* Let us use a dummy dfield to make the conversion
 
4159
      from the MySQL column format to the InnoDB format */
 
4160
 
 
4161
      dict_col_copy_type(prebuilt->table->cols + i,
 
4162
                 &dfield.type);
 
4163
 
 
4164
      if (n_len != UNIV_SQL_NULL) {
 
4165
        buf = row_mysql_store_col_in_innobase_format(
 
4166
          &dfield,
 
4167
          (byte*)buf,
 
4168
          TRUE,
 
4169
          new_mysql_row_col,
 
4170
          col_pack_len,
 
4171
          dict_table_is_comp(prebuilt->table));
 
4172
        dfield_copy_data(&ufield->new_val, &dfield);
 
4173
      } else {
 
4174
        dfield_set_null(&ufield->new_val);
 
4175
      }
 
4176
 
 
4177
      ufield->exp = NULL;
 
4178
      ufield->orig_len = 0;
 
4179
      ufield->field_no = dict_col_get_clust_pos(
 
4180
        &prebuilt->table->cols[i], clust_index);
 
4181
      n_changed++;
 
4182
    }
 
4183
  }
 
4184
 
 
4185
  uvect->n_fields = n_changed;
 
4186
  uvect->info_bits = 0;
 
4187
 
 
4188
  ut_a(buf <= (byte*)original_upd_buff + buff_len);
 
4189
 
 
4190
  return(0);
4128
4191
}
4129
4192
 
4130
4193
/**********************************************************************//**
4134
4197
TODO: currently InnoDB does not prevent the 'Halloween problem':
4135
4198
in a searched update a single row can get updated several times
4136
4199
if its index columns are updated!
4137
 
@return error number or 0 */
 
4200
@return error number or 0 */
4138
4201
UNIV_INTERN
4139
4202
int
4140
4203
ha_innobase::update_row(
4141
4204
/*====================*/
4142
 
        const unsigned char*    old_row,/*!< in: old row in MySQL format */
4143
 
        unsigned char*          new_row)/*!< in: new row in MySQL format */
 
4205
  const unsigned char*  old_row,/*!< in: old row in MySQL format */
 
4206
  unsigned char*    new_row)/*!< in: new row in MySQL format */
4144
4207
{
4145
 
        upd_t*          uvect;
4146
 
        int             error = 0;
4147
 
        trx_t*          trx = session_to_trx(user_session);
4148
 
 
4149
 
        ut_a(prebuilt->trx == trx);
4150
 
 
4151
 
        ha_statistic_increment(&system_status_var::ha_update_count);
4152
 
 
4153
 
        if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
4154
 
                table->timestamp_field->set_time();
4155
 
 
4156
 
        if (prebuilt->upd_node) {
4157
 
                uvect = prebuilt->upd_node->update;
4158
 
        } else {
4159
 
                uvect = row_get_prebuilt_update_vector(prebuilt);
4160
 
        }
4161
 
 
4162
 
        /* Build an update vector from the modified fields in the rows
4163
 
        (uses upd_buff of the handle) */
4164
 
 
4165
 
        calc_row_difference(uvect, (unsigned char*) old_row, new_row, table,
4166
 
                        upd_buff, (ulint)upd_and_key_val_buff_len,
4167
 
                        prebuilt, user_session);
4168
 
 
4169
 
        /* This is not a delete */
4170
 
        prebuilt->upd_node->is_delete = FALSE;
4171
 
 
4172
 
        ut_a(prebuilt->template_type == ROW_MYSQL_WHOLE_ROW);
4173
 
 
4174
 
        innodb_srv_conc_enter_innodb(trx);
4175
 
 
4176
 
        error = row_update_for_mysql((byte*) old_row, prebuilt);
4177
 
 
4178
 
        /* We need to do some special AUTOINC handling for the following case:
4179
 
 
4180
 
        INSERT INTO t (c1,c2) VALUES(x,y) ON DUPLICATE KEY UPDATE ...
4181
 
 
4182
 
        We need to use the AUTOINC counter that was actually used by
4183
 
        MySQL in the UPDATE statement, which can be different from the
4184
 
        value used in the INSERT statement.*/
4185
 
 
4186
 
        if (error == DB_SUCCESS
4187
 
            && table->next_number_field
4188
 
            && new_row == table->record[0]
4189
 
            && session_sql_command(user_session) == SQLCOM_INSERT
4190
 
            && (trx->duplicates & (TRX_DUP_IGNORE | TRX_DUP_REPLACE))
4191
 
                == TRX_DUP_IGNORE)  {
4192
 
 
4193
 
                uint64_t        auto_inc;
4194
 
                uint64_t        col_max_value;
4195
 
 
4196
 
                auto_inc = table->next_number_field->val_int();
4197
 
 
4198
 
                /* We need the upper limit of the col type to check for
4199
 
                whether we update the table autoinc counter or not. */
4200
 
                col_max_value = innobase_get_int_col_max_value(
4201
 
                        table->next_number_field);
4202
 
 
4203
 
                if (auto_inc <= col_max_value && auto_inc != 0) {
4204
 
 
4205
 
                        uint64_t        need;
4206
 
                        uint64_t        offset;
4207
 
 
4208
 
                        offset = prebuilt->autoinc_offset;
4209
 
                        need = prebuilt->autoinc_increment;
4210
 
 
4211
 
                        auto_inc = innobase_next_autoinc(
4212
 
                                auto_inc, need, offset, col_max_value);
4213
 
 
4214
 
                        error = innobase_set_max_autoinc(auto_inc);
4215
 
                }
4216
 
        }
4217
 
 
4218
 
        innodb_srv_conc_exit_innodb(trx);
4219
 
 
4220
 
        error = convert_error_code_to_mysql(error,
4221
 
                                            prebuilt->table->flags,
 
4208
  upd_t*    uvect;
 
4209
  int   error = 0;
 
4210
  trx_t*    trx = session_to_trx(user_session);
 
4211
 
 
4212
  ut_a(prebuilt->trx == trx);
 
4213
 
 
4214
  ha_statistic_increment(&system_status_var::ha_update_count);
 
4215
 
 
4216
  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
 
4217
    table->timestamp_field->set_time();
 
4218
 
 
4219
  if (prebuilt->upd_node) {
 
4220
    uvect = prebuilt->upd_node->update;
 
4221
  } else {
 
4222
    uvect = row_get_prebuilt_update_vector(prebuilt);
 
4223
  }
 
4224
 
 
4225
  /* Build an update vector from the modified fields in the rows
 
4226
  (uses upd_buff of the handle) */
 
4227
 
 
4228
  calc_row_difference(uvect, (unsigned char*) old_row, new_row, table,
 
4229
      upd_buff, (ulint)upd_and_key_val_buff_len,
 
4230
      prebuilt, user_session);
 
4231
 
 
4232
  /* This is not a delete */
 
4233
  prebuilt->upd_node->is_delete = FALSE;
 
4234
 
 
4235
  ut_a(prebuilt->template_type == ROW_MYSQL_WHOLE_ROW);
 
4236
 
 
4237
  innodb_srv_conc_enter_innodb(trx);
 
4238
 
 
4239
  error = row_update_for_mysql((byte*) old_row, prebuilt);
 
4240
 
 
4241
  /* We need to do some special AUTOINC handling for the following case:
 
4242
 
 
4243
  INSERT INTO t (c1,c2) VALUES(x,y) ON DUPLICATE KEY UPDATE ...
 
4244
 
 
4245
  We need to use the AUTOINC counter that was actually used by
 
4246
  MySQL in the UPDATE statement, which can be different from the
 
4247
  value used in the INSERT statement.*/
 
4248
 
 
4249
  if (error == DB_SUCCESS
 
4250
      && table->next_number_field
 
4251
      && new_row == table->record[0]
 
4252
      && session_sql_command(user_session) == SQLCOM_INSERT
 
4253
      && (trx->duplicates & (TRX_DUP_IGNORE | TRX_DUP_REPLACE))
 
4254
    == TRX_DUP_IGNORE)  {
 
4255
 
 
4256
    uint64_t  auto_inc;
 
4257
    uint64_t  col_max_value;
 
4258
 
 
4259
    auto_inc = table->next_number_field->val_int();
 
4260
 
 
4261
    /* We need the upper limit of the col type to check for
 
4262
    whether we update the table autoinc counter or not. */
 
4263
    col_max_value = innobase_get_int_col_max_value(
 
4264
      table->next_number_field);
 
4265
 
 
4266
    if (auto_inc <= col_max_value && auto_inc != 0) {
 
4267
 
 
4268
      uint64_t  need;
 
4269
      uint64_t  offset;
 
4270
 
 
4271
      offset = prebuilt->autoinc_offset;
 
4272
      need = prebuilt->autoinc_increment;
 
4273
 
 
4274
      auto_inc = innobase_next_autoinc(
 
4275
        auto_inc, need, offset, col_max_value);
 
4276
 
 
4277
      error = innobase_set_max_autoinc(auto_inc);
 
4278
    }
 
4279
  }
 
4280
 
 
4281
  innodb_srv_conc_exit_innodb(trx);
 
4282
 
 
4283
  error = convert_error_code_to_mysql(error,
 
4284
              prebuilt->table->flags,
4222
4285
                                            user_session);
4223
4286
 
4224
 
        if (error == 0 /* success */
4225
 
            && uvect->n_fields == 0 /* no columns were updated */) {
4226
 
 
4227
 
                /* This is the same as success, but instructs
4228
 
                MySQL that the row is not really updated and it
4229
 
                should not increase the count of updated rows.
4230
 
                This is fix for http://bugs.mysql.com/29157 */
4231
 
                error = HA_ERR_RECORD_IS_THE_SAME;
4232
 
        }
4233
 
 
4234
 
        /* Tell InnoDB server that there might be work for
4235
 
        utility threads: */
4236
 
 
4237
 
        innobase_active_small();
4238
 
 
4239
 
        return(error);
 
4287
  if (error == 0 /* success */
 
4288
      && uvect->n_fields == 0 /* no columns were updated */) {
 
4289
 
 
4290
    /* This is the same as success, but instructs
 
4291
    MySQL that the row is not really updated and it
 
4292
    should not increase the count of updated rows.
 
4293
    This is fix for http://bugs.mysql.com/29157 */
 
4294
    error = HA_ERR_RECORD_IS_THE_SAME;
 
4295
  }
 
4296
 
 
4297
  /* Tell InnoDB server that there might be work for
 
4298
  utility threads: */
 
4299
 
 
4300
  innobase_active_small();
 
4301
 
 
4302
  return(error);
4240
4303
}
4241
4304
 
4242
4305
/**********************************************************************//**
4243
4306
Deletes a row given as the parameter.
4244
 
@return error number or 0 */
 
4307
@return error number or 0 */
4245
4308
UNIV_INTERN
4246
4309
int
4247
4310
ha_innobase::delete_row(
4248
4311
/*====================*/
4249
 
        const unsigned char*    record) /*!< in: a row in MySQL format */
 
4312
  const unsigned char*  record) /*!< in: a row in MySQL format */
4250
4313
{
4251
 
        int             error = 0;
4252
 
        trx_t*          trx = session_to_trx(user_session);
4253
 
 
4254
 
        ut_a(prebuilt->trx == trx);
4255
 
 
4256
 
        ha_statistic_increment(&system_status_var::ha_delete_count);
4257
 
 
4258
 
        if (!prebuilt->upd_node) {
4259
 
                row_get_prebuilt_update_vector(prebuilt);
4260
 
        }
4261
 
 
4262
 
        /* This is a delete */
4263
 
 
4264
 
        prebuilt->upd_node->is_delete = TRUE;
4265
 
 
4266
 
        innodb_srv_conc_enter_innodb(trx);
4267
 
 
4268
 
        error = row_update_for_mysql((byte*) record, prebuilt);
4269
 
 
4270
 
        innodb_srv_conc_exit_innodb(trx);
4271
 
 
4272
 
        error = convert_error_code_to_mysql(
4273
 
                error, prebuilt->table->flags, user_session);
4274
 
 
4275
 
        /* Tell the InnoDB server that there might be work for
4276
 
        utility threads: */
4277
 
 
4278
 
        innobase_active_small();
4279
 
 
4280
 
        return(error);
 
4314
  int   error = 0;
 
4315
  trx_t*    trx = session_to_trx(user_session);
 
4316
 
 
4317
  ut_a(prebuilt->trx == trx);
 
4318
 
 
4319
  ha_statistic_increment(&system_status_var::ha_delete_count);
 
4320
 
 
4321
  if (!prebuilt->upd_node) {
 
4322
    row_get_prebuilt_update_vector(prebuilt);
 
4323
  }
 
4324
 
 
4325
  /* This is a delete */
 
4326
 
 
4327
  prebuilt->upd_node->is_delete = TRUE;
 
4328
 
 
4329
  innodb_srv_conc_enter_innodb(trx);
 
4330
 
 
4331
  error = row_update_for_mysql((byte*) record, prebuilt);
 
4332
 
 
4333
  innodb_srv_conc_exit_innodb(trx);
 
4334
 
 
4335
  error = convert_error_code_to_mysql(
 
4336
    error, prebuilt->table->flags, user_session);
 
4337
 
 
4338
  /* Tell the InnoDB server that there might be work for
 
4339
  utility threads: */
 
4340
 
 
4341
  innobase_active_small();
 
4342
 
 
4343
  return(error);
4281
4344
}
4282
4345
 
4283
4346
/**********************************************************************//**
4289
4352
ha_innobase::unlock_row(void)
4290
4353
/*=========================*/
4291
4354
{
4292
 
        /* Consistent read does not take any locks, thus there is
4293
 
        nothing to unlock. */
4294
 
 
4295
 
        if (prebuilt->select_lock_type == LOCK_NONE) {
4296
 
          return;
4297
 
        }
4298
 
 
4299
 
        switch (prebuilt->row_read_type) {
4300
 
        case ROW_READ_WITH_LOCKS:
4301
 
                if (!srv_locks_unsafe_for_binlog
4302
 
                    && prebuilt->trx->isolation_level
4303
 
                    != TRX_ISO_READ_COMMITTED) {
4304
 
                        break;
4305
 
                }
4306
 
                /* fall through */
4307
 
        case ROW_READ_TRY_SEMI_CONSISTENT:
4308
 
                row_unlock_for_mysql(prebuilt, FALSE);
4309
 
                break;
4310
 
        case ROW_READ_DID_SEMI_CONSISTENT:
4311
 
                prebuilt->row_read_type = ROW_READ_TRY_SEMI_CONSISTENT;
4312
 
                break;
4313
 
        }
4314
 
 
4315
 
        return;
 
4355
  /* Consistent read does not take any locks, thus there is
 
4356
  nothing to unlock. */
 
4357
 
 
4358
  if (prebuilt->select_lock_type == LOCK_NONE) {
 
4359
    return;
 
4360
  }
 
4361
 
 
4362
  switch (prebuilt->row_read_type) {
 
4363
  case ROW_READ_WITH_LOCKS:
 
4364
    if (!srv_locks_unsafe_for_binlog
 
4365
        && prebuilt->trx->isolation_level
 
4366
        != TRX_ISO_READ_COMMITTED) {
 
4367
      break;
 
4368
    }
 
4369
    /* fall through */
 
4370
  case ROW_READ_TRY_SEMI_CONSISTENT:
 
4371
    row_unlock_for_mysql(prebuilt, FALSE);
 
4372
    break;
 
4373
  case ROW_READ_DID_SEMI_CONSISTENT:
 
4374
    prebuilt->row_read_type = ROW_READ_TRY_SEMI_CONSISTENT;
 
4375
    break;
 
4376
  }
 
4377
 
 
4378
  return;
4316
4379
}
4317
4380
 
4318
4381
/* See Cursor.h and row0mysql.h for docs on this function. */
4321
4384
ha_innobase::was_semi_consistent_read(void)
4322
4385
/*=======================================*/
4323
4386
{
4324
 
        return(prebuilt->row_read_type == ROW_READ_DID_SEMI_CONSISTENT);
 
4387
  return(prebuilt->row_read_type == ROW_READ_DID_SEMI_CONSISTENT);
4325
4388
}
4326
4389
 
4327
4390
/* See Cursor.h and row0mysql.h for docs on this function. */
4330
4393
ha_innobase::try_semi_consistent_read(bool yes)
4331
4394
/*===========================================*/
4332
4395
{
4333
 
        ut_a(prebuilt->trx == session_to_trx(ha_session()));
4334
 
 
4335
 
        /* Row read type is set to semi consistent read if this was
4336
 
        requested by the MySQL and either innodb_locks_unsafe_for_binlog
4337
 
        option is used or this session is using READ COMMITTED isolation
4338
 
        level. */
4339
 
 
4340
 
        if (yes
4341
 
            && (srv_locks_unsafe_for_binlog
4342
 
                || prebuilt->trx->isolation_level == TRX_ISO_READ_COMMITTED)) {
4343
 
                prebuilt->row_read_type = ROW_READ_TRY_SEMI_CONSISTENT;
4344
 
        } else {
4345
 
                prebuilt->row_read_type = ROW_READ_WITH_LOCKS;
4346
 
        }
 
4396
  ut_a(prebuilt->trx == session_to_trx(ha_session()));
 
4397
 
 
4398
  /* Row read type is set to semi consistent read if this was
 
4399
  requested by the MySQL and either innodb_locks_unsafe_for_binlog
 
4400
  option is used or this session is using READ COMMITTED isolation
 
4401
  level. */
 
4402
 
 
4403
  if (yes
 
4404
      && (srv_locks_unsafe_for_binlog
 
4405
    || prebuilt->trx->isolation_level == TRX_ISO_READ_COMMITTED)) {
 
4406
    prebuilt->row_read_type = ROW_READ_TRY_SEMI_CONSISTENT;
 
4407
  } else {
 
4408
    prebuilt->row_read_type = ROW_READ_WITH_LOCKS;
 
4409
  }
4347
4410
}
4348
4411
 
4349
4412
/******************************************************************//**
4350
4413
Initializes a handle to use an index.
4351
 
@return 0 or error number */
 
4414
@return 0 or error number */
4352
4415
UNIV_INTERN
4353
4416
int
4354
4417
ha_innobase::index_init(
4355
4418
/*====================*/
4356
 
        uint    keynr,  /*!< in: key (index) number */
4357
 
        bool )          /*!< in: 1 if result MUST be sorted according to index */
 
4419
  uint  keynr,  /*!< in: key (index) number */
 
4420
  bool )    /*!< in: 1 if result MUST be sorted according to index */
4358
4421
{
4359
 
        return(change_active_index(keynr));
 
4422
  return(change_active_index(keynr));
4360
4423
}
4361
4424
 
4362
4425
/******************************************************************//**
4363
4426
Currently does nothing.
4364
 
@return 0 */
 
4427
@return 0 */
4365
4428
UNIV_INTERN
4366
4429
int
4367
4430
ha_innobase::index_end(void)
4368
4431
/*========================*/
4369
4432
{
4370
 
        int     error   = 0;
4371
 
        active_index=MAX_KEY;
4372
 
        return(error);
 
4433
  int error = 0;
 
4434
  active_index=MAX_KEY;
 
4435
  return(error);
4373
4436
}
4374
4437
 
4375
4438
/*********************************************************************//**
4379
4442
ulint
4380
4443
convert_search_mode_to_innobase(
4381
4444
/*============================*/
4382
 
        enum ha_rkey_function   find_flag)
 
4445
  enum ha_rkey_function find_flag)
4383
4446
{
4384
 
        switch (find_flag) {
4385
 
        case HA_READ_KEY_EXACT:
4386
 
                /* this does not require the index to be UNIQUE */
4387
 
                return(PAGE_CUR_GE);
4388
 
        case HA_READ_KEY_OR_NEXT:
4389
 
                return(PAGE_CUR_GE);
4390
 
        case HA_READ_KEY_OR_PREV:
4391
 
                return(PAGE_CUR_LE);
4392
 
        case HA_READ_AFTER_KEY: 
4393
 
                return(PAGE_CUR_G);
4394
 
        case HA_READ_BEFORE_KEY:
4395
 
                return(PAGE_CUR_L);
4396
 
        case HA_READ_PREFIX:
4397
 
                return(PAGE_CUR_GE);
4398
 
        case HA_READ_PREFIX_LAST:
4399
 
                return(PAGE_CUR_LE);
4400
 
        case HA_READ_PREFIX_LAST_OR_PREV:
4401
 
                return(PAGE_CUR_LE);
4402
 
                /* In MySQL-4.0 HA_READ_PREFIX and HA_READ_PREFIX_LAST always
4403
 
                pass a complete-field prefix of a key value as the search
4404
 
                tuple. I.e., it is not allowed that the last field would
4405
 
                just contain n first bytes of the full field value.
4406
 
                MySQL uses a 'padding' trick to convert LIKE 'abc%'
4407
 
                type queries so that it can use as a search tuple
4408
 
                a complete-field-prefix of a key value. Thus, the InnoDB
4409
 
                search mode PAGE_CUR_LE_OR_EXTENDS is never used.
4410
 
                TODO: when/if MySQL starts to use also partial-field
4411
 
                prefixes, we have to deal with stripping of spaces
4412
 
                and comparison of non-latin1 char type fields in
4413
 
                innobase_mysql_cmp() to get PAGE_CUR_LE_OR_EXTENDS to
4414
 
                work correctly. */
4415
 
        case HA_READ_MBR_CONTAIN:
4416
 
        case HA_READ_MBR_INTERSECT:
4417
 
        case HA_READ_MBR_WITHIN:
4418
 
        case HA_READ_MBR_DISJOINT:
4419
 
        case HA_READ_MBR_EQUAL:
4420
 
                return(PAGE_CUR_UNSUPP);
4421
 
        /* do not use "default:" in order to produce a gcc warning:
4422
 
        enumeration value '...' not handled in switch
4423
 
        (if -Wswitch or -Wall is used) */
4424
 
        }
4425
 
 
4426
 
        my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "this functionality");
4427
 
 
4428
 
        return(PAGE_CUR_UNSUPP);
 
4447
  switch (find_flag) {
 
4448
  case HA_READ_KEY_EXACT:
 
4449
    /* this does not require the index to be UNIQUE */
 
4450
    return(PAGE_CUR_GE);
 
4451
  case HA_READ_KEY_OR_NEXT:
 
4452
    return(PAGE_CUR_GE);
 
4453
  case HA_READ_KEY_OR_PREV:
 
4454
    return(PAGE_CUR_LE);
 
4455
  case HA_READ_AFTER_KEY: 
 
4456
    return(PAGE_CUR_G);
 
4457
  case HA_READ_BEFORE_KEY:
 
4458
    return(PAGE_CUR_L);
 
4459
  case HA_READ_PREFIX:
 
4460
    return(PAGE_CUR_GE);
 
4461
  case HA_READ_PREFIX_LAST:
 
4462
    return(PAGE_CUR_LE);
 
4463
  case HA_READ_PREFIX_LAST_OR_PREV:
 
4464
    return(PAGE_CUR_LE);
 
4465
    /* In MySQL-4.0 HA_READ_PREFIX and HA_READ_PREFIX_LAST always
 
4466
    pass a complete-field prefix of a key value as the search
 
4467
    tuple. I.e., it is not allowed that the last field would
 
4468
    just contain n first bytes of the full field value.
 
4469
    MySQL uses a 'padding' trick to convert LIKE 'abc%'
 
4470
    type queries so that it can use as a search tuple
 
4471
    a complete-field-prefix of a key value. Thus, the InnoDB
 
4472
    search mode PAGE_CUR_LE_OR_EXTENDS is never used.
 
4473
    TODO: when/if MySQL starts to use also partial-field
 
4474
    prefixes, we have to deal with stripping of spaces
 
4475
    and comparison of non-latin1 char type fields in
 
4476
    innobase_mysql_cmp() to get PAGE_CUR_LE_OR_EXTENDS to
 
4477
    work correctly. */
 
4478
  case HA_READ_MBR_CONTAIN:
 
4479
  case HA_READ_MBR_INTERSECT:
 
4480
  case HA_READ_MBR_WITHIN:
 
4481
  case HA_READ_MBR_DISJOINT:
 
4482
  case HA_READ_MBR_EQUAL:
 
4483
    return(PAGE_CUR_UNSUPP);
 
4484
  /* do not use "default:" in order to produce a gcc warning:
 
4485
  enumeration value '...' not handled in switch
 
4486
  (if -Wswitch or -Wall is used) */
 
4487
  }
 
4488
 
 
4489
  my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "this functionality");
 
4490
 
 
4491
  return(PAGE_CUR_UNSUPP);
4429
4492
}
4430
4493
 
4431
4494
/*
4489
4552
/**********************************************************************//**
4490
4553
Positions an index cursor to the index specified in the handle. Fetches the
4491
4554
row if any.
4492
 
@return 0, HA_ERR_KEY_NOT_FOUND, or error number */
 
4555
@return 0, HA_ERR_KEY_NOT_FOUND, or error number */
4493
4556
UNIV_INTERN
4494
4557
int
4495
4558
ha_innobase::index_read(
4496
4559
/*====================*/
4497
 
        unsigned char*          buf,    /*!< in/out: buffer for the returned
4498
 
                                        row */
4499
 
        const unsigned char*    key_ptr,/*!< in: key value; if this is NULL
4500
 
                                        we position the cursor at the
4501
 
                                        start or end of index; this can
4502
 
                                        also contain an InnoDB row id, in
4503
 
                                        which case key_len is the InnoDB
4504
 
                                        row id length; the key value can
4505
 
                                        also be a prefix of a full key value,
4506
 
                                        and the last column can be a prefix
4507
 
                                        of a full column */
4508
 
        uint                    key_len,/*!< in: key value length */
4509
 
        enum ha_rkey_function find_flag)/*!< in: search flags from my_base.h */
 
4560
  unsigned char*    buf,  /*!< in/out: buffer for the returned
 
4561
          row */
 
4562
  const unsigned char*  key_ptr,/*!< in: key value; if this is NULL
 
4563
          we position the cursor at the
 
4564
          start or end of index; this can
 
4565
          also contain an InnoDB row id, in
 
4566
          which case key_len is the InnoDB
 
4567
          row id length; the key value can
 
4568
          also be a prefix of a full key value,
 
4569
          and the last column can be a prefix
 
4570
          of a full column */
 
4571
  uint      key_len,/*!< in: key value length */
 
4572
  enum ha_rkey_function find_flag)/*!< in: search flags from my_base.h */
4510
4573
{
4511
 
        ulint           mode;
4512
 
        dict_index_t*   index;
4513
 
        ulint           match_mode      = 0;
4514
 
        int             error;
4515
 
        ulint           ret;
4516
 
 
4517
 
        ut_a(prebuilt->trx == session_to_trx(user_session));
4518
 
 
4519
 
        ha_statistic_increment(&system_status_var::ha_read_key_count);
4520
 
 
4521
 
        index = prebuilt->index;
4522
 
 
4523
 
        /* Note that if the index for which the search template is built is not
4524
 
        necessarily prebuilt->index, but can also be the clustered index */
4525
 
 
4526
 
        if (prebuilt->sql_stat_start) {
4527
 
                build_template(prebuilt, user_session, table,
4528
 
                               ROW_MYSQL_REC_FIELDS);
4529
 
        }
4530
 
 
4531
 
        if (key_ptr) {
4532
 
                /* Convert the search key value to InnoDB format into
4533
 
                prebuilt->search_tuple */
4534
 
 
4535
 
                row_sel_convert_mysql_key_to_innobase(
4536
 
                        prebuilt->search_tuple,
4537
 
                        (byte*) key_val_buff,
4538
 
                        (ulint)upd_and_key_val_buff_len,
4539
 
                        index,
4540
 
                        (byte*) key_ptr,
4541
 
                        (ulint) key_len,
4542
 
                        prebuilt->trx);
4543
 
        } else {
4544
 
                /* We position the cursor to the last or the first entry
4545
 
                in the index */
4546
 
 
4547
 
                dtuple_set_n_fields(prebuilt->search_tuple, 0);
4548
 
        }
4549
 
 
4550
 
        mode = convert_search_mode_to_innobase(find_flag);
4551
 
 
4552
 
        match_mode = 0;
4553
 
 
4554
 
        if (find_flag == HA_READ_KEY_EXACT) {
4555
 
 
4556
 
                match_mode = ROW_SEL_EXACT;
4557
 
 
4558
 
        } else if (find_flag == HA_READ_PREFIX
4559
 
                   || find_flag == HA_READ_PREFIX_LAST) {
4560
 
 
4561
 
                match_mode = ROW_SEL_EXACT_PREFIX;
4562
 
        }
4563
 
 
4564
 
        last_match_mode = (uint) match_mode;
4565
 
 
4566
 
        if (mode != PAGE_CUR_UNSUPP) {
4567
 
 
4568
 
                innodb_srv_conc_enter_innodb(prebuilt->trx);
4569
 
 
4570
 
                ret = row_search_for_mysql((byte*) buf, mode, prebuilt,
4571
 
                                           match_mode, 0);
4572
 
 
4573
 
                innodb_srv_conc_exit_innodb(prebuilt->trx);
4574
 
        } else {
4575
 
 
4576
 
                ret = DB_UNSUPPORTED;
4577
 
        }
4578
 
 
4579
 
        switch (ret) {
4580
 
        case DB_SUCCESS:
4581
 
                error = 0;
4582
 
                table->status = 0;
4583
 
                break;
4584
 
        case DB_RECORD_NOT_FOUND:
4585
 
                error = HA_ERR_KEY_NOT_FOUND;
4586
 
                table->status = STATUS_NOT_FOUND;
4587
 
                break;
4588
 
        case DB_END_OF_INDEX:
4589
 
                error = HA_ERR_KEY_NOT_FOUND;
4590
 
                table->status = STATUS_NOT_FOUND;
4591
 
                break;
4592
 
        default:
4593
 
                error = convert_error_code_to_mysql((int) ret,
4594
 
                                                    prebuilt->table->flags,
4595
 
                                                    user_session);
4596
 
                table->status = STATUS_NOT_FOUND;
4597
 
                break;
4598
 
        }
4599
 
 
4600
 
        return(error);
 
4574
  ulint   mode;
 
4575
  dict_index_t* index;
 
4576
  ulint   match_mode  = 0;
 
4577
  int   error;
 
4578
  ulint   ret;
 
4579
 
 
4580
  ut_a(prebuilt->trx == session_to_trx(user_session));
 
4581
 
 
4582
  ha_statistic_increment(&system_status_var::ha_read_key_count);
 
4583
 
 
4584
  index = prebuilt->index;
 
4585
 
 
4586
  /* Note that if the index for which the search template is built is not
 
4587
  necessarily prebuilt->index, but can also be the clustered index */
 
4588
 
 
4589
  if (prebuilt->sql_stat_start) {
 
4590
    build_template(prebuilt, user_session, table,
 
4591
             ROW_MYSQL_REC_FIELDS);
 
4592
  }
 
4593
 
 
4594
  if (key_ptr) {
 
4595
    /* Convert the search key value to InnoDB format into
 
4596
    prebuilt->search_tuple */
 
4597
 
 
4598
    row_sel_convert_mysql_key_to_innobase(
 
4599
      prebuilt->search_tuple,
 
4600
      (byte*) key_val_buff,
 
4601
      (ulint)upd_and_key_val_buff_len,
 
4602
      index,
 
4603
      (byte*) key_ptr,
 
4604
      (ulint) key_len,
 
4605
      prebuilt->trx);
 
4606
  } else {
 
4607
    /* We position the cursor to the last or the first entry
 
4608
    in the index */
 
4609
 
 
4610
    dtuple_set_n_fields(prebuilt->search_tuple, 0);
 
4611
  }
 
4612
 
 
4613
  mode = convert_search_mode_to_innobase(find_flag);
 
4614
 
 
4615
  match_mode = 0;
 
4616
 
 
4617
  if (find_flag == HA_READ_KEY_EXACT) {
 
4618
 
 
4619
    match_mode = ROW_SEL_EXACT;
 
4620
 
 
4621
  } else if (find_flag == HA_READ_PREFIX
 
4622
       || find_flag == HA_READ_PREFIX_LAST) {
 
4623
 
 
4624
    match_mode = ROW_SEL_EXACT_PREFIX;
 
4625
  }
 
4626
 
 
4627
  last_match_mode = (uint) match_mode;
 
4628
 
 
4629
  if (mode != PAGE_CUR_UNSUPP) {
 
4630
 
 
4631
    innodb_srv_conc_enter_innodb(prebuilt->trx);
 
4632
 
 
4633
    ret = row_search_for_mysql((byte*) buf, mode, prebuilt,
 
4634
             match_mode, 0);
 
4635
 
 
4636
    innodb_srv_conc_exit_innodb(prebuilt->trx);
 
4637
  } else {
 
4638
 
 
4639
    ret = DB_UNSUPPORTED;
 
4640
  }
 
4641
 
 
4642
  switch (ret) {
 
4643
  case DB_SUCCESS:
 
4644
    error = 0;
 
4645
    table->status = 0;
 
4646
    break;
 
4647
  case DB_RECORD_NOT_FOUND:
 
4648
    error = HA_ERR_KEY_NOT_FOUND;
 
4649
    table->status = STATUS_NOT_FOUND;
 
4650
    break;
 
4651
  case DB_END_OF_INDEX:
 
4652
    error = HA_ERR_KEY_NOT_FOUND;
 
4653
    table->status = STATUS_NOT_FOUND;
 
4654
    break;
 
4655
  default:
 
4656
    error = convert_error_code_to_mysql((int) ret,
 
4657
                prebuilt->table->flags,
 
4658
                user_session);
 
4659
    table->status = STATUS_NOT_FOUND;
 
4660
    break;
 
4661
  }
 
4662
 
 
4663
  return(error);
4601
4664
}
4602
4665
 
4603
4666
/*******************************************************************//**
4604
4667
The following functions works like index_read, but it find the last
4605
4668
row with the current key value or prefix.
4606
 
@return 0, HA_ERR_KEY_NOT_FOUND, or an error code */
 
4669
@return 0, HA_ERR_KEY_NOT_FOUND, or an error code */
4607
4670
UNIV_INTERN
4608
4671
int
4609
4672
ha_innobase::index_read_last(
4610
4673
/*=========================*/
4611
 
        unsigned char*  buf,    /*!< out: fetched row */
4612
 
        const unsigned char*    key_ptr,/*!< in: key value, or a prefix of a full
4613
 
                                key value */
4614
 
        uint            key_len)/*!< in: length of the key val or prefix
4615
 
                                in bytes */
 
4674
  unsigned char*  buf,  /*!< out: fetched row */
 
4675
  const unsigned char*  key_ptr,/*!< in: key value, or a prefix of a full
 
4676
        key value */
 
4677
  uint    key_len)/*!< in: length of the key val or prefix
 
4678
        in bytes */
4616
4679
{
4617
 
        return(index_read(buf, key_ptr, key_len, HA_READ_PREFIX_LAST));
 
4680
  return(index_read(buf, key_ptr, key_len, HA_READ_PREFIX_LAST));
4618
4681
}
4619
4682
 
4620
4683
/********************************************************************//**
4621
4684
Get the index for a handle. Does not change active index.
4622
 
@return NULL or index instance. */
 
4685
@return NULL or index instance. */
4623
4686
UNIV_INTERN
4624
4687
dict_index_t*
4625
4688
ha_innobase::innobase_get_index(
4626
4689
/*============================*/
4627
 
        uint            keynr)  /*!< in: use this index; MAX_KEY means always
4628
 
                                clustered index, even if it was internally
4629
 
                                generated by InnoDB */
 
4690
  uint    keynr)  /*!< in: use this index; MAX_KEY means always
 
4691
        clustered index, even if it was internally
 
4692
        generated by InnoDB */
4630
4693
{
4631
 
        KEY*            key = 0;
4632
 
        dict_index_t*   index = 0;
4633
 
 
4634
 
        ha_statistic_increment(&system_status_var::ha_read_key_count);
4635
 
 
4636
 
        ut_ad(user_session == ha_session());
4637
 
        ut_a(prebuilt->trx == session_to_trx(user_session));
4638
 
 
4639
 
        if (keynr != MAX_KEY && table->s->keys > 0) {
4640
 
                key = table->key_info + keynr;
4641
 
 
4642
 
                index = dict_table_get_index_on_name(prebuilt->table,
4643
 
                                                     key->name);
4644
 
        } else {
4645
 
                index = dict_table_get_first_index(prebuilt->table);
4646
 
        }
4647
 
 
4648
 
        if (!index) {
4649
 
                errmsg_printf(ERRMSG_LVL_ERROR, 
4650
 
                        "Innodb could not find key n:o %u with name %s "
4651
 
                        "from dict cache for table %s",
4652
 
                        keynr, key ? key->name : "NULL",
4653
 
                        prebuilt->table->name);
4654
 
        }
4655
 
 
4656
 
        return(index);
 
4694
  KEY*    key = 0;
 
4695
  dict_index_t* index = 0;
 
4696
 
 
4697
  ha_statistic_increment(&system_status_var::ha_read_key_count);
 
4698
 
 
4699
  ut_ad(user_session == ha_session());
 
4700
  ut_a(prebuilt->trx == session_to_trx(user_session));
 
4701
 
 
4702
  if (keynr != MAX_KEY && table->s->keys > 0) {
 
4703
    key = table->key_info + keynr;
 
4704
 
 
4705
    index = dict_table_get_index_on_name(prebuilt->table,
 
4706
                 key->name);
 
4707
  } else {
 
4708
    index = dict_table_get_first_index(prebuilt->table);
 
4709
  }
 
4710
 
 
4711
  if (!index) {
 
4712
    errmsg_printf(ERRMSG_LVL_ERROR, 
 
4713
      "Innodb could not find key n:o %u with name %s "
 
4714
      "from dict cache for table %s",
 
4715
      keynr, key ? key->name : "NULL",
 
4716
      prebuilt->table->name);
 
4717
  }
 
4718
 
 
4719
  return(index);
4657
4720
}
4658
4721
 
4659
4722
/********************************************************************//**
4660
4723
Changes the active index of a handle.
4661
 
@return 0 or error code */
 
4724
@return 0 or error code */
4662
4725
UNIV_INTERN
4663
4726
int
4664
4727
ha_innobase::change_active_index(
4665
4728
/*=============================*/
4666
 
        uint    keynr)  /*!< in: use this index; MAX_KEY means always clustered
4667
 
                        index, even if it was internally generated by
4668
 
                        InnoDB */
 
4729
  uint  keynr)  /*!< in: use this index; MAX_KEY means always clustered
 
4730
      index, even if it was internally generated by
 
4731
      InnoDB */
4669
4732
{
4670
 
        ut_ad(user_session == ha_session());
4671
 
        ut_a(prebuilt->trx == session_to_trx(user_session));
4672
 
 
4673
 
        active_index = keynr;
4674
 
 
4675
 
        prebuilt->index = innobase_get_index(keynr);
4676
 
 
4677
 
        if (UNIV_UNLIKELY(!prebuilt->index)) {
4678
 
                errmsg_printf(ERRMSG_LVL_WARN, "InnoDB: change_active_index(%u) failed",
4679
 
                                  keynr);
4680
 
                return(1);
4681
 
        }
4682
 
 
4683
 
        prebuilt->index_usable = row_merge_is_index_usable(prebuilt->trx,
4684
 
                                                           prebuilt->index);
4685
 
 
4686
 
        if (UNIV_UNLIKELY(!prebuilt->index_usable)) {
4687
 
                errmsg_printf(ERRMSG_LVL_WARN,
4688
 
                                 "InnoDB: insufficient history for index %u",
4689
 
                                  keynr);
4690
 
                /* The caller seems to ignore this.  Thus, we must check
4691
 
                this again in row_search_for_mysql(). */
4692
 
                return(2);
4693
 
        }
4694
 
 
4695
 
        ut_a(prebuilt->search_tuple != 0);
4696
 
 
4697
 
        dtuple_set_n_fields(prebuilt->search_tuple, prebuilt->index->n_fields);
4698
 
 
4699
 
        dict_index_copy_types(prebuilt->search_tuple, prebuilt->index,
4700
 
                        prebuilt->index->n_fields);
4701
 
 
4702
 
        /* MySQL changes the active index for a handle also during some
4703
 
        queries, for example SELECT MAX(a), SUM(a) first retrieves the MAX()
4704
 
        and then calculates the sum. Previously we played safe and used
4705
 
        the flag ROW_MYSQL_WHOLE_ROW below, but that caused unnecessary
4706
 
        copying. Starting from MySQL-4.1 we use a more efficient flag here. */
4707
 
 
4708
 
        build_template(prebuilt, user_session, table, ROW_MYSQL_REC_FIELDS);
4709
 
 
4710
 
        return(0);
 
4733
  ut_ad(user_session == ha_session());
 
4734
  ut_a(prebuilt->trx == session_to_trx(user_session));
 
4735
 
 
4736
  active_index = keynr;
 
4737
 
 
4738
  prebuilt->index = innobase_get_index(keynr);
 
4739
 
 
4740
  if (UNIV_UNLIKELY(!prebuilt->index)) {
 
4741
    errmsg_printf(ERRMSG_LVL_WARN, "InnoDB: change_active_index(%u) failed",
 
4742
          keynr);
 
4743
    return(1);
 
4744
  }
 
4745
 
 
4746
  prebuilt->index_usable = row_merge_is_index_usable(prebuilt->trx,
 
4747
                 prebuilt->index);
 
4748
 
 
4749
  if (UNIV_UNLIKELY(!prebuilt->index_usable)) {
 
4750
    errmsg_printf(ERRMSG_LVL_WARN,
 
4751
         "InnoDB: insufficient history for index %u",
 
4752
          keynr);
 
4753
    /* The caller seems to ignore this.  Thus, we must check
 
4754
    this again in row_search_for_mysql(). */
 
4755
    return(2);
 
4756
  }
 
4757
 
 
4758
  ut_a(prebuilt->search_tuple != 0);
 
4759
 
 
4760
  dtuple_set_n_fields(prebuilt->search_tuple, prebuilt->index->n_fields);
 
4761
 
 
4762
  dict_index_copy_types(prebuilt->search_tuple, prebuilt->index,
 
4763
      prebuilt->index->n_fields);
 
4764
 
 
4765
  /* MySQL changes the active index for a handle also during some
 
4766
  queries, for example SELECT MAX(a), SUM(a) first retrieves the MAX()
 
4767
  and then calculates the sum. Previously we played safe and used
 
4768
  the flag ROW_MYSQL_WHOLE_ROW below, but that caused unnecessary
 
4769
  copying. Starting from MySQL-4.1 we use a more efficient flag here. */
 
4770
 
 
4771
  build_template(prebuilt, user_session, table, ROW_MYSQL_REC_FIELDS);
 
4772
 
 
4773
  return(0);
4711
4774
}
4712
4775
 
4713
4776
/**********************************************************************//**
4714
4777
Positions an index cursor to the index specified in keynr. Fetches the
4715
4778
row if any.
4716
4779
??? This is only used to read whole keys ???
4717
 
@return error number or 0 */
 
4780
@return error number or 0 */
4718
4781
UNIV_INTERN
4719
4782
int
4720
4783
ha_innobase::index_read_idx(
4721
4784
/*========================*/
4722
 
        unsigned char*  buf,            /*!< in/out: buffer for the returned
4723
 
                                        row */
4724
 
        uint            keynr,          /*!< in: use this index */
4725
 
        const unsigned char*    key,    /*!< in: key value; if this is NULL
4726
 
                                        we position the cursor at the
4727
 
                                        start or end of index */
4728
 
        uint            key_len,        /*!< in: key value length */
4729
 
        enum ha_rkey_function find_flag)/*!< in: search flags from my_base.h */
 
4785
  unsigned char*  buf,    /*!< in/out: buffer for the returned
 
4786
          row */
 
4787
  uint    keynr,    /*!< in: use this index */
 
4788
  const unsigned char*  key,  /*!< in: key value; if this is NULL
 
4789
          we position the cursor at the
 
4790
          start or end of index */
 
4791
  uint    key_len,  /*!< in: key value length */
 
4792
  enum ha_rkey_function find_flag)/*!< in: search flags from my_base.h */
4730
4793
{
4731
 
        if (change_active_index(keynr)) {
4732
 
 
4733
 
                return(1);
4734
 
        }
4735
 
 
4736
 
        return(index_read(buf, key, key_len, find_flag));
 
4794
  if (change_active_index(keynr)) {
 
4795
 
 
4796
    return(1);
 
4797
  }
 
4798
 
 
4799
  return(index_read(buf, key, key_len, find_flag));
4737
4800
}
4738
4801
 
4739
4802
/***********************************************************************//**
4740
4803
Reads the next or previous row from a cursor, which must have previously been
4741
4804
positioned using index_read.
4742
 
@return 0, HA_ERR_END_OF_FILE, or error number */
 
4805
@return 0, HA_ERR_END_OF_FILE, or error number */
4743
4806
UNIV_INTERN
4744
4807
int
4745
4808
ha_innobase::general_fetch(
4746
4809
/*=======================*/
4747
 
        unsigned char*  buf,    /*!< in/out: buffer for next row in MySQL
4748
 
                                format */
4749
 
        uint    direction,      /*!< in: ROW_SEL_NEXT or ROW_SEL_PREV */
4750
 
        uint    match_mode)     /*!< in: 0, ROW_SEL_EXACT, or
4751
 
                                ROW_SEL_EXACT_PREFIX */
 
4810
  unsigned char*  buf,  /*!< in/out: buffer for next row in MySQL
 
4811
        format */
 
4812
  uint  direction,  /*!< in: ROW_SEL_NEXT or ROW_SEL_PREV */
 
4813
  uint  match_mode) /*!< in: 0, ROW_SEL_EXACT, or
 
4814
        ROW_SEL_EXACT_PREFIX */
4752
4815
{
4753
 
        ulint           ret;
4754
 
        int             error   = 0;
4755
 
 
4756
 
        ut_a(prebuilt->trx == session_to_trx(user_session));
4757
 
 
4758
 
        innodb_srv_conc_enter_innodb(prebuilt->trx);
4759
 
 
4760
 
        ret = row_search_for_mysql(
4761
 
                (byte*)buf, 0, prebuilt, match_mode, direction);
4762
 
 
4763
 
        innodb_srv_conc_exit_innodb(prebuilt->trx);
4764
 
 
4765
 
        switch (ret) {
4766
 
        case DB_SUCCESS:
4767
 
                error = 0;
4768
 
                table->status = 0;
4769
 
                break;
4770
 
        case DB_RECORD_NOT_FOUND:
4771
 
                error = HA_ERR_END_OF_FILE;
4772
 
                table->status = STATUS_NOT_FOUND;
4773
 
                break;
4774
 
        case DB_END_OF_INDEX:
4775
 
                error = HA_ERR_END_OF_FILE;
4776
 
                table->status = STATUS_NOT_FOUND;
4777
 
                break;
4778
 
        default:
4779
 
                error = convert_error_code_to_mysql(
4780
 
                        (int) ret, prebuilt->table->flags, user_session);
4781
 
                table->status = STATUS_NOT_FOUND;
4782
 
                break;
4783
 
        }
4784
 
 
4785
 
        return(error);
 
4816
  ulint   ret;
 
4817
  int   error = 0;
 
4818
 
 
4819
  ut_a(prebuilt->trx == session_to_trx(user_session));
 
4820
 
 
4821
  innodb_srv_conc_enter_innodb(prebuilt->trx);
 
4822
 
 
4823
  ret = row_search_for_mysql(
 
4824
    (byte*)buf, 0, prebuilt, match_mode, direction);
 
4825
 
 
4826
  innodb_srv_conc_exit_innodb(prebuilt->trx);
 
4827
 
 
4828
  switch (ret) {
 
4829
  case DB_SUCCESS:
 
4830
    error = 0;
 
4831
    table->status = 0;
 
4832
    break;
 
4833
  case DB_RECORD_NOT_FOUND:
 
4834
    error = HA_ERR_END_OF_FILE;
 
4835
    table->status = STATUS_NOT_FOUND;
 
4836
    break;
 
4837
  case DB_END_OF_INDEX:
 
4838
    error = HA_ERR_END_OF_FILE;
 
4839
    table->status = STATUS_NOT_FOUND;
 
4840
    break;
 
4841
  default:
 
4842
    error = convert_error_code_to_mysql(
 
4843
      (int) ret, prebuilt->table->flags, user_session);
 
4844
    table->status = STATUS_NOT_FOUND;
 
4845
    break;
 
4846
  }
 
4847
 
 
4848
  return(error);
4786
4849
}
4787
4850
 
4788
4851
/***********************************************************************//**
4789
4852
Reads the next row from a cursor, which must have previously been
4790
4853
positioned using index_read.
4791
 
@return 0, HA_ERR_END_OF_FILE, or error number */
 
4854
@return 0, HA_ERR_END_OF_FILE, or error number */
4792
4855
UNIV_INTERN
4793
4856
int
4794
4857
ha_innobase::index_next(
4795
4858
/*====================*/
4796
 
        unsigned char*  buf)    /*!< in/out: buffer for next row in MySQL
4797
 
                                format */
 
4859
  unsigned char*  buf)  /*!< in/out: buffer for next row in MySQL
 
4860
        format */
4798
4861
{
4799
 
        ha_statistic_increment(&system_status_var::ha_read_next_count);
 
4862
  ha_statistic_increment(&system_status_var::ha_read_next_count);
4800
4863
 
4801
 
        return(general_fetch(buf, ROW_SEL_NEXT, 0));
 
4864
  return(general_fetch(buf, ROW_SEL_NEXT, 0));
4802
4865
}
4803
4866
 
4804
4867
/*******************************************************************//**
4805
4868
Reads the next row matching to the key value given as the parameter.
4806
 
@return 0, HA_ERR_END_OF_FILE, or error number */
 
4869
@return 0, HA_ERR_END_OF_FILE, or error number */
4807
4870
UNIV_INTERN
4808
4871
int
4809
4872
ha_innobase::index_next_same(
4810
4873
/*=========================*/
4811
 
        unsigned char*          buf,    /*!< in/out: buffer for the row */
4812
 
        const unsigned char*    ,       /*!< in: key value */
4813
 
        uint            )       /*!< in: key value length */
 
4874
  unsigned char*    buf,  /*!< in/out: buffer for the row */
 
4875
  const unsigned char*  , /*!< in: key value */
 
4876
  uint    ) /*!< in: key value length */
4814
4877
{
4815
 
        ha_statistic_increment(&system_status_var::ha_read_next_count);
 
4878
  ha_statistic_increment(&system_status_var::ha_read_next_count);
4816
4879
 
4817
 
        return(general_fetch(buf, ROW_SEL_NEXT, last_match_mode));
 
4880
  return(general_fetch(buf, ROW_SEL_NEXT, last_match_mode));
4818
4881
}
4819
4882
 
4820
4883
/***********************************************************************//**
4821
4884
Reads the previous row from a cursor, which must have previously been
4822
4885
positioned using index_read.
4823
 
@return 0, HA_ERR_END_OF_FILE, or error number */
 
4886
@return 0, HA_ERR_END_OF_FILE, or error number */
4824
4887
UNIV_INTERN
4825
4888
int
4826
4889
ha_innobase::index_prev(
4827
4890
/*====================*/
4828
 
        unsigned char*  buf)    /*!< in/out: buffer for previous row in MySQL format */
 
4891
  unsigned char*  buf)  /*!< in/out: buffer for previous row in MySQL format */
4829
4892
{
4830
 
        ha_statistic_increment(&system_status_var::ha_read_prev_count);
 
4893
  ha_statistic_increment(&system_status_var::ha_read_prev_count);
4831
4894
 
4832
 
        return(general_fetch(buf, ROW_SEL_PREV, 0));
 
4895
  return(general_fetch(buf, ROW_SEL_PREV, 0));
4833
4896
}
4834
4897
 
4835
4898
/********************************************************************//**
4836
4899
Positions a cursor on the first record in an index and reads the
4837
4900
corresponding row to buf.
4838
 
@return 0, HA_ERR_END_OF_FILE, or error code */
 
4901
@return 0, HA_ERR_END_OF_FILE, or error code */
4839
4902
UNIV_INTERN
4840
4903
int
4841
4904
ha_innobase::index_first(
4842
4905
/*=====================*/
4843
 
        unsigned char*  buf)    /*!< in/out: buffer for the row */
 
4906
  unsigned char*  buf)  /*!< in/out: buffer for the row */
4844
4907
{
4845
 
        int     error;
4846
 
 
4847
 
        ha_statistic_increment(&system_status_var::ha_read_first_count);
4848
 
 
4849
 
        error = index_read(buf, NULL, 0, HA_READ_AFTER_KEY);
4850
 
 
4851
 
        /* MySQL does not seem to allow this to return HA_ERR_KEY_NOT_FOUND */
4852
 
 
4853
 
        if (error == HA_ERR_KEY_NOT_FOUND) {
4854
 
                error = HA_ERR_END_OF_FILE;
4855
 
        }
4856
 
 
4857
 
        return(error);
 
4908
  int error;
 
4909
 
 
4910
  ha_statistic_increment(&system_status_var::ha_read_first_count);
 
4911
 
 
4912
  error = index_read(buf, NULL, 0, HA_READ_AFTER_KEY);
 
4913
 
 
4914
  /* MySQL does not seem to allow this to return HA_ERR_KEY_NOT_FOUND */
 
4915
 
 
4916
  if (error == HA_ERR_KEY_NOT_FOUND) {
 
4917
    error = HA_ERR_END_OF_FILE;
 
4918
  }
 
4919
 
 
4920
  return(error);
4858
4921
}
4859
4922
 
4860
4923
/********************************************************************//**
4861
4924
Positions a cursor on the last record in an index and reads the
4862
4925
corresponding row to buf.
4863
 
@return 0, HA_ERR_END_OF_FILE, or error code */
 
4926
@return 0, HA_ERR_END_OF_FILE, or error code */
4864
4927
UNIV_INTERN
4865
4928
int
4866
4929
ha_innobase::index_last(
4867
4930
/*====================*/
4868
 
        unsigned char*  buf)    /*!< in/out: buffer for the row */
 
4931
  unsigned char*  buf)  /*!< in/out: buffer for the row */
4869
4932
{
4870
 
        int     error;
4871
 
 
4872
 
        ha_statistic_increment(&system_status_var::ha_read_last_count);
4873
 
 
4874
 
        error = index_read(buf, NULL, 0, HA_READ_BEFORE_KEY);
4875
 
 
4876
 
        /* MySQL does not seem to allow this to return HA_ERR_KEY_NOT_FOUND */
4877
 
 
4878
 
        if (error == HA_ERR_KEY_NOT_FOUND) {
4879
 
                error = HA_ERR_END_OF_FILE;
4880
 
        }
4881
 
 
4882
 
        return(error);
 
4933
  int error;
 
4934
 
 
4935
  ha_statistic_increment(&system_status_var::ha_read_last_count);
 
4936
 
 
4937
  error = index_read(buf, NULL, 0, HA_READ_BEFORE_KEY);
 
4938
 
 
4939
  /* MySQL does not seem to allow this to return HA_ERR_KEY_NOT_FOUND */
 
4940
 
 
4941
  if (error == HA_ERR_KEY_NOT_FOUND) {
 
4942
    error = HA_ERR_END_OF_FILE;
 
4943
  }
 
4944
 
 
4945
  return(error);
4883
4946
}
4884
4947
 
4885
4948
/****************************************************************//**
4886
4949
Initialize a table scan.
4887
 
@return 0 or error number */
 
4950
@return 0 or error number */
4888
4951
UNIV_INTERN
4889
4952
int
4890
4953
ha_innobase::rnd_init(
4891
4954
/*==================*/
4892
 
        bool    scan)   /*!< in: TRUE if table/index scan FALSE otherwise */
 
4955
  bool  scan) /*!< in: TRUE if table/index scan FALSE otherwise */
4893
4956
{
4894
 
        int     err;
4895
 
 
4896
 
        /* Store the active index value so that we can restore the original
4897
 
        value after a scan */
4898
 
 
4899
 
        if (prebuilt->clust_index_was_generated) {
4900
 
                err = change_active_index(MAX_KEY);
4901
 
        } else {
4902
 
                err = change_active_index(primary_key);
4903
 
        }
4904
 
 
4905
 
        /* Don't use semi-consistent read in random row reads (by position).
4906
 
        This means we must disable semi_consistent_read if scan is false */
4907
 
 
4908
 
        if (!scan) {
4909
 
                try_semi_consistent_read(0);
4910
 
        }
4911
 
 
4912
 
        start_of_scan = 1;
4913
 
 
4914
 
        return(err);
 
4957
  int err;
 
4958
 
 
4959
  /* Store the active index value so that we can restore the original
 
4960
  value after a scan */
 
4961
 
 
4962
  if (prebuilt->clust_index_was_generated) {
 
4963
    err = change_active_index(MAX_KEY);
 
4964
  } else {
 
4965
    err = change_active_index(primary_key);
 
4966
  }
 
4967
 
 
4968
  /* Don't use semi-consistent read in random row reads (by position).
 
4969
  This means we must disable semi_consistent_read if scan is false */
 
4970
 
 
4971
  if (!scan) {
 
4972
    try_semi_consistent_read(0);
 
4973
  }
 
4974
 
 
4975
  start_of_scan = 1;
 
4976
 
 
4977
  return(err);
4915
4978
}
4916
4979
 
4917
4980
/*****************************************************************//**
4918
4981
Ends a table scan.
4919
 
@return 0 or error number */
 
4982
@return 0 or error number */
4920
4983
UNIV_INTERN
4921
4984
int
4922
4985
ha_innobase::rnd_end(void)
4923
4986
/*======================*/
4924
4987
{
4925
 
        return(index_end());
 
4988
  return(index_end());
4926
4989
}
4927
4990
 
4928
4991
/*****************************************************************//**
4929
4992
Reads the next row in a table scan (also used to read the FIRST row
4930
4993
in a table scan).
4931
 
@return 0, HA_ERR_END_OF_FILE, or error number */
 
4994
@return 0, HA_ERR_END_OF_FILE, or error number */
4932
4995
UNIV_INTERN
4933
4996
int
4934
4997
ha_innobase::rnd_next(
4935
4998
/*==================*/
4936
 
        unsigned char*  buf)    /*!< in/out: returns the row in this buffer,
4937
 
                        in MySQL format */
 
4999
  unsigned char*  buf)  /*!< in/out: returns the row in this buffer,
 
5000
      in MySQL format */
4938
5001
{
4939
 
        int     error;
4940
 
 
4941
 
        ha_statistic_increment(&system_status_var::ha_read_rnd_next_count);
4942
 
 
4943
 
        if (start_of_scan) {
4944
 
                error = index_first(buf);
4945
 
 
4946
 
                if (error == HA_ERR_KEY_NOT_FOUND) {
4947
 
                        error = HA_ERR_END_OF_FILE;
4948
 
                }
4949
 
 
4950
 
                start_of_scan = 0;
4951
 
        } else {
4952
 
                error = general_fetch(buf, ROW_SEL_NEXT, 0);
4953
 
        }
4954
 
 
4955
 
        return(error);
 
5002
  int error;
 
5003
 
 
5004
  ha_statistic_increment(&system_status_var::ha_read_rnd_next_count);
 
5005
 
 
5006
  if (start_of_scan) {
 
5007
    error = index_first(buf);
 
5008
 
 
5009
    if (error == HA_ERR_KEY_NOT_FOUND) {
 
5010
      error = HA_ERR_END_OF_FILE;
 
5011
    }
 
5012
 
 
5013
    start_of_scan = 0;
 
5014
  } else {
 
5015
    error = general_fetch(buf, ROW_SEL_NEXT, 0);
 
5016
  }
 
5017
 
 
5018
  return(error);
4956
5019
}
4957
5020
 
4958
5021
/**********************************************************************//**
4959
5022
Fetches a row from the table based on a row reference.
4960
 
@return 0, HA_ERR_KEY_NOT_FOUND, or error code */
 
5023
@return 0, HA_ERR_KEY_NOT_FOUND, or error code */
4961
5024
UNIV_INTERN
4962
5025
int
4963
5026
ha_innobase::rnd_pos(
4964
5027
/*=================*/
4965
 
        unsigned char*  buf,    /*!< in/out: buffer for the row */
4966
 
        unsigned char*  pos)    /*!< in: primary key value of the row in the
4967
 
                        MySQL format, or the row id if the clustered
4968
 
                        index was internally generated by InnoDB; the
4969
 
                        length of data in pos has to be ref_length */
 
5028
  unsigned char*  buf,  /*!< in/out: buffer for the row */
 
5029
  unsigned char*  pos)  /*!< in: primary key value of the row in the
 
5030
      MySQL format, or the row id if the clustered
 
5031
      index was internally generated by InnoDB; the
 
5032
      length of data in pos has to be ref_length */
4970
5033
{
4971
 
        int             error;
4972
 
        uint            keynr   = active_index;
4973
 
 
4974
 
        ha_statistic_increment(&system_status_var::ha_read_rnd_count);
4975
 
 
4976
 
        ut_a(prebuilt->trx == session_to_trx(ha_session()));
4977
 
 
4978
 
        if (prebuilt->clust_index_was_generated) {
4979
 
                /* No primary key was defined for the table and we
4980
 
                generated the clustered index from the row id: the
4981
 
                row reference is the row id, not any key value
4982
 
                that MySQL knows of */
4983
 
 
4984
 
                error = change_active_index(MAX_KEY);
4985
 
        } else {
4986
 
                error = change_active_index(primary_key);
4987
 
        }
4988
 
 
4989
 
        if (error) {
4990
 
                return(error);
4991
 
        }
4992
 
 
4993
 
        /* Note that we assume the length of the row reference is fixed
4994
 
        for the table, and it is == ref_length */
4995
 
 
4996
 
        error = index_read(buf, pos, ref_length, HA_READ_KEY_EXACT);
4997
 
 
4998
 
        if (error) {
4999
 
        }
5000
 
 
5001
 
        change_active_index(keynr);
5002
 
 
5003
 
        return(error);
 
5034
  int   error;
 
5035
  uint    keynr = active_index;
 
5036
 
 
5037
  ha_statistic_increment(&system_status_var::ha_read_rnd_count);
 
5038
 
 
5039
  ut_a(prebuilt->trx == session_to_trx(ha_session()));
 
5040
 
 
5041
  if (prebuilt->clust_index_was_generated) {
 
5042
    /* No primary key was defined for the table and we
 
5043
    generated the clustered index from the row id: the
 
5044
    row reference is the row id, not any key value
 
5045
    that MySQL knows of */
 
5046
 
 
5047
    error = change_active_index(MAX_KEY);
 
5048
  } else {
 
5049
    error = change_active_index(primary_key);
 
5050
  }
 
5051
 
 
5052
  if (error) {
 
5053
    return(error);
 
5054
  }
 
5055
 
 
5056
  /* Note that we assume the length of the row reference is fixed
 
5057
  for the table, and it is == ref_length */
 
5058
 
 
5059
  error = index_read(buf, pos, ref_length, HA_READ_KEY_EXACT);
 
5060
 
 
5061
  if (error) {
 
5062
  }
 
5063
 
 
5064
  change_active_index(keynr);
 
5065
 
 
5066
  return(error);
5004
5067
}
5005
5068
 
5006
5069
/*********************************************************************//**
5015
5078
void
5016
5079
ha_innobase::position(
5017
5080
/*==================*/
5018
 
        const unsigned char*    record) /*!< in: row in MySQL format */
 
5081
  const unsigned char*  record) /*!< in: row in MySQL format */
5019
5082
{
5020
 
        uint            len;
5021
 
 
5022
 
        ut_a(prebuilt->trx == session_to_trx(ha_session()));
5023
 
 
5024
 
        if (prebuilt->clust_index_was_generated) {
5025
 
                /* No primary key was defined for the table and we
5026
 
                generated the clustered index from row id: the
5027
 
                row reference will be the row id, not any key value
5028
 
                that MySQL knows of */
5029
 
 
5030
 
                len = DATA_ROW_ID_LEN;
5031
 
 
5032
 
                memcpy(ref, prebuilt->row_id, len);
5033
 
        } else {
5034
 
                len = store_key_val_for_row(primary_key, (char*)ref,
5035
 
                                                         ref_length, record);
5036
 
        }
5037
 
 
5038
 
        /* We assume that the 'ref' value len is always fixed for the same
5039
 
        table. */
5040
 
 
5041
 
        if (len != ref_length) {
5042
 
          errmsg_printf(ERRMSG_LVL_ERROR, "Stored ref len is %lu, but table ref len is %lu",
5043
 
                          (ulong) len, (ulong) ref_length);
5044
 
        }
 
5083
  uint    len;
 
5084
 
 
5085
  ut_a(prebuilt->trx == session_to_trx(ha_session()));
 
5086
 
 
5087
  if (prebuilt->clust_index_was_generated) {
 
5088
    /* No primary key was defined for the table and we
 
5089
    generated the clustered index from row id: the
 
5090
    row reference will be the row id, not any key value
 
5091
    that MySQL knows of */
 
5092
 
 
5093
    len = DATA_ROW_ID_LEN;
 
5094
 
 
5095
    memcpy(ref, prebuilt->row_id, len);
 
5096
  } else {
 
5097
    len = store_key_val_for_row(primary_key, (char*)ref,
 
5098
               ref_length, record);
 
5099
  }
 
5100
 
 
5101
  /* We assume that the 'ref' value len is always fixed for the same
 
5102
  table. */
 
5103
 
 
5104
  if (len != ref_length) {
 
5105
    errmsg_printf(ERRMSG_LVL_ERROR, "Stored ref len is %lu, but table ref len is %lu",
 
5106
        (ulong) len, (ulong) ref_length);
 
5107
  }
5045
5108
}
5046
5109
 
5047
5110
 
5051
5114
int
5052
5115
create_table_def(
5053
5116
/*=============*/
5054
 
        trx_t*          trx,            /*!< in: InnoDB transaction handle */
5055
 
        Table*          form,           /*!< in: information on table
5056
 
                                        columns and indexes */
5057
 
        const char*     table_name,     /*!< in: table name */
5058
 
        const char*     path_of_temp_table,/*!< in: if this is a table explicitly
5059
 
                                        created by the user with the
5060
 
                                        TEMPORARY keyword, then this
5061
 
                                        parameter is the dir path where the
5062
 
                                        table should be placed if we create
5063
 
                                        an .ibd file for it (no .ibd extension
5064
 
                                        in the path, though); otherwise this
5065
 
                                        is NULL */
5066
 
        ulint           flags)          /*!< in: table flags */
 
5117
  trx_t*    trx,    /*!< in: InnoDB transaction handle */
 
5118
  Table*    form,   /*!< in: information on table
 
5119
          columns and indexes */
 
5120
  const char* table_name, /*!< in: table name */
 
5121
  const char* path_of_temp_table,/*!< in: if this is a table explicitly
 
5122
          created by the user with the
 
5123
          TEMPORARY keyword, then this
 
5124
          parameter is the dir path where the
 
5125
          table should be placed if we create
 
5126
          an .ibd file for it (no .ibd extension
 
5127
          in the path, though); otherwise this
 
5128
          is NULL */
 
5129
  ulint   flags)    /*!< in: table flags */
5067
5130
{
5068
 
        Field*          field;
5069
 
        dict_table_t*   table;
5070
 
        ulint           n_cols;
5071
 
        int             error;
5072
 
        ulint           col_type;
5073
 
        ulint           col_len;
5074
 
        ulint           nulls_allowed;
5075
 
        ulint           unsigned_type;
5076
 
        ulint           binary_type;
5077
 
        ulint           long_true_varchar;
5078
 
        ulint           charset_no;
5079
 
        ulint           i;
5080
 
 
5081
 
        n_cols = form->s->fields;
5082
 
 
5083
 
        /* We pass 0 as the space id, and determine at a lower level the space
5084
 
        id where to store the table */
5085
 
 
5086
 
        table = dict_mem_table_create(table_name, 0, n_cols, flags);
5087
 
 
5088
 
        if (path_of_temp_table) {
5089
 
                table->dir_path_of_temp_table =
5090
 
                        mem_heap_strdup(table->heap, path_of_temp_table);
5091
 
        }
5092
 
 
5093
 
        for (i = 0; i < n_cols; i++) {
5094
 
                field = form->field[i];
5095
 
 
5096
 
                col_type = get_innobase_type_from_mysql_type(&unsigned_type,
5097
 
                                                                        field);
5098
 
                if (field->null_ptr) {
5099
 
                        nulls_allowed = 0;
5100
 
                } else {
5101
 
                        nulls_allowed = DATA_NOT_NULL;
5102
 
                }
5103
 
 
5104
 
                if (field->binary()) {
5105
 
                        binary_type = DATA_BINARY_TYPE;
5106
 
                } else {
5107
 
                        binary_type = 0;
5108
 
                }
5109
 
 
5110
 
                charset_no = 0;
5111
 
 
5112
 
                if (dtype_is_string_type(col_type)) {
5113
 
 
5114
 
                        charset_no = (ulint)field->charset()->number;
5115
 
 
5116
 
                        if (UNIV_UNLIKELY(charset_no >= 256)) {
5117
 
                                /* in data0type.h we assume that the
5118
 
                                number fits in one byte in prtype */
5119
 
                                push_warning_printf(
5120
 
                                        (Session*) trx->mysql_thd,
5121
 
                                        DRIZZLE_ERROR::WARN_LEVEL_ERROR,
5122
 
                                        ER_CANT_CREATE_TABLE,
5123
 
                                        "In InnoDB, charset-collation codes"
5124
 
                                        " must be below 256."
5125
 
                                        " Unsupported code %lu.",
5126
 
                                        (ulong) charset_no);
5127
 
                                return(ER_CANT_CREATE_TABLE);
5128
 
                        }
5129
 
                }
5130
 
 
5131
 
                ut_a(field->type() < 256); /* we assume in dtype_form_prtype()
5132
 
                                           that this fits in one byte */
5133
 
                col_len = field->pack_length();
5134
 
 
5135
 
                /* The MySQL pack length contains 1 or 2 bytes length field
5136
 
                for a true VARCHAR. Let us subtract that, so that the InnoDB
5137
 
                column length in the InnoDB data dictionary is the real
5138
 
                maximum byte length of the actual data. */
5139
 
 
5140
 
                long_true_varchar = 0;
5141
 
 
5142
 
                if (field->type() == DRIZZLE_TYPE_VARCHAR) {
5143
 
                        col_len -= ((Field_varstring*)field)->length_bytes;
5144
 
 
5145
 
                        if (((Field_varstring*)field)->length_bytes == 2) {
5146
 
                                long_true_varchar = DATA_LONG_TRUE_VARCHAR;
5147
 
                        }
5148
 
                }
5149
 
 
5150
 
                dict_mem_table_add_col(table, table->heap,
5151
 
                        (char*) field->field_name,
5152
 
                        col_type,
5153
 
                        dtype_form_prtype(
5154
 
                                (ulint)field->type()
5155
 
                                | nulls_allowed | unsigned_type
5156
 
                                | binary_type | long_true_varchar,
5157
 
                                charset_no),
5158
 
                        col_len);
5159
 
        }
5160
 
 
5161
 
        error = row_create_table_for_mysql(table, trx);
5162
 
 
5163
 
        error = convert_error_code_to_mysql(error, flags, NULL);
5164
 
 
5165
 
        return(error);
 
5131
  Field*    field;
 
5132
  dict_table_t* table;
 
5133
  ulint   n_cols;
 
5134
  int   error;
 
5135
  ulint   col_type;
 
5136
  ulint   col_len;
 
5137
  ulint   nulls_allowed;
 
5138
  ulint   unsigned_type;
 
5139
  ulint   binary_type;
 
5140
  ulint   long_true_varchar;
 
5141
  ulint   charset_no;
 
5142
  ulint   i;
 
5143
 
 
5144
  n_cols = form->s->fields;
 
5145
 
 
5146
  /* We pass 0 as the space id, and determine at a lower level the space
 
5147
  id where to store the table */
 
5148
 
 
5149
  table = dict_mem_table_create(table_name, 0, n_cols, flags);
 
5150
 
 
5151
  if (path_of_temp_table) {
 
5152
    table->dir_path_of_temp_table =
 
5153
      mem_heap_strdup(table->heap, path_of_temp_table);
 
5154
  }
 
5155
 
 
5156
  for (i = 0; i < n_cols; i++) {
 
5157
    field = form->field[i];
 
5158
 
 
5159
    col_type = get_innobase_type_from_mysql_type(&unsigned_type,
 
5160
                  field);
 
5161
    if (field->null_ptr) {
 
5162
      nulls_allowed = 0;
 
5163
    } else {
 
5164
      nulls_allowed = DATA_NOT_NULL;
 
5165
    }
 
5166
 
 
5167
    if (field->binary()) {
 
5168
      binary_type = DATA_BINARY_TYPE;
 
5169
    } else {
 
5170
      binary_type = 0;
 
5171
    }
 
5172
 
 
5173
    charset_no = 0;
 
5174
 
 
5175
    if (dtype_is_string_type(col_type)) {
 
5176
 
 
5177
      charset_no = (ulint)field->charset()->number;
 
5178
 
 
5179
      if (UNIV_UNLIKELY(charset_no >= 256)) {
 
5180
        /* in data0type.h we assume that the
 
5181
        number fits in one byte in prtype */
 
5182
        push_warning_printf(
 
5183
          (Session*) trx->mysql_thd,
 
5184
          DRIZZLE_ERROR::WARN_LEVEL_ERROR,
 
5185
          ER_CANT_CREATE_TABLE,
 
5186
          "In InnoDB, charset-collation codes"
 
5187
          " must be below 256."
 
5188
          " Unsupported code %lu.",
 
5189
          (ulong) charset_no);
 
5190
        return(ER_CANT_CREATE_TABLE);
 
5191
      }
 
5192
    }
 
5193
 
 
5194
    ut_a(field->type() < 256); /* we assume in dtype_form_prtype()
 
5195
             that this fits in one byte */
 
5196
    col_len = field->pack_length();
 
5197
 
 
5198
    /* The MySQL pack length contains 1 or 2 bytes length field
 
5199
    for a true VARCHAR. Let us subtract that, so that the InnoDB
 
5200
    column length in the InnoDB data dictionary is the real
 
5201
    maximum byte length of the actual data. */
 
5202
 
 
5203
    long_true_varchar = 0;
 
5204
 
 
5205
    if (field->type() == DRIZZLE_TYPE_VARCHAR) {
 
5206
      col_len -= ((Field_varstring*)field)->length_bytes;
 
5207
 
 
5208
      if (((Field_varstring*)field)->length_bytes == 2) {
 
5209
        long_true_varchar = DATA_LONG_TRUE_VARCHAR;
 
5210
      }
 
5211
    }
 
5212
 
 
5213
    dict_mem_table_add_col(table, table->heap,
 
5214
      (char*) field->field_name,
 
5215
      col_type,
 
5216
      dtype_form_prtype(
 
5217
        (ulint)field->type()
 
5218
        | nulls_allowed | unsigned_type
 
5219
        | binary_type | long_true_varchar,
 
5220
        charset_no),
 
5221
      col_len);
 
5222
  }
 
5223
 
 
5224
  error = row_create_table_for_mysql(table, trx);
 
5225
 
 
5226
  error = convert_error_code_to_mysql(error, flags, NULL);
 
5227
 
 
5228
  return(error);
5166
5229
}
5167
5230
 
5168
5231
/*****************************************************************//**
5171
5234
int
5172
5235
create_index(
5173
5236
/*=========*/
5174
 
        trx_t*          trx,            /*!< in: InnoDB transaction handle */
5175
 
        Table*          form,           /*!< in: information on table
5176
 
                                        columns and indexes */
5177
 
        ulint           flags,          /*!< in: InnoDB table flags */
5178
 
        const char*     table_name,     /*!< in: table name */
5179
 
        uint            key_num)        /*!< in: index number */
 
5237
  trx_t*    trx,    /*!< in: InnoDB transaction handle */
 
5238
  Table*    form,   /*!< in: information on table
 
5239
          columns and indexes */
 
5240
  ulint   flags,    /*!< in: InnoDB table flags */
 
5241
  const char* table_name, /*!< in: table name */
 
5242
  uint    key_num)  /*!< in: index number */
5180
5243
{
5181
 
        Field*          field;
5182
 
        dict_index_t*   index;
5183
 
        int             error;
5184
 
        ulint           n_fields;
5185
 
        KEY*            key;
5186
 
        KEY_PART_INFO*  key_part;
5187
 
        ulint           ind_type;
5188
 
        ulint           col_type;
5189
 
        ulint           prefix_len;
5190
 
        ulint           is_unsigned;
5191
 
        ulint           i;
5192
 
        ulint           j;
5193
 
        ulint*          field_lengths;
5194
 
 
5195
 
        key = form->key_info + key_num;
5196
 
 
5197
 
        n_fields = key->key_parts;
5198
 
 
5199
 
        ind_type = 0;
5200
 
 
5201
 
        if (key_num == form->s->primary_key) {
5202
 
                ind_type = ind_type | DICT_CLUSTERED;
5203
 
        }
5204
 
 
5205
 
        if (key->flags & HA_NOSAME ) {
5206
 
                ind_type = ind_type | DICT_UNIQUE;
5207
 
        }
5208
 
 
5209
 
        /* We pass 0 as the space id, and determine at a lower level the space
5210
 
        id where to store the table */
5211
 
 
5212
 
        index = dict_mem_index_create(table_name, key->name, 0,
5213
 
                                      ind_type, n_fields);
5214
 
 
5215
 
        field_lengths = (ulint*) malloc(sizeof(ulint) * n_fields);
5216
 
 
5217
 
        for (i = 0; i < n_fields; i++) {
5218
 
                key_part = key->key_part + i;
5219
 
 
5220
 
                /* (The flag HA_PART_KEY_SEG denotes in MySQL a column prefix
5221
 
                field in an index: we only store a specified number of first
5222
 
                bytes of the column to the index field.) The flag does not
5223
 
                seem to be properly set by MySQL. Let us fall back on testing
5224
 
                the length of the key part versus the column. */
5225
 
 
5226
 
                field = NULL;
5227
 
                for (j = 0; j < form->s->fields; j++) {
5228
 
 
5229
 
                        field = form->field[j];
5230
 
 
5231
 
                        if (0 == innobase_strcasecmp(
5232
 
                                        field->field_name,
5233
 
                                        key_part->field->field_name)) {
5234
 
                                /* Found the corresponding column */
5235
 
 
5236
 
                                break;
5237
 
                        }
5238
 
                }
5239
 
 
5240
 
                ut_a(j < form->s->fields);
5241
 
 
5242
 
                col_type = get_innobase_type_from_mysql_type(
5243
 
                                        &is_unsigned, key_part->field);
5244
 
 
5245
 
                if (DATA_BLOB == col_type
5246
 
                        || (key_part->length < field->pack_length()
5247
 
                                && field->type() != DRIZZLE_TYPE_VARCHAR)
5248
 
                        || (field->type() == DRIZZLE_TYPE_VARCHAR
5249
 
                                && key_part->length < field->pack_length()
5250
 
                                - ((Field_varstring*)field)->length_bytes)) {
5251
 
 
5252
 
                        prefix_len = key_part->length;
5253
 
 
5254
 
                        if (col_type == DATA_INT
5255
 
                                || col_type == DATA_FLOAT
5256
 
                                || col_type == DATA_DOUBLE
5257
 
                                || col_type == DATA_DECIMAL) {
5258
 
                                errmsg_printf(ERRMSG_LVL_ERROR, 
5259
 
                                        "MySQL is trying to create a column "
5260
 
                                        "prefix index field, on an "
5261
 
                                        "inappropriate data type. Table "
5262
 
                                        "name %s, column name %s.",
5263
 
                                        table_name,
5264
 
                                        key_part->field->field_name);
5265
 
 
5266
 
                                prefix_len = 0;
5267
 
                        }
5268
 
                } else {
5269
 
                        prefix_len = 0;
5270
 
                }
5271
 
 
5272
 
                field_lengths[i] = key_part->length;
5273
 
 
5274
 
                dict_mem_index_add_field(index,
5275
 
                        (char*) key_part->field->field_name, prefix_len);
5276
 
        }
5277
 
 
5278
 
        /* Even though we've defined max_supported_key_part_length, we
5279
 
        still do our own checking using field_lengths to be absolutely
5280
 
        sure we don't create too long indexes. */
5281
 
        error = row_create_index_for_mysql(index, trx, field_lengths);
5282
 
 
5283
 
        error = convert_error_code_to_mysql(error, flags, NULL);
5284
 
 
5285
 
        free(field_lengths);
5286
 
 
5287
 
        return(error);
 
5244
  Field*    field;
 
5245
  dict_index_t* index;
 
5246
  int   error;
 
5247
  ulint   n_fields;
 
5248
  KEY*    key;
 
5249
  KEY_PART_INFO*  key_part;
 
5250
  ulint   ind_type;
 
5251
  ulint   col_type;
 
5252
  ulint   prefix_len;
 
5253
  ulint   is_unsigned;
 
5254
  ulint   i;
 
5255
  ulint   j;
 
5256
  ulint*    field_lengths;
 
5257
 
 
5258
  key = form->key_info + key_num;
 
5259
 
 
5260
  n_fields = key->key_parts;
 
5261
 
 
5262
  ind_type = 0;
 
5263
 
 
5264
  if (key_num == form->s->primary_key) {
 
5265
    ind_type = ind_type | DICT_CLUSTERED;
 
5266
  }
 
5267
 
 
5268
  if (key->flags & HA_NOSAME ) {
 
5269
    ind_type = ind_type | DICT_UNIQUE;
 
5270
  }
 
5271
 
 
5272
  /* We pass 0 as the space id, and determine at a lower level the space
 
5273
  id where to store the table */
 
5274
 
 
5275
  index = dict_mem_index_create(table_name, key->name, 0,
 
5276
              ind_type, n_fields);
 
5277
 
 
5278
  field_lengths = (ulint*) malloc(sizeof(ulint) * n_fields);
 
5279
 
 
5280
  for (i = 0; i < n_fields; i++) {
 
5281
    key_part = key->key_part + i;
 
5282
 
 
5283
    /* (The flag HA_PART_KEY_SEG denotes in MySQL a column prefix
 
5284
    field in an index: we only store a specified number of first
 
5285
    bytes of the column to the index field.) The flag does not
 
5286
    seem to be properly set by MySQL. Let us fall back on testing
 
5287
    the length of the key part versus the column. */
 
5288
 
 
5289
    field = NULL;
 
5290
    for (j = 0; j < form->s->fields; j++) {
 
5291
 
 
5292
      field = form->field[j];
 
5293
 
 
5294
      if (0 == innobase_strcasecmp(
 
5295
          field->field_name,
 
5296
          key_part->field->field_name)) {
 
5297
        /* Found the corresponding column */
 
5298
 
 
5299
        break;
 
5300
      }
 
5301
    }
 
5302
 
 
5303
    ut_a(j < form->s->fields);
 
5304
 
 
5305
    col_type = get_innobase_type_from_mysql_type(
 
5306
          &is_unsigned, key_part->field);
 
5307
 
 
5308
    if (DATA_BLOB == col_type
 
5309
      || (key_part->length < field->pack_length()
 
5310
        && field->type() != DRIZZLE_TYPE_VARCHAR)
 
5311
      || (field->type() == DRIZZLE_TYPE_VARCHAR
 
5312
        && key_part->length < field->pack_length()
 
5313
        - ((Field_varstring*)field)->length_bytes)) {
 
5314
 
 
5315
      prefix_len = key_part->length;
 
5316
 
 
5317
      if (col_type == DATA_INT
 
5318
        || col_type == DATA_FLOAT
 
5319
        || col_type == DATA_DOUBLE
 
5320
        || col_type == DATA_DECIMAL) {
 
5321
        errmsg_printf(ERRMSG_LVL_ERROR, 
 
5322
          "MySQL is trying to create a column "
 
5323
          "prefix index field, on an "
 
5324
          "inappropriate data type. Table "
 
5325
          "name %s, column name %s.",
 
5326
          table_name,
 
5327
          key_part->field->field_name);
 
5328
 
 
5329
        prefix_len = 0;
 
5330
      }
 
5331
    } else {
 
5332
      prefix_len = 0;
 
5333
    }
 
5334
 
 
5335
    field_lengths[i] = key_part->length;
 
5336
 
 
5337
    dict_mem_index_add_field(index,
 
5338
      (char*) key_part->field->field_name, prefix_len);
 
5339
  }
 
5340
 
 
5341
  /* Even though we've defined max_supported_key_part_length, we
 
5342
  still do our own checking using field_lengths to be absolutely
 
5343
  sure we don't create too long indexes. */
 
5344
  error = row_create_index_for_mysql(index, trx, field_lengths);
 
5345
 
 
5346
  error = convert_error_code_to_mysql(error, flags, NULL);
 
5347
 
 
5348
  free(field_lengths);
 
5349
 
 
5350
  return(error);
5288
5351
}
5289
5352
 
5290
5353
/*****************************************************************//**
5294
5357
int
5295
5358
create_clustered_index_when_no_primary(
5296
5359
/*===================================*/
5297
 
        trx_t*          trx,            /*!< in: InnoDB transaction handle */
5298
 
        ulint           flags,          /*!< in: InnoDB table flags */
5299
 
        const char*     table_name)     /*!< in: table name */
 
5360
  trx_t*    trx,    /*!< in: InnoDB transaction handle */
 
5361
  ulint   flags,    /*!< in: InnoDB table flags */
 
5362
  const char* table_name) /*!< in: table name */
5300
5363
{
5301
 
        dict_index_t*   index;
5302
 
        int             error;
5303
 
 
5304
 
        /* We pass 0 as the space id, and determine at a lower level the space
5305
 
        id where to store the table */
5306
 
 
5307
 
        index = dict_mem_index_create(table_name, "GEN_CLUST_INDEX",
5308
 
                                      0, DICT_CLUSTERED, 0);
5309
 
 
5310
 
        error = row_create_index_for_mysql(index, trx, NULL);
5311
 
 
5312
 
        error = convert_error_code_to_mysql(error, flags, NULL);
5313
 
 
5314
 
        return(error);
 
5364
  dict_index_t* index;
 
5365
  int   error;
 
5366
 
 
5367
  /* We pass 0 as the space id, and determine at a lower level the space
 
5368
  id where to store the table */
 
5369
 
 
5370
  index = dict_mem_index_create(table_name, "GEN_CLUST_INDEX",
 
5371
              0, DICT_CLUSTERED, 0);
 
5372
 
 
5373
  error = row_create_index_for_mysql(index, trx, NULL);
 
5374
 
 
5375
  error = convert_error_code_to_mysql(error, flags, NULL);
 
5376
 
 
5377
  return(error);
5315
5378
}
5316
5379
 
5317
5380
/*****************************************************************//**
5319
5382
in future. For now, it checks two specifiers:
5320
5383
KEY_BLOCK_SIZE and ROW_FORMAT
5321
5384
If innodb_strict_mode is not set then this function is a no-op
5322
 
@return TRUE if valid. */
 
5385
@return TRUE if valid. */
5323
5386
static
5324
5387
ibool
5325
5388
create_options_are_valid(
5326
5389
/*=====================*/
5327
 
        Session*        session,        /*!< in: connection thread. */
5328
 
        Table&          form,           /*!< in: information on table
5329
 
                                        columns and indexes */
 
5390
  Session*  session,  /*!< in: connection thread. */
 
5391
  Table&    form,   /*!< in: information on table
 
5392
          columns and indexes */
5330
5393
        message::Table& create_proto)
5331
5394
{
5332
 
        ibool   kbs_specified   = FALSE;
5333
 
        ibool   ret             = TRUE;
5334
 
 
5335
 
 
5336
 
        ut_ad(session != NULL);
5337
 
 
5338
 
        /* If innodb_strict_mode is not set don't do any validation. */
5339
 
        if (!(SessionVAR(session, strict_mode))) {
5340
 
                return(TRUE);
5341
 
        }
5342
 
 
5343
 
        /* First check if KEY_BLOCK_SIZE was specified. */
5344
 
        if (create_proto.options().has_key_block_size()) {
5345
 
 
5346
 
                kbs_specified = TRUE;
5347
 
                switch (create_proto.options().key_block_size()) {
5348
 
                case 1:
5349
 
                case 2:
5350
 
                case 4:
5351
 
                case 8:
5352
 
                case 16:
5353
 
                        /* Valid value. */
5354
 
                        break;
5355
 
                default:
5356
 
                        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
5357
 
                                            ER_ILLEGAL_HA_CREATE_OPTION,
5358
 
                                            "InnoDB: invalid"
5359
 
                                            " KEY_BLOCK_SIZE = %lu."
5360
 
                                            " Valid values are"
5361
 
                                            " [1, 2, 4, 8, 16]",
5362
 
                                            create_proto.options().key_block_size());
5363
 
                        ret = FALSE;
5364
 
                }
5365
 
        }
5366
 
        
5367
 
        /* If KEY_BLOCK_SIZE was specified, check for its
5368
 
        dependencies. */
5369
 
        if (kbs_specified && !srv_file_per_table) {
5370
 
                push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
5371
 
                             ER_ILLEGAL_HA_CREATE_OPTION,
5372
 
                             "InnoDB: KEY_BLOCK_SIZE"
5373
 
                             " requires innodb_file_per_table.");
5374
 
                ret = FALSE;
5375
 
        }
5376
 
 
5377
 
        if (kbs_specified && srv_file_format < DICT_TF_FORMAT_ZIP) {
5378
 
                push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
5379
 
                             ER_ILLEGAL_HA_CREATE_OPTION,
5380
 
                             "InnoDB: KEY_BLOCK_SIZE"
5381
 
                             " requires innodb_file_format >"
5382
 
                             " Antelope.");
5383
 
                ret = FALSE;
5384
 
        }
5385
 
 
5386
 
        /* Now check for ROW_FORMAT specifier. */
5387
 
        if (create_proto.options().has_row_type()) {
5388
 
                switch (form.s->row_type) {
5389
 
                        const char* row_format_name;
5390
 
                case ROW_TYPE_COMPRESSED:
5391
 
                case ROW_TYPE_DYNAMIC:
5392
 
                        row_format_name
5393
 
                                = form.s->row_type == ROW_TYPE_COMPRESSED
5394
 
                                ? "COMPRESSED"
5395
 
                                : "DYNAMIC";
5396
 
 
5397
 
                        /* These two ROW_FORMATs require
5398
 
                        srv_file_per_table and srv_file_format */
5399
 
                        if (!srv_file_per_table) {
5400
 
                                push_warning_printf(
5401
 
                                        session,
5402
 
                                        DRIZZLE_ERROR::WARN_LEVEL_ERROR,
5403
 
                                        ER_ILLEGAL_HA_CREATE_OPTION,
5404
 
                                        "InnoDB: ROW_FORMAT=%s"
5405
 
                                        " requires innodb_file_per_table.",
5406
 
                                        row_format_name);
5407
 
                                        ret = FALSE;
5408
 
 
5409
 
                        }
5410
 
 
5411
 
                        if (srv_file_format < DICT_TF_FORMAT_ZIP) {
5412
 
                                push_warning_printf(
5413
 
                                        session,
5414
 
                                        DRIZZLE_ERROR::WARN_LEVEL_ERROR,
5415
 
                                        ER_ILLEGAL_HA_CREATE_OPTION,
5416
 
                                        "InnoDB: ROW_FORMAT=%s"
5417
 
                                        " requires innodb_file_format >"
5418
 
                                        " Antelope.",
5419
 
                                        row_format_name);
5420
 
                                        ret = FALSE;
5421
 
                        }
5422
 
 
5423
 
                        /* Cannot specify KEY_BLOCK_SIZE with
5424
 
                        ROW_FORMAT = DYNAMIC.
5425
 
                        However, we do allow COMPRESSED to be
5426
 
                        specified with KEY_BLOCK_SIZE. */
5427
 
                        if (kbs_specified
5428
 
                            && form.s->row_type == ROW_TYPE_DYNAMIC) {
5429
 
                                push_warning_printf(
5430
 
                                        session,
5431
 
                                        DRIZZLE_ERROR::WARN_LEVEL_ERROR,
5432
 
                                        ER_ILLEGAL_HA_CREATE_OPTION,
5433
 
                                        "InnoDB: cannot specify"
5434
 
                                        " ROW_FORMAT = DYNAMIC with"
5435
 
                                        " KEY_BLOCK_SIZE.");
5436
 
                                        ret = FALSE;
5437
 
                        }
5438
 
 
5439
 
                        break;
5440
 
 
5441
 
                case ROW_TYPE_REDUNDANT:
5442
 
                case ROW_TYPE_COMPACT:
5443
 
                case ROW_TYPE_DEFAULT:
5444
 
                        /* Default is COMPACT. */
5445
 
                        row_format_name
5446
 
                                = form.s->row_type == ROW_TYPE_REDUNDANT
5447
 
                                ? "REDUNDANT"
5448
 
                                : "COMPACT";
5449
 
 
5450
 
                        /* Cannot specify KEY_BLOCK_SIZE with these
5451
 
                        format specifiers. */
5452
 
                        if (kbs_specified) {
5453
 
                                push_warning_printf(
5454
 
                                        session,
5455
 
                                        DRIZZLE_ERROR::WARN_LEVEL_ERROR,
5456
 
                                        ER_ILLEGAL_HA_CREATE_OPTION,
5457
 
                                        "InnoDB: cannot specify"
5458
 
                                        " ROW_FORMAT = %s with"
5459
 
                                        " KEY_BLOCK_SIZE.",
5460
 
                                        row_format_name);
5461
 
                                        ret = FALSE;
5462
 
                        }
5463
 
 
5464
 
                        break;
5465
 
 
5466
 
                default:
5467
 
                        push_warning(session,
5468
 
                                     DRIZZLE_ERROR::WARN_LEVEL_ERROR,
5469
 
                                     ER_ILLEGAL_HA_CREATE_OPTION,
5470
 
                                     "InnoDB: invalid ROW_FORMAT specifier.");
5471
 
                        ret = FALSE;
5472
 
 
5473
 
                }
5474
 
        }
5475
 
 
5476
 
        return(ret);
 
5395
  ibool kbs_specified = FALSE;
 
5396
  ibool ret   = TRUE;
 
5397
 
 
5398
 
 
5399
  ut_ad(session != NULL);
 
5400
 
 
5401
  /* If innodb_strict_mode is not set don't do any validation. */
 
5402
  if (!(SessionVAR(session, strict_mode))) {
 
5403
    return(TRUE);
 
5404
  }
 
5405
 
 
5406
  /* First check if KEY_BLOCK_SIZE was specified. */
 
5407
  if (create_proto.options().has_key_block_size()) {
 
5408
 
 
5409
    kbs_specified = TRUE;
 
5410
    switch (create_proto.options().key_block_size()) {
 
5411
    case 1:
 
5412
    case 2:
 
5413
    case 4:
 
5414
    case 8:
 
5415
    case 16:
 
5416
      /* Valid value. */
 
5417
      break;
 
5418
    default:
 
5419
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
 
5420
              ER_ILLEGAL_HA_CREATE_OPTION,
 
5421
              "InnoDB: invalid"
 
5422
              " KEY_BLOCK_SIZE = %lu."
 
5423
              " Valid values are"
 
5424
              " [1, 2, 4, 8, 16]",
 
5425
              create_proto.options().key_block_size());
 
5426
      ret = FALSE;
 
5427
    }
 
5428
  }
 
5429
  
 
5430
  /* If KEY_BLOCK_SIZE was specified, check for its
 
5431
  dependencies. */
 
5432
  if (kbs_specified && !srv_file_per_table) {
 
5433
    push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
 
5434
           ER_ILLEGAL_HA_CREATE_OPTION,
 
5435
           "InnoDB: KEY_BLOCK_SIZE"
 
5436
           " requires innodb_file_per_table.");
 
5437
    ret = FALSE;
 
5438
  }
 
5439
 
 
5440
  if (kbs_specified && srv_file_format < DICT_TF_FORMAT_ZIP) {
 
5441
    push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
 
5442
           ER_ILLEGAL_HA_CREATE_OPTION,
 
5443
           "InnoDB: KEY_BLOCK_SIZE"
 
5444
           " requires innodb_file_format >"
 
5445
           " Antelope.");
 
5446
    ret = FALSE;
 
5447
  }
 
5448
 
 
5449
  /* Now check for ROW_FORMAT specifier. */
 
5450
  if (create_proto.options().has_row_type()) {
 
5451
    switch (form.s->row_type) {
 
5452
      const char* row_format_name;
 
5453
    case ROW_TYPE_COMPRESSED:
 
5454
    case ROW_TYPE_DYNAMIC:
 
5455
      row_format_name
 
5456
        = form.s->row_type == ROW_TYPE_COMPRESSED
 
5457
        ? "COMPRESSED"
 
5458
        : "DYNAMIC";
 
5459
 
 
5460
      /* These two ROW_FORMATs require
 
5461
      srv_file_per_table and srv_file_format */
 
5462
      if (!srv_file_per_table) {
 
5463
        push_warning_printf(
 
5464
          session,
 
5465
          DRIZZLE_ERROR::WARN_LEVEL_ERROR,
 
5466
          ER_ILLEGAL_HA_CREATE_OPTION,
 
5467
          "InnoDB: ROW_FORMAT=%s"
 
5468
          " requires innodb_file_per_table.",
 
5469
          row_format_name);
 
5470
          ret = FALSE;
 
5471
 
 
5472
      }
 
5473
 
 
5474
      if (srv_file_format < DICT_TF_FORMAT_ZIP) {
 
5475
        push_warning_printf(
 
5476
          session,
 
5477
          DRIZZLE_ERROR::WARN_LEVEL_ERROR,
 
5478
          ER_ILLEGAL_HA_CREATE_OPTION,
 
5479
          "InnoDB: ROW_FORMAT=%s"
 
5480
          " requires innodb_file_format >"
 
5481
          " Antelope.",
 
5482
          row_format_name);
 
5483
          ret = FALSE;
 
5484
      }
 
5485
 
 
5486
      /* Cannot specify KEY_BLOCK_SIZE with
 
5487
      ROW_FORMAT = DYNAMIC.
 
5488
      However, we do allow COMPRESSED to be
 
5489
      specified with KEY_BLOCK_SIZE. */
 
5490
      if (kbs_specified
 
5491
          && form.s->row_type == ROW_TYPE_DYNAMIC) {
 
5492
        push_warning_printf(
 
5493
          session,
 
5494
          DRIZZLE_ERROR::WARN_LEVEL_ERROR,
 
5495
          ER_ILLEGAL_HA_CREATE_OPTION,
 
5496
          "InnoDB: cannot specify"
 
5497
          " ROW_FORMAT = DYNAMIC with"
 
5498
          " KEY_BLOCK_SIZE.");
 
5499
          ret = FALSE;
 
5500
      }
 
5501
 
 
5502
      break;
 
5503
 
 
5504
    case ROW_TYPE_REDUNDANT:
 
5505
    case ROW_TYPE_COMPACT:
 
5506
    case ROW_TYPE_DEFAULT:
 
5507
      /* Default is COMPACT. */
 
5508
      row_format_name
 
5509
        = form.s->row_type == ROW_TYPE_REDUNDANT
 
5510
        ? "REDUNDANT"
 
5511
        : "COMPACT";
 
5512
 
 
5513
      /* Cannot specify KEY_BLOCK_SIZE with these
 
5514
      format specifiers. */
 
5515
      if (kbs_specified) {
 
5516
        push_warning_printf(
 
5517
          session,
 
5518
          DRIZZLE_ERROR::WARN_LEVEL_ERROR,
 
5519
          ER_ILLEGAL_HA_CREATE_OPTION,
 
5520
          "InnoDB: cannot specify"
 
5521
          " ROW_FORMAT = %s with"
 
5522
          " KEY_BLOCK_SIZE.",
 
5523
          row_format_name);
 
5524
          ret = FALSE;
 
5525
      }
 
5526
 
 
5527
      break;
 
5528
 
 
5529
    default:
 
5530
      push_warning(session,
 
5531
             DRIZZLE_ERROR::WARN_LEVEL_ERROR,
 
5532
             ER_ILLEGAL_HA_CREATE_OPTION,
 
5533
             "InnoDB: invalid ROW_FORMAT specifier.");
 
5534
      ret = FALSE;
 
5535
 
 
5536
    }
 
5537
  }
 
5538
 
 
5539
  return(ret);
5477
5540
}
5478
5541
 
5479
5542
/*********************************************************************
5482
5545
int
5483
5546
InnobaseEngine::doCreateTable(
5484
5547
/*================*/
5485
 
        Session*        session,        /*!< in: Session */
5486
 
        const char*     table_name,     /*!< in: table name */
5487
 
        Table&          form,           /*!< in: information on table
5488
 
                                        columns and indexes */
 
5548
  Session         &session, /*!< in: Session */
 
5549
  Table&    form,   /*!< in: information on table columns and indexes */
 
5550
        drizzled::TableIdentifier &identifier,
5489
5551
        message::Table& create_proto)
5490
5552
{
5491
 
        int             error;
5492
 
        dict_table_t*   innobase_table;
5493
 
        trx_t*          parent_trx;
5494
 
        trx_t*          trx;
5495
 
        int             primary_key_no;
5496
 
        uint            i;
5497
 
        char            name2[FN_REFLEN];
5498
 
        char            norm_name[FN_REFLEN];
5499
 
        ib_int64_t      auto_inc_value;
5500
 
        ulint           iflags;
5501
 
        /* Cache the value of innodb_file_format, in case it is
5502
 
        modified by another thread while the table is being created. */
5503
 
        const ulint     file_format = srv_file_format;
 
5553
  int   error;
 
5554
  dict_table_t* innobase_table;
 
5555
  trx_t*    parent_trx;
 
5556
  trx_t*    trx;
 
5557
  int   primary_key_no;
 
5558
  uint    i;
 
5559
  char    name2[FN_REFLEN];
 
5560
  char    norm_name[FN_REFLEN];
 
5561
  ib_int64_t  auto_inc_value;
 
5562
  ulint   iflags;
 
5563
  /* Cache the value of innodb_file_format, in case it is
 
5564
  modified by another thread while the table is being created. */
 
5565
  const ulint file_format = srv_file_format;
5504
5566
        bool lex_identified_temp_table= (create_proto.type() == message::Table::TEMPORARY);
5505
5567
 
5506
 
        assert(session != NULL);
 
5568
  const char *table_name= identifier.getPath().c_str();
5507
5569
 
5508
5570
#ifdef __WIN__
5509
 
        /* Names passed in from server are in two formats:
5510
 
        1. <database_name>/<table_name>: for normal table creation
5511
 
        2. full path: for temp table creation, or sym link
5512
 
 
5513
 
        When srv_file_per_table is on, check for full path pattern, i.e.
5514
 
        X:\dir\...,             X is a driver letter, or
5515
 
        \\dir1\dir2\...,        UNC path
5516
 
        returns error if it is in full path format, but not creating a temp.
5517
 
        table. Currently InnoDB does not support symbolic link on Windows. */
5518
 
 
5519
 
        if (srv_file_per_table
5520
 
            && (! lex_identified_temp_table)) {
5521
 
 
5522
 
                if ((table_name[1] == ':')
5523
 
                    || (table_name[0] == '\\' && table_name[1] == '\\')) {
5524
 
                        errmsg_printf(ERRMSG_LVL_ERROR, "Cannot create table %s\n", table_name);
5525
 
                        return(HA_ERR_GENERIC);
5526
 
                }
5527
 
        }
 
5571
  /* Names passed in from server are in two formats:
 
5572
  1. <database_name>/<table_name>: for normal table creation
 
5573
  2. full path: for temp table creation, or sym link
 
5574
 
 
5575
  When srv_file_per_table is on, check for full path pattern, i.e.
 
5576
  X:\dir\...,   X is a driver letter, or
 
5577
  \\dir1\dir2\...,  UNC path
 
5578
  returns error if it is in full path format, but not creating a temp.
 
5579
  table. Currently InnoDB does not support symbolic link on Windows. */
 
5580
 
 
5581
  if (srv_file_per_table
 
5582
      && (! lex_identified_temp_table)) {
 
5583
 
 
5584
    if ((table_name[1] == ':')
 
5585
        || (table_name[0] == '\\' && table_name[1] == '\\')) {
 
5586
      errmsg_printf(ERRMSG_LVL_ERROR, "Cannot create table %s\n", table_name);
 
5587
      return(HA_ERR_GENERIC);
 
5588
    }
 
5589
  }
5528
5590
#endif
5529
5591
 
5530
 
        if (form.s->fields > 1000) {
5531
 
                /* The limit probably should be REC_MAX_N_FIELDS - 3 = 1020,
5532
 
                but we play safe here */
5533
 
 
5534
 
                return(HA_ERR_TO_BIG_ROW);
5535
 
        }
5536
 
 
5537
 
        /* Get the transaction associated with the current session, or create one
5538
 
        if not yet created */
5539
 
 
5540
 
        parent_trx = check_trx_exists(session);
5541
 
 
5542
 
        /* In case MySQL calls this in the middle of a SELECT query, release
5543
 
        possible adaptive hash latch to avoid deadlocks of threads */
5544
 
 
5545
 
        trx_search_latch_release_if_reserved(parent_trx);
5546
 
 
5547
 
        trx = innobase_trx_allocate(session);
5548
 
 
5549
 
        srv_lower_case_table_names = TRUE;
5550
 
 
5551
 
        strcpy(name2, table_name);
5552
 
 
5553
 
        normalize_table_name(norm_name, name2);
5554
 
 
5555
 
        /* Latch the InnoDB data dictionary exclusively so that no deadlocks
5556
 
        or lock waits can happen in it during a table create operation.
5557
 
        Drop table etc. do this latching in row0mysql.c. */
5558
 
 
5559
 
        row_mysql_lock_data_dictionary(trx);
5560
 
 
5561
 
        /* Create the table definition in InnoDB */
5562
 
 
5563
 
        iflags = 0;
5564
 
 
5565
 
        /* Validate create options if innodb_strict_mode is set. */
5566
 
        if (! create_options_are_valid(session, form, create_proto)) {
5567
 
                error = ER_ILLEGAL_HA_CREATE_OPTION;
5568
 
                goto cleanup;
5569
 
        }
5570
 
 
5571
 
        if (create_proto.options().has_key_block_size()) {
5572
 
                /* Determine the page_zip.ssize corresponding to the
5573
 
                requested page size (key_block_size) in kilobytes. */
5574
 
 
5575
 
                ulint   ssize, ksize;
5576
 
                ulint   key_block_size = create_proto.options().key_block_size();
5577
 
 
5578
 
                for (ssize = ksize = 1; ssize <= DICT_TF_ZSSIZE_MAX;
5579
 
                     ssize++, ksize <<= 1) {
5580
 
                        if (key_block_size == ksize) {
5581
 
                                iflags = ssize << DICT_TF_ZSSIZE_SHIFT
5582
 
                                        | DICT_TF_COMPACT
5583
 
                                        | DICT_TF_FORMAT_ZIP
5584
 
                                          << DICT_TF_FORMAT_SHIFT;
5585
 
                                break;
5586
 
                        }
5587
 
                }
5588
 
 
5589
 
                if (!srv_file_per_table) {
5590
 
                        push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
5591
 
                                     ER_ILLEGAL_HA_CREATE_OPTION,
5592
 
                                     "InnoDB: KEY_BLOCK_SIZE"
5593
 
                                     " requires innodb_file_per_table.");
5594
 
                        iflags = 0;
5595
 
                }
5596
 
 
5597
 
                if (file_format < DICT_TF_FORMAT_ZIP) {
5598
 
                        push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
5599
 
                                     ER_ILLEGAL_HA_CREATE_OPTION,
5600
 
                                     "InnoDB: KEY_BLOCK_SIZE"
5601
 
                                     " requires innodb_file_format >"
5602
 
                                     " Antelope.");
5603
 
                        iflags = 0;
5604
 
                }
5605
 
 
5606
 
                if (!iflags) {
5607
 
                        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
5608
 
                                            ER_ILLEGAL_HA_CREATE_OPTION,
5609
 
                                            "InnoDB: ignoring"
5610
 
                                            " KEY_BLOCK_SIZE=%lu.",
5611
 
                                            create_proto.options().key_block_size());
5612
 
                }
5613
 
        }
5614
 
 
5615
 
        if (create_proto.options().has_row_type()) {
5616
 
                if (iflags) {
5617
 
                        /* KEY_BLOCK_SIZE was specified. */
5618
 
                        if (form.s->row_type != ROW_TYPE_COMPRESSED) {
5619
 
                                /* ROW_FORMAT other than COMPRESSED
5620
 
                                ignores KEY_BLOCK_SIZE.  It does not
5621
 
                                make sense to reject conflicting
5622
 
                                KEY_BLOCK_SIZE and ROW_FORMAT, because
5623
 
                                such combinations can be obtained
5624
 
                                with ALTER TABLE anyway. */
5625
 
                                push_warning_printf(
5626
 
                                        session,
5627
 
                                        DRIZZLE_ERROR::WARN_LEVEL_WARN,
5628
 
                                        ER_ILLEGAL_HA_CREATE_OPTION,
5629
 
                                        "InnoDB: ignoring KEY_BLOCK_SIZE=%lu"
5630
 
                                        " unless ROW_FORMAT=COMPRESSED.",
5631
 
                                        create_proto.options().key_block_size());
5632
 
                                iflags = 0;
5633
 
                        }
5634
 
                } else {
5635
 
                        /* No KEY_BLOCK_SIZE */
5636
 
                        if (form.s->row_type == ROW_TYPE_COMPRESSED) {
5637
 
                                /* ROW_FORMAT=COMPRESSED without
5638
 
                                KEY_BLOCK_SIZE implies half the
5639
 
                                maximum KEY_BLOCK_SIZE. */
5640
 
                                iflags = (DICT_TF_ZSSIZE_MAX - 1)
5641
 
                                        << DICT_TF_ZSSIZE_SHIFT
5642
 
                                        | DICT_TF_COMPACT
5643
 
                                        | DICT_TF_FORMAT_ZIP
5644
 
                                        << DICT_TF_FORMAT_SHIFT;
 
5592
  if (form.s->fields > 1000) {
 
5593
    /* The limit probably should be REC_MAX_N_FIELDS - 3 = 1020,
 
5594
    but we play safe here */
 
5595
 
 
5596
    return(HA_ERR_TO_BIG_ROW);
 
5597
  }
 
5598
 
 
5599
  /* Get the transaction associated with the current session, or create one
 
5600
  if not yet created */
 
5601
 
 
5602
  parent_trx = check_trx_exists(&session);
 
5603
 
 
5604
  /* In case MySQL calls this in the middle of a SELECT query, release
 
5605
  possible adaptive hash latch to avoid deadlocks of threads */
 
5606
 
 
5607
  trx_search_latch_release_if_reserved(parent_trx);
 
5608
 
 
5609
  trx = innobase_trx_allocate(&session);
 
5610
 
 
5611
  srv_lower_case_table_names = TRUE;
 
5612
 
 
5613
  strcpy(name2, table_name);
 
5614
 
 
5615
  normalize_table_name(norm_name, name2);
 
5616
 
 
5617
  /* Latch the InnoDB data dictionary exclusively so that no deadlocks
 
5618
  or lock waits can happen in it during a table create operation.
 
5619
  Drop table etc. do this latching in row0mysql.c. */
 
5620
 
 
5621
  row_mysql_lock_data_dictionary(trx);
 
5622
 
 
5623
  /* Create the table definition in InnoDB */
 
5624
 
 
5625
  iflags = 0;
 
5626
 
 
5627
  /* Validate create options if innodb_strict_mode is set. */
 
5628
  if (! create_options_are_valid(&session, form, create_proto)) {
 
5629
    error = ER_ILLEGAL_HA_CREATE_OPTION;
 
5630
    goto cleanup;
 
5631
  }
 
5632
 
 
5633
  if (create_proto.options().has_key_block_size()) {
 
5634
    /* Determine the page_zip.ssize corresponding to the
 
5635
    requested page size (key_block_size) in kilobytes. */
 
5636
 
 
5637
    ulint ssize, ksize;
 
5638
    ulint key_block_size = create_proto.options().key_block_size();
 
5639
 
 
5640
    for (ssize = ksize = 1; ssize <= DICT_TF_ZSSIZE_MAX;
 
5641
         ssize++, ksize <<= 1) {
 
5642
      if (key_block_size == ksize) {
 
5643
        iflags = ssize << DICT_TF_ZSSIZE_SHIFT
 
5644
          | DICT_TF_COMPACT
 
5645
          | DICT_TF_FORMAT_ZIP
 
5646
            << DICT_TF_FORMAT_SHIFT;
 
5647
        break;
 
5648
      }
 
5649
    }
 
5650
 
 
5651
    if (!srv_file_per_table) {
 
5652
      push_warning(&session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
5653
             ER_ILLEGAL_HA_CREATE_OPTION,
 
5654
             "InnoDB: KEY_BLOCK_SIZE"
 
5655
             " requires innodb_file_per_table.");
 
5656
      iflags = 0;
 
5657
    }
 
5658
 
 
5659
    if (file_format < DICT_TF_FORMAT_ZIP) {
 
5660
      push_warning(&session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
5661
             ER_ILLEGAL_HA_CREATE_OPTION,
 
5662
             "InnoDB: KEY_BLOCK_SIZE"
 
5663
             " requires innodb_file_format >"
 
5664
             " Antelope.");
 
5665
      iflags = 0;
 
5666
    }
 
5667
 
 
5668
    if (!iflags) {
 
5669
      push_warning_printf(&session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
5670
              ER_ILLEGAL_HA_CREATE_OPTION,
 
5671
              "InnoDB: ignoring"
 
5672
              " KEY_BLOCK_SIZE=%lu.",
 
5673
              create_proto.options().key_block_size());
 
5674
    }
 
5675
  }
 
5676
 
 
5677
  if (create_proto.options().has_row_type()) {
 
5678
    if (iflags) {
 
5679
      /* KEY_BLOCK_SIZE was specified. */
 
5680
      if (form.s->row_type != ROW_TYPE_COMPRESSED) {
 
5681
        /* ROW_FORMAT other than COMPRESSED
 
5682
        ignores KEY_BLOCK_SIZE.  It does not
 
5683
        make sense to reject conflicting
 
5684
        KEY_BLOCK_SIZE and ROW_FORMAT, because
 
5685
        such combinations can be obtained
 
5686
        with ALTER TABLE anyway. */
 
5687
        push_warning_printf(
 
5688
          &session,
 
5689
          DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
5690
          ER_ILLEGAL_HA_CREATE_OPTION,
 
5691
          "InnoDB: ignoring KEY_BLOCK_SIZE=%lu"
 
5692
          " unless ROW_FORMAT=COMPRESSED.",
 
5693
          create_proto.options().key_block_size());
 
5694
        iflags = 0;
 
5695
      }
 
5696
    } else {
 
5697
      /* No KEY_BLOCK_SIZE */
 
5698
      if (form.s->row_type == ROW_TYPE_COMPRESSED) {
 
5699
        /* ROW_FORMAT=COMPRESSED without
 
5700
        KEY_BLOCK_SIZE implies half the
 
5701
        maximum KEY_BLOCK_SIZE. */
 
5702
        iflags = (DICT_TF_ZSSIZE_MAX - 1)
 
5703
          << DICT_TF_ZSSIZE_SHIFT
 
5704
          | DICT_TF_COMPACT
 
5705
          | DICT_TF_FORMAT_ZIP
 
5706
          << DICT_TF_FORMAT_SHIFT;
5645
5707
#if DICT_TF_ZSSIZE_MAX < 1
5646
5708
# error "DICT_TF_ZSSIZE_MAX < 1"
5647
5709
#endif
5648
 
                        }
5649
 
                }
5650
 
 
5651
 
                switch (form.s->row_type) {
5652
 
                        const char* row_format_name;
5653
 
                case ROW_TYPE_REDUNDANT:
5654
 
                        break;
5655
 
                case ROW_TYPE_COMPRESSED:
5656
 
                case ROW_TYPE_DYNAMIC:
5657
 
                        row_format_name
5658
 
                                = form.s->row_type == ROW_TYPE_COMPRESSED
5659
 
                                ? "COMPRESSED"
5660
 
                                : "DYNAMIC";
5661
 
 
5662
 
                        if (!srv_file_per_table) {
5663
 
                                push_warning_printf(
5664
 
                                        session,
5665
 
                                        DRIZZLE_ERROR::WARN_LEVEL_WARN,
5666
 
                                        ER_ILLEGAL_HA_CREATE_OPTION,
5667
 
                                        "InnoDB: ROW_FORMAT=%s"
5668
 
                                        " requires innodb_file_per_table.",
5669
 
                                        row_format_name);
5670
 
                        } else if (file_format < DICT_TF_FORMAT_ZIP) {
5671
 
                                push_warning_printf(
5672
 
                                        session,
5673
 
                                        DRIZZLE_ERROR::WARN_LEVEL_WARN,
5674
 
                                        ER_ILLEGAL_HA_CREATE_OPTION,
5675
 
                                        "InnoDB: ROW_FORMAT=%s"
5676
 
                                        " requires innodb_file_format >"
5677
 
                                        " Antelope.",
5678
 
                                        row_format_name);
5679
 
                        } else {
5680
 
                                iflags |= DICT_TF_COMPACT
5681
 
                                        | (DICT_TF_FORMAT_ZIP
5682
 
                                           << DICT_TF_FORMAT_SHIFT);
5683
 
                                break;
5684
 
                        }
5685
 
 
5686
 
                        /* fall through */
5687
 
                case ROW_TYPE_NOT_USED:
5688
 
                case ROW_TYPE_FIXED:
5689
 
                default:
 
5710
      }
 
5711
    }
 
5712
 
 
5713
    switch (form.s->row_type) {
 
5714
      const char* row_format_name;
 
5715
    case ROW_TYPE_REDUNDANT:
 
5716
      break;
 
5717
    case ROW_TYPE_COMPRESSED:
 
5718
    case ROW_TYPE_DYNAMIC:
 
5719
      row_format_name
 
5720
        = form.s->row_type == ROW_TYPE_COMPRESSED
 
5721
        ? "COMPRESSED"
 
5722
        : "DYNAMIC";
 
5723
 
 
5724
      if (!srv_file_per_table) {
 
5725
        push_warning_printf(
 
5726
          &session,
 
5727
          DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
5728
          ER_ILLEGAL_HA_CREATE_OPTION,
 
5729
          "InnoDB: ROW_FORMAT=%s"
 
5730
          " requires innodb_file_per_table.",
 
5731
          row_format_name);
 
5732
      } else if (file_format < DICT_TF_FORMAT_ZIP) {
 
5733
        push_warning_printf(
 
5734
          &session,
 
5735
          DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
5736
          ER_ILLEGAL_HA_CREATE_OPTION,
 
5737
          "InnoDB: ROW_FORMAT=%s"
 
5738
          " requires innodb_file_format >"
 
5739
          " Antelope.",
 
5740
          row_format_name);
 
5741
      } else {
 
5742
        iflags |= DICT_TF_COMPACT
 
5743
          | (DICT_TF_FORMAT_ZIP
 
5744
             << DICT_TF_FORMAT_SHIFT);
 
5745
        break;
 
5746
      }
 
5747
 
 
5748
      /* fall through */
 
5749
    case ROW_TYPE_NOT_USED:
 
5750
    case ROW_TYPE_FIXED:
 
5751
    default:
5690
5752
                        error = ER_ILLEGAL_HA_CREATE_OPTION;
5691
5753
                        goto cleanup;
5692
 
                case ROW_TYPE_DEFAULT:
5693
 
                case ROW_TYPE_COMPACT:
5694
 
                        iflags = DICT_TF_COMPACT;
5695
 
                        break;
5696
 
                }
5697
 
        } else if (!iflags) {
5698
 
                /* No KEY_BLOCK_SIZE or ROW_FORMAT specified:
5699
 
                use ROW_FORMAT=COMPACT by default. */
5700
 
                iflags = DICT_TF_COMPACT;
5701
 
        }
5702
 
 
5703
 
        error = create_table_def(trx, &form, norm_name,
5704
 
                lex_identified_temp_table ? name2 : NULL,
5705
 
                iflags);
5706
 
 
5707
 
        if (error) {
5708
 
                goto cleanup;
5709
 
        }
5710
 
 
5711
 
        /* Look for a primary key */
5712
 
 
5713
 
        primary_key_no= (form.s->primary_key != MAX_KEY ?
5714
 
                         (int) form.s->primary_key :
5715
 
                         -1);
5716
 
 
5717
 
        /* Our function row_get_mysql_key_number_for_index assumes
5718
 
        the primary key is always number 0, if it exists */
5719
 
 
5720
 
        assert(primary_key_no == -1 || primary_key_no == 0);
5721
 
 
5722
 
        /* Create the keys */
5723
 
 
5724
 
        if (form.s->keys == 0 || primary_key_no == -1) {
5725
 
                /* Create an index which is used as the clustered index;
5726
 
                order the rows by their row id which is internally generated
5727
 
                by InnoDB */
5728
 
 
5729
 
                error = create_clustered_index_when_no_primary(
5730
 
                        trx, iflags, norm_name);
5731
 
                if (error) {
5732
 
                        goto cleanup;
5733
 
                }
5734
 
        }
5735
 
 
5736
 
        if (primary_key_no != -1) {
5737
 
                /* In InnoDB the clustered index must always be created
5738
 
                first */
5739
 
                if ((error = create_index(trx, &form, iflags, norm_name,
5740
 
                                          (uint) primary_key_no))) {
5741
 
                        goto cleanup;
5742
 
                }
5743
 
        }
5744
 
 
5745
 
        for (i = 0; i < form.s->keys; i++) {
5746
 
 
5747
 
                if (i != (uint) primary_key_no) {
5748
 
 
5749
 
                        if ((error = create_index(trx, &form, iflags, norm_name,
5750
 
                                                  i))) {
5751
 
                                goto cleanup;
5752
 
                        }
5753
 
                }
5754
 
        }
5755
 
 
5756
 
        if (trx->mysql_query_str) {
5757
 
                error = row_table_add_foreign_constraints(trx,
5758
 
                        trx->mysql_query_str, norm_name,
5759
 
                        lex_identified_temp_table);
5760
 
 
5761
 
                error = convert_error_code_to_mysql(error, iflags, NULL);
5762
 
 
5763
 
                if (error) {
5764
 
                        goto cleanup;
5765
 
                }
5766
 
        }
5767
 
 
5768
 
        innobase_commit_low(trx);
5769
 
 
5770
 
        row_mysql_unlock_data_dictionary(trx);
5771
 
 
5772
 
        /* Flush the log to reduce probability that the .frm files and
5773
 
        the InnoDB data dictionary get out-of-sync if the user runs
5774
 
        with innodb_flush_log_at_trx_commit = 0 */
5775
 
 
5776
 
        log_buffer_flush_to_disk();
5777
 
 
5778
 
        innobase_table = dict_table_get(norm_name, FALSE);
5779
 
 
5780
 
        assert(innobase_table != 0);
5781
 
 
5782
 
        if (innobase_table) {
5783
 
                /* We update the highest file format in the system table
5784
 
                space, if this table has higher file format setting. */
5785
 
 
5786
 
                trx_sys_file_format_max_upgrade(
5787
 
                        (const char**) &innobase_file_format_check,
5788
 
                        dict_table_get_format(innobase_table));
5789
 
        }
5790
 
 
5791
 
        /* Note: We can't call update_session() as prebuilt will not be
5792
 
        setup at this stage and so we use session. */
5793
 
 
5794
 
        /* We need to copy the AUTOINC value from the old table if
5795
 
        this is an ALTER TABLE. */
5796
 
 
5797
 
        if ((create_proto.options().has_auto_increment_value()
5798
 
            || session_sql_command(session) == SQLCOM_ALTER_TABLE)
5799
 
            && create_proto.options().auto_increment_value() != 0) {
5800
 
 
5801
 
                /* Query was ALTER TABLE...AUTO_INCREMENT = x; or
5802
 
                CREATE TABLE ...AUTO_INCREMENT = x; Find out a table
5803
 
                definition from the dictionary and get the current value
5804
 
                of the auto increment field. Set a new value to the
5805
 
                auto increment field if the value is greater than the
5806
 
                maximum value in the column. */
5807
 
 
5808
 
                auto_inc_value = create_proto.options().auto_increment_value();
5809
 
 
5810
 
                dict_table_autoinc_lock(innobase_table);
5811
 
                dict_table_autoinc_initialize(innobase_table, auto_inc_value);
5812
 
                dict_table_autoinc_unlock(innobase_table);
5813
 
        }
5814
 
 
5815
 
        /* Tell the InnoDB server that there might be work for
5816
 
        utility threads: */
5817
 
 
5818
 
        srv_active_wake_master_thread();
5819
 
 
5820
 
        trx_free_for_mysql(trx);
5821
 
 
5822
 
        return(0);
 
5754
    case ROW_TYPE_DEFAULT:
 
5755
    case ROW_TYPE_COMPACT:
 
5756
      iflags = DICT_TF_COMPACT;
 
5757
      break;
 
5758
    }
 
5759
  } else if (!iflags) {
 
5760
    /* No KEY_BLOCK_SIZE or ROW_FORMAT specified:
 
5761
    use ROW_FORMAT=COMPACT by default. */
 
5762
    iflags = DICT_TF_COMPACT;
 
5763
  }
 
5764
 
 
5765
  error = create_table_def(trx, &form, norm_name,
 
5766
    lex_identified_temp_table ? name2 : NULL,
 
5767
    iflags);
 
5768
 
 
5769
  if (error) {
 
5770
    goto cleanup;
 
5771
  }
 
5772
 
 
5773
  /* Look for a primary key */
 
5774
 
 
5775
  primary_key_no= (form.s->primary_key != MAX_KEY ?
 
5776
       (int) form.s->primary_key :
 
5777
       -1);
 
5778
 
 
5779
  /* Our function row_get_mysql_key_number_for_index assumes
 
5780
  the primary key is always number 0, if it exists */
 
5781
 
 
5782
  assert(primary_key_no == -1 || primary_key_no == 0);
 
5783
 
 
5784
  /* Create the keys */
 
5785
 
 
5786
  if (form.s->keys == 0 || primary_key_no == -1) {
 
5787
    /* Create an index which is used as the clustered index;
 
5788
    order the rows by their row id which is internally generated
 
5789
    by InnoDB */
 
5790
 
 
5791
    error = create_clustered_index_when_no_primary(
 
5792
      trx, iflags, norm_name);
 
5793
    if (error) {
 
5794
      goto cleanup;
 
5795
    }
 
5796
  }
 
5797
 
 
5798
  if (primary_key_no != -1) {
 
5799
    /* In InnoDB the clustered index must always be created
 
5800
    first */
 
5801
    if ((error = create_index(trx, &form, iflags, norm_name,
 
5802
            (uint) primary_key_no))) {
 
5803
      goto cleanup;
 
5804
    }
 
5805
  }
 
5806
 
 
5807
  for (i = 0; i < form.s->keys; i++) {
 
5808
 
 
5809
    if (i != (uint) primary_key_no) {
 
5810
 
 
5811
      if ((error = create_index(trx, &form, iflags, norm_name,
 
5812
              i))) {
 
5813
        goto cleanup;
 
5814
      }
 
5815
    }
 
5816
  }
 
5817
 
 
5818
  if (trx->mysql_query_str) {
 
5819
    error = row_table_add_foreign_constraints(trx,
 
5820
      trx->mysql_query_str, norm_name,
 
5821
      lex_identified_temp_table);
 
5822
 
 
5823
    error = convert_error_code_to_mysql(error, iflags, NULL);
 
5824
 
 
5825
    if (error) {
 
5826
      goto cleanup;
 
5827
    }
 
5828
  }
 
5829
 
 
5830
  innobase_commit_low(trx);
 
5831
 
 
5832
  row_mysql_unlock_data_dictionary(trx);
 
5833
 
 
5834
  /* Flush the log to reduce probability that the .frm files and
 
5835
  the InnoDB data dictionary get out-of-sync if the user runs
 
5836
  with innodb_flush_log_at_trx_commit = 0 */
 
5837
 
 
5838
  log_buffer_flush_to_disk();
 
5839
 
 
5840
  innobase_table = dict_table_get(norm_name, FALSE);
 
5841
 
 
5842
  assert(innobase_table != 0);
 
5843
 
 
5844
  if (innobase_table) {
 
5845
    /* We update the highest file format in the system table
 
5846
    space, if this table has higher file format setting. */
 
5847
 
 
5848
    trx_sys_file_format_max_upgrade(
 
5849
      (const char**) &innobase_file_format_check,
 
5850
      dict_table_get_format(innobase_table));
 
5851
  }
 
5852
 
 
5853
  /* Note: We can't call update_session() as prebuilt will not be
 
5854
  setup at this stage and so we use session. */
 
5855
 
 
5856
  /* We need to copy the AUTOINC value from the old table if
 
5857
  this is an ALTER TABLE. */
 
5858
 
 
5859
  if ((create_proto.options().has_auto_increment_value()
 
5860
      || session_sql_command(&session) == SQLCOM_ALTER_TABLE)
 
5861
      && create_proto.options().auto_increment_value() != 0) {
 
5862
 
 
5863
    /* Query was ALTER TABLE...AUTO_INCREMENT = x; or
 
5864
    CREATE TABLE ...AUTO_INCREMENT = x; Find out a table
 
5865
    definition from the dictionary and get the current value
 
5866
    of the auto increment field. Set a new value to the
 
5867
    auto increment field if the value is greater than the
 
5868
    maximum value in the column. */
 
5869
 
 
5870
    auto_inc_value = create_proto.options().auto_increment_value();
 
5871
 
 
5872
    dict_table_autoinc_lock(innobase_table);
 
5873
    dict_table_autoinc_initialize(innobase_table, auto_inc_value);
 
5874
    dict_table_autoinc_unlock(innobase_table);
 
5875
  }
 
5876
 
 
5877
  /* Tell the InnoDB server that there might be work for
 
5878
  utility threads: */
 
5879
 
 
5880
  srv_active_wake_master_thread();
 
5881
 
 
5882
  trx_free_for_mysql(trx);
 
5883
 
 
5884
        StorageEngine::writeDefinitionFromPath(identifier, create_proto);
 
5885
 
 
5886
  return(0);
5823
5887
 
5824
5888
cleanup:
5825
 
        innobase_commit_low(trx);
5826
 
 
5827
 
        row_mysql_unlock_data_dictionary(trx);
5828
 
 
5829
 
        trx_free_for_mysql(trx);
5830
 
 
5831
 
        return(error);
 
5889
  innobase_commit_low(trx);
 
5890
 
 
5891
  row_mysql_unlock_data_dictionary(trx);
 
5892
 
 
5893
  trx_free_for_mysql(trx);
 
5894
 
 
5895
  return(error);
5832
5896
}
5833
5897
 
5834
5898
/*****************************************************************//**
5835
5899
Discards or imports an InnoDB tablespace.
5836
 
@return 0 == success, -1 == error */
 
5900
@return 0 == success, -1 == error */
5837
5901
UNIV_INTERN
5838
5902
int
5839
5903
ha_innobase::discard_or_import_tablespace(
5840
5904
/*======================================*/
5841
 
        my_bool discard)        /*!< in: TRUE if discard, else import */
 
5905
  my_bool discard)  /*!< in: TRUE if discard, else import */
5842
5906
{
5843
 
        dict_table_t*   dict_table;
5844
 
        trx_t*          trx;
5845
 
        int             err;
5846
 
 
5847
 
        ut_a(prebuilt->trx);
5848
 
        ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N);
5849
 
        ut_a(prebuilt->trx == session_to_trx(ha_session()));
5850
 
 
5851
 
        dict_table = prebuilt->table;
5852
 
        trx = prebuilt->trx;
5853
 
 
5854
 
        if (discard) {
5855
 
                err = row_discard_tablespace_for_mysql(dict_table->name, trx);
5856
 
        } else {
5857
 
                err = row_import_tablespace_for_mysql(dict_table->name, trx);
5858
 
        }
5859
 
 
5860
 
        err = convert_error_code_to_mysql(err, dict_table->flags, NULL);
5861
 
 
5862
 
        return(err);
 
5907
  dict_table_t* dict_table;
 
5908
  trx_t*    trx;
 
5909
  int   err;
 
5910
 
 
5911
  ut_a(prebuilt->trx);
 
5912
  ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N);
 
5913
  ut_a(prebuilt->trx == session_to_trx(ha_session()));
 
5914
 
 
5915
  dict_table = prebuilt->table;
 
5916
  trx = prebuilt->trx;
 
5917
 
 
5918
  if (discard) {
 
5919
    err = row_discard_tablespace_for_mysql(dict_table->name, trx);
 
5920
  } else {
 
5921
    err = row_import_tablespace_for_mysql(dict_table->name, trx);
 
5922
  }
 
5923
 
 
5924
  err = convert_error_code_to_mysql(err, dict_table->flags, NULL);
 
5925
 
 
5926
  return(err);
5863
5927
}
5864
5928
 
5865
5929
/*****************************************************************//**
5866
5930
Deletes all rows of an InnoDB table.
5867
 
@return error number */
 
5931
@return error number */
5868
5932
UNIV_INTERN
5869
5933
int
5870
5934
ha_innobase::delete_all_rows(void)
5871
5935
/*==============================*/
5872
5936
{
5873
 
        int             error;
5874
 
 
5875
 
        /* Get the transaction associated with the current session, or create one
5876
 
        if not yet created, and update prebuilt->trx */
5877
 
 
5878
 
        update_session(ha_session());
5879
 
 
5880
 
        if (session_sql_command(user_session) != SQLCOM_TRUNCATE) {
5881
 
        fallback:
5882
 
                /* We only handle TRUNCATE TABLE t as a special case.
5883
 
                DELETE FROM t will have to use ha_innobase::delete_row(),
5884
 
                because DELETE is transactional while TRUNCATE is not. */
5885
 
                return(errno=HA_ERR_WRONG_COMMAND);
5886
 
        }
5887
 
 
5888
 
        /* Truncate the table in InnoDB */
5889
 
 
5890
 
        error = row_truncate_table_for_mysql(prebuilt->table, prebuilt->trx);
5891
 
        if (error == DB_ERROR) {
5892
 
                /* Cannot truncate; resort to ha_innobase::delete_row() */
5893
 
                goto fallback;
5894
 
        }
5895
 
 
5896
 
        error = convert_error_code_to_mysql(error, prebuilt->table->flags,
5897
 
                                            NULL);
5898
 
 
5899
 
        return(error);
 
5937
  int   error;
 
5938
 
 
5939
  /* Get the transaction associated with the current session, or create one
 
5940
  if not yet created, and update prebuilt->trx */
 
5941
 
 
5942
  update_session(ha_session());
 
5943
 
 
5944
  if (session_sql_command(user_session) != SQLCOM_TRUNCATE) {
 
5945
  fallback:
 
5946
    /* We only handle TRUNCATE TABLE t as a special case.
 
5947
    DELETE FROM t will have to use ha_innobase::delete_row(),
 
5948
    because DELETE is transactional while TRUNCATE is not. */
 
5949
    return(errno=HA_ERR_WRONG_COMMAND);
 
5950
  }
 
5951
 
 
5952
  /* Truncate the table in InnoDB */
 
5953
 
 
5954
  error = row_truncate_table_for_mysql(prebuilt->table, prebuilt->trx);
 
5955
  if (error == DB_ERROR) {
 
5956
    /* Cannot truncate; resort to ha_innobase::delete_row() */
 
5957
    goto fallback;
 
5958
  }
 
5959
 
 
5960
  error = convert_error_code_to_mysql(error, prebuilt->table->flags,
 
5961
              NULL);
 
5962
 
 
5963
  return(error);
5900
5964
}
5901
5965
 
5902
5966
/*****************************************************************//**
5905
5969
Then the current user cannot have locks set on the table. Drop table
5906
5970
operation inside InnoDB will remove all locks any user has on the table
5907
5971
inside InnoDB.
5908
 
@return error number */
 
5972
@return error number */
5909
5973
UNIV_INTERN
5910
5974
int
5911
5975
InnobaseEngine::doDropTable(
5912
5976
/*======================*/
5913
 
        Session& session,
5914
 
        const string &table_path)       /* in: table name */
 
5977
        Session &session,
 
5978
        TableIdentifier &identifier)
5915
5979
{
5916
 
        int     error;
5917
 
        trx_t*  parent_trx;
5918
 
        trx_t*  trx;
5919
 
        char    norm_name[1000];
5920
 
 
5921
 
        ut_a(table_path.length() < 1000);
5922
 
 
5923
 
        /* Strangely, MySQL passes the table name without the '.frm'
5924
 
        extension, in contrast to ::create */
5925
 
        normalize_table_name(norm_name, table_path.c_str());
5926
 
 
5927
 
        /* Get the transaction associated with the current session, or create one
5928
 
        if not yet created */
5929
 
 
5930
 
        parent_trx = check_trx_exists(&session);
5931
 
 
5932
 
        /* In case MySQL calls this in the middle of a SELECT query, release
5933
 
        possible adaptive hash latch to avoid deadlocks of threads */
5934
 
 
5935
 
        trx_search_latch_release_if_reserved(parent_trx);
5936
 
 
5937
 
        trx = innobase_trx_allocate(&session);
5938
 
 
5939
 
        srv_lower_case_table_names = TRUE;
5940
 
 
5941
 
        /* Drop the table in InnoDB */
5942
 
 
5943
 
        error = row_drop_table_for_mysql(norm_name, trx,
5944
 
                                         session_sql_command(&session)
5945
 
                                         == SQLCOM_DROP_DB);
5946
 
 
5947
 
        /* Flush the log to reduce probability that the .frm files and
5948
 
        the InnoDB data dictionary get out-of-sync if the user runs
5949
 
        with innodb_flush_log_at_trx_commit = 0 */
5950
 
 
5951
 
        log_buffer_flush_to_disk();
5952
 
 
5953
 
        /* Tell the InnoDB server that there might be work for
5954
 
        utility threads: */
5955
 
 
5956
 
        srv_active_wake_master_thread();
5957
 
 
5958
 
        innobase_commit_low(trx);
5959
 
 
5960
 
        trx_free_for_mysql(trx);
5961
 
 
5962
 
        if(error!=ENOENT)
5963
 
          error = convert_error_code_to_mysql(error, 0, NULL);
5964
 
 
5965
 
        return(error);
 
5980
  int error;
 
5981
  trx_t*  parent_trx;
 
5982
  trx_t*  trx;
 
5983
  char  norm_name[1000];
 
5984
 
 
5985
  ut_a(identifier.getPath().length() < 1000);
 
5986
 
 
5987
  /* Strangely, MySQL passes the table name without the '.frm'
 
5988
  extension, in contrast to ::create */
 
5989
  normalize_table_name(norm_name, identifier.getPath().c_str());
 
5990
 
 
5991
  /* Get the transaction associated with the current session, or create one
 
5992
  if not yet created */
 
5993
 
 
5994
  parent_trx = check_trx_exists(&session);
 
5995
 
 
5996
  /* In case MySQL calls this in the middle of a SELECT query, release
 
5997
  possible adaptive hash latch to avoid deadlocks of threads */
 
5998
 
 
5999
  trx_search_latch_release_if_reserved(parent_trx);
 
6000
 
 
6001
  trx = innobase_trx_allocate(&session);
 
6002
 
 
6003
  srv_lower_case_table_names = TRUE;
 
6004
 
 
6005
  /* Drop the table in InnoDB */
 
6006
 
 
6007
  error = row_drop_table_for_mysql(norm_name, trx,
 
6008
           session_sql_command(&session)
 
6009
           == SQLCOM_DROP_DB);
 
6010
 
 
6011
  /* Flush the log to reduce probability that the .frm files and
 
6012
  the InnoDB data dictionary get out-of-sync if the user runs
 
6013
  with innodb_flush_log_at_trx_commit = 0 */
 
6014
 
 
6015
  log_buffer_flush_to_disk();
 
6016
 
 
6017
  /* Tell the InnoDB server that there might be work for
 
6018
  utility threads: */
 
6019
 
 
6020
  srv_active_wake_master_thread();
 
6021
 
 
6022
  innobase_commit_low(trx);
 
6023
 
 
6024
  trx_free_for_mysql(trx);
 
6025
 
 
6026
  if(error!=ENOENT)
 
6027
    error = convert_error_code_to_mysql(error, 0, NULL);
 
6028
 
 
6029
        if (error == 0 || error == ENOENT)
 
6030
        {
 
6031
          string path(identifier.getPath());
 
6032
 
 
6033
          path.append(DEFAULT_FILE_EXTENSION);
 
6034
 
 
6035
          (void)internal::my_delete(path.c_str(), MYF(0));
 
6036
        }
 
6037
 
 
6038
  return(error);
5966
6039
}
5967
6040
 
5968
6041
/*****************************************************************//**
5970
6043
bool
5971
6044
InnobaseEngine::doDropSchema(
5972
6045
/*===================*/
5973
 
                             const std::string &schema_name)
5974
 
                /*!< in: database path; inside InnoDB the name
5975
 
                        of the last directory in the path is used as
5976
 
                        the database name: for example, in 'mysql/data/test'
5977
 
                        the database name is 'test' */
 
6046
                             SchemaIdentifier &identifier)
 
6047
    /*!< in: database path; inside InnoDB the name
 
6048
      of the last directory in the path is used as
 
6049
      the database name: for example, in 'mysql/data/test'
 
6050
      the database name is 'test' */
5978
6051
{
5979
 
        trx_t*  trx;
5980
 
        int     error;
5981
 
        string schema_path(schema_name);
5982
 
        Session*        session         = current_session;
5983
 
 
5984
 
        /* Get the transaction associated with the current session, or create one
5985
 
        if not yet created */
5986
 
 
5987
 
        assert(this == innodb_engine_ptr);
5988
 
 
5989
 
        /* In the Windows plugin, session = current_session is always NULL */
5990
 
        if (session) {
5991
 
                trx_t*  parent_trx = check_trx_exists(session);
5992
 
 
5993
 
                /* In case Drizzle calls this in the middle of a SELECT
5994
 
                query, release possible adaptive hash latch to avoid
5995
 
                deadlocks of threads */
5996
 
 
5997
 
                trx_search_latch_release_if_reserved(parent_trx);
5998
 
        }
 
6052
  trx_t*  trx;
 
6053
  int error;
 
6054
  string schema_path(identifier.getPath());
 
6055
  Session*  session   = current_session;
 
6056
 
 
6057
  /* Get the transaction associated with the current session, or create one
 
6058
  if not yet created */
 
6059
 
 
6060
  assert(this == innodb_engine_ptr);
 
6061
 
 
6062
  /* In the Windows plugin, session = current_session is always NULL */
 
6063
  if (session) {
 
6064
    trx_t*  parent_trx = check_trx_exists(session);
 
6065
 
 
6066
    /* In case Drizzle calls this in the middle of a SELECT
 
6067
    query, release possible adaptive hash latch to avoid
 
6068
    deadlocks of threads */
 
6069
 
 
6070
    trx_search_latch_release_if_reserved(parent_trx);
 
6071
  }
5999
6072
 
6000
6073
        schema_path.append("/");
6001
 
        trx = innobase_trx_allocate(session);
6002
 
        error = row_drop_database_for_mysql(schema_path.c_str(), trx);
6003
 
 
6004
 
        /* Flush the log to reduce probability that the .frm files and
6005
 
        the InnoDB data dictionary get out-of-sync if the user runs
6006
 
        with innodb_flush_log_at_trx_commit = 0 */
6007
 
 
6008
 
        log_buffer_flush_to_disk();
6009
 
 
6010
 
        /* Tell the InnoDB server that there might be work for
6011
 
        utility threads: */
6012
 
 
6013
 
        srv_active_wake_master_thread();
6014
 
 
6015
 
        innobase_commit_low(trx);
6016
 
        trx_free_for_mysql(trx);
 
6074
  trx = innobase_trx_allocate(session);
 
6075
  error = row_drop_database_for_mysql(schema_path.c_str(), trx);
 
6076
 
 
6077
  /* Flush the log to reduce probability that the .frm files and
 
6078
  the InnoDB data dictionary get out-of-sync if the user runs
 
6079
  with innodb_flush_log_at_trx_commit = 0 */
 
6080
 
 
6081
  log_buffer_flush_to_disk();
 
6082
 
 
6083
  /* Tell the InnoDB server that there might be work for
 
6084
  utility threads: */
 
6085
 
 
6086
  srv_active_wake_master_thread();
 
6087
 
 
6088
  innobase_commit_low(trx);
 
6089
  trx_free_for_mysql(trx);
6017
6090
 
6018
6091
        return false; // We are just a listener since we lack control over DDL, so we give no positive acknowledgement. 
6019
6092
}
6020
6093
/*********************************************************************//**
6021
6094
Renames an InnoDB table.
6022
 
@return 0 or error code */
 
6095
@return 0 or error code */
6023
6096
static
6024
6097
int
6025
6098
innobase_rename_table(
6026
6099
/*==================*/
6027
 
        trx_t*          trx,    /*!< in: transaction */
6028
 
        const char*     from,   /*!< in: old name of the table */
6029
 
        const char*     to,     /*!< in: new name of the table */
6030
 
        ibool           lock_and_commit)
6031
 
                                /*!< in: TRUE=lock data dictionary and commit */
 
6100
  trx_t*    trx,  /*!< in: transaction */
 
6101
  const char* from, /*!< in: old name of the table */
 
6102
  const char* to, /*!< in: new name of the table */
 
6103
  ibool   lock_and_commit)
 
6104
        /*!< in: TRUE=lock data dictionary and commit */
6032
6105
{
6033
 
        int     error;
6034
 
        char*   norm_to;
6035
 
        char*   norm_from;
6036
 
 
6037
 
        srv_lower_case_table_names = TRUE;
6038
 
 
6039
 
        // Magic number 64 arbitrary
6040
 
        norm_to = (char*) malloc(strlen(to) + 64);
6041
 
        norm_from = (char*) malloc(strlen(from) + 64);
6042
 
 
6043
 
        normalize_table_name(norm_to, to);
6044
 
        normalize_table_name(norm_from, from);
6045
 
 
6046
 
        /* Serialize data dictionary operations with dictionary mutex:
6047
 
        no deadlocks can occur then in these operations */
6048
 
 
6049
 
        if (lock_and_commit) {
6050
 
                row_mysql_lock_data_dictionary(trx);
6051
 
        }
6052
 
 
6053
 
        error = row_rename_table_for_mysql(
6054
 
                norm_from, norm_to, trx, lock_and_commit);
6055
 
 
6056
 
        if (error != DB_SUCCESS) {
6057
 
                FILE* ef = dict_foreign_err_file;
6058
 
 
6059
 
                fputs("InnoDB: Renaming table ", ef);
6060
 
                ut_print_name(ef, trx, TRUE, norm_from);
6061
 
                fputs(" to ", ef);
6062
 
                ut_print_name(ef, trx, TRUE, norm_to);
6063
 
                fputs(" failed!\n", ef);
6064
 
        }
6065
 
 
6066
 
        if (lock_and_commit) {
6067
 
                row_mysql_unlock_data_dictionary(trx);
6068
 
 
6069
 
                /* Flush the log to reduce probability that the .frm
6070
 
                files and the InnoDB data dictionary get out-of-sync
6071
 
                if the user runs with innodb_flush_log_at_trx_commit = 0 */
6072
 
 
6073
 
                log_buffer_flush_to_disk();
6074
 
        }
6075
 
 
6076
 
        free(norm_to);
6077
 
        free(norm_from);
6078
 
 
6079
 
        return error;
 
6106
  int error;
 
6107
  char* norm_to;
 
6108
  char* norm_from;
 
6109
 
 
6110
  srv_lower_case_table_names = TRUE;
 
6111
 
 
6112
  // Magic number 64 arbitrary
 
6113
  norm_to = (char*) malloc(strlen(to) + 64);
 
6114
  norm_from = (char*) malloc(strlen(from) + 64);
 
6115
 
 
6116
  normalize_table_name(norm_to, to);
 
6117
  normalize_table_name(norm_from, from);
 
6118
 
 
6119
  /* Serialize data dictionary operations with dictionary mutex:
 
6120
  no deadlocks can occur then in these operations */
 
6121
 
 
6122
  if (lock_and_commit) {
 
6123
    row_mysql_lock_data_dictionary(trx);
 
6124
  }
 
6125
 
 
6126
  error = row_rename_table_for_mysql(
 
6127
    norm_from, norm_to, trx, lock_and_commit);
 
6128
 
 
6129
  if (error != DB_SUCCESS) {
 
6130
    FILE* ef = dict_foreign_err_file;
 
6131
 
 
6132
    fputs("InnoDB: Renaming table ", ef);
 
6133
    ut_print_name(ef, trx, TRUE, norm_from);
 
6134
    fputs(" to ", ef);
 
6135
    ut_print_name(ef, trx, TRUE, norm_to);
 
6136
    fputs(" failed!\n", ef);
 
6137
  }
 
6138
 
 
6139
  if (lock_and_commit) {
 
6140
    row_mysql_unlock_data_dictionary(trx);
 
6141
 
 
6142
    /* Flush the log to reduce probability that the .frm
 
6143
    files and the InnoDB data dictionary get out-of-sync
 
6144
    if the user runs with innodb_flush_log_at_trx_commit = 0 */
 
6145
 
 
6146
    log_buffer_flush_to_disk();
 
6147
  }
 
6148
 
 
6149
  free(norm_to);
 
6150
  free(norm_from);
 
6151
 
 
6152
  return error;
6080
6153
}
6081
6154
/*********************************************************************//**
6082
6155
Renames an InnoDB table.
6083
 
@return 0 or error code */
6084
 
UNIV_INTERN
6085
 
int
6086
 
InnobaseEngine::doRenameTable(
6087
 
/*======================*/
6088
 
        Session*        session,
6089
 
        const char*     from,   /*!< in: old name of the table */
6090
 
        const char*     to)     /*!< in: new name of the table */
 
6156
@return 0 or error code */
 
6157
UNIV_INTERN int InnobaseEngine::doRenameTable(Session &session, TableIdentifier &from, TableIdentifier &to)
6091
6158
{
6092
 
        trx_t*  trx;
6093
 
        int     error;
6094
 
        trx_t*  parent_trx;
6095
 
 
6096
 
        /* Get the transaction associated with the current session, or create one
6097
 
        if not yet created */
6098
 
 
6099
 
        parent_trx = check_trx_exists(session);
6100
 
 
6101
 
        /* In case MySQL calls this in the middle of a SELECT query, release
6102
 
        possible adaptive hash latch to avoid deadlocks of threads */
6103
 
 
6104
 
        trx_search_latch_release_if_reserved(parent_trx);
6105
 
 
6106
 
        trx = innobase_trx_allocate(session);
6107
 
 
6108
 
        error = innobase_rename_table(trx, from, to, TRUE);
6109
 
 
6110
 
        /* Tell the InnoDB server that there might be work for
6111
 
        utility threads: */
6112
 
 
6113
 
        srv_active_wake_master_thread();
6114
 
 
6115
 
        innobase_commit_low(trx);
6116
 
        trx_free_for_mysql(trx);
6117
 
 
6118
 
        error = convert_error_code_to_mysql(error, 0, NULL);
6119
 
 
6120
 
        return(error);
 
6159
        // A temp table alter table/rename is a shallow rename and only the
 
6160
        // definition needs to be updated.
 
6161
        if (to.getType() == message::Table::TEMPORARY && from.getType() == message::Table::TEMPORARY)
 
6162
        {
 
6163
          return plugin::StorageEngine::renameDefinitionFromPath(to, from);
 
6164
        }
 
6165
 
 
6166
  trx_t*  trx;
 
6167
  int error;
 
6168
  trx_t*  parent_trx;
 
6169
 
 
6170
  /* Get the transaction associated with the current session, or create one
 
6171
  if not yet created */
 
6172
 
 
6173
  parent_trx = check_trx_exists(&session);
 
6174
 
 
6175
  /* In case MySQL calls this in the middle of a SELECT query, release
 
6176
  possible adaptive hash latch to avoid deadlocks of threads */
 
6177
 
 
6178
  trx_search_latch_release_if_reserved(parent_trx);
 
6179
 
 
6180
  trx = innobase_trx_allocate(&session);
 
6181
 
 
6182
  error = innobase_rename_table(trx, from.getPath().c_str(), to.getPath().c_str(), TRUE);
 
6183
 
 
6184
  /* Tell the InnoDB server that there might be work for
 
6185
  utility threads: */
 
6186
 
 
6187
  srv_active_wake_master_thread();
 
6188
 
 
6189
  innobase_commit_low(trx);
 
6190
  trx_free_for_mysql(trx);
 
6191
 
 
6192
  error = convert_error_code_to_mysql(error, 0, NULL);
 
6193
 
 
6194
        if (not error)
 
6195
        {
 
6196
          // If this fails, we are in trouble
 
6197
          plugin::StorageEngine::renameDefinitionFromPath(to, from);
 
6198
        }
 
6199
 
 
6200
  return(error);
6121
6201
}
6122
6202
 
6123
6203
/*********************************************************************//**
6124
6204
Estimates the number of index records in a range.
6125
 
@return estimated number of rows */
 
6205
@return estimated number of rows */
6126
6206
UNIV_INTERN
6127
6207
ha_rows
6128
6208
ha_innobase::records_in_range(
6129
6209
/*==========================*/
6130
 
        uint                    keynr,          /*!< in: index number */
6131
 
        key_range               *min_key,       /*!< in: start key value of the
6132
 
                                                   range, may also be 0 */
6133
 
        key_range               *max_key)       /*!< in: range end key val, may
6134
 
                                                   also be 0 */
 
6210
  uint      keynr,    /*!< in: index number */
 
6211
  key_range   *min_key, /*!< in: start key value of the
 
6212
               range, may also be 0 */
 
6213
  key_range   *max_key) /*!< in: range end key val, may
 
6214
               also be 0 */
6135
6215
{
6136
 
        KEY*            key;
6137
 
        dict_index_t*   index;
6138
 
        unsigned char*          key_val_buff2   = (unsigned char*) malloc(
6139
 
                                                  table->s->stored_rec_length
6140
 
                                        + table->s->max_key_length + 100);
6141
 
        ulint           buff2_len = table->s->stored_rec_length
6142
 
                                        + table->s->max_key_length + 100;
6143
 
        dtuple_t*       range_start;
6144
 
        dtuple_t*       range_end;
6145
 
        ib_int64_t      n_rows;
6146
 
        ulint           mode1;
6147
 
        ulint           mode2;
6148
 
        mem_heap_t*     heap;
6149
 
 
6150
 
        ut_a(prebuilt->trx == session_to_trx(ha_session()));
6151
 
 
6152
 
        prebuilt->trx->op_info = (char*)"estimating records in index range";
6153
 
 
6154
 
        /* In case MySQL calls this in the middle of a SELECT query, release
6155
 
        possible adaptive hash latch to avoid deadlocks of threads */
6156
 
 
6157
 
        trx_search_latch_release_if_reserved(prebuilt->trx);
6158
 
 
6159
 
        active_index = keynr;
6160
 
 
6161
 
        key = table->key_info + active_index;
6162
 
 
6163
 
        index = dict_table_get_index_on_name(prebuilt->table, key->name);
6164
 
 
6165
 
        /* MySQL knows about this index and so we must be able to find it.*/
6166
 
        ut_a(index);
6167
 
 
6168
 
        heap = mem_heap_create(2 * (key->key_parts * sizeof(dfield_t)
6169
 
                                    + sizeof(dtuple_t)));
6170
 
 
6171
 
        range_start = dtuple_create(heap, key->key_parts);
6172
 
        dict_index_copy_types(range_start, index, key->key_parts);
6173
 
 
6174
 
        range_end = dtuple_create(heap, key->key_parts);
6175
 
        dict_index_copy_types(range_end, index, key->key_parts);
6176
 
 
6177
 
        row_sel_convert_mysql_key_to_innobase(
6178
 
                                range_start, (byte*) key_val_buff,
6179
 
                                (ulint)upd_and_key_val_buff_len,
6180
 
                                index,
6181
 
                                (byte*) (min_key ? min_key->key :
6182
 
                                         (const unsigned char*) 0),
6183
 
                                (ulint) (min_key ? min_key->length : 0),
6184
 
                                prebuilt->trx);
6185
 
 
6186
 
        row_sel_convert_mysql_key_to_innobase(
6187
 
                                range_end, (byte*) key_val_buff2,
6188
 
                                buff2_len, index,
6189
 
                                (byte*) (max_key ? max_key->key :
6190
 
                                         (const unsigned char*) 0),
6191
 
                                (ulint) (max_key ? max_key->length : 0),
6192
 
                                prebuilt->trx);
6193
 
 
6194
 
        mode1 = convert_search_mode_to_innobase(min_key ? min_key->flag :
6195
 
                                                HA_READ_KEY_EXACT);
6196
 
        mode2 = convert_search_mode_to_innobase(max_key ? max_key->flag :
6197
 
                                                HA_READ_KEY_EXACT);
6198
 
 
6199
 
        if (mode1 != PAGE_CUR_UNSUPP && mode2 != PAGE_CUR_UNSUPP) {
6200
 
 
6201
 
                n_rows = btr_estimate_n_rows_in_range(index, range_start,
6202
 
                                                      mode1, range_end,
6203
 
                                                      mode2);
6204
 
        } else {
6205
 
 
6206
 
                n_rows = HA_POS_ERROR;
6207
 
        }
6208
 
 
6209
 
        mem_heap_free(heap);
6210
 
 
6211
 
        free(key_val_buff2);
6212
 
 
6213
 
        prebuilt->trx->op_info = (char*)"";
6214
 
 
6215
 
        /* The MySQL optimizer seems to believe an estimate of 0 rows is
6216
 
        always accurate and may return the result 'Empty set' based on that.
6217
 
        The accuracy is not guaranteed, and even if it were, for a locking
6218
 
        read we should anyway perform the search to set the next-key lock.
6219
 
        Add 1 to the value to make sure MySQL does not make the assumption! */
6220
 
 
6221
 
        if (n_rows == 0) {
6222
 
                n_rows = 1;
6223
 
        }
6224
 
 
6225
 
        return((ha_rows) n_rows);
 
6216
  KEY*    key;
 
6217
  dict_index_t* index;
 
6218
  unsigned char*    key_val_buff2 = (unsigned char*) malloc(
 
6219
              table->s->stored_rec_length
 
6220
          + table->s->max_key_length + 100);
 
6221
  ulint   buff2_len = table->s->stored_rec_length
 
6222
          + table->s->max_key_length + 100;
 
6223
  dtuple_t* range_start;
 
6224
  dtuple_t* range_end;
 
6225
  ib_int64_t  n_rows;
 
6226
  ulint   mode1;
 
6227
  ulint   mode2;
 
6228
  mem_heap_t* heap;
 
6229
 
 
6230
  ut_a(prebuilt->trx == session_to_trx(ha_session()));
 
6231
 
 
6232
  prebuilt->trx->op_info = (char*)"estimating records in index range";
 
6233
 
 
6234
  /* In case MySQL calls this in the middle of a SELECT query, release
 
6235
  possible adaptive hash latch to avoid deadlocks of threads */
 
6236
 
 
6237
  trx_search_latch_release_if_reserved(prebuilt->trx);
 
6238
 
 
6239
  active_index = keynr;
 
6240
 
 
6241
  key = table->key_info + active_index;
 
6242
 
 
6243
  index = dict_table_get_index_on_name(prebuilt->table, key->name);
 
6244
 
 
6245
  /* MySQL knows about this index and so we must be able to find it.*/
 
6246
  ut_a(index);
 
6247
 
 
6248
  heap = mem_heap_create(2 * (key->key_parts * sizeof(dfield_t)
 
6249
            + sizeof(dtuple_t)));
 
6250
 
 
6251
  range_start = dtuple_create(heap, key->key_parts);
 
6252
  dict_index_copy_types(range_start, index, key->key_parts);
 
6253
 
 
6254
  range_end = dtuple_create(heap, key->key_parts);
 
6255
  dict_index_copy_types(range_end, index, key->key_parts);
 
6256
 
 
6257
  row_sel_convert_mysql_key_to_innobase(
 
6258
        range_start, (byte*) key_val_buff,
 
6259
        (ulint)upd_and_key_val_buff_len,
 
6260
        index,
 
6261
        (byte*) (min_key ? min_key->key :
 
6262
           (const unsigned char*) 0),
 
6263
        (ulint) (min_key ? min_key->length : 0),
 
6264
        prebuilt->trx);
 
6265
 
 
6266
  row_sel_convert_mysql_key_to_innobase(
 
6267
        range_end, (byte*) key_val_buff2,
 
6268
        buff2_len, index,
 
6269
        (byte*) (max_key ? max_key->key :
 
6270
           (const unsigned char*) 0),
 
6271
        (ulint) (max_key ? max_key->length : 0),
 
6272
        prebuilt->trx);
 
6273
 
 
6274
  mode1 = convert_search_mode_to_innobase(min_key ? min_key->flag :
 
6275
            HA_READ_KEY_EXACT);
 
6276
  mode2 = convert_search_mode_to_innobase(max_key ? max_key->flag :
 
6277
            HA_READ_KEY_EXACT);
 
6278
 
 
6279
  if (mode1 != PAGE_CUR_UNSUPP && mode2 != PAGE_CUR_UNSUPP) {
 
6280
 
 
6281
    n_rows = btr_estimate_n_rows_in_range(index, range_start,
 
6282
                  mode1, range_end,
 
6283
                  mode2);
 
6284
  } else {
 
6285
 
 
6286
    n_rows = HA_POS_ERROR;
 
6287
  }
 
6288
 
 
6289
  mem_heap_free(heap);
 
6290
 
 
6291
  free(key_val_buff2);
 
6292
 
 
6293
  prebuilt->trx->op_info = (char*)"";
 
6294
 
 
6295
  /* The MySQL optimizer seems to believe an estimate of 0 rows is
 
6296
  always accurate and may return the result 'Empty set' based on that.
 
6297
  The accuracy is not guaranteed, and even if it were, for a locking
 
6298
  read we should anyway perform the search to set the next-key lock.
 
6299
  Add 1 to the value to make sure MySQL does not make the assumption! */
 
6300
 
 
6301
  if (n_rows == 0) {
 
6302
    n_rows = 1;
 
6303
  }
 
6304
 
 
6305
  return((ha_rows) n_rows);
6226
6306
}
6227
6307
 
6228
6308
/*********************************************************************//**
6229
6309
Gives an UPPER BOUND to the number of rows in a table. This is used in
6230
6310
filesort.cc.
6231
 
@return upper bound of rows */
 
6311
@return upper bound of rows */
6232
6312
UNIV_INTERN
6233
6313
ha_rows
6234
6314
ha_innobase::estimate_rows_upper_bound(void)
6235
6315
/*======================================*/
6236
6316
{
6237
 
        dict_index_t*   index;
6238
 
        uint64_t        estimate;
6239
 
        uint64_t        local_data_file_length;
6240
 
 
6241
 
        /* We do not know if MySQL can call this function before calling
6242
 
        external_lock(). To be safe, update the session of the current table
6243
 
        handle. */
6244
 
 
6245
 
        update_session(ha_session());
6246
 
 
6247
 
        prebuilt->trx->op_info = (char*)
6248
 
                                 "calculating upper bound for table rows";
6249
 
 
6250
 
        /* In case MySQL calls this in the middle of a SELECT query, release
6251
 
        possible adaptive hash latch to avoid deadlocks of threads */
6252
 
 
6253
 
        trx_search_latch_release_if_reserved(prebuilt->trx);
6254
 
 
6255
 
        index = dict_table_get_first_index(prebuilt->table);
6256
 
 
6257
 
        ut_a(index->stat_n_leaf_pages > 0);
6258
 
 
6259
 
        local_data_file_length =
6260
 
                ((uint64_t) index->stat_n_leaf_pages) * UNIV_PAGE_SIZE;
6261
 
 
6262
 
 
6263
 
        /* Calculate a minimum length for a clustered index record and from
6264
 
        that an upper bound for the number of rows. Since we only calculate
6265
 
        new statistics in row0mysql.c when a table has grown by a threshold
6266
 
        factor, we must add a safety factor 2 in front of the formula below. */
6267
 
 
6268
 
        estimate = 2 * local_data_file_length /
6269
 
                                         dict_index_calc_min_rec_len(index);
6270
 
 
6271
 
        prebuilt->trx->op_info = (char*)"";
6272
 
 
6273
 
        return((ha_rows) estimate);
 
6317
  dict_index_t* index;
 
6318
  uint64_t  estimate;
 
6319
  uint64_t  local_data_file_length;
 
6320
 
 
6321
  /* We do not know if MySQL can call this function before calling
 
6322
  external_lock(). To be safe, update the session of the current table
 
6323
  handle. */
 
6324
 
 
6325
  update_session(ha_session());
 
6326
 
 
6327
  prebuilt->trx->op_info = (char*)
 
6328
         "calculating upper bound for table rows";
 
6329
 
 
6330
  /* In case MySQL calls this in the middle of a SELECT query, release
 
6331
  possible adaptive hash latch to avoid deadlocks of threads */
 
6332
 
 
6333
  trx_search_latch_release_if_reserved(prebuilt->trx);
 
6334
 
 
6335
  index = dict_table_get_first_index(prebuilt->table);
 
6336
 
 
6337
  ut_a(index->stat_n_leaf_pages > 0);
 
6338
 
 
6339
  local_data_file_length =
 
6340
    ((uint64_t) index->stat_n_leaf_pages) * UNIV_PAGE_SIZE;
 
6341
 
 
6342
 
 
6343
  /* Calculate a minimum length for a clustered index record and from
 
6344
  that an upper bound for the number of rows. Since we only calculate
 
6345
  new statistics in row0mysql.c when a table has grown by a threshold
 
6346
  factor, we must add a safety factor 2 in front of the formula below. */
 
6347
 
 
6348
  estimate = 2 * local_data_file_length /
 
6349
           dict_index_calc_min_rec_len(index);
 
6350
 
 
6351
  prebuilt->trx->op_info = (char*)"";
 
6352
 
 
6353
  return((ha_rows) estimate);
6274
6354
}
6275
6355
 
6276
6356
/*********************************************************************//**
6277
6357
How many seeks it will take to read through the table. This is to be
6278
6358
comparable to the number returned by records_in_range so that we can
6279
6359
decide if we should scan the table or use keys.
6280
 
@return estimated time measured in disk seeks */
 
6360
@return estimated time measured in disk seeks */
6281
6361
UNIV_INTERN
6282
6362
double
6283
6363
ha_innobase::scan_time()
6284
6364
/*====================*/
6285
6365
{
6286
 
        /* Since MySQL seems to favor table scans too much over index
6287
 
        searches, we pretend that a sequential read takes the same time
6288
 
        as a random disk read, that is, we do not divide the following
6289
 
        by 10, which would be physically realistic. */
 
6366
  /* Since MySQL seems to favor table scans too much over index
 
6367
  searches, we pretend that a sequential read takes the same time
 
6368
  as a random disk read, that is, we do not divide the following
 
6369
  by 10, which would be physically realistic. */
6290
6370
 
6291
 
        return((double) (prebuilt->table->stat_clustered_index_size));
 
6371
  return((double) (prebuilt->table->stat_clustered_index_size));
6292
6372
}
6293
6373
 
6294
6374
/******************************************************************//**
6295
6375
Calculate the time it takes to read a set of ranges through an index
6296
6376
This enables us to optimise reads for clustered indexes.
6297
 
@return estimated time measured in disk seeks */
 
6377
@return estimated time measured in disk seeks */
6298
6378
UNIV_INTERN
6299
6379
double
6300
6380
ha_innobase::read_time(
6301
6381
/*===================*/
6302
 
        uint    index,  /*!< in: key number */
6303
 
        uint    ranges, /*!< in: how many ranges */
6304
 
        ha_rows rows)   /*!< in: estimated number of rows in the ranges */
 
6382
  uint  index,  /*!< in: key number */
 
6383
  uint  ranges, /*!< in: how many ranges */
 
6384
  ha_rows rows) /*!< in: estimated number of rows in the ranges */
6305
6385
{
6306
 
        ha_rows total_rows;
6307
 
        double  time_for_scan;
6308
 
 
6309
 
        if (index != table->s->primary_key) {
6310
 
                /* Not clustered */
6311
 
                return(Cursor::read_time(index, ranges, rows));
6312
 
        }
6313
 
 
6314
 
        if (rows <= 2) {
6315
 
 
6316
 
                return((double) rows);
6317
 
        }
6318
 
 
6319
 
        /* Assume that the read time is proportional to the scan time for all
6320
 
        rows + at most one seek per range. */
6321
 
 
6322
 
        time_for_scan = scan_time();
6323
 
 
6324
 
        if ((total_rows = estimate_rows_upper_bound()) < rows) {
6325
 
 
6326
 
                return(time_for_scan);
6327
 
        }
6328
 
 
6329
 
        return(ranges + (double) rows / (double) total_rows * time_for_scan);
 
6386
  ha_rows total_rows;
 
6387
  double  time_for_scan;
 
6388
 
 
6389
  if (index != table->s->primary_key) {
 
6390
    /* Not clustered */
 
6391
    return(Cursor::read_time(index, ranges, rows));
 
6392
  }
 
6393
 
 
6394
  if (rows <= 2) {
 
6395
 
 
6396
    return((double) rows);
 
6397
  }
 
6398
 
 
6399
  /* Assume that the read time is proportional to the scan time for all
 
6400
  rows + at most one seek per range. */
 
6401
 
 
6402
  time_for_scan = scan_time();
 
6403
 
 
6404
  if ((total_rows = estimate_rows_upper_bound()) < rows) {
 
6405
 
 
6406
    return(time_for_scan);
 
6407
  }
 
6408
 
 
6409
  return(ranges + (double) rows / (double) total_rows * time_for_scan);
6330
6410
}
6331
6411
 
6332
6412
/*********************************************************************//**
6336
6416
int
6337
6417
ha_innobase::info(
6338
6418
/*==============*/
6339
 
        uint flag)      /*!< in: what information MySQL requests */
 
6419
  uint flag)  /*!< in: what information MySQL requests */
6340
6420
{
6341
 
        dict_table_t*   ib_table;
6342
 
        dict_index_t*   index;
6343
 
        ha_rows         rec_per_key;
6344
 
        ib_int64_t      n_rows;
6345
 
        ulong           j;
6346
 
        ulong           i;
6347
 
        char            path[FN_REFLEN];
6348
 
        os_file_stat_t  stat_info;
6349
 
 
6350
 
        /* If we are forcing recovery at a high level, we will suppress
6351
 
        statistics calculation on tables, because that may crash the
6352
 
        server if an index is badly corrupted. */
6353
 
 
6354
 
        if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
6355
 
 
6356
 
                /* We return success (0) instead of HA_ERR_CRASHED,
6357
 
                because we want MySQL to process this query and not
6358
 
                stop, like it would do if it received the error code
6359
 
                HA_ERR_CRASHED. */
6360
 
 
6361
 
                return(0);
6362
 
        }
6363
 
 
6364
 
        /* We do not know if MySQL can call this function before calling
6365
 
        external_lock(). To be safe, update the session of the current table
6366
 
        handle. */
6367
 
 
6368
 
        update_session(ha_session());
6369
 
 
6370
 
        /* In case MySQL calls this in the middle of a SELECT query, release
6371
 
        possible adaptive hash latch to avoid deadlocks of threads */
6372
 
 
6373
 
        prebuilt->trx->op_info = (char*)"returning various info to MySQL";
6374
 
 
6375
 
        trx_search_latch_release_if_reserved(prebuilt->trx);
6376
 
 
6377
 
        ib_table = prebuilt->table;
6378
 
 
6379
 
        if (flag & HA_STATUS_TIME) {
6380
 
                if (innobase_stats_on_metadata) {
6381
 
                        /* In sql_show we call with this flag: update
6382
 
                        then statistics so that they are up-to-date */
6383
 
 
6384
 
                        prebuilt->trx->op_info = "updating table statistics";
6385
 
 
6386
 
                        dict_update_statistics(ib_table);
6387
 
 
6388
 
                        prebuilt->trx->op_info = "returning various info to MySQL";
6389
 
                }
6390
 
 
6391
 
                snprintf(path, sizeof(path), "%s/%s%s",
6392
 
                               drizzle_data_home, ib_table->name, ".dfe");
6393
 
 
6394
 
                internal::unpack_filename(path,path);
6395
 
 
6396
 
                /* Note that we do not know the access time of the table,
6397
 
                nor the CHECK TABLE time, nor the UPDATE or INSERT time. */
6398
 
 
6399
 
                if (os_file_get_status(path,&stat_info)) {
6400
 
                        stats.create_time = (ulong) stat_info.ctime;
6401
 
                }
6402
 
        }
6403
 
 
6404
 
        if (flag & HA_STATUS_VARIABLE) {
6405
 
                n_rows = ib_table->stat_n_rows;
6406
 
 
6407
 
                /* Because we do not protect stat_n_rows by any mutex in a
6408
 
                delete, it is theoretically possible that the value can be
6409
 
                smaller than zero! TODO: fix this race.
6410
 
 
6411
 
                The MySQL optimizer seems to assume in a left join that n_rows
6412
 
                is an accurate estimate if it is zero. Of course, it is not,
6413
 
                since we do not have any locks on the rows yet at this phase.
6414
 
                Since SHOW TABLE STATUS seems to call this function with the
6415
 
                HA_STATUS_TIME flag set, while the left join optimizer does not
6416
 
                set that flag, we add one to a zero value if the flag is not
6417
 
                set. That way SHOW TABLE STATUS will show the best estimate,
6418
 
                while the optimizer never sees the table empty. */
6419
 
 
6420
 
                if (n_rows < 0) {
6421
 
                        n_rows = 0;
6422
 
                }
6423
 
 
6424
 
                if (n_rows == 0 && !(flag & HA_STATUS_TIME)) {
6425
 
                        n_rows++;
6426
 
                }
6427
 
 
6428
 
                /* Fix bug#40386: Not flushing query cache after truncate.
6429
 
                n_rows can not be 0 unless the table is empty, set to 1
6430
 
                instead. The original problem of bug#29507 is actually
6431
 
                fixed in the server code. */
6432
 
                if (session_sql_command(user_session) == SQLCOM_TRUNCATE) {
6433
 
 
6434
 
                        n_rows = 1;
6435
 
 
6436
 
                        /* We need to reset the prebuilt value too, otherwise
6437
 
                        checks for values greater than the last value written
6438
 
                        to the table will fail and the autoinc counter will
6439
 
                        not be updated. This will force write_row() into
6440
 
                        attempting an update of the table's AUTOINC counter. */
6441
 
 
6442
 
                        prebuilt->autoinc_last_value = 0;
6443
 
                }
6444
 
 
6445
 
                stats.records = (ha_rows)n_rows;
6446
 
                stats.deleted = 0;
6447
 
                stats.data_file_length = ((uint64_t)
6448
 
                                ib_table->stat_clustered_index_size)
6449
 
                                        * UNIV_PAGE_SIZE;
6450
 
                stats.index_file_length = ((uint64_t)
6451
 
                                ib_table->stat_sum_of_other_index_sizes)
6452
 
                                        * UNIV_PAGE_SIZE;
6453
 
 
6454
 
                /* Since fsp_get_available_space_in_free_extents() is
6455
 
                acquiring latches inside InnoDB, we do not call it if we
6456
 
                are asked by MySQL to avoid locking. Another reason to
6457
 
                avoid the call is that it uses quite a lot of CPU.
6458
 
                See Bug#38185.
6459
 
                We do not update delete_length if no locking is requested
6460
 
                so the "old" value can remain. delete_length is initialized
6461
 
                to 0 in the ha_statistics' constructor. */
6462
 
                if (!(flag & HA_STATUS_NO_LOCK)) {
6463
 
 
6464
 
                        /* lock the data dictionary to avoid races with
6465
 
                        ibd_file_missing and tablespace_discarded */
6466
 
                        row_mysql_lock_data_dictionary(prebuilt->trx);
6467
 
 
6468
 
                        /* ib_table->space must be an existent tablespace */
6469
 
                        if (!ib_table->ibd_file_missing
6470
 
                            && !ib_table->tablespace_discarded) {
6471
 
 
6472
 
                                stats.delete_length =
6473
 
                                        fsp_get_available_space_in_free_extents(
6474
 
                                                ib_table->space) * 1024;
6475
 
                        } else {
6476
 
 
6477
 
                                Session*        session;
6478
 
 
6479
 
                                session = ha_session();
6480
 
 
6481
 
                                push_warning_printf(
6482
 
                                        session,
6483
 
                                        DRIZZLE_ERROR::WARN_LEVEL_WARN,
6484
 
                                        ER_CANT_GET_STAT,
6485
 
                                        "InnoDB: Trying to get the free "
6486
 
                                        "space for table %s but its "
6487
 
                                        "tablespace has been discarded or "
6488
 
                                        "the .ibd file is missing. Setting "
6489
 
                                        "the free space to zero.",
6490
 
                                        ib_table->name);
6491
 
 
6492
 
                                stats.delete_length = 0;
6493
 
                        }
6494
 
 
6495
 
                        row_mysql_unlock_data_dictionary(prebuilt->trx);
6496
 
                }
6497
 
 
6498
 
                stats.check_time = 0;
6499
 
 
6500
 
                if (stats.records == 0) {
6501
 
                        stats.mean_rec_length = 0;
6502
 
                } else {
6503
 
                        stats.mean_rec_length = (ulong) (stats.data_file_length / stats.records);
6504
 
                }
6505
 
        }
6506
 
 
6507
 
        if (flag & HA_STATUS_CONST) {
6508
 
                index = dict_table_get_first_index(ib_table);
6509
 
 
6510
 
                if (prebuilt->clust_index_was_generated) {
6511
 
                        index = dict_table_get_next_index(index);
6512
 
                }
6513
 
 
6514
 
                for (i = 0; i < table->s->keys; i++) {
6515
 
                        if (index == NULL) {
6516
 
                                errmsg_printf(ERRMSG_LVL_ERROR, "Table %s contains fewer "
6517
 
                                                "indexes inside InnoDB than "
6518
 
                                                "are defined in the MySQL "
6519
 
                                                ".frm file. Have you mixed up "
6520
 
                                                ".frm files from different "
6521
 
                                                "installations? See "
6522
 
                                                REFMAN
6523
 
                                                "innodb-troubleshooting.html\n",
6524
 
                                                ib_table->name);
6525
 
                                break;
6526
 
                        }
6527
 
 
6528
 
                        for (j = 0; j < table->key_info[i].key_parts; j++) {
6529
 
 
6530
 
                                if (j + 1 > index->n_uniq) {
6531
 
                                        errmsg_printf(ERRMSG_LVL_ERROR, 
 
6421
  dict_table_t* ib_table;
 
6422
  dict_index_t* index;
 
6423
  ha_rows   rec_per_key;
 
6424
  ib_int64_t  n_rows;
 
6425
  ulong   j;
 
6426
  ulong   i;
 
6427
  char    path[FN_REFLEN];
 
6428
  os_file_stat_t  stat_info;
 
6429
 
 
6430
  /* If we are forcing recovery at a high level, we will suppress
 
6431
  statistics calculation on tables, because that may crash the
 
6432
  server if an index is badly corrupted. */
 
6433
 
 
6434
  if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
 
6435
 
 
6436
    /* We return success (0) instead of HA_ERR_CRASHED,
 
6437
    because we want MySQL to process this query and not
 
6438
    stop, like it would do if it received the error code
 
6439
    HA_ERR_CRASHED. */
 
6440
 
 
6441
    return(0);
 
6442
  }
 
6443
 
 
6444
  /* We do not know if MySQL can call this function before calling
 
6445
  external_lock(). To be safe, update the session of the current table
 
6446
  handle. */
 
6447
 
 
6448
  update_session(ha_session());
 
6449
 
 
6450
  /* In case MySQL calls this in the middle of a SELECT query, release
 
6451
  possible adaptive hash latch to avoid deadlocks of threads */
 
6452
 
 
6453
  prebuilt->trx->op_info = (char*)"returning various info to MySQL";
 
6454
 
 
6455
  trx_search_latch_release_if_reserved(prebuilt->trx);
 
6456
 
 
6457
  ib_table = prebuilt->table;
 
6458
 
 
6459
  if (flag & HA_STATUS_TIME) {
 
6460
    if (innobase_stats_on_metadata) {
 
6461
      /* In sql_show we call with this flag: update
 
6462
      then statistics so that they are up-to-date */
 
6463
 
 
6464
      prebuilt->trx->op_info = "updating table statistics";
 
6465
 
 
6466
      dict_update_statistics(ib_table);
 
6467
 
 
6468
      prebuilt->trx->op_info = "returning various info to MySQL";
 
6469
    }
 
6470
 
 
6471
    snprintf(path, sizeof(path), "%s/%s%s",
 
6472
             drizzle_data_home, ib_table->name, ".dfe");
 
6473
 
 
6474
    internal::unpack_filename(path,path);
 
6475
 
 
6476
    /* Note that we do not know the access time of the table,
 
6477
    nor the CHECK TABLE time, nor the UPDATE or INSERT time. */
 
6478
 
 
6479
    if (os_file_get_status(path,&stat_info)) {
 
6480
      stats.create_time = (ulong) stat_info.ctime;
 
6481
    }
 
6482
  }
 
6483
 
 
6484
  if (flag & HA_STATUS_VARIABLE) {
 
6485
    n_rows = ib_table->stat_n_rows;
 
6486
 
 
6487
    /* Because we do not protect stat_n_rows by any mutex in a
 
6488
    delete, it is theoretically possible that the value can be
 
6489
    smaller than zero! TODO: fix this race.
 
6490
 
 
6491
    The MySQL optimizer seems to assume in a left join that n_rows
 
6492
    is an accurate estimate if it is zero. Of course, it is not,
 
6493
    since we do not have any locks on the rows yet at this phase.
 
6494
    Since SHOW TABLE STATUS seems to call this function with the
 
6495
    HA_STATUS_TIME flag set, while the left join optimizer does not
 
6496
    set that flag, we add one to a zero value if the flag is not
 
6497
    set. That way SHOW TABLE STATUS will show the best estimate,
 
6498
    while the optimizer never sees the table empty. */
 
6499
 
 
6500
    if (n_rows < 0) {
 
6501
      n_rows = 0;
 
6502
    }
 
6503
 
 
6504
    if (n_rows == 0 && !(flag & HA_STATUS_TIME)) {
 
6505
      n_rows++;
 
6506
    }
 
6507
 
 
6508
    /* Fix bug#40386: Not flushing query cache after truncate.
 
6509
    n_rows can not be 0 unless the table is empty, set to 1
 
6510
    instead. The original problem of bug#29507 is actually
 
6511
    fixed in the server code. */
 
6512
    if (session_sql_command(user_session) == SQLCOM_TRUNCATE) {
 
6513
 
 
6514
      n_rows = 1;
 
6515
 
 
6516
      /* We need to reset the prebuilt value too, otherwise
 
6517
      checks for values greater than the last value written
 
6518
      to the table will fail and the autoinc counter will
 
6519
      not be updated. This will force write_row() into
 
6520
      attempting an update of the table's AUTOINC counter. */
 
6521
 
 
6522
      prebuilt->autoinc_last_value = 0;
 
6523
    }
 
6524
 
 
6525
    stats.records = (ha_rows)n_rows;
 
6526
    stats.deleted = 0;
 
6527
    stats.data_file_length = ((uint64_t)
 
6528
        ib_table->stat_clustered_index_size)
 
6529
          * UNIV_PAGE_SIZE;
 
6530
    stats.index_file_length = ((uint64_t)
 
6531
        ib_table->stat_sum_of_other_index_sizes)
 
6532
          * UNIV_PAGE_SIZE;
 
6533
 
 
6534
    /* Since fsp_get_available_space_in_free_extents() is
 
6535
    acquiring latches inside InnoDB, we do not call it if we
 
6536
    are asked by MySQL to avoid locking. Another reason to
 
6537
    avoid the call is that it uses quite a lot of CPU.
 
6538
    See Bug#38185.
 
6539
    We do not update delete_length if no locking is requested
 
6540
    so the "old" value can remain. delete_length is initialized
 
6541
    to 0 in the ha_statistics' constructor. */
 
6542
    if (!(flag & HA_STATUS_NO_LOCK)) {
 
6543
 
 
6544
      /* lock the data dictionary to avoid races with
 
6545
      ibd_file_missing and tablespace_discarded */
 
6546
      row_mysql_lock_data_dictionary(prebuilt->trx);
 
6547
 
 
6548
      /* ib_table->space must be an existent tablespace */
 
6549
      if (!ib_table->ibd_file_missing
 
6550
          && !ib_table->tablespace_discarded) {
 
6551
 
 
6552
        stats.delete_length =
 
6553
          fsp_get_available_space_in_free_extents(
 
6554
            ib_table->space) * 1024;
 
6555
      } else {
 
6556
 
 
6557
        Session*  session;
 
6558
 
 
6559
        session = ha_session();
 
6560
 
 
6561
        push_warning_printf(
 
6562
          session,
 
6563
          DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
6564
          ER_CANT_GET_STAT,
 
6565
          "InnoDB: Trying to get the free "
 
6566
          "space for table %s but its "
 
6567
          "tablespace has been discarded or "
 
6568
          "the .ibd file is missing. Setting "
 
6569
          "the free space to zero.",
 
6570
          ib_table->name);
 
6571
 
 
6572
        stats.delete_length = 0;
 
6573
      }
 
6574
 
 
6575
      row_mysql_unlock_data_dictionary(prebuilt->trx);
 
6576
    }
 
6577
 
 
6578
    stats.check_time = 0;
 
6579
 
 
6580
    if (stats.records == 0) {
 
6581
      stats.mean_rec_length = 0;
 
6582
    } else {
 
6583
      stats.mean_rec_length = (ulong) (stats.data_file_length / stats.records);
 
6584
    }
 
6585
  }
 
6586
 
 
6587
  if (flag & HA_STATUS_CONST) {
 
6588
    index = dict_table_get_first_index(ib_table);
 
6589
 
 
6590
    if (prebuilt->clust_index_was_generated) {
 
6591
      index = dict_table_get_next_index(index);
 
6592
    }
 
6593
 
 
6594
    for (i = 0; i < table->s->keys; i++) {
 
6595
      if (index == NULL) {
 
6596
        errmsg_printf(ERRMSG_LVL_ERROR, "Table %s contains fewer "
 
6597
            "indexes inside InnoDB than "
 
6598
            "are defined in the MySQL "
 
6599
            ".frm file. Have you mixed up "
 
6600
            ".frm files from different "
 
6601
            "installations? See "
 
6602
            REFMAN
 
6603
            "innodb-troubleshooting.html\n",
 
6604
            ib_table->name);
 
6605
        break;
 
6606
      }
 
6607
 
 
6608
      for (j = 0; j < table->key_info[i].key_parts; j++) {
 
6609
 
 
6610
        if (j + 1 > index->n_uniq) {
 
6611
          errmsg_printf(ERRMSG_LVL_ERROR, 
6532
6612
"Index %s of %s has %lu columns unique inside InnoDB, but MySQL is asking "
6533
6613
"statistics for %lu columns. Have you mixed up .frm files from different "
6534
6614
"installations? "
6535
6615
"See " REFMAN "innodb-troubleshooting.html\n",
6536
 
                                                        index->name,
6537
 
                                                        ib_table->name,
6538
 
                                                        (unsigned long)
6539
 
                                                        index->n_uniq, j + 1);
6540
 
                                        break;
6541
 
                                }
6542
 
 
6543
 
                                if (index->stat_n_diff_key_vals[j + 1] == 0) {
6544
 
 
6545
 
                                        rec_per_key = stats.records;
6546
 
                                } else {
6547
 
                                        rec_per_key = (ha_rows)(stats.records /
6548
 
                                         index->stat_n_diff_key_vals[j + 1]);
6549
 
                                }
6550
 
 
6551
 
                                /* Since MySQL seems to favor table scans
6552
 
                                too much over index searches, we pretend
6553
 
                                index selectivity is 2 times better than
6554
 
                                our estimate: */
6555
 
 
6556
 
                                rec_per_key = rec_per_key / 2;
6557
 
 
6558
 
                                if (rec_per_key == 0) {
6559
 
                                        rec_per_key = 1;
6560
 
                                }
6561
 
 
6562
 
                                table->key_info[i].rec_per_key[j]=
6563
 
                                  rec_per_key >= ~(ulong) 0 ? ~(ulong) 0 :
6564
 
                                  (ulong) rec_per_key;
6565
 
                        }
6566
 
 
6567
 
                        index = dict_table_get_next_index(index);
6568
 
                }
6569
 
        }
6570
 
 
6571
 
        if (flag & HA_STATUS_ERRKEY) {
6572
 
                const dict_index_t*     err_index;
6573
 
 
6574
 
                ut_a(prebuilt->trx);
6575
 
                ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N);
6576
 
 
6577
 
                err_index = trx_get_error_info(prebuilt->trx);
6578
 
 
6579
 
                if (err_index) {
6580
 
                        errkey = (unsigned int)
6581
 
                                row_get_mysql_key_number_for_index(err_index);
6582
 
                } else {
6583
 
                        errkey = (unsigned int) prebuilt->trx->error_key_num;
6584
 
                }
6585
 
        }
6586
 
 
6587
 
        if ((flag & HA_STATUS_AUTO) && table->found_next_number_field) {
6588
 
                stats.auto_increment_value = innobase_peek_autoinc();
6589
 
        }
6590
 
 
6591
 
        prebuilt->trx->op_info = (char*)"";
6592
 
 
6593
 
        return(0);
 
6616
              index->name,
 
6617
              ib_table->name,
 
6618
              (unsigned long)
 
6619
              index->n_uniq, j + 1);
 
6620
          break;
 
6621
        }
 
6622
 
 
6623
        if (index->stat_n_diff_key_vals[j + 1] == 0) {
 
6624
 
 
6625
          rec_per_key = stats.records;
 
6626
        } else {
 
6627
          rec_per_key = (ha_rows)(stats.records /
 
6628
           index->stat_n_diff_key_vals[j + 1]);
 
6629
        }
 
6630
 
 
6631
        /* Since MySQL seems to favor table scans
 
6632
        too much over index searches, we pretend
 
6633
        index selectivity is 2 times better than
 
6634
        our estimate: */
 
6635
 
 
6636
        rec_per_key = rec_per_key / 2;
 
6637
 
 
6638
        if (rec_per_key == 0) {
 
6639
          rec_per_key = 1;
 
6640
        }
 
6641
 
 
6642
        table->key_info[i].rec_per_key[j]=
 
6643
          rec_per_key >= ~(ulong) 0 ? ~(ulong) 0 :
 
6644
          (ulong) rec_per_key;
 
6645
      }
 
6646
 
 
6647
      index = dict_table_get_next_index(index);
 
6648
    }
 
6649
  }
 
6650
 
 
6651
  if (flag & HA_STATUS_ERRKEY) {
 
6652
    const dict_index_t* err_index;
 
6653
 
 
6654
    ut_a(prebuilt->trx);
 
6655
    ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N);
 
6656
 
 
6657
    err_index = trx_get_error_info(prebuilt->trx);
 
6658
 
 
6659
    if (err_index) {
 
6660
      errkey = (unsigned int)
 
6661
        row_get_mysql_key_number_for_index(err_index);
 
6662
    } else {
 
6663
      errkey = (unsigned int) prebuilt->trx->error_key_num;
 
6664
    }
 
6665
  }
 
6666
 
 
6667
  if ((flag & HA_STATUS_AUTO) && table->found_next_number_field) {
 
6668
    stats.auto_increment_value = innobase_peek_autoinc();
 
6669
  }
 
6670
 
 
6671
  prebuilt->trx->op_info = (char*)"";
 
6672
 
 
6673
  return(0);
6594
6674
}
6595
6675
 
6596
6676
/**********************************************************************//**
6597
6677
Updates index cardinalities of the table, based on 8 random dives into
6598
6678
each index tree. This does NOT calculate exact statistics on the table.
6599
 
@return returns always 0 (success) */
 
6679
@return returns always 0 (success) */
6600
6680
UNIV_INTERN
6601
6681
int
6602
6682
ha_innobase::analyze(
6603
6683
/*=================*/
6604
 
        Session*)               /*!< in: connection thread handle */
 
6684
  Session*)   /*!< in: connection thread handle */
6605
6685
{
6606
 
        /* Simply call ::info() with all the flags */
6607
 
        info(HA_STATUS_TIME | HA_STATUS_CONST | HA_STATUS_VARIABLE);
 
6686
  /* Simply call ::info() with all the flags */
 
6687
  info(HA_STATUS_TIME | HA_STATUS_CONST | HA_STATUS_VARIABLE);
6608
6688
 
6609
 
        return(0);
 
6689
  return(0);
6610
6690
}
6611
6691
 
6612
6692
/*******************************************************************//**
6613
6693
Tries to check that an InnoDB table is not corrupted. If corruption is
6614
6694
noticed, prints to stderr information about it. In case of corruption
6615
6695
may also assert a failure and crash the server.
6616
 
@return HA_ADMIN_CORRUPT or HA_ADMIN_OK */
 
6696
@return HA_ADMIN_CORRUPT or HA_ADMIN_OK */
6617
6697
UNIV_INTERN
6618
6698
int
6619
6699
ha_innobase::check(
6620
6700
/*===============*/
6621
 
        Session*        session)        /*!< in: user thread handle */
 
6701
  Session*  session)  /*!< in: user thread handle */
6622
6702
{
6623
 
        ulint           ret;
6624
 
 
6625
 
        assert(session == ha_session());
6626
 
        ut_a(prebuilt->trx);
6627
 
        ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N);
6628
 
        ut_a(prebuilt->trx == session_to_trx(session));
6629
 
 
6630
 
        if (prebuilt->mysql_template == NULL) {
6631
 
                /* Build the template; we will use a dummy template
6632
 
                in index scans done in checking */
6633
 
 
6634
 
                build_template(prebuilt, NULL, table, ROW_MYSQL_WHOLE_ROW);
6635
 
        }
6636
 
 
6637
 
        ret = row_check_table_for_mysql(prebuilt);
6638
 
 
6639
 
        if (ret == DB_SUCCESS) {
6640
 
                return(HA_ADMIN_OK);
6641
 
        }
6642
 
 
6643
 
        return(HA_ADMIN_CORRUPT);
 
6703
  ulint   ret;
 
6704
 
 
6705
  assert(session == ha_session());
 
6706
  ut_a(prebuilt->trx);
 
6707
  ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N);
 
6708
  ut_a(prebuilt->trx == session_to_trx(session));
 
6709
 
 
6710
  if (prebuilt->mysql_template == NULL) {
 
6711
    /* Build the template; we will use a dummy template
 
6712
    in index scans done in checking */
 
6713
 
 
6714
    build_template(prebuilt, NULL, table, ROW_MYSQL_WHOLE_ROW);
 
6715
  }
 
6716
 
 
6717
  ret = row_check_table_for_mysql(prebuilt);
 
6718
 
 
6719
  if (ret == DB_SUCCESS) {
 
6720
    return(HA_ADMIN_OK);
 
6721
  }
 
6722
 
 
6723
  return(HA_ADMIN_CORRUPT);
6644
6724
}
6645
6725
 
6646
6726
/*************************************************************//**
6647
6727
Adds information about free space in the InnoDB tablespace to a table comment
6648
6728
which is printed out when a user calls SHOW TABLE STATUS. Adds also info on
6649
6729
foreign keys.
6650
 
@return table comment + InnoDB free space + info on foreign keys */
 
6730
@return table comment + InnoDB free space + info on foreign keys */
6651
6731
UNIV_INTERN
6652
6732
char*
6653
6733
ha_innobase::update_table_comment(
6654
6734
/*==============================*/
6655
 
        const char*     comment)/*!< in: table comment defined by user */
 
6735
  const char* comment)/*!< in: table comment defined by user */
6656
6736
{
6657
 
        uint    length = (uint) strlen(comment);
6658
 
        char*   str;
6659
 
        long    flen;
6660
 
 
6661
 
        /* We do not know if MySQL can call this function before calling
6662
 
        external_lock(). To be safe, update the session of the current table
6663
 
        handle. */
6664
 
 
6665
 
        if (length > 64000 - 3) {
6666
 
                return((char*)comment); /* string too long */
6667
 
        }
6668
 
 
6669
 
        update_session(ha_session());
6670
 
 
6671
 
        prebuilt->trx->op_info = (char*)"returning table comment";
6672
 
 
6673
 
        /* In case MySQL calls this in the middle of a SELECT query, release
6674
 
        possible adaptive hash latch to avoid deadlocks of threads */
6675
 
 
6676
 
        trx_search_latch_release_if_reserved(prebuilt->trx);
6677
 
        str = NULL;
6678
 
 
6679
 
        /* output the data to a temporary file */
6680
 
 
6681
 
        mutex_enter(&srv_dict_tmpfile_mutex);
6682
 
        rewind(srv_dict_tmpfile);
6683
 
 
6684
 
        fprintf(srv_dict_tmpfile, "InnoDB free: %llu kB",
6685
 
                fsp_get_available_space_in_free_extents(
6686
 
                        prebuilt->table->space));
6687
 
 
6688
 
        dict_print_info_on_foreign_keys(FALSE, srv_dict_tmpfile,
6689
 
                                prebuilt->trx, prebuilt->table);
6690
 
        flen = ftell(srv_dict_tmpfile);
6691
 
        if (flen < 0) {
6692
 
                flen = 0;
6693
 
        } else if (length + flen + 3 > 64000) {
6694
 
                flen = 64000 - 3 - length;
6695
 
        }
6696
 
 
6697
 
        /* allocate buffer for the full string, and
6698
 
        read the contents of the temporary file */
6699
 
 
6700
 
        str = (char*) malloc(length + flen + 3);
6701
 
 
6702
 
        if (str) {
6703
 
                char* pos       = str + length;
6704
 
                if (length) {
6705
 
                        memcpy(str, comment, length);
6706
 
                        *pos++ = ';';
6707
 
                        *pos++ = ' ';
6708
 
                }
6709
 
                rewind(srv_dict_tmpfile);
6710
 
                flen = (uint) fread(pos, 1, flen, srv_dict_tmpfile);
6711
 
                pos[flen] = 0;
6712
 
        }
6713
 
 
6714
 
        mutex_exit(&srv_dict_tmpfile_mutex);
6715
 
 
6716
 
        prebuilt->trx->op_info = (char*)"";
6717
 
 
6718
 
        return(str ? str : (char*) comment);
 
6737
  uint  length = (uint) strlen(comment);
 
6738
  char* str;
 
6739
  long  flen;
 
6740
 
 
6741
  /* We do not know if MySQL can call this function before calling
 
6742
  external_lock(). To be safe, update the session of the current table
 
6743
  handle. */
 
6744
 
 
6745
  if (length > 64000 - 3) {
 
6746
    return((char*)comment); /* string too long */
 
6747
  }
 
6748
 
 
6749
  update_session(ha_session());
 
6750
 
 
6751
  prebuilt->trx->op_info = (char*)"returning table comment";
 
6752
 
 
6753
  /* In case MySQL calls this in the middle of a SELECT query, release
 
6754
  possible adaptive hash latch to avoid deadlocks of threads */
 
6755
 
 
6756
  trx_search_latch_release_if_reserved(prebuilt->trx);
 
6757
  str = NULL;
 
6758
 
 
6759
  /* output the data to a temporary file */
 
6760
 
 
6761
  mutex_enter(&srv_dict_tmpfile_mutex);
 
6762
  rewind(srv_dict_tmpfile);
 
6763
 
 
6764
  fprintf(srv_dict_tmpfile, "InnoDB free: %llu kB",
 
6765
    fsp_get_available_space_in_free_extents(
 
6766
      prebuilt->table->space));
 
6767
 
 
6768
  dict_print_info_on_foreign_keys(FALSE, srv_dict_tmpfile,
 
6769
        prebuilt->trx, prebuilt->table);
 
6770
  flen = ftell(srv_dict_tmpfile);
 
6771
  if (flen < 0) {
 
6772
    flen = 0;
 
6773
  } else if (length + flen + 3 > 64000) {
 
6774
    flen = 64000 - 3 - length;
 
6775
  }
 
6776
 
 
6777
  /* allocate buffer for the full string, and
 
6778
  read the contents of the temporary file */
 
6779
 
 
6780
  str = (char*) malloc(length + flen + 3);
 
6781
 
 
6782
  if (str) {
 
6783
    char* pos = str + length;
 
6784
    if (length) {
 
6785
      memcpy(str, comment, length);
 
6786
      *pos++ = ';';
 
6787
      *pos++ = ' ';
 
6788
    }
 
6789
    rewind(srv_dict_tmpfile);
 
6790
    flen = (uint) fread(pos, 1, flen, srv_dict_tmpfile);
 
6791
    pos[flen] = 0;
 
6792
  }
 
6793
 
 
6794
  mutex_exit(&srv_dict_tmpfile_mutex);
 
6795
 
 
6796
  prebuilt->trx->op_info = (char*)"";
 
6797
 
 
6798
  return(str ? str : (char*) comment);
6719
6799
}
6720
6800
 
6721
6801
/*******************************************************************//**
6728
6808
ha_innobase::get_foreign_key_create_info(void)
6729
6809
/*==========================================*/
6730
6810
{
6731
 
        char*   str     = 0;
6732
 
        long    flen;
6733
 
 
6734
 
        ut_a(prebuilt != NULL);
6735
 
 
6736
 
        /* We do not know if MySQL can call this function before calling
6737
 
        external_lock(). To be safe, update the session of the current table
6738
 
        handle. */
6739
 
 
6740
 
        update_session(ha_session());
6741
 
 
6742
 
        prebuilt->trx->op_info = (char*)"getting info on foreign keys";
6743
 
 
6744
 
        /* In case MySQL calls this in the middle of a SELECT query,
6745
 
        release possible adaptive hash latch to avoid
6746
 
        deadlocks of threads */
6747
 
 
6748
 
        trx_search_latch_release_if_reserved(prebuilt->trx);
6749
 
 
6750
 
        mutex_enter(&srv_dict_tmpfile_mutex);
6751
 
        rewind(srv_dict_tmpfile);
6752
 
 
6753
 
        /* output the data to a temporary file */
6754
 
        dict_print_info_on_foreign_keys(TRUE, srv_dict_tmpfile,
6755
 
                                prebuilt->trx, prebuilt->table);
6756
 
        prebuilt->trx->op_info = (char*)"";
6757
 
 
6758
 
        flen = ftell(srv_dict_tmpfile);
6759
 
        if (flen < 0) {
6760
 
                flen = 0;
6761
 
        } else if (flen > 64000 - 1) {
6762
 
                flen = 64000 - 1;
6763
 
        }
6764
 
 
6765
 
        /* allocate buffer for the string, and
6766
 
        read the contents of the temporary file */
6767
 
 
6768
 
        str = (char*) malloc(flen + 1);
6769
 
 
6770
 
        if (str) {
6771
 
                rewind(srv_dict_tmpfile);
6772
 
                flen = (uint) fread(str, 1, flen, srv_dict_tmpfile);
6773
 
                str[flen] = 0;
6774
 
        }
6775
 
 
6776
 
        mutex_exit(&srv_dict_tmpfile_mutex);
6777
 
 
6778
 
        return(str);
 
6811
  char* str = 0;
 
6812
  long  flen;
 
6813
 
 
6814
  ut_a(prebuilt != NULL);
 
6815
 
 
6816
  /* We do not know if MySQL can call this function before calling
 
6817
  external_lock(). To be safe, update the session of the current table
 
6818
  handle. */
 
6819
 
 
6820
  update_session(ha_session());
 
6821
 
 
6822
  prebuilt->trx->op_info = (char*)"getting info on foreign keys";
 
6823
 
 
6824
  /* In case MySQL calls this in the middle of a SELECT query,
 
6825
  release possible adaptive hash latch to avoid
 
6826
  deadlocks of threads */
 
6827
 
 
6828
  trx_search_latch_release_if_reserved(prebuilt->trx);
 
6829
 
 
6830
  mutex_enter(&srv_dict_tmpfile_mutex);
 
6831
  rewind(srv_dict_tmpfile);
 
6832
 
 
6833
  /* output the data to a temporary file */
 
6834
  dict_print_info_on_foreign_keys(TRUE, srv_dict_tmpfile,
 
6835
        prebuilt->trx, prebuilt->table);
 
6836
  prebuilt->trx->op_info = (char*)"";
 
6837
 
 
6838
  flen = ftell(srv_dict_tmpfile);
 
6839
  if (flen < 0) {
 
6840
    flen = 0;
 
6841
  } else if (flen > 64000 - 1) {
 
6842
    flen = 64000 - 1;
 
6843
  }
 
6844
 
 
6845
  /* allocate buffer for the string, and
 
6846
  read the contents of the temporary file */
 
6847
 
 
6848
  str = (char*) malloc(flen + 1);
 
6849
 
 
6850
  if (str) {
 
6851
    rewind(srv_dict_tmpfile);
 
6852
    flen = (uint) fread(str, 1, flen, srv_dict_tmpfile);
 
6853
    str[flen] = 0;
 
6854
  }
 
6855
 
 
6856
  mutex_exit(&srv_dict_tmpfile_mutex);
 
6857
 
 
6858
  return(str);
6779
6859
}
6780
6860
 
6781
6861
 
6782
6862
UNIV_INTERN
6783
6863
int
6784
 
ha_innobase::get_foreign_key_list(Session *session, List<FOREIGN_KEY_INFO> *f_key_list)
 
6864
ha_innobase::get_foreign_key_list(Session *session, List<ForeignKeyInfo> *f_key_list)
6785
6865
{
6786
6866
  dict_foreign_t* foreign;
6787
6867
 
6793
6873
  foreign = UT_LIST_GET_FIRST(prebuilt->table->foreign_list);
6794
6874
 
6795
6875
  while (foreign != NULL) {
6796
 
          uint i;
6797
 
          FOREIGN_KEY_INFO f_key_info;
6798
 
          LEX_STRING *name= 0;
6799
 
          uint ulen;
6800
 
          char uname[NAME_LEN+1];           /* Unencoded name */
6801
 
          char db_name[NAME_LEN+1];
6802
 
          const char *tmp_buff;
6803
 
 
6804
 
          tmp_buff= foreign->id;
6805
 
          i= 0;
6806
 
          while (tmp_buff[i] != '/')
6807
 
                  i++;
6808
 
          tmp_buff+= i + 1;
6809
 
          f_key_info.forein_id = session->make_lex_string(NULL, tmp_buff, strlen(tmp_buff), true);
6810
 
          tmp_buff= foreign->referenced_table_name;
6811
 
 
6812
 
          /* Database name */
6813
 
          i= 0;
6814
 
          while (tmp_buff[i] != '/')
6815
 
          {
6816
 
            db_name[i]= tmp_buff[i];
6817
 
            i++;
6818
 
          }
6819
 
          db_name[i]= 0;
6820
 
          ulen= filename_to_tablename(db_name, uname, sizeof(uname));
6821
 
          f_key_info.referenced_db = session->make_lex_string(NULL, uname, ulen, true);
6822
 
 
6823
 
          /* Table name */
6824
 
          tmp_buff+= i + 1;
6825
 
          ulen= filename_to_tablename(tmp_buff, uname, sizeof(uname));
6826
 
          f_key_info.referenced_table = session->make_lex_string(NULL, uname, ulen, true);
6827
 
 
6828
 
          for (i= 0;;) {
6829
 
                  tmp_buff= foreign->foreign_col_names[i];
6830
 
                  name = session->make_lex_string(name, tmp_buff, strlen(tmp_buff), true);
6831
 
                  f_key_info.foreign_fields.push_back(name);
6832
 
                  tmp_buff= foreign->referenced_col_names[i];
6833
 
                  name = session->make_lex_string(name, tmp_buff, strlen(tmp_buff), true);
6834
 
                  f_key_info.referenced_fields.push_back(name);
6835
 
                  if (++i >= foreign->n_fields)
6836
 
                          break;
6837
 
          }
 
6876
 
 
6877
    uint i;
 
6878
    LEX_STRING *name = 0;
 
6879
      uint ulen;
 
6880
      char uname[NAME_LEN + 1];           /* Unencoded name */
 
6881
      char db_name[NAME_LEN + 1];
 
6882
    const char *tmp_buff;
 
6883
 
 
6884
    /** Foreign id **/
 
6885
    tmp_buff = foreign->id;
 
6886
    i = 0;
 
6887
    while (tmp_buff[i] != '/')
 
6888
      i++;
 
6889
    tmp_buff += i + 1;
 
6890
    LEX_STRING *tmp_foreign_id = session->make_lex_string(NULL, tmp_buff, strlen(tmp_buff), true);
 
6891
 
 
6892
      /* Database name */
 
6893
    tmp_buff = foreign->referenced_table_name;
 
6894
 
 
6895
    i= 0;
 
6896
    while (tmp_buff[i] != '/')
 
6897
      {
 
6898
        db_name[i]= tmp_buff[i];
 
6899
        i++;
 
6900
      }
 
6901
      db_name[i] = 0;
 
6902
      ulen= filename_to_tablename(db_name, uname, sizeof(uname));
 
6903
    LEX_STRING *tmp_referenced_db = session->make_lex_string(NULL, uname, ulen, true);
 
6904
 
 
6905
      /* Table name */
 
6906
    tmp_buff += i + 1;
 
6907
      ulen= filename_to_tablename(tmp_buff, uname, sizeof(uname));
 
6908
    LEX_STRING *tmp_referenced_table = session->make_lex_string(NULL, uname, ulen, true);
 
6909
 
 
6910
      /** Foreign Fields **/
 
6911
  List<LEX_STRING> tmp_foreign_fields;
 
6912
  List<LEX_STRING> tmp_referenced_fields;
 
6913
    for (i= 0;;) {
 
6914
      tmp_buff= foreign->foreign_col_names[i];
 
6915
      name = session->make_lex_string(name, tmp_buff, strlen(tmp_buff), true);
 
6916
      tmp_foreign_fields.push_back(name);
 
6917
      tmp_buff= foreign->referenced_col_names[i];
 
6918
      name = session->make_lex_string(name, tmp_buff, strlen(tmp_buff), true);
 
6919
      tmp_referenced_fields.push_back(name);
 
6920
      if (++i >= foreign->n_fields)
 
6921
        break;
 
6922
    }
6838
6923
 
6839
6924
          ulong length;
6840
6925
          if (foreign->type & DICT_FOREIGN_ON_DELETE_CASCADE)
6857
6942
            length=8;
6858
6943
            tmp_buff= "RESTRICT";
6859
6944
          }
6860
 
          f_key_info.delete_method = session->make_lex_string(
6861
 
                  f_key_info.delete_method, tmp_buff, length, true);
 
6945
    LEX_STRING *tmp_delete_method = session->make_lex_string(NULL, tmp_buff, length, true);
6862
6946
 
6863
6947
 
6864
6948
          if (foreign->type & DICT_FOREIGN_ON_UPDATE_CASCADE)
6881
6965
            length=8;
6882
6966
            tmp_buff= "RESTRICT";
6883
6967
          }
6884
 
          f_key_info.update_method = session->make_lex_string(
6885
 
                  f_key_info.update_method, tmp_buff, length, true);
 
6968
    LEX_STRING *tmp_update_method = session->make_lex_string(NULL, tmp_buff, length, true);
 
6969
 
 
6970
    LEX_STRING *tmp_referenced_key_name = NULL;
 
6971
 
6886
6972
          if (foreign->referenced_index &&
6887
6973
              foreign->referenced_index->name)
6888
6974
          {
6889
 
            f_key_info.referenced_key_name = session->make_lex_string(
6890
 
                    f_key_info.referenced_key_name,
6891
 
                    foreign->referenced_index->name,
6892
 
                    strlen(foreign->referenced_index->name), true);
 
6975
        tmp_referenced_key_name = session->make_lex_string(NULL,
 
6976
        foreign->referenced_index->name, strlen(foreign->referenced_index->name), true);
6893
6977
          }
6894
 
          else
6895
 
            f_key_info.referenced_key_name= 0;
6896
 
 
6897
 
          FOREIGN_KEY_INFO *pf_key_info = (FOREIGN_KEY_INFO *)
6898
 
                  session_memdup(session, &f_key_info, sizeof(FOREIGN_KEY_INFO));
6899
 
          f_key_list->push_back(pf_key_info);
6900
 
          foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
 
6978
 
 
6979
      ForeignKeyInfo f_key_info(
 
6980
        tmp_foreign_id, tmp_referenced_db, tmp_referenced_table,
 
6981
        tmp_update_method, tmp_delete_method, tmp_referenced_key_name,
 
6982
        tmp_foreign_fields, tmp_referenced_fields);
 
6983
 
 
6984
    ForeignKeyInfo *pf_key_info = (ForeignKeyInfo *)
 
6985
      session_memdup(session, &f_key_info, sizeof(ForeignKeyInfo));
 
6986
    f_key_list->push_back(pf_key_info);
 
6987
    foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
6901
6988
  }
6902
6989
  mutex_exit(&(dict_sys->mutex));
6903
6990
  prebuilt->trx->op_info = (char*)"";
6909
6996
Checks if ALTER TABLE may change the storage engine of the table.
6910
6997
Changing storage engines is not allowed for tables for which there
6911
6998
are foreign key constraints (parent or child tables).
6912
 
@return TRUE if can switch engines */
 
6999
@return TRUE if can switch engines */
6913
7000
UNIV_INTERN
6914
7001
bool
6915
7002
ha_innobase::can_switch_engines(void)
6916
7003
/*=================================*/
6917
7004
{
6918
 
        bool    can_switch;
6919
 
 
6920
 
        ut_a(prebuilt->trx == session_to_trx(ha_session()));
6921
 
 
6922
 
        prebuilt->trx->op_info =
6923
 
                        "determining if there are foreign key constraints";
6924
 
        row_mysql_lock_data_dictionary(prebuilt->trx);
6925
 
 
6926
 
        can_switch = !UT_LIST_GET_FIRST(prebuilt->table->referenced_list)
6927
 
                        && !UT_LIST_GET_FIRST(prebuilt->table->foreign_list);
6928
 
 
6929
 
        row_mysql_unlock_data_dictionary(prebuilt->trx);
6930
 
        prebuilt->trx->op_info = "";
6931
 
 
6932
 
        return(can_switch);
 
7005
  bool  can_switch;
 
7006
 
 
7007
  ut_a(prebuilt->trx == session_to_trx(ha_session()));
 
7008
 
 
7009
  prebuilt->trx->op_info =
 
7010
      "determining if there are foreign key constraints";
 
7011
  row_mysql_lock_data_dictionary(prebuilt->trx);
 
7012
 
 
7013
  can_switch = !UT_LIST_GET_FIRST(prebuilt->table->referenced_list)
 
7014
      && !UT_LIST_GET_FIRST(prebuilt->table->foreign_list);
 
7015
 
 
7016
  row_mysql_unlock_data_dictionary(prebuilt->trx);
 
7017
  prebuilt->trx->op_info = "";
 
7018
 
 
7019
  return(can_switch);
6933
7020
}
6934
7021
 
6935
7022
/*******************************************************************//**
6937
7024
a REPLACE is either equivalent to an INSERT, or DELETE(s) + INSERT. Only a
6938
7025
delete is then allowed internally to resolve a duplicate key conflict in
6939
7026
REPLACE, not an update.
6940
 
@return > 0 if referenced by a FOREIGN KEY */
 
7027
@return > 0 if referenced by a FOREIGN KEY */
6941
7028
UNIV_INTERN
6942
7029
uint
6943
7030
ha_innobase::referenced_by_foreign_key(void)
6944
7031
/*========================================*/
6945
7032
{
6946
 
        if (dict_table_is_referenced_by_foreign_key(prebuilt->table)) {
6947
 
 
6948
 
                return(1);
6949
 
        }
6950
 
 
6951
 
        return(0);
 
7033
  if (dict_table_is_referenced_by_foreign_key(prebuilt->table)) {
 
7034
 
 
7035
    return(1);
 
7036
  }
 
7037
 
 
7038
  return(0);
6952
7039
}
6953
7040
 
6954
7041
/*******************************************************************//**
6958
7045
void
6959
7046
ha_innobase::free_foreign_key_create_info(
6960
7047
/*======================================*/
6961
 
        char*   str)    /*!< in, own: create info string to free */
 
7048
  char* str)  /*!< in, own: create info string to free */
6962
7049
{
6963
 
        if (str) {
6964
 
                free(str);
6965
 
        }
 
7050
  if (str) {
 
7051
    free(str);
 
7052
  }
6966
7053
}
6967
7054
 
6968
7055
/*******************************************************************//**
6969
7056
Tells something additional to the Cursor about how to do things.
6970
 
@return 0 or error number */
 
7057
@return 0 or error number */
6971
7058
UNIV_INTERN
6972
7059
int
6973
7060
ha_innobase::extra(
6974
7061
/*===============*/
6975
 
        enum ha_extra_function operation)
6976
 
                           /*!< in: HA_EXTRA_FLUSH or some other flag */
 
7062
  enum ha_extra_function operation)
 
7063
         /*!< in: HA_EXTRA_FLUSH or some other flag */
6977
7064
{
6978
 
        /* Warning: since it is not sure that MySQL calls external_lock
6979
 
        before calling this function, the trx field in prebuilt can be
6980
 
        obsolete! */
6981
 
 
6982
 
        switch (operation) {
6983
 
                case HA_EXTRA_FLUSH:
6984
 
                        if (prebuilt->blob_heap) {
6985
 
                                row_mysql_prebuilt_free_blob_heap(prebuilt);
6986
 
                        }
6987
 
                        break;
6988
 
                case HA_EXTRA_RESET_STATE:
6989
 
                        reset_template(prebuilt);
6990
 
                        break;
6991
 
                case HA_EXTRA_NO_KEYREAD:
6992
 
                        prebuilt->read_just_key = 0;
6993
 
                        break;
6994
 
                case HA_EXTRA_KEYREAD:
6995
 
                        prebuilt->read_just_key = 1;
6996
 
                        break;
6997
 
                case HA_EXTRA_KEYREAD_PRESERVE_FIELDS:
6998
 
                        prebuilt->keep_other_fields_on_keyread = 1;
6999
 
                        break;
7000
 
 
7001
 
                        /* IMPORTANT: prebuilt->trx can be obsolete in
7002
 
                        this method, because it is not sure that MySQL
7003
 
                        calls external_lock before this method with the
7004
 
                        parameters below.  We must not invoke update_session()
7005
 
                        either, because the calling threads may change.
7006
 
                        CAREFUL HERE, OR MEMORY CORRUPTION MAY OCCUR! */
7007
 
                case HA_EXTRA_IGNORE_DUP_KEY:
7008
 
                        session_to_trx(ha_session())->duplicates |= TRX_DUP_IGNORE;
7009
 
                        break;
7010
 
                case HA_EXTRA_WRITE_CAN_REPLACE:
7011
 
                        session_to_trx(ha_session())->duplicates |= TRX_DUP_REPLACE;
7012
 
                        break;
7013
 
                case HA_EXTRA_WRITE_CANNOT_REPLACE:
7014
 
                        session_to_trx(ha_session())->duplicates &= ~TRX_DUP_REPLACE;
7015
 
                        break;
7016
 
                case HA_EXTRA_NO_IGNORE_DUP_KEY:
7017
 
                        session_to_trx(ha_session())->duplicates &=
7018
 
                                ~(TRX_DUP_IGNORE | TRX_DUP_REPLACE);
7019
 
                        break;
7020
 
                default:/* Do nothing */
7021
 
                        ;
7022
 
        }
7023
 
 
7024
 
        return(0);
 
7065
  /* Warning: since it is not sure that MySQL calls external_lock
 
7066
  before calling this function, the trx field in prebuilt can be
 
7067
  obsolete! */
 
7068
 
 
7069
  switch (operation) {
 
7070
    case HA_EXTRA_FLUSH:
 
7071
      if (prebuilt->blob_heap) {
 
7072
        row_mysql_prebuilt_free_blob_heap(prebuilt);
 
7073
      }
 
7074
      break;
 
7075
    case HA_EXTRA_RESET_STATE:
 
7076
      reset_template(prebuilt);
 
7077
      break;
 
7078
    case HA_EXTRA_NO_KEYREAD:
 
7079
      prebuilt->read_just_key = 0;
 
7080
      break;
 
7081
    case HA_EXTRA_KEYREAD:
 
7082
      prebuilt->read_just_key = 1;
 
7083
      break;
 
7084
    case HA_EXTRA_KEYREAD_PRESERVE_FIELDS:
 
7085
      prebuilt->keep_other_fields_on_keyread = 1;
 
7086
      break;
 
7087
 
 
7088
      /* IMPORTANT: prebuilt->trx can be obsolete in
 
7089
      this method, because it is not sure that MySQL
 
7090
      calls external_lock before this method with the
 
7091
      parameters below.  We must not invoke update_session()
 
7092
      either, because the calling threads may change.
 
7093
      CAREFUL HERE, OR MEMORY CORRUPTION MAY OCCUR! */
 
7094
    case HA_EXTRA_IGNORE_DUP_KEY:
 
7095
      session_to_trx(ha_session())->duplicates |= TRX_DUP_IGNORE;
 
7096
      break;
 
7097
    case HA_EXTRA_WRITE_CAN_REPLACE:
 
7098
      session_to_trx(ha_session())->duplicates |= TRX_DUP_REPLACE;
 
7099
      break;
 
7100
    case HA_EXTRA_WRITE_CANNOT_REPLACE:
 
7101
      session_to_trx(ha_session())->duplicates &= ~TRX_DUP_REPLACE;
 
7102
      break;
 
7103
    case HA_EXTRA_NO_IGNORE_DUP_KEY:
 
7104
      session_to_trx(ha_session())->duplicates &=
 
7105
        ~(TRX_DUP_IGNORE | TRX_DUP_REPLACE);
 
7106
      break;
 
7107
    default:/* Do nothing */
 
7108
      ;
 
7109
  }
 
7110
 
 
7111
  return(0);
7025
7112
}
7026
7113
 
7027
7114
UNIV_INTERN
7028
7115
int
7029
7116
ha_innobase::reset()
7030
7117
{
7031
 
        if (prebuilt->blob_heap) {
7032
 
                row_mysql_prebuilt_free_blob_heap(prebuilt);
7033
 
        }
7034
 
 
7035
 
        reset_template(prebuilt);
7036
 
 
7037
 
        /* TODO: This should really be reset in reset_template() but for now
7038
 
        it's safer to do it explicitly here. */
7039
 
 
7040
 
        /* This is a statement level counter. */
7041
 
        prebuilt->autoinc_last_value = 0;
7042
 
 
7043
 
        return(0);
 
7118
  if (prebuilt->blob_heap) {
 
7119
    row_mysql_prebuilt_free_blob_heap(prebuilt);
 
7120
  }
 
7121
 
 
7122
  reset_template(prebuilt);
 
7123
 
 
7124
  /* TODO: This should really be reset in reset_template() but for now
 
7125
  it's safer to do it explicitly here. */
 
7126
 
 
7127
  /* This is a statement level counter. */
 
7128
  prebuilt->autoinc_last_value = 0;
 
7129
 
 
7130
  return(0);
7044
7131
}
7045
7132
 
7046
7133
/******************************************************************//**
7047
7134
Maps a MySQL trx isolation level code to the InnoDB isolation level code
7048
 
@return InnoDB isolation level */
 
7135
@return InnoDB isolation level */
7049
7136
static inline
7050
7137
ulint
7051
7138
innobase_map_isolation_level(
7052
7139
/*=========================*/
7053
 
        enum_tx_isolation       iso)    /*!< in: MySQL isolation level code */
 
7140
  enum_tx_isolation iso)  /*!< in: MySQL isolation level code */
7054
7141
{
7055
 
        switch(iso) {
7056
 
                case ISO_REPEATABLE_READ: return(TRX_ISO_REPEATABLE_READ);
7057
 
                case ISO_READ_COMMITTED: return(TRX_ISO_READ_COMMITTED);
7058
 
                case ISO_SERIALIZABLE: return(TRX_ISO_SERIALIZABLE);
7059
 
                case ISO_READ_UNCOMMITTED: return(TRX_ISO_READ_UNCOMMITTED);
7060
 
                default: ut_a(0); return(0);
7061
 
        }
 
7142
  switch(iso) {
 
7143
    case ISO_REPEATABLE_READ: return(TRX_ISO_REPEATABLE_READ);
 
7144
    case ISO_READ_COMMITTED: return(TRX_ISO_READ_COMMITTED);
 
7145
    case ISO_SERIALIZABLE: return(TRX_ISO_SERIALIZABLE);
 
7146
    case ISO_READ_UNCOMMITTED: return(TRX_ISO_READ_UNCOMMITTED);
 
7147
    default: ut_a(0); return(0);
 
7148
  }
7062
7149
}
7063
7150
 
7064
7151
/******************************************************************//**
7065
7152
As MySQL will execute an external lock for every new table it uses when it
7066
7153
starts to process an SQL statement.  We can use this function to store the pointer to
7067
7154
the Session in the handle.
7068
 
@return 0 */
 
7155
@return 0 */
7069
7156
UNIV_INTERN
7070
7157
int
7071
7158
ha_innobase::external_lock(
7072
7159
/*=======================*/
7073
 
        Session*        session,        /*!< in: handle to the user thread */
7074
 
        int     lock_type)      /*!< in: lock type */
 
7160
  Session*  session,  /*!< in: handle to the user thread */
 
7161
  int lock_type)  /*!< in: lock type */
7075
7162
{
7076
 
        update_session(session);
 
7163
  update_session(session);
7077
7164
 
7078
7165
  trx_t *trx= prebuilt->trx;
7079
7166
 
7080
 
        prebuilt->sql_stat_start = TRUE;
7081
 
        prebuilt->hint_need_to_fetch_extra_cols = 0;
7082
 
 
7083
 
        reset_template(prebuilt);
7084
 
 
7085
 
        if (lock_type == F_WRLCK) {
7086
 
 
7087
 
                /* If this is a SELECT, then it is in UPDATE TABLE ...
7088
 
                or SELECT ... FOR UPDATE */
7089
 
                prebuilt->select_lock_type = LOCK_X;
7090
 
                prebuilt->stored_select_lock_type = LOCK_X;
7091
 
        }
7092
 
 
7093
 
        if (lock_type != F_UNLCK) {
7094
 
                /* MySQL is setting a new table lock */
7095
 
 
7096
 
                if (trx->isolation_level == TRX_ISO_SERIALIZABLE
7097
 
                        && prebuilt->select_lock_type == LOCK_NONE
7098
 
                        && session_test_options(session,
7099
 
                                OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
7100
 
 
7101
 
                        /* To get serializable execution, we let InnoDB
7102
 
                        conceptually add 'LOCK IN SHARE MODE' to all SELECTs
7103
 
                        which otherwise would have been consistent reads. An
7104
 
                        exception is consistent reads in the AUTOCOMMIT=1 mode:
7105
 
                        we know that they are read-only transactions, and they
7106
 
                        can be serialized also if performed as consistent
7107
 
                        reads. */
7108
 
 
7109
 
                        prebuilt->select_lock_type = LOCK_S;
7110
 
                        prebuilt->stored_select_lock_type = LOCK_S;
7111
 
                }
7112
 
 
7113
 
                /* Starting from 4.1.9, no InnoDB table lock is taken in LOCK
7114
 
                TABLES if AUTOCOMMIT=1. It does not make much sense to acquire
7115
 
                an InnoDB table lock if it is released immediately at the end
7116
 
                of LOCK TABLES, and InnoDB's table locks in that case cause
7117
 
                VERY easily deadlocks.
7118
 
 
7119
 
                We do not set InnoDB table locks if user has not explicitly
7120
 
                requested a table lock. Note that session_in_lock_tables(session)
7121
 
                can hold in some cases, e.g., at the start of a stored
7122
 
                procedure call (SQLCOM_CALL). */
7123
 
 
7124
 
                if (prebuilt->select_lock_type != LOCK_NONE) {
7125
 
                        trx->mysql_n_tables_locked++;
7126
 
                }
7127
 
 
7128
 
                prebuilt->mysql_has_locked = TRUE;
7129
 
 
7130
 
                return(0);
7131
 
        }
7132
 
 
7133
 
        /* MySQL is releasing a table lock */
7134
 
        prebuilt->mysql_has_locked = FALSE;
7135
 
        trx->mysql_n_tables_locked= 0;
7136
 
 
7137
 
        return(0);
 
7167
  prebuilt->sql_stat_start = TRUE;
 
7168
  prebuilt->hint_need_to_fetch_extra_cols = 0;
 
7169
 
 
7170
  reset_template(prebuilt);
 
7171
 
 
7172
  if (lock_type == F_WRLCK) {
 
7173
 
 
7174
    /* If this is a SELECT, then it is in UPDATE TABLE ...
 
7175
    or SELECT ... FOR UPDATE */
 
7176
    prebuilt->select_lock_type = LOCK_X;
 
7177
    prebuilt->stored_select_lock_type = LOCK_X;
 
7178
  }
 
7179
 
 
7180
  if (lock_type != F_UNLCK) {
 
7181
    /* MySQL is setting a new table lock */
 
7182
 
 
7183
    if (trx->isolation_level == TRX_ISO_SERIALIZABLE
 
7184
      && prebuilt->select_lock_type == LOCK_NONE
 
7185
      && session_test_options(session,
 
7186
        OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
 
7187
 
 
7188
      /* To get serializable execution, we let InnoDB
 
7189
      conceptually add 'LOCK IN SHARE MODE' to all SELECTs
 
7190
      which otherwise would have been consistent reads. An
 
7191
      exception is consistent reads in the AUTOCOMMIT=1 mode:
 
7192
      we know that they are read-only transactions, and they
 
7193
      can be serialized also if performed as consistent
 
7194
      reads. */
 
7195
 
 
7196
      prebuilt->select_lock_type = LOCK_S;
 
7197
      prebuilt->stored_select_lock_type = LOCK_S;
 
7198
    }
 
7199
 
 
7200
    /* Starting from 4.1.9, no InnoDB table lock is taken in LOCK
 
7201
    TABLES if AUTOCOMMIT=1. It does not make much sense to acquire
 
7202
    an InnoDB table lock if it is released immediately at the end
 
7203
    of LOCK TABLES, and InnoDB's table locks in that case cause
 
7204
    VERY easily deadlocks.
 
7205
 
 
7206
    We do not set InnoDB table locks if user has not explicitly
 
7207
    requested a table lock. Note that session_in_lock_tables(session)
 
7208
    can hold in some cases, e.g., at the start of a stored
 
7209
    procedure call (SQLCOM_CALL). */
 
7210
 
 
7211
    if (prebuilt->select_lock_type != LOCK_NONE) {
 
7212
      trx->mysql_n_tables_locked++;
 
7213
    }
 
7214
 
 
7215
    prebuilt->mysql_has_locked = TRUE;
 
7216
 
 
7217
    return(0);
 
7218
  }
 
7219
 
 
7220
  /* MySQL is releasing a table lock */
 
7221
  prebuilt->mysql_has_locked = FALSE;
 
7222
  trx->mysql_n_tables_locked= 0;
 
7223
 
 
7224
  return(0);
7138
7225
}
7139
7226
 
7140
7227
/************************************************************************//**
7144
7231
bool
7145
7232
innodb_show_status(
7146
7233
/*===============*/
7147
 
        plugin::StorageEngine*  engine, /*!< in: the innodb StorageEngine */
7148
 
        Session*        session,/*!< in: the MySQL query thread of the caller */
7149
 
        stat_print_fn *stat_print)
 
7234
  plugin::StorageEngine*  engine, /*!< in: the innodb StorageEngine */
 
7235
  Session*  session,/*!< in: the MySQL query thread of the caller */
 
7236
  stat_print_fn *stat_print)
7150
7237
{
7151
 
        trx_t*                  trx;
7152
 
        static const char       truncated_msg[] = "... truncated...\n";
7153
 
        const long              MAX_STATUS_SIZE = 64000;
7154
 
        ulint                   trx_list_start = ULINT_UNDEFINED;
7155
 
        ulint                   trx_list_end = ULINT_UNDEFINED;
7156
 
 
7157
 
        assert(engine == innodb_engine_ptr);
7158
 
 
7159
 
        trx = check_trx_exists(session);
7160
 
 
7161
 
        innobase_release_stat_resources(trx);
7162
 
 
7163
 
        /* We let the InnoDB Monitor to output at most MAX_STATUS_SIZE
7164
 
        bytes of text. */
7165
 
 
7166
 
        long    flen, usable_len;
7167
 
        char*   str;
7168
 
 
7169
 
        mutex_enter(&srv_monitor_file_mutex);
7170
 
        rewind(srv_monitor_file);
7171
 
        srv_printf_innodb_monitor(srv_monitor_file,
7172
 
                                &trx_list_start, &trx_list_end);
7173
 
        flen = ftell(srv_monitor_file);
7174
 
        os_file_set_eof(srv_monitor_file);
7175
 
 
7176
 
        if (flen < 0) {
7177
 
                flen = 0;
7178
 
        }
7179
 
 
7180
 
        if (flen > MAX_STATUS_SIZE) {
7181
 
                usable_len = MAX_STATUS_SIZE;
7182
 
        } else {
7183
 
                usable_len = flen;
7184
 
        }
7185
 
 
7186
 
        /* allocate buffer for the string, and
7187
 
        read the contents of the temporary file */
7188
 
 
7189
 
        if (!(str = (char*) malloc(usable_len + 1))) {
7190
 
          mutex_exit(&srv_monitor_file_mutex);
7191
 
          return(TRUE);
7192
 
        }
7193
 
 
7194
 
        rewind(srv_monitor_file);
7195
 
        if (flen < MAX_STATUS_SIZE) {
7196
 
                /* Display the entire output. */
7197
 
                flen = (long) fread(str, 1, flen, srv_monitor_file);
7198
 
        } else if (trx_list_end < (ulint) flen
7199
 
                        && trx_list_start < trx_list_end
7200
 
                        && trx_list_start + (flen - trx_list_end)
7201
 
                        < MAX_STATUS_SIZE - sizeof truncated_msg - 1) {
7202
 
                /* Omit the beginning of the list of active transactions. */
7203
 
                long len = (long) fread(str, 1, trx_list_start, srv_monitor_file);
7204
 
                memcpy(str + len, truncated_msg, sizeof truncated_msg - 1);
7205
 
                len += sizeof truncated_msg - 1;
7206
 
                usable_len = (MAX_STATUS_SIZE - 1) - len;
7207
 
                fseek(srv_monitor_file, flen - usable_len, SEEK_SET);
7208
 
                len += (long) fread(str + len, 1, usable_len, srv_monitor_file);
7209
 
                flen = len;
7210
 
        } else {
7211
 
                /* Omit the end of the output. */
7212
 
                flen = (long) fread(str, 1, MAX_STATUS_SIZE - 1, srv_monitor_file);
7213
 
        }
7214
 
 
7215
 
        mutex_exit(&srv_monitor_file_mutex);
7216
 
 
7217
 
        bool result = FALSE;
7218
 
 
7219
 
        if (stat_print(session, innobase_engine_name, strlen(innobase_engine_name),
7220
 
                        STRING_WITH_LEN(""), str, flen)) {
7221
 
                result= TRUE;
7222
 
        }
7223
 
        free(str);
7224
 
 
7225
 
        return(FALSE);
 
7238
  trx_t*      trx;
 
7239
  static const char truncated_msg[] = "... truncated...\n";
 
7240
  const long    MAX_STATUS_SIZE = 64000;
 
7241
  ulint     trx_list_start = ULINT_UNDEFINED;
 
7242
  ulint     trx_list_end = ULINT_UNDEFINED;
 
7243
 
 
7244
  assert(engine == innodb_engine_ptr);
 
7245
 
 
7246
  trx = check_trx_exists(session);
 
7247
 
 
7248
  innobase_release_stat_resources(trx);
 
7249
 
 
7250
  /* We let the InnoDB Monitor to output at most MAX_STATUS_SIZE
 
7251
  bytes of text. */
 
7252
 
 
7253
  long  flen, usable_len;
 
7254
  char* str;
 
7255
 
 
7256
  mutex_enter(&srv_monitor_file_mutex);
 
7257
  rewind(srv_monitor_file);
 
7258
  srv_printf_innodb_monitor(srv_monitor_file,
 
7259
        &trx_list_start, &trx_list_end);
 
7260
  flen = ftell(srv_monitor_file);
 
7261
  os_file_set_eof(srv_monitor_file);
 
7262
 
 
7263
  if (flen < 0) {
 
7264
    flen = 0;
 
7265
  }
 
7266
 
 
7267
  if (flen > MAX_STATUS_SIZE) {
 
7268
    usable_len = MAX_STATUS_SIZE;
 
7269
  } else {
 
7270
    usable_len = flen;
 
7271
  }
 
7272
 
 
7273
  /* allocate buffer for the string, and
 
7274
  read the contents of the temporary file */
 
7275
 
 
7276
  if (!(str = (char*) malloc(usable_len + 1))) {
 
7277
    mutex_exit(&srv_monitor_file_mutex);
 
7278
    return(TRUE);
 
7279
  }
 
7280
 
 
7281
  rewind(srv_monitor_file);
 
7282
  if (flen < MAX_STATUS_SIZE) {
 
7283
    /* Display the entire output. */
 
7284
    flen = (long) fread(str, 1, flen, srv_monitor_file);
 
7285
  } else if (trx_list_end < (ulint) flen
 
7286
      && trx_list_start < trx_list_end
 
7287
      && trx_list_start + (flen - trx_list_end)
 
7288
      < MAX_STATUS_SIZE - sizeof truncated_msg - 1) {
 
7289
    /* Omit the beginning of the list of active transactions. */
 
7290
    long len = (long) fread(str, 1, trx_list_start, srv_monitor_file);
 
7291
    memcpy(str + len, truncated_msg, sizeof truncated_msg - 1);
 
7292
    len += sizeof truncated_msg - 1;
 
7293
    usable_len = (MAX_STATUS_SIZE - 1) - len;
 
7294
    fseek(srv_monitor_file, flen - usable_len, SEEK_SET);
 
7295
    len += (long) fread(str + len, 1, usable_len, srv_monitor_file);
 
7296
    flen = len;
 
7297
  } else {
 
7298
    /* Omit the end of the output. */
 
7299
    flen = (long) fread(str, 1, MAX_STATUS_SIZE - 1, srv_monitor_file);
 
7300
  }
 
7301
 
 
7302
  mutex_exit(&srv_monitor_file_mutex);
 
7303
 
 
7304
  bool result = FALSE;
 
7305
 
 
7306
  if (stat_print(session, innobase_engine_name, strlen(innobase_engine_name),
 
7307
      STRING_WITH_LEN(""), str, flen)) {
 
7308
    result= TRUE;
 
7309
  }
 
7310
  free(str);
 
7311
 
 
7312
  return(FALSE);
7226
7313
}
7227
7314
 
7228
7315
/************************************************************************//**
7231
7318
bool
7232
7319
innodb_mutex_show_status(
7233
7320
/*=====================*/
7234
 
        plugin::StorageEngine*  engine,         /*!< in: the innodb StorageEngine */
7235
 
        Session*        session,        /*!< in: the MySQL query thread of the
7236
 
                                        caller */
7237
 
        stat_print_fn*  stat_print)
 
7321
  plugin::StorageEngine*  engine,   /*!< in: the innodb StorageEngine */
 
7322
  Session*  session,  /*!< in: the MySQL query thread of the
 
7323
          caller */
 
7324
  stat_print_fn*  stat_print)
7238
7325
{
7239
 
        char buf1[IO_SIZE], buf2[IO_SIZE];
7240
 
        mutex_t*        mutex;
7241
 
        rw_lock_t*      lock;
 
7326
  char buf1[IO_SIZE], buf2[IO_SIZE];
 
7327
  mutex_t*  mutex;
 
7328
  rw_lock_t*  lock;
7242
7329
#ifdef UNIV_DEBUG
7243
 
        ulint     rw_lock_count= 0;
7244
 
        ulint     rw_lock_count_spin_loop= 0;
7245
 
        ulint     rw_lock_count_spin_rounds= 0;
7246
 
        ulint     rw_lock_count_os_wait= 0;
7247
 
        ulint     rw_lock_count_os_yield= 0;
7248
 
        uint64_t rw_lock_wait_time= 0;
 
7330
  ulint   rw_lock_count= 0;
 
7331
  ulint   rw_lock_count_spin_loop= 0;
 
7332
  ulint   rw_lock_count_spin_rounds= 0;
 
7333
  ulint   rw_lock_count_os_wait= 0;
 
7334
  ulint   rw_lock_count_os_yield= 0;
 
7335
  uint64_t rw_lock_wait_time= 0;
7249
7336
#endif /* UNIV_DEBUG */
7250
 
        uint      engine_name_len= strlen(innobase_engine_name), buf1len, buf2len;
7251
 
        assert(engine == innodb_engine_ptr);
7252
 
 
7253
 
        mutex_enter(&mutex_list_mutex);
7254
 
 
7255
 
        mutex = UT_LIST_GET_FIRST(mutex_list);
7256
 
 
7257
 
        while (mutex != NULL) {
7258
 
                if (mutex->count_os_wait == 0
7259
 
                    || buf_pool_is_block_mutex(mutex)) {
7260
 
                        goto next_mutex;
7261
 
                }
 
7337
  uint    engine_name_len= strlen(innobase_engine_name), buf1len, buf2len;
 
7338
  assert(engine == innodb_engine_ptr);
 
7339
 
 
7340
  mutex_enter(&mutex_list_mutex);
 
7341
 
 
7342
  mutex = UT_LIST_GET_FIRST(mutex_list);
 
7343
 
 
7344
  while (mutex != NULL) {
 
7345
    if (mutex->count_os_wait == 0
 
7346
        || buf_pool_is_block_mutex(mutex)) {
 
7347
      goto next_mutex;
 
7348
    }
7262
7349
#ifdef UNIV_DEBUG
7263
 
                if (mutex->mutex_type != 1) {
7264
 
                        if (mutex->count_using > 0) {
7265
 
                                buf1len= my_snprintf(buf1, sizeof(buf1),
7266
 
                                        "%s:%s",
7267
 
                                        mutex->cmutex_name, mutex->cfile_name);
7268
 
                                buf2len= my_snprintf(buf2, sizeof(buf2),
7269
 
                                        "count=%lu, spin_waits=%lu,"
7270
 
                                        " spin_rounds=%lu, "
7271
 
                                        "os_waits=%lu, os_yields=%lu,"
7272
 
                                        " os_wait_times=%lu",
7273
 
                                        mutex->count_using,
7274
 
                                        mutex->count_spin_loop,
7275
 
                                        mutex->count_spin_rounds,
7276
 
                                        mutex->count_os_wait,
7277
 
                                        mutex->count_os_yield,
7278
 
                                        (ulong) (mutex->lspent_time/1000));
 
7350
    if (mutex->mutex_type != 1) {
 
7351
      if (mutex->count_using > 0) {
 
7352
        buf1len= my_snprintf(buf1, sizeof(buf1),
 
7353
          "%s:%s",
 
7354
          mutex->cmutex_name, mutex->cfile_name);
 
7355
        buf2len= my_snprintf(buf2, sizeof(buf2),
 
7356
          "count=%lu, spin_waits=%lu,"
 
7357
          " spin_rounds=%lu, "
 
7358
          "os_waits=%lu, os_yields=%lu,"
 
7359
          " os_wait_times=%lu",
 
7360
          mutex->count_using,
 
7361
          mutex->count_spin_loop,
 
7362
          mutex->count_spin_rounds,
 
7363
          mutex->count_os_wait,
 
7364
          mutex->count_os_yield,
 
7365
          (ulong) (mutex->lspent_time/1000));
7279
7366
 
7280
 
                                if (stat_print(session, innobase_engine_name,
7281
 
                                                engine_name_len, buf1, buf1len,
7282
 
                                                buf2, buf2len)) {
7283
 
                                        mutex_exit(&mutex_list_mutex);
7284
 
                                        return(1);
7285
 
                                }
7286
 
                        }
7287
 
                }
7288
 
                else {
7289
 
                        rw_lock_count += mutex->count_using;
7290
 
                        rw_lock_count_spin_loop += mutex->count_spin_loop;
7291
 
                        rw_lock_count_spin_rounds += mutex->count_spin_rounds;
7292
 
                        rw_lock_count_os_wait += mutex->count_os_wait;
7293
 
                        rw_lock_count_os_yield += mutex->count_os_yield;
7294
 
                        rw_lock_wait_time += mutex->lspent_time;
7295
 
                }
 
7367
        if (stat_print(session, innobase_engine_name,
 
7368
            engine_name_len, buf1, buf1len,
 
7369
            buf2, buf2len)) {
 
7370
          mutex_exit(&mutex_list_mutex);
 
7371
          return(1);
 
7372
        }
 
7373
      }
 
7374
    }
 
7375
    else {
 
7376
      rw_lock_count += mutex->count_using;
 
7377
      rw_lock_count_spin_loop += mutex->count_spin_loop;
 
7378
      rw_lock_count_spin_rounds += mutex->count_spin_rounds;
 
7379
      rw_lock_count_os_wait += mutex->count_os_wait;
 
7380
      rw_lock_count_os_yield += mutex->count_os_yield;
 
7381
      rw_lock_wait_time += mutex->lspent_time;
 
7382
    }
7296
7383
#else /* UNIV_DEBUG */
7297
 
                buf1len= snprintf(buf1, sizeof(buf1), "%s:%lu",
7298
 
                                  mutex->cfile_name, (ulong) mutex->cline);
7299
 
                buf2len= snprintf(buf2, sizeof(buf2), "os_waits=%lu",
7300
 
                                  mutex->count_os_wait);
 
7384
    buf1len= snprintf(buf1, sizeof(buf1), "%s:%lu",
 
7385
          mutex->cfile_name, (ulong) mutex->cline);
 
7386
    buf2len= snprintf(buf2, sizeof(buf2), "os_waits=%lu",
 
7387
          mutex->count_os_wait);
7301
7388
 
7302
 
                if (stat_print(session, innobase_engine_name,
7303
 
                               engine_name_len, buf1, buf1len,
7304
 
                               buf2, buf2len)) {
7305
 
                        mutex_exit(&mutex_list_mutex);
7306
 
                        return(1);
7307
 
                }
 
7389
    if (stat_print(session, innobase_engine_name,
 
7390
             engine_name_len, buf1, buf1len,
 
7391
             buf2, buf2len)) {
 
7392
      mutex_exit(&mutex_list_mutex);
 
7393
      return(1);
 
7394
    }
7308
7395
#endif /* UNIV_DEBUG */
7309
7396
 
7310
7397
next_mutex:
7311
 
                mutex = UT_LIST_GET_NEXT(list, mutex);
7312
 
        }
7313
 
 
7314
 
        mutex_exit(&mutex_list_mutex);
7315
 
 
7316
 
        mutex_enter(&rw_lock_list_mutex);
7317
 
 
7318
 
        lock = UT_LIST_GET_FIRST(rw_lock_list);
7319
 
 
7320
 
        while (lock != NULL) {
7321
 
                if (lock->count_os_wait
 
7398
    mutex = UT_LIST_GET_NEXT(list, mutex);
 
7399
  }
 
7400
 
 
7401
  mutex_exit(&mutex_list_mutex);
 
7402
 
 
7403
  mutex_enter(&rw_lock_list_mutex);
 
7404
 
 
7405
  lock = UT_LIST_GET_FIRST(rw_lock_list);
 
7406
 
 
7407
  while (lock != NULL) {
 
7408
    if (lock->count_os_wait
7322
7409
                    && !buf_pool_is_block_lock(lock)) {
7323
 
                        buf1len= snprintf(buf1, sizeof(buf1), "%s:%lu",
 
7410
      buf1len= snprintf(buf1, sizeof(buf1), "%s:%lu",
7324
7411
                                    lock->cfile_name, (unsigned long) lock->cline);
7325
 
                        buf2len= snprintf(buf2, sizeof(buf2),
 
7412
      buf2len= snprintf(buf2, sizeof(buf2),
7326
7413
                                    "os_waits=%lu", lock->count_os_wait);
7327
7414
 
7328
 
                        if (stat_print(session, innobase_engine_name,
7329
 
                                       engine_name_len, buf1, buf1len,
7330
 
                                       buf2, buf2len)) {
7331
 
                                mutex_exit(&rw_lock_list_mutex);
7332
 
                                return(1);
7333
 
                        }
7334
 
                }
7335
 
                lock = UT_LIST_GET_NEXT(list, lock);
7336
 
        }
 
7415
      if (stat_print(session, innobase_engine_name,
 
7416
               engine_name_len, buf1, buf1len,
 
7417
               buf2, buf2len)) {
 
7418
        mutex_exit(&rw_lock_list_mutex);
 
7419
        return(1);
 
7420
      }
 
7421
    }
 
7422
    lock = UT_LIST_GET_NEXT(list, lock);
 
7423
  }
7337
7424
 
7338
 
        mutex_exit(&rw_lock_list_mutex);
 
7425
  mutex_exit(&rw_lock_list_mutex);
7339
7426
 
7340
7427
#ifdef UNIV_DEBUG
7341
 
        buf2len= my_snprintf(buf2, sizeof(buf2),
7342
 
                "count=%lu, spin_waits=%lu, spin_rounds=%lu, "
7343
 
                "os_waits=%lu, os_yields=%lu, os_wait_times=%lu",
7344
 
                rw_lock_count, rw_lock_count_spin_loop,
7345
 
                rw_lock_count_spin_rounds,
7346
 
                rw_lock_count_os_wait, rw_lock_count_os_yield,
7347
 
                (ulong) (rw_lock_wait_time/1000));
 
7428
  buf2len= my_snprintf(buf2, sizeof(buf2),
 
7429
    "count=%lu, spin_waits=%lu, spin_rounds=%lu, "
 
7430
    "os_waits=%lu, os_yields=%lu, os_wait_times=%lu",
 
7431
    rw_lock_count, rw_lock_count_spin_loop,
 
7432
    rw_lock_count_spin_rounds,
 
7433
    rw_lock_count_os_wait, rw_lock_count_os_yield,
 
7434
    (ulong) (rw_lock_wait_time/1000));
7348
7435
 
7349
 
        if (stat_print(session, innobase_engine_name, engine_name_len,
7350
 
                        STRING_WITH_LEN("rw_lock_mutexes"), buf2, buf2len)) {
7351
 
                return(1);
7352
 
        }
 
7436
  if (stat_print(session, innobase_engine_name, engine_name_len,
 
7437
      STRING_WITH_LEN("rw_lock_mutexes"), buf2, buf2len)) {
 
7438
    return(1);
 
7439
  }
7353
7440
#endif /* UNIV_DEBUG */
7354
7441
 
7355
 
        return(FALSE);
 
7442
  return(FALSE);
7356
7443
}
7357
7444
 
7358
7445
bool InnobaseEngine::show_status(Session* session, 
7359
7446
                                 stat_print_fn* stat_print,
7360
7447
                                 enum ha_stat_type stat_type)
7361
7448
{
7362
 
        assert(this == innodb_engine_ptr);
 
7449
  assert(this == innodb_engine_ptr);
7363
7450
 
7364
 
        switch (stat_type) {
7365
 
        case HA_ENGINE_STATUS:
7366
 
                return innodb_show_status(this, session, stat_print);
7367
 
        case HA_ENGINE_MUTEX:
7368
 
                return innodb_mutex_show_status(this, session, stat_print);
7369
 
        default:
7370
 
                return(FALSE);
7371
 
        }
 
7451
  switch (stat_type) {
 
7452
  case HA_ENGINE_STATUS:
 
7453
    return innodb_show_status(this, session, stat_print);
 
7454
  case HA_ENGINE_MUTEX:
 
7455
    return innodb_mutex_show_status(this, session, stat_print);
 
7456
  default:
 
7457
    return(FALSE);
 
7458
  }
7372
7459
}
7373
7460
 
7374
7461
/************************************************************************//**
7378
7465
 
7379
7466
static INNOBASE_SHARE* get_share(const char* table_name)
7380
7467
{
7381
 
        INNOBASE_SHARE *share;
7382
 
        pthread_mutex_lock(&innobase_share_mutex);
7383
 
 
7384
 
        ulint   fold = ut_fold_string(table_name);
7385
 
 
7386
 
        HASH_SEARCH(table_name_hash, innobase_open_tables, fold,
7387
 
                    INNOBASE_SHARE*, share,
7388
 
                    ut_ad(share->use_count > 0),
7389
 
                    !strcmp(share->table_name, table_name));
7390
 
 
7391
 
        if (!share) {
7392
 
 
7393
 
                uint length = (uint) strlen(table_name);
7394
 
 
7395
 
                /* TODO: invoke HASH_MIGRATE if innobase_open_tables
7396
 
                grows too big */
7397
 
 
7398
 
                share = (INNOBASE_SHARE *) malloc(sizeof(*share)+length+1);
 
7468
  INNOBASE_SHARE *share;
 
7469
  pthread_mutex_lock(&innobase_share_mutex);
 
7470
 
 
7471
  ulint fold = ut_fold_string(table_name);
 
7472
 
 
7473
  HASH_SEARCH(table_name_hash, innobase_open_tables, fold,
 
7474
        INNOBASE_SHARE*, share,
 
7475
        ut_ad(share->use_count > 0),
 
7476
        !strcmp(share->table_name, table_name));
 
7477
 
 
7478
  if (!share) {
 
7479
 
 
7480
    uint length = (uint) strlen(table_name);
 
7481
 
 
7482
    /* TODO: invoke HASH_MIGRATE if innobase_open_tables
 
7483
    grows too big */
 
7484
 
 
7485
    share = (INNOBASE_SHARE *) malloc(sizeof(*share)+length+1);
7399
7486
                memset(share, 0, sizeof(*share)+length+1);
7400
7487
 
7401
 
                share->table_name = (char*) memcpy(share + 1,
7402
 
                                                   table_name, length + 1);
7403
 
 
7404
 
                HASH_INSERT(INNOBASE_SHARE, table_name_hash,
7405
 
                            innobase_open_tables, fold, share);
7406
 
 
7407
 
                thr_lock_init(&share->lock);
7408
 
        }
7409
 
 
7410
 
        share->use_count++;
7411
 
        pthread_mutex_unlock(&innobase_share_mutex);
7412
 
 
7413
 
        return(share);
 
7488
    share->table_name = (char*) memcpy(share + 1,
 
7489
               table_name, length + 1);
 
7490
 
 
7491
    HASH_INSERT(INNOBASE_SHARE, table_name_hash,
 
7492
          innobase_open_tables, fold, share);
 
7493
 
 
7494
    thr_lock_init(&share->lock);
 
7495
  }
 
7496
 
 
7497
  share->use_count++;
 
7498
  pthread_mutex_unlock(&innobase_share_mutex);
 
7499
 
 
7500
  return(share);
7414
7501
}
7415
7502
 
7416
7503
static void free_share(INNOBASE_SHARE* share)
7417
7504
{
7418
 
        pthread_mutex_lock(&innobase_share_mutex);
 
7505
  pthread_mutex_lock(&innobase_share_mutex);
7419
7506
 
7420
7507
#ifdef UNIV_DEBUG
7421
 
        INNOBASE_SHARE* share2;
7422
 
        ulint   fold = ut_fold_string(share->table_name);
7423
 
 
7424
 
        HASH_SEARCH(table_name_hash, innobase_open_tables, fold,
7425
 
                    INNOBASE_SHARE*, share2,
7426
 
                    ut_ad(share->use_count > 0),
7427
 
                    !strcmp(share->table_name, share2->table_name));
7428
 
 
7429
 
        ut_a(share2 == share);
 
7508
  INNOBASE_SHARE* share2;
 
7509
  ulint fold = ut_fold_string(share->table_name);
 
7510
 
 
7511
  HASH_SEARCH(table_name_hash, innobase_open_tables, fold,
 
7512
        INNOBASE_SHARE*, share2,
 
7513
        ut_ad(share->use_count > 0),
 
7514
        !strcmp(share->table_name, share2->table_name));
 
7515
 
 
7516
  ut_a(share2 == share);
7430
7517
#endif /* UNIV_DEBUG */
7431
7518
 
7432
 
        if (!--share->use_count) {
7433
 
                ulint   fold = ut_fold_string(share->table_name);
7434
 
 
7435
 
                HASH_DELETE(INNOBASE_SHARE, table_name_hash,
7436
 
                            innobase_open_tables, fold, share);
7437
 
                thr_lock_delete(&share->lock);
7438
 
                free(share);
7439
 
 
7440
 
                /* TODO: invoke HASH_MIGRATE if innobase_open_tables
7441
 
                shrinks too much */
7442
 
        }
7443
 
 
7444
 
        pthread_mutex_unlock(&innobase_share_mutex);
 
7519
  if (!--share->use_count) {
 
7520
    ulint fold = ut_fold_string(share->table_name);
 
7521
 
 
7522
    HASH_DELETE(INNOBASE_SHARE, table_name_hash,
 
7523
          innobase_open_tables, fold, share);
 
7524
    thr_lock_delete(&share->lock);
 
7525
    free(share);
 
7526
 
 
7527
    /* TODO: invoke HASH_MIGRATE if innobase_open_tables
 
7528
    shrinks too much */
 
7529
  }
 
7530
 
 
7531
  pthread_mutex_unlock(&innobase_share_mutex);
7445
7532
}
7446
7533
 
7447
7534
/*****************************************************************//**
7452
7539
SELECT the read lock is released early on the 'const' tables where we only
7453
7540
fetch one row. MySQL does not call this when it releases all locks at the
7454
7541
end of an SQL statement.
7455
 
@return pointer to the next element in the 'to' array */
 
7542
@return pointer to the next element in the 'to' array */
7456
7543
UNIV_INTERN
7457
7544
THR_LOCK_DATA**
7458
7545
ha_innobase::store_lock(
7459
7546
/*====================*/
7460
 
        Session*                session,        /*!< in: user thread handle */
7461
 
        THR_LOCK_DATA**         to,             /*!< in: pointer to an array
7462
 
                                                of pointers to lock structs;
7463
 
                                                pointer to the 'lock' field
7464
 
                                                of current handle is stored
7465
 
                                                next to this array */
7466
 
        enum thr_lock_type      lock_type)      /*!< in: lock type to store in
7467
 
                                                'lock'; this may also be
7468
 
                                                TL_IGNORE */
 
7547
  Session*    session,  /*!< in: user thread handle */
 
7548
  THR_LOCK_DATA**   to,   /*!< in: pointer to an array
 
7549
            of pointers to lock structs;
 
7550
            pointer to the 'lock' field
 
7551
            of current handle is stored
 
7552
            next to this array */
 
7553
  enum thr_lock_type  lock_type)  /*!< in: lock type to store in
 
7554
            'lock'; this may also be
 
7555
            TL_IGNORE */
7469
7556
{
7470
 
        trx_t*          trx;
7471
 
 
7472
 
        /* Note that trx in this function is NOT necessarily prebuilt->trx
7473
 
        because we call update_session() later, in ::external_lock()! Failure to
7474
 
        understand this caused a serious memory corruption bug in 5.1.11. */
7475
 
 
7476
 
        trx = check_trx_exists(session);
7477
 
 
7478
 
        assert(EQ_CURRENT_SESSION(session));
7479
 
        const uint32_t sql_command = session_sql_command(session);
7480
 
 
7481
 
        if (sql_command == SQLCOM_DROP_TABLE) {
7482
 
 
7483
 
                /* MySQL calls this function in DROP Table though this table
7484
 
                handle may belong to another session that is running a query.
7485
 
                Let us in that case skip any changes to the prebuilt struct. */ 
7486
 
 
7487
 
        } else if (lock_type == TL_READ_WITH_SHARED_LOCKS
7488
 
                   || lock_type == TL_READ_NO_INSERT
7489
 
                   || (lock_type != TL_IGNORE
7490
 
                       && sql_command != SQLCOM_SELECT)) {
7491
 
 
7492
 
                /* The OR cases above are in this order:
7493
 
                1) MySQL is doing LOCK TABLES ... READ LOCAL, or we
7494
 
                are processing a stored procedure or function, or
7495
 
                2) (we do not know when TL_READ_HIGH_PRIORITY is used), or
7496
 
                3) this is a SELECT ... IN SHARE MODE, or
7497
 
                4) we are doing a complex SQL statement like
7498
 
                INSERT INTO ... SELECT ... and the logical logging (MySQL
7499
 
                binlog) requires the use of a locking read, or
7500
 
                MySQL is doing LOCK TABLES ... READ.
7501
 
                5) we let InnoDB do locking reads for all SQL statements that
7502
 
                are not simple SELECTs; note that select_lock_type in this
7503
 
                case may get strengthened in ::external_lock() to LOCK_X.
7504
 
                Note that we MUST use a locking read in all data modifying
7505
 
                SQL statements, because otherwise the execution would not be
7506
 
                serializable, and also the results from the update could be
7507
 
                unexpected if an obsolete consistent read view would be
7508
 
                used. */
7509
 
 
7510
 
                ulint   isolation_level;
7511
 
 
7512
 
                isolation_level = trx->isolation_level;
7513
 
 
7514
 
                if ((srv_locks_unsafe_for_binlog
7515
 
                     || isolation_level == TRX_ISO_READ_COMMITTED)
7516
 
                    && isolation_level != TRX_ISO_SERIALIZABLE
7517
 
                    && (lock_type == TL_READ || lock_type == TL_READ_NO_INSERT)
7518
 
                    && (sql_command == SQLCOM_INSERT_SELECT
7519
 
                        || sql_command == SQLCOM_UPDATE
7520
 
                        || sql_command == SQLCOM_CREATE_TABLE)) {
7521
 
 
7522
 
                        /* If we either have innobase_locks_unsafe_for_binlog
7523
 
                        option set or this session is using READ COMMITTED
7524
 
                        isolation level and isolation level of the transaction
7525
 
                        is not set to serializable and MySQL is doing
7526
 
                        INSERT INTO...SELECT or UPDATE ... = (SELECT ...) or
7527
 
                        CREATE  ... SELECT... without FOR UPDATE or
7528
 
                        IN SHARE MODE in select, then we use consistent
7529
 
                        read for select. */
7530
 
 
7531
 
                        prebuilt->select_lock_type = LOCK_NONE;
7532
 
                        prebuilt->stored_select_lock_type = LOCK_NONE;
7533
 
                } else if (sql_command == SQLCOM_CHECKSUM) {
7534
 
                        /* Use consistent read for checksum table */
7535
 
 
7536
 
                        prebuilt->select_lock_type = LOCK_NONE;
7537
 
                        prebuilt->stored_select_lock_type = LOCK_NONE;
7538
 
                } else {
7539
 
                        prebuilt->select_lock_type = LOCK_S;
7540
 
                        prebuilt->stored_select_lock_type = LOCK_S;
7541
 
                }
7542
 
 
7543
 
        } else if (lock_type != TL_IGNORE) {
7544
 
 
7545
 
                /* We set possible LOCK_X value in external_lock, not yet
7546
 
                here even if this would be SELECT ... FOR UPDATE */
7547
 
 
7548
 
                prebuilt->select_lock_type = LOCK_NONE;
7549
 
                prebuilt->stored_select_lock_type = LOCK_NONE;
7550
 
        }
7551
 
 
7552
 
        if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK) {
7553
 
 
7554
 
                /* If we are not doing a LOCK TABLE, DISCARD/IMPORT
7555
 
                TABLESPACE or TRUNCATE TABLE then allow multiple
7556
 
                writers. Note that ALTER TABLE uses a TL_WRITE_ALLOW_READ
7557
 
                < TL_WRITE_CONCURRENT_INSERT.
7558
 
                */
7559
 
 
7560
 
                if ((lock_type >= TL_WRITE_CONCURRENT_INSERT
7561
 
                     && lock_type <= TL_WRITE)
7562
 
                    && !session_tablespace_op(session)
7563
 
                    && sql_command != SQLCOM_TRUNCATE
7564
 
                    && sql_command != SQLCOM_CREATE_TABLE) {
7565
 
 
7566
 
                        lock_type = TL_WRITE_ALLOW_WRITE;
7567
 
                }
7568
 
 
7569
 
                /* In queries of type INSERT INTO t1 SELECT ... FROM t2 ...
7570
 
                MySQL would use the lock TL_READ_NO_INSERT on t2, and that
7571
 
                would conflict with TL_WRITE_ALLOW_WRITE, blocking all inserts
7572
 
                to t2. Convert the lock to a normal read lock to allow
7573
 
                concurrent inserts to t2.
7574
 
    */
7575
 
 
7576
 
                if (lock_type == TL_READ_NO_INSERT) {
7577
 
 
7578
 
                        lock_type = TL_READ;
7579
 
                }
7580
 
 
7581
 
                lock.type = lock_type;
7582
 
        }
7583
 
 
7584
 
        *to++= &lock;
7585
 
 
7586
 
        return(to);
 
7557
  trx_t*    trx;
 
7558
 
 
7559
  /* Note that trx in this function is NOT necessarily prebuilt->trx
 
7560
  because we call update_session() later, in ::external_lock()! Failure to
 
7561
  understand this caused a serious memory corruption bug in 5.1.11. */
 
7562
 
 
7563
  trx = check_trx_exists(session);
 
7564
 
 
7565
  assert(EQ_CURRENT_SESSION(session));
 
7566
  const uint32_t sql_command = session_sql_command(session);
 
7567
 
 
7568
  if (sql_command == SQLCOM_DROP_TABLE) {
 
7569
 
 
7570
    /* MySQL calls this function in DROP Table though this table
 
7571
    handle may belong to another session that is running a query.
 
7572
    Let us in that case skip any changes to the prebuilt struct. */ 
 
7573
 
 
7574
  } else if (lock_type == TL_READ_WITH_SHARED_LOCKS
 
7575
       || lock_type == TL_READ_NO_INSERT
 
7576
       || (lock_type != TL_IGNORE
 
7577
           && sql_command != SQLCOM_SELECT)) {
 
7578
 
 
7579
    /* The OR cases above are in this order:
 
7580
    1) MySQL is doing LOCK TABLES ... READ LOCAL, or we
 
7581
    are processing a stored procedure or function, or
 
7582
    2) (we do not know when TL_READ_HIGH_PRIORITY is used), or
 
7583
    3) this is a SELECT ... IN SHARE MODE, or
 
7584
    4) we are doing a complex SQL statement like
 
7585
    INSERT INTO ... SELECT ... and the logical logging (MySQL
 
7586
    binlog) requires the use of a locking read, or
 
7587
    MySQL is doing LOCK TABLES ... READ.
 
7588
    5) we let InnoDB do locking reads for all SQL statements that
 
7589
    are not simple SELECTs; note that select_lock_type in this
 
7590
    case may get strengthened in ::external_lock() to LOCK_X.
 
7591
    Note that we MUST use a locking read in all data modifying
 
7592
    SQL statements, because otherwise the execution would not be
 
7593
    serializable, and also the results from the update could be
 
7594
    unexpected if an obsolete consistent read view would be
 
7595
    used. */
 
7596
 
 
7597
    ulint isolation_level;
 
7598
 
 
7599
    isolation_level = trx->isolation_level;
 
7600
 
 
7601
    if ((srv_locks_unsafe_for_binlog
 
7602
         || isolation_level == TRX_ISO_READ_COMMITTED)
 
7603
        && isolation_level != TRX_ISO_SERIALIZABLE
 
7604
        && (lock_type == TL_READ || lock_type == TL_READ_NO_INSERT)
 
7605
        && (sql_command == SQLCOM_INSERT_SELECT
 
7606
      || sql_command == SQLCOM_UPDATE
 
7607
      || sql_command == SQLCOM_CREATE_TABLE)) {
 
7608
 
 
7609
      /* If we either have innobase_locks_unsafe_for_binlog
 
7610
      option set or this session is using READ COMMITTED
 
7611
      isolation level and isolation level of the transaction
 
7612
      is not set to serializable and MySQL is doing
 
7613
      INSERT INTO...SELECT or UPDATE ... = (SELECT ...) or
 
7614
      CREATE  ... SELECT... without FOR UPDATE or
 
7615
      IN SHARE MODE in select, then we use consistent
 
7616
      read for select. */
 
7617
 
 
7618
      prebuilt->select_lock_type = LOCK_NONE;
 
7619
      prebuilt->stored_select_lock_type = LOCK_NONE;
 
7620
    } else if (sql_command == SQLCOM_CHECKSUM) {
 
7621
      /* Use consistent read for checksum table */
 
7622
 
 
7623
      prebuilt->select_lock_type = LOCK_NONE;
 
7624
      prebuilt->stored_select_lock_type = LOCK_NONE;
 
7625
    } else {
 
7626
      prebuilt->select_lock_type = LOCK_S;
 
7627
      prebuilt->stored_select_lock_type = LOCK_S;
 
7628
    }
 
7629
 
 
7630
  } else if (lock_type != TL_IGNORE) {
 
7631
 
 
7632
    /* We set possible LOCK_X value in external_lock, not yet
 
7633
    here even if this would be SELECT ... FOR UPDATE */
 
7634
 
 
7635
    prebuilt->select_lock_type = LOCK_NONE;
 
7636
    prebuilt->stored_select_lock_type = LOCK_NONE;
 
7637
  }
 
7638
 
 
7639
  if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK) {
 
7640
 
 
7641
    /* If we are not doing a LOCK TABLE, DISCARD/IMPORT
 
7642
    TABLESPACE or TRUNCATE TABLE then allow multiple
 
7643
    writers. Note that ALTER TABLE uses a TL_WRITE_ALLOW_READ
 
7644
    < TL_WRITE_CONCURRENT_INSERT.
 
7645
    */
 
7646
 
 
7647
    if ((lock_type >= TL_WRITE_CONCURRENT_INSERT
 
7648
         && lock_type <= TL_WRITE)
 
7649
        && !session_tablespace_op(session)
 
7650
        && sql_command != SQLCOM_TRUNCATE
 
7651
        && sql_command != SQLCOM_CREATE_TABLE) {
 
7652
 
 
7653
      lock_type = TL_WRITE_ALLOW_WRITE;
 
7654
    }
 
7655
 
 
7656
    /* In queries of type INSERT INTO t1 SELECT ... FROM t2 ...
 
7657
    MySQL would use the lock TL_READ_NO_INSERT on t2, and that
 
7658
    would conflict with TL_WRITE_ALLOW_WRITE, blocking all inserts
 
7659
    to t2. Convert the lock to a normal read lock to allow
 
7660
    concurrent inserts to t2.
 
7661
    */
 
7662
 
 
7663
    if (lock_type == TL_READ_NO_INSERT) {
 
7664
 
 
7665
      lock_type = TL_READ;
 
7666
    }
 
7667
 
 
7668
    lock.type = lock_type;
 
7669
  }
 
7670
 
 
7671
  *to++= &lock;
 
7672
 
 
7673
  return(to);
7587
7674
}
7588
7675
 
7589
7676
/*********************************************************************//**
7590
7677
Read the next autoinc value. Acquire the relevant locks before reading
7591
7678
the AUTOINC value. If SUCCESS then the table AUTOINC mutex will be locked
7592
7679
on return and all relevant locks acquired.
7593
 
@return DB_SUCCESS or error code */
 
7680
@return DB_SUCCESS or error code */
7594
7681
UNIV_INTERN
7595
7682
ulint
7596
7683
ha_innobase::innobase_get_autoinc(
7597
7684
/*==============================*/
7598
 
        uint64_t*       value)          /*!< out: autoinc value */
 
7685
  uint64_t* value)    /*!< out: autoinc value */
7599
7686
{
7600
 
        *value = 0;
 
7687
  *value = 0;
7601
7688
 
7602
 
        prebuilt->autoinc_error = innobase_lock_autoinc();
7603
 
 
7604
 
        if (prebuilt->autoinc_error == DB_SUCCESS) {
7605
 
 
7606
 
                /* Determine the first value of the interval */
7607
 
                *value = dict_table_autoinc_read(prebuilt->table);
7608
 
 
7609
 
                /* It should have been initialized during open. */
7610
 
                ut_a(*value != 0);
7611
 
        }
7612
 
 
7613
 
        return(prebuilt->autoinc_error);
 
7689
  prebuilt->autoinc_error = innobase_lock_autoinc();
 
7690
 
 
7691
  if (prebuilt->autoinc_error == DB_SUCCESS) {
 
7692
 
 
7693
    /* Determine the first value of the interval */
 
7694
    *value = dict_table_autoinc_read(prebuilt->table);
 
7695
 
 
7696
    /* It should have been initialized during open. */
 
7697
    ut_a(*value != 0);
 
7698
  }
 
7699
 
 
7700
  return(prebuilt->autoinc_error);
7614
7701
}
7615
7702
 
7616
7703
/*******************************************************************//**
7617
7704
This function reads the global auto-inc counter. It doesn't use the 
7618
7705
AUTOINC lock even if the lock mode is set to TRADITIONAL.
7619
 
@return the autoinc value */
 
7706
@return the autoinc value */
7620
7707
UNIV_INTERN
7621
7708
uint64_t
7622
7709
ha_innobase::innobase_peek_autoinc(void)
7623
7710
/*====================================*/
7624
7711
{
7625
 
        uint64_t        auto_inc;
7626
 
        dict_table_t*   innodb_table;
7627
 
 
7628
 
        ut_a(prebuilt != NULL);
7629
 
        ut_a(prebuilt->table != NULL);
7630
 
 
7631
 
        innodb_table = prebuilt->table;
7632
 
 
7633
 
        dict_table_autoinc_lock(innodb_table);
7634
 
 
7635
 
        auto_inc = dict_table_autoinc_read(innodb_table);
7636
 
 
7637
 
        ut_a(auto_inc > 0);
7638
 
 
7639
 
        dict_table_autoinc_unlock(innodb_table);
7640
 
 
7641
 
        return(auto_inc);
 
7712
  uint64_t  auto_inc;
 
7713
  dict_table_t* innodb_table;
 
7714
 
 
7715
  ut_a(prebuilt != NULL);
 
7716
  ut_a(prebuilt->table != NULL);
 
7717
 
 
7718
  innodb_table = prebuilt->table;
 
7719
 
 
7720
  dict_table_autoinc_lock(innodb_table);
 
7721
 
 
7722
  auto_inc = dict_table_autoinc_read(innodb_table);
 
7723
 
 
7724
  ut_a(auto_inc > 0);
 
7725
 
 
7726
  dict_table_autoinc_unlock(innodb_table);
 
7727
 
 
7728
  return(auto_inc);
7642
7729
}
7643
7730
 
7644
7731
/*********************************************************************//**
7652
7739
void
7653
7740
ha_innobase::get_auto_increment(
7654
7741
/*============================*/
7655
 
        uint64_t        offset,              /*!< in: table autoinc offset */
7656
 
        uint64_t        increment,           /*!< in: table autoinc increment */
7657
 
        uint64_t        nb_desired_values,   /*!< in: number of values reqd */
7658
 
        uint64_t        *first_value,        /*!< out: the autoinc value */
7659
 
        uint64_t        *nb_reserved_values) /*!< out: count of reserved values */
 
7742
        uint64_t  offset,              /*!< in: table autoinc offset */
 
7743
        uint64_t  increment,           /*!< in: table autoinc increment */
 
7744
        uint64_t  nb_desired_values,   /*!< in: number of values reqd */
 
7745
        uint64_t  *first_value,        /*!< out: the autoinc value */
 
7746
        uint64_t  *nb_reserved_values) /*!< out: count of reserved values */
7660
7747
{
7661
 
        trx_t*          trx;
7662
 
        ulint           error;
7663
 
        uint64_t        autoinc = 0;
7664
 
 
7665
 
        /* Prepare prebuilt->trx in the table handle */
7666
 
        update_session(ha_session());
7667
 
 
7668
 
        error = innobase_get_autoinc(&autoinc);
7669
 
 
7670
 
        if (error != DB_SUCCESS) {
7671
 
                *first_value = (~(uint64_t) 0);
7672
 
                return;
7673
 
        }
7674
 
 
7675
 
        /* This is a hack, since nb_desired_values seems to be accurate only
7676
 
        for the first call to get_auto_increment() for multi-row INSERT and
7677
 
        meaningless for other statements e.g, LOAD etc. Subsequent calls to
7678
 
        this method for the same statement results in different values which
7679
 
        don't make sense. Therefore we store the value the first time we are
7680
 
        called and count down from that as rows are written (see write_row()).
7681
 
        */
7682
 
 
7683
 
        trx = prebuilt->trx;
7684
 
 
7685
 
        /* Note: We can't rely on *first_value since some MySQL engines,
7686
 
        in particular the partition engine, don't initialize it to 0 when
7687
 
        invoking this method. So we are not sure if it's guaranteed to
7688
 
        be 0 or not. */
7689
 
 
7690
 
        /* Called for the first time ? */
7691
 
        if (trx->n_autoinc_rows == 0) {
7692
 
 
7693
 
                trx->n_autoinc_rows = (ulint) nb_desired_values;
7694
 
 
7695
 
                /* It's possible for nb_desired_values to be 0:
7696
 
                e.g., INSERT INTO T1(C) SELECT C FROM T2; */
7697
 
                if (nb_desired_values == 0) {
7698
 
 
7699
 
                        trx->n_autoinc_rows = 1;
7700
 
                }
7701
 
 
7702
 
                set_if_bigger(*first_value, autoinc);
7703
 
        /* Not in the middle of a mult-row INSERT. */
7704
 
        } else if (prebuilt->autoinc_last_value == 0) {
7705
 
                set_if_bigger(*first_value, autoinc);
7706
 
        }
7707
 
 
7708
 
        *nb_reserved_values = trx->n_autoinc_rows;
7709
 
 
7710
 
        /* With old style AUTOINC locking we only update the table's
7711
 
        AUTOINC counter after attempting to insert the row. */
7712
 
        if (innobase_autoinc_lock_mode != AUTOINC_OLD_STYLE_LOCKING) {
7713
 
                uint64_t        need;
7714
 
                uint64_t        next_value;
7715
 
                uint64_t        col_max_value;
7716
 
 
7717
 
                /* We need the upper limit of the col type to check for
7718
 
                whether we update the table autoinc counter or not. */
7719
 
                col_max_value = innobase_get_int_col_max_value(
7720
 
                        table->next_number_field);
7721
 
 
7722
 
                need = *nb_reserved_values * increment;
7723
 
 
7724
 
                /* Compute the last value in the interval */
7725
 
                next_value = innobase_next_autoinc(
7726
 
                        *first_value, need, offset, col_max_value);
7727
 
 
7728
 
                prebuilt->autoinc_last_value = next_value;
7729
 
 
7730
 
                if (prebuilt->autoinc_last_value < *first_value) {
7731
 
                        *first_value = (~(unsigned long long) 0);
7732
 
                } else {
7733
 
                        /* Update the table autoinc variable */
7734
 
                        dict_table_autoinc_update_if_greater(
7735
 
                                prebuilt->table, prebuilt->autoinc_last_value);
7736
 
                }
7737
 
        } else {
7738
 
                /* This will force write_row() into attempting an update
7739
 
                of the table's AUTOINC counter. */
7740
 
                prebuilt->autoinc_last_value = 0;
7741
 
        }
7742
 
 
7743
 
        /* The increment to be used to increase the AUTOINC value, we use
7744
 
        this in write_row() and update_row() to increase the autoinc counter
7745
 
        for columns that are filled by the user. We need the offset and
7746
 
        the increment. */
7747
 
        prebuilt->autoinc_offset = offset;
7748
 
        prebuilt->autoinc_increment = increment;
7749
 
 
7750
 
        dict_table_autoinc_unlock(prebuilt->table);
 
7748
  trx_t*    trx;
 
7749
  ulint   error;
 
7750
  uint64_t  autoinc = 0;
 
7751
 
 
7752
  /* Prepare prebuilt->trx in the table handle */
 
7753
  update_session(ha_session());
 
7754
 
 
7755
  error = innobase_get_autoinc(&autoinc);
 
7756
 
 
7757
  if (error != DB_SUCCESS) {
 
7758
    *first_value = (~(uint64_t) 0);
 
7759
    return;
 
7760
  }
 
7761
 
 
7762
  /* This is a hack, since nb_desired_values seems to be accurate only
 
7763
  for the first call to get_auto_increment() for multi-row INSERT and
 
7764
  meaningless for other statements e.g, LOAD etc. Subsequent calls to
 
7765
  this method for the same statement results in different values which
 
7766
  don't make sense. Therefore we store the value the first time we are
 
7767
  called and count down from that as rows are written (see write_row()).
 
7768
  */
 
7769
 
 
7770
  trx = prebuilt->trx;
 
7771
 
 
7772
  /* Note: We can't rely on *first_value since some MySQL engines,
 
7773
  in particular the partition engine, don't initialize it to 0 when
 
7774
  invoking this method. So we are not sure if it's guaranteed to
 
7775
  be 0 or not. */
 
7776
 
 
7777
  /* Called for the first time ? */
 
7778
  if (trx->n_autoinc_rows == 0) {
 
7779
 
 
7780
    trx->n_autoinc_rows = (ulint) nb_desired_values;
 
7781
 
 
7782
    /* It's possible for nb_desired_values to be 0:
 
7783
    e.g., INSERT INTO T1(C) SELECT C FROM T2; */
 
7784
    if (nb_desired_values == 0) {
 
7785
 
 
7786
      trx->n_autoinc_rows = 1;
 
7787
    }
 
7788
 
 
7789
    set_if_bigger(*first_value, autoinc);
 
7790
  /* Not in the middle of a mult-row INSERT. */
 
7791
  } else if (prebuilt->autoinc_last_value == 0) {
 
7792
    set_if_bigger(*first_value, autoinc);
 
7793
  }
 
7794
 
 
7795
  *nb_reserved_values = trx->n_autoinc_rows;
 
7796
 
 
7797
  /* With old style AUTOINC locking we only update the table's
 
7798
  AUTOINC counter after attempting to insert the row. */
 
7799
  if (innobase_autoinc_lock_mode != AUTOINC_OLD_STYLE_LOCKING) {
 
7800
    uint64_t  need;
 
7801
    uint64_t  next_value;
 
7802
    uint64_t  col_max_value;
 
7803
 
 
7804
    /* We need the upper limit of the col type to check for
 
7805
    whether we update the table autoinc counter or not. */
 
7806
    col_max_value = innobase_get_int_col_max_value(
 
7807
      table->next_number_field);
 
7808
 
 
7809
    need = *nb_reserved_values * increment;
 
7810
 
 
7811
    /* Compute the last value in the interval */
 
7812
    next_value = innobase_next_autoinc(
 
7813
      *first_value, need, offset, col_max_value);
 
7814
 
 
7815
    prebuilt->autoinc_last_value = next_value;
 
7816
 
 
7817
    if (prebuilt->autoinc_last_value < *first_value) {
 
7818
      *first_value = (~(unsigned long long) 0);
 
7819
    } else {
 
7820
      /* Update the table autoinc variable */
 
7821
      dict_table_autoinc_update_if_greater(
 
7822
        prebuilt->table, prebuilt->autoinc_last_value);
 
7823
    }
 
7824
  } else {
 
7825
    /* This will force write_row() into attempting an update
 
7826
    of the table's AUTOINC counter. */
 
7827
    prebuilt->autoinc_last_value = 0;
 
7828
  }
 
7829
 
 
7830
  /* The increment to be used to increase the AUTOINC value, we use
 
7831
  this in write_row() and update_row() to increase the autoinc counter
 
7832
  for columns that are filled by the user. We need the offset and
 
7833
  the increment. */
 
7834
  prebuilt->autoinc_offset = offset;
 
7835
  prebuilt->autoinc_increment = increment;
 
7836
 
 
7837
  dict_table_autoinc_unlock(prebuilt->table);
7751
7838
}
7752
7839
 
7753
7840
/*******************************************************************//**
7755
7842
inserted will get the given value. This is called e.g. after TRUNCATE
7756
7843
is emulated by doing a 'DELETE FROM t'. HA_ERR_WRONG_COMMAND is
7757
7844
returned by storage engines that don't support this operation.
7758
 
@return 0 or error code */
 
7845
@return 0 or error code */
7759
7846
UNIV_INTERN
7760
7847
int
7761
7848
ha_innobase::reset_auto_increment(
7762
7849
/*==============================*/
7763
 
        uint64_t        value)          /*!< in: new value for table autoinc */
 
7850
  uint64_t  value)    /*!< in: new value for table autoinc */
7764
7851
{
7765
 
        int     error;
7766
 
 
7767
 
        update_session(ha_session());
7768
 
 
7769
 
        error = row_lock_table_autoinc_for_mysql(prebuilt);
7770
 
 
7771
 
        if (error != DB_SUCCESS) {
7772
 
                error = convert_error_code_to_mysql(error,
7773
 
                                                    prebuilt->table->flags,
7774
 
                                                    user_session);
7775
 
 
7776
 
                return(error);
7777
 
        }
7778
 
 
7779
 
        /* The next value can never be 0. */
7780
 
        if (value == 0) {
7781
 
                value = 1;
7782
 
        }
7783
 
 
7784
 
        innobase_reset_autoinc(value);
7785
 
 
7786
 
        return 0;
 
7852
  int error;
 
7853
 
 
7854
  update_session(ha_session());
 
7855
 
 
7856
  error = row_lock_table_autoinc_for_mysql(prebuilt);
 
7857
 
 
7858
  if (error != DB_SUCCESS) {
 
7859
    error = convert_error_code_to_mysql(error,
 
7860
                prebuilt->table->flags,
 
7861
                user_session);
 
7862
 
 
7863
    return(error);
 
7864
  }
 
7865
 
 
7866
  /* The next value can never be 0. */
 
7867
  if (value == 0) {
 
7868
    value = 1;
 
7869
  }
 
7870
 
 
7871
  innobase_reset_autoinc(value);
 
7872
 
 
7873
  return 0;
7787
7874
}
7788
7875
 
7789
7876
/* See comment in Cursor.cc */
7791
7878
bool
7792
7879
InnobaseEngine::get_error_message(int, String *buf)
7793
7880
{
7794
 
        trx_t*  trx = check_trx_exists(current_session);
7795
 
 
7796
 
        buf->copy(trx->detailed_error, (uint) strlen(trx->detailed_error),
7797
 
                system_charset_info);
7798
 
 
7799
 
        return(FALSE);
 
7881
  trx_t*  trx = check_trx_exists(current_session);
 
7882
 
 
7883
  buf->copy(trx->detailed_error, (uint) strlen(trx->detailed_error),
 
7884
    system_charset_info);
 
7885
 
 
7886
  return(FALSE);
7800
7887
}
7801
7888
 
7802
7889
/*******************************************************************//**
7803
7890
Compares two 'refs'. A 'ref' is the (internal) primary key value of the row.
7804
7891
If there is no explicitly declared non-null unique key or a primary key, then
7805
7892
InnoDB internally uses the row id as the primary key.
7806
 
@return < 0 if ref1 < ref2, 0 if equal, else > 0 */
 
7893
@return < 0 if ref1 < ref2, 0 if equal, else > 0 */
7807
7894
UNIV_INTERN
7808
7895
int
7809
7896
ha_innobase::cmp_ref(
7810
7897
/*=================*/
7811
 
        const unsigned char*    ref1,   /*!< in: an (internal) primary key value in the
7812
 
                                MySQL key value format */
7813
 
        const unsigned char*    ref2)   /*!< in: an (internal) primary key value in the
7814
 
                                MySQL key value format */
 
7898
  const unsigned char*  ref1, /*!< in: an (internal) primary key value in the
 
7899
        MySQL key value format */
 
7900
  const unsigned char*  ref2) /*!< in: an (internal) primary key value in the
 
7901
        MySQL key value format */
7815
7902
{
7816
 
        enum_field_types mysql_type;
7817
 
        Field*          field;
7818
 
        KEY_PART_INFO*  key_part;
7819
 
        KEY_PART_INFO*  key_part_end;
7820
 
        uint            len1;
7821
 
        uint            len2;
7822
 
        int             result;
7823
 
 
7824
 
        if (prebuilt->clust_index_was_generated) {
7825
 
                /* The 'ref' is an InnoDB row id */
7826
 
 
7827
 
                return(memcmp(ref1, ref2, DATA_ROW_ID_LEN));
7828
 
        }
7829
 
 
7830
 
        /* Do a type-aware comparison of primary key fields. PK fields
7831
 
        are always NOT NULL, so no checks for NULL are performed. */
7832
 
 
7833
 
        key_part = table->key_info[table->s->primary_key].key_part;
7834
 
 
7835
 
        key_part_end = key_part
7836
 
                        + table->key_info[table->s->primary_key].key_parts;
7837
 
 
7838
 
        for (; key_part != key_part_end; ++key_part) {
7839
 
                field = key_part->field;
7840
 
                mysql_type = field->type();
7841
 
 
7842
 
                if (mysql_type == DRIZZLE_TYPE_BLOB) {
7843
 
 
7844
 
                        /* In the MySQL key value format, a column prefix of
7845
 
                        a BLOB is preceded by a 2-byte length field */
7846
 
 
7847
 
                        len1 = innobase_read_from_2_little_endian(ref1);
7848
 
                        len2 = innobase_read_from_2_little_endian(ref2);
7849
 
 
7850
 
                        ref1 += 2;
7851
 
                        ref2 += 2;
7852
 
                        result = ((Field_blob*)field)->cmp( ref1, len1,
 
7903
  enum_field_types mysql_type;
 
7904
  Field*    field;
 
7905
  KEY_PART_INFO*  key_part;
 
7906
  KEY_PART_INFO*  key_part_end;
 
7907
  uint    len1;
 
7908
  uint    len2;
 
7909
  int   result;
 
7910
 
 
7911
  if (prebuilt->clust_index_was_generated) {
 
7912
    /* The 'ref' is an InnoDB row id */
 
7913
 
 
7914
    return(memcmp(ref1, ref2, DATA_ROW_ID_LEN));
 
7915
  }
 
7916
 
 
7917
  /* Do a type-aware comparison of primary key fields. PK fields
 
7918
  are always NOT NULL, so no checks for NULL are performed. */
 
7919
 
 
7920
  key_part = table->key_info[table->s->primary_key].key_part;
 
7921
 
 
7922
  key_part_end = key_part
 
7923
      + table->key_info[table->s->primary_key].key_parts;
 
7924
 
 
7925
  for (; key_part != key_part_end; ++key_part) {
 
7926
    field = key_part->field;
 
7927
    mysql_type = field->type();
 
7928
 
 
7929
    if (mysql_type == DRIZZLE_TYPE_BLOB) {
 
7930
 
 
7931
      /* In the MySQL key value format, a column prefix of
 
7932
      a BLOB is preceded by a 2-byte length field */
 
7933
 
 
7934
      len1 = innobase_read_from_2_little_endian(ref1);
 
7935
      len2 = innobase_read_from_2_little_endian(ref2);
 
7936
 
 
7937
      ref1 += 2;
 
7938
      ref2 += 2;
 
7939
      result = ((Field_blob*)field)->cmp( ref1, len1,
7853
7940
                                                            ref2, len2);
7854
 
                } else {
7855
 
                        result = field->key_cmp(ref1, ref2);
7856
 
                }
7857
 
 
7858
 
                if (result) {
7859
 
 
7860
 
                        return(result);
7861
 
                }
7862
 
 
7863
 
                ref1 += key_part->store_length;
7864
 
                ref2 += key_part->store_length;
7865
 
        }
7866
 
 
7867
 
        return(0);
 
7941
    } else {
 
7942
      result = field->key_cmp(ref1, ref2);
 
7943
    }
 
7944
 
 
7945
    if (result) {
 
7946
 
 
7947
      return(result);
 
7948
    }
 
7949
 
 
7950
    ref1 += key_part->store_length;
 
7951
    ref2 += key_part->store_length;
 
7952
  }
 
7953
 
 
7954
  return(0);
7868
7955
}
7869
7956
 
7870
7957
/**********************************************************************
7872
7959
characters for prefix indexes using a multibyte character set. The function
7873
7960
finds charset information and returns length of prefix_len characters in the
7874
7961
index field in bytes.
7875
 
@return number of bytes occupied by the first n characters */
 
7962
@return number of bytes occupied by the first n characters */
7876
7963
extern "C" UNIV_INTERN
7877
7964
ulint
7878
7965
innobase_get_at_most_n_mbchars(
7879
7966
/*===========================*/
7880
 
        ulint charset_id,       /*!< in: character set id */
7881
 
        ulint prefix_len,       /*!< in: prefix length in bytes of the index
7882
 
                                (this has to be divided by mbmaxlen to get the
7883
 
                                number of CHARACTERS n in the prefix) */
7884
 
        ulint data_len,         /*!< in: length of the string in bytes */
7885
 
        const char* str);       /*!< in: character string */
 
7967
  ulint charset_id, /*!< in: character set id */
 
7968
  ulint prefix_len, /*!< in: prefix length in bytes of the index
 
7969
        (this has to be divided by mbmaxlen to get the
 
7970
        number of CHARACTERS n in the prefix) */
 
7971
  ulint data_len,   /*!< in: length of the string in bytes */
 
7972
  const char* str); /*!< in: character string */
7886
7973
 
7887
7974
ulint
7888
7975
innobase_get_at_most_n_mbchars(
7889
7976
/*===========================*/
7890
 
        ulint charset_id,       /*!< in: character set id */
7891
 
        ulint prefix_len,       /*!< in: prefix length in bytes of the index
7892
 
                                (this has to be divided by mbmaxlen to get the
7893
 
                                number of CHARACTERS n in the prefix) */
7894
 
        ulint data_len,         /*!< in: length of the string in bytes */
7895
 
        const char* str)        /*!< in: character string */
 
7977
  ulint charset_id, /*!< in: character set id */
 
7978
  ulint prefix_len, /*!< in: prefix length in bytes of the index
 
7979
        (this has to be divided by mbmaxlen to get the
 
7980
        number of CHARACTERS n in the prefix) */
 
7981
  ulint data_len,   /*!< in: length of the string in bytes */
 
7982
  const char* str)  /*!< in: character string */
7896
7983
{
7897
 
        ulint char_length;              /*!< character length in bytes */
7898
 
        ulint n_chars;                  /*!< number of characters in prefix */
7899
 
        const CHARSET_INFO* charset;    /*!< charset used in the field */
7900
 
 
7901
 
        charset = get_charset((uint) charset_id);
7902
 
 
7903
 
        ut_ad(charset);
7904
 
        ut_ad(charset->mbmaxlen);
7905
 
 
7906
 
        /* Calculate how many characters at most the prefix index contains */
7907
 
 
7908
 
        n_chars = prefix_len / charset->mbmaxlen;
7909
 
 
7910
 
        /* If the charset is multi-byte, then we must find the length of the
7911
 
        first at most n chars in the string. If the string contains less
7912
 
        characters than n, then we return the length to the end of the last
7913
 
        character. */
7914
 
 
7915
 
        if (charset->mbmaxlen > 1) {
7916
 
                /* my_charpos() returns the byte length of the first n_chars
7917
 
                characters, or a value bigger than the length of str, if
7918
 
                there were not enough full characters in str.
7919
 
 
7920
 
                Why does the code below work:
7921
 
                Suppose that we are looking for n UTF-8 characters.
7922
 
 
7923
 
                1) If the string is long enough, then the prefix contains at
7924
 
                least n complete UTF-8 characters + maybe some extra
7925
 
                characters + an incomplete UTF-8 character. No problem in
7926
 
                this case. The function returns the pointer to the
7927
 
                end of the nth character.
7928
 
 
7929
 
                2) If the string is not long enough, then the string contains
7930
 
                the complete value of a column, that is, only complete UTF-8
7931
 
                characters, and we can store in the column prefix index the
7932
 
                whole string. */
7933
 
 
7934
 
                char_length = my_charpos(charset, str,
7935
 
                                                str + data_len, (int) n_chars);
7936
 
                if (char_length > data_len) {
7937
 
                        char_length = data_len;
7938
 
                }
7939
 
        } else {
7940
 
                if (data_len < prefix_len) {
7941
 
                        char_length = data_len;
7942
 
                } else {
7943
 
                        char_length = prefix_len;
7944
 
                }
7945
 
        }
7946
 
 
7947
 
        return(char_length);
 
7984
  ulint char_length;    /*!< character length in bytes */
 
7985
  ulint n_chars;      /*!< number of characters in prefix */
 
7986
  const CHARSET_INFO* charset;  /*!< charset used in the field */
 
7987
 
 
7988
  charset = get_charset((uint) charset_id);
 
7989
 
 
7990
  ut_ad(charset);
 
7991
  ut_ad(charset->mbmaxlen);
 
7992
 
 
7993
  /* Calculate how many characters at most the prefix index contains */
 
7994
 
 
7995
  n_chars = prefix_len / charset->mbmaxlen;
 
7996
 
 
7997
  /* If the charset is multi-byte, then we must find the length of the
 
7998
  first at most n chars in the string. If the string contains less
 
7999
  characters than n, then we return the length to the end of the last
 
8000
  character. */
 
8001
 
 
8002
  if (charset->mbmaxlen > 1) {
 
8003
    /* my_charpos() returns the byte length of the first n_chars
 
8004
    characters, or a value bigger than the length of str, if
 
8005
    there were not enough full characters in str.
 
8006
 
 
8007
    Why does the code below work:
 
8008
    Suppose that we are looking for n UTF-8 characters.
 
8009
 
 
8010
    1) If the string is long enough, then the prefix contains at
 
8011
    least n complete UTF-8 characters + maybe some extra
 
8012
    characters + an incomplete UTF-8 character. No problem in
 
8013
    this case. The function returns the pointer to the
 
8014
    end of the nth character.
 
8015
 
 
8016
    2) If the string is not long enough, then the string contains
 
8017
    the complete value of a column, that is, only complete UTF-8
 
8018
    characters, and we can store in the column prefix index the
 
8019
    whole string. */
 
8020
 
 
8021
    char_length = my_charpos(charset, str,
 
8022
            str + data_len, (int) n_chars);
 
8023
    if (char_length > data_len) {
 
8024
      char_length = data_len;
 
8025
    }
 
8026
  } else {
 
8027
    if (data_len < prefix_len) {
 
8028
      char_length = data_len;
 
8029
    } else {
 
8030
      char_length = prefix_len;
 
8031
    }
 
8032
  }
 
8033
 
 
8034
  return(char_length);
7948
8035
}
7949
8036
/**
7950
8037
 * We will also use this function to communicate
7954
8041
 */
7955
8042
void
7956
8043
InnobaseEngine::doStartStatement(
7957
 
        Session *session) /*!< in: handle to the Drizzle session */
 
8044
  Session *session) /*!< in: handle to the Drizzle session */
7958
8045
{
7959
8046
  /* 
7960
8047
   * Create the InnoDB transaction structure
7961
8048
   * for the session
7962
8049
   */
7963
 
        trx_t *trx= check_trx_exists(session);
 
8050
  trx_t *trx= check_trx_exists(session);
7964
8051
 
7965
8052
  /* "reset" the error message for the transaction */
7966
8053
  trx->detailed_error[0]= '\0';
7967
8054
 
7968
 
        /* Set the isolation level of the transaction. */
 
8055
  /* Set the isolation level of the transaction. */
7969
8056
  trx->isolation_level= innobase_map_isolation_level((enum_tx_isolation) session_tx_isolation(session));
7970
8057
}
7971
8058
 
8002
8089
 
8003
8090
/*******************************************************************//**
8004
8091
This function is used to prepare an X/Open XA distributed transaction.
8005
 
@return 0 or error number */
 
8092
@return 0 or error number */
8006
8093
int
8007
8094
InnobaseEngine::doXaPrepare(
8008
8095
/*================*/
8009
 
        Session*        session,/*!< in: handle to the MySQL thread of
8010
 
                                the user whose XA transaction should
8011
 
                                be prepared */
8012
 
        bool            all)    /*!< in: TRUE - commit transaction
8013
 
                                FALSE - the current SQL statement
8014
 
                                ended */
 
8096
  Session*  session,/*!< in: handle to the MySQL thread of
 
8097
        the user whose XA transaction should
 
8098
        be prepared */
 
8099
  bool    all)  /*!< in: TRUE - commit transaction
 
8100
        FALSE - the current SQL statement
 
8101
        ended */
8015
8102
{
8016
 
        int error = 0;
8017
 
        trx_t* trx = check_trx_exists(session);
8018
 
 
8019
 
        assert(this == innodb_engine_ptr);
8020
 
 
8021
 
        /* we use support_xa value as it was seen at transaction start
8022
 
        time, not the current session variable value. Any possible changes
8023
 
        to the session variable take effect only in the next transaction */
8024
 
        if (!trx->support_xa) {
8025
 
 
8026
 
                return(0);
8027
 
        }
8028
 
 
8029
 
        session_get_xid(session, reinterpret_cast<DRIZZLE_XID*>(&trx->xid));
8030
 
 
8031
 
        /* Release a possible FIFO ticket and search latch. Since we will
8032
 
        reserve the kernel mutex, we have to release the search system latch
8033
 
        first to obey the latching order. */
8034
 
 
8035
 
        innobase_release_stat_resources(trx);
8036
 
 
8037
 
        if (all
8038
 
                || (!session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
8039
 
 
8040
 
                /* We were instructed to prepare the whole transaction, or
8041
 
                this is an SQL statement end and autocommit is on */
8042
 
 
8043
 
                ut_ad(trx->conc_state != TRX_NOT_STARTED);
8044
 
 
8045
 
                error = (int) trx_prepare_for_mysql(trx);
8046
 
        } else {
8047
 
                /* We just mark the SQL statement ended and do not do a
8048
 
                transaction prepare */
8049
 
 
8050
 
                /* If we had reserved the auto-inc lock for some
8051
 
                table in this SQL statement we release it now */
8052
 
 
8053
 
                row_unlock_table_autoinc_for_mysql(trx);
8054
 
 
8055
 
                /* Store the current undo_no of the transaction so that we
8056
 
                know where to roll back if we have to roll back the next
8057
 
                SQL statement */
8058
 
 
8059
 
                trx_mark_sql_stat_end(trx);
8060
 
        }
8061
 
 
8062
 
        /* Tell the InnoDB server that there might be work for utility
8063
 
        threads: */
8064
 
 
8065
 
        srv_active_wake_master_thread();
8066
 
 
8067
 
        if (all || !session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
8068
 
        {
8069
 
 
8070
 
                /* For ibbackup to work the order of transactions in binlog
8071
 
                and InnoDB must be the same. Consider the situation
8072
 
 
8073
 
                  thread1> prepare; write to binlog; ...
8074
 
                          <context switch>
8075
 
                  thread2> prepare; write to binlog; commit
8076
 
                  thread1>                           ... commit
8077
 
 
8078
 
                To ensure this will not happen we're taking the mutex on
8079
 
                prepare, and releasing it on commit.
8080
 
 
8081
 
                Note: only do it for normal commits, done via ha_commit_trans.
8082
 
                If 2pc protocol is executed by external transaction
8083
 
                coordinator, it will be just a regular MySQL client
8084
 
                executing XA PREPARE and XA COMMIT commands.
8085
 
                In this case we cannot know how many minutes or hours
8086
 
                will be between XA PREPARE and XA COMMIT, and we don't want
8087
 
                to block for undefined period of time.
8088
 
                */
8089
 
                pthread_mutex_lock(&prepare_commit_mutex);
8090
 
                trx->conc_state = TRX_PREPARED;
8091
 
        }
8092
 
        return(error);
 
8103
  int error = 0;
 
8104
  trx_t* trx = check_trx_exists(session);
 
8105
 
 
8106
  assert(this == innodb_engine_ptr);
 
8107
 
 
8108
  /* we use support_xa value as it was seen at transaction start
 
8109
  time, not the current session variable value. Any possible changes
 
8110
  to the session variable take effect only in the next transaction */
 
8111
  if (!trx->support_xa) {
 
8112
 
 
8113
    return(0);
 
8114
  }
 
8115
 
 
8116
  session_get_xid(session, reinterpret_cast<DRIZZLE_XID*>(&trx->xid));
 
8117
 
 
8118
  /* Release a possible FIFO ticket and search latch. Since we will
 
8119
  reserve the kernel mutex, we have to release the search system latch
 
8120
  first to obey the latching order. */
 
8121
 
 
8122
  innobase_release_stat_resources(trx);
 
8123
 
 
8124
  if (all
 
8125
    || (!session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
 
8126
 
 
8127
    /* We were instructed to prepare the whole transaction, or
 
8128
    this is an SQL statement end and autocommit is on */
 
8129
 
 
8130
    ut_ad(trx->conc_state != TRX_NOT_STARTED);
 
8131
 
 
8132
    error = (int) trx_prepare_for_mysql(trx);
 
8133
  } else {
 
8134
    /* We just mark the SQL statement ended and do not do a
 
8135
    transaction prepare */
 
8136
 
 
8137
    /* If we had reserved the auto-inc lock for some
 
8138
    table in this SQL statement we release it now */
 
8139
 
 
8140
    row_unlock_table_autoinc_for_mysql(trx);
 
8141
 
 
8142
    /* Store the current undo_no of the transaction so that we
 
8143
    know where to roll back if we have to roll back the next
 
8144
    SQL statement */
 
8145
 
 
8146
    trx_mark_sql_stat_end(trx);
 
8147
  }
 
8148
 
 
8149
  /* Tell the InnoDB server that there might be work for utility
 
8150
  threads: */
 
8151
 
 
8152
  srv_active_wake_master_thread();
 
8153
 
 
8154
  return(error);
8093
8155
}
8094
8156
 
8095
8157
/*******************************************************************//**
8096
8158
This function is used to recover X/Open XA distributed transactions.
8097
 
@return number of prepared transactions stored in xid_list */
 
8159
@return number of prepared transactions stored in xid_list */
8098
8160
int
8099
8161
InnobaseEngine::doXaRecover(
8100
8162
/*================*/
8101
 
        ::drizzled::XID*        xid_list,/*!< in/out: prepared transactions */
8102
 
        size_t len)     /*!< in: number of slots in xid_list */
 
8163
  ::drizzled::XID*  xid_list,/*!< in/out: prepared transactions */
 
8164
  size_t len) /*!< in: number of slots in xid_list */
8103
8165
{
8104
 
        assert(this == innodb_engine_ptr);
8105
 
 
8106
 
        if (len == 0 || xid_list == NULL) {
8107
 
 
8108
 
                return(0);
8109
 
        }
8110
 
 
8111
 
        return(trx_recover_for_mysql((::XID *)xid_list, len));
 
8166
  assert(this == innodb_engine_ptr);
 
8167
 
 
8168
  if (len == 0 || xid_list == NULL) {
 
8169
 
 
8170
    return(0);
 
8171
  }
 
8172
 
 
8173
  return(trx_recover_for_mysql((::XID *)xid_list, len));
8112
8174
}
8113
8175
 
8114
8176
/*******************************************************************//**
8115
8177
This function is used to commit one X/Open XA distributed transaction
8116
8178
which is in the prepared state
8117
 
@return 0 or error number */
 
8179
@return 0 or error number */
8118
8180
int
8119
8181
InnobaseEngine::doXaCommitXid(
8120
8182
/*===================*/
8121
 
        ::drizzled::XID*        xid)    /*!< in: X/Open XA transaction identification */
 
8183
  ::drizzled::XID*  xid)  /*!< in: X/Open XA transaction identification */
8122
8184
{
8123
 
        trx_t*  trx;
8124
 
 
8125
 
        assert(this == innodb_engine_ptr);
8126
 
 
8127
 
        trx = trx_get_trx_by_xid((::XID *)xid);
8128
 
 
8129
 
        if (trx) {
8130
 
                innobase_commit_low(trx);
8131
 
 
8132
 
                return(XA_OK);
8133
 
        } else {
8134
 
                return(XAER_NOTA);
8135
 
        }
 
8185
  trx_t*  trx;
 
8186
 
 
8187
  assert(this == innodb_engine_ptr);
 
8188
 
 
8189
  trx = trx_get_trx_by_xid((::XID *)xid);
 
8190
 
 
8191
  if (trx) {
 
8192
    innobase_commit_low(trx);
 
8193
 
 
8194
    return(XA_OK);
 
8195
  } else {
 
8196
    return(XAER_NOTA);
 
8197
  }
8136
8198
}
8137
8199
 
8138
8200
/*******************************************************************//**
8139
8201
This function is used to rollback one X/Open XA distributed transaction
8140
8202
which is in the prepared state
8141
 
@return 0 or error number */
 
8203
@return 0 or error number */
8142
8204
int
8143
8205
InnobaseEngine::doXaRollbackXid(
8144
8206
/*=====================*/
8145
 
        ::drizzled::XID*                xid)    /*!< in: X/Open XA transaction
8146
 
                                identification */
 
8207
  ::drizzled::XID*    xid)  /*!< in: X/Open XA transaction
 
8208
        identification */
8147
8209
{
8148
 
        trx_t*  trx;
8149
 
 
8150
 
        assert(this == innodb_engine_ptr);
8151
 
 
8152
 
        trx = trx_get_trx_by_xid((::XID *)xid);
8153
 
 
8154
 
        if (trx) {
8155
 
                return(innobase_rollback_trx(trx));
8156
 
        } else {
8157
 
                return(XAER_NOTA);
8158
 
        }
 
8210
  trx_t*  trx;
 
8211
 
 
8212
  assert(this == innodb_engine_ptr);
 
8213
 
 
8214
  trx = trx_get_trx_by_xid((::XID *)xid);
 
8215
 
 
8216
  if (trx) {
 
8217
    return(innobase_rollback_trx(trx));
 
8218
  } else {
 
8219
    return(XAER_NOTA);
 
8220
  }
8159
8221
}
8160
8222
 
8161
8223
 
8162
8224
/************************************************************//**
8163
8225
Validate the file format name and return its corresponding id.
8164
 
@return valid file format id */
 
8226
@return valid file format id */
8165
8227
static
8166
8228
uint
8167
8229
innobase_file_format_name_lookup(
8168
8230
/*=============================*/
8169
 
        const char*     format_name)    /*!< in: pointer to file format name */
 
8231
  const char* format_name)  /*!< in: pointer to file format name */
8170
8232
{
8171
 
        char*   endp;
8172
 
        uint    format_id;
8173
 
 
8174
 
        ut_a(format_name != NULL);
8175
 
 
8176
 
        /* The format name can contain the format id itself instead of
8177
 
        the name and we check for that. */
8178
 
        format_id = (uint) strtoul(format_name, &endp, 10);
8179
 
 
8180
 
        /* Check for valid parse. */
8181
 
        if (*endp == '\0' && *format_name != '\0') {
8182
 
 
8183
 
                if (format_id <= DICT_TF_FORMAT_MAX) {
8184
 
 
8185
 
                        return(format_id);
8186
 
                }
8187
 
        } else {
8188
 
 
8189
 
                for (format_id = 0; format_id <= DICT_TF_FORMAT_MAX;
8190
 
                     format_id++) {
8191
 
                        const char*     name;
8192
 
 
8193
 
                        name = trx_sys_file_format_id_to_name(format_id);
8194
 
 
8195
 
                        if (!innobase_strcasecmp(format_name, name)) {
8196
 
 
8197
 
                                return(format_id);
8198
 
                        }
8199
 
                }
8200
 
        }
8201
 
 
8202
 
        return(DICT_TF_FORMAT_MAX + 1);
 
8233
  char* endp;
 
8234
  uint  format_id;
 
8235
 
 
8236
  ut_a(format_name != NULL);
 
8237
 
 
8238
  /* The format name can contain the format id itself instead of
 
8239
  the name and we check for that. */
 
8240
  format_id = (uint) strtoul(format_name, &endp, 10);
 
8241
 
 
8242
  /* Check for valid parse. */
 
8243
  if (*endp == '\0' && *format_name != '\0') {
 
8244
 
 
8245
    if (format_id <= DICT_TF_FORMAT_MAX) {
 
8246
 
 
8247
      return(format_id);
 
8248
    }
 
8249
  } else {
 
8250
 
 
8251
    for (format_id = 0; format_id <= DICT_TF_FORMAT_MAX;
 
8252
         format_id++) {
 
8253
      const char* name;
 
8254
 
 
8255
      name = trx_sys_file_format_id_to_name(format_id);
 
8256
 
 
8257
      if (!innobase_strcasecmp(format_name, name)) {
 
8258
 
 
8259
        return(format_id);
 
8260
      }
 
8261
    }
 
8262
  }
 
8263
 
 
8264
  return(DICT_TF_FORMAT_MAX + 1);
8203
8265
}
8204
8266
 
8205
8267
/************************************************************//**
8206
8268
Validate the file format check value, is it one of "on" or "off",
8207
8269
as a side effect it sets the srv_check_file_format_at_startup variable.
8208
 
@return true if config value one of "on" or  "off" */
 
8270
@return true if config value one of "on" or  "off" */
8209
8271
static
8210
8272
bool
8211
8273
innobase_file_format_check_on_off(
8212
8274
/*==============================*/
8213
 
        const char*     format_check)   /*!< in: parameter value */
 
8275
  const char* format_check) /*!< in: parameter value */
8214
8276
{
8215
 
        bool            ret = true;
8216
 
 
8217
 
        if (!innobase_strcasecmp(format_check, "off")) {
8218
 
 
8219
 
                /* Set the value to disable checking. */
8220
 
                srv_check_file_format_at_startup = DICT_TF_FORMAT_MAX + 1;
8221
 
 
8222
 
        } else if (!innobase_strcasecmp(format_check, "on")) {
8223
 
 
8224
 
                /* Set the value to the lowest supported format. */
8225
 
                srv_check_file_format_at_startup = DICT_TF_FORMAT_51;
8226
 
        } else {
8227
 
                ret = FALSE;
8228
 
        }
8229
 
 
8230
 
        return(ret);
 
8277
  bool    ret = true;
 
8278
 
 
8279
  if (!innobase_strcasecmp(format_check, "off")) {
 
8280
 
 
8281
    /* Set the value to disable checking. */
 
8282
    srv_check_file_format_at_startup = DICT_TF_FORMAT_MAX + 1;
 
8283
 
 
8284
  } else if (!innobase_strcasecmp(format_check, "on")) {
 
8285
 
 
8286
    /* Set the value to the lowest supported format. */
 
8287
    srv_check_file_format_at_startup = DICT_TF_FORMAT_51;
 
8288
  } else {
 
8289
    ret = FALSE;
 
8290
  }
 
8291
 
 
8292
  return(ret);
8231
8293
}
8232
8294
 
8233
8295
/************************************************************//**
8234
8296
Validate the file format check config parameters, as a side effect it
8235
8297
sets the srv_check_file_format_at_startup variable.
8236
 
@return true if valid config value */
 
8298
@return true if valid config value */
8237
8299
static
8238
8300
bool
8239
8301
innobase_file_format_check_validate(
8240
8302
/*================================*/
8241
 
        const char*     format_check)   /*!< in: parameter value */
 
8303
  const char* format_check) /*!< in: parameter value */
8242
8304
{
8243
 
        uint            format_id;
8244
 
        bool            ret = true;
8245
 
 
8246
 
        format_id = innobase_file_format_name_lookup(format_check);
8247
 
 
8248
 
        if (format_id < DICT_TF_FORMAT_MAX + 1) {
8249
 
                srv_check_file_format_at_startup = format_id;
8250
 
        } else {
8251
 
                ret = false;
8252
 
        }
8253
 
 
8254
 
        return(ret);
 
8305
  uint    format_id;
 
8306
  bool    ret = true;
 
8307
 
 
8308
  format_id = innobase_file_format_name_lookup(format_check);
 
8309
 
 
8310
  if (format_id < DICT_TF_FORMAT_MAX + 1) {
 
8311
    srv_check_file_format_at_startup = format_id;
 
8312
  } else {
 
8313
    ret = false;
 
8314
  }
 
8315
 
 
8316
  return(ret);
8255
8317
}
8256
8318
 
8257
8319
/*************************************************************//**
8258
8320
Check if it is a valid file format. This function is registered as
8259
8321
a callback with MySQL.
8260
 
@return 0 for valid file format */
 
8322
@return 0 for valid file format */
8261
8323
static
8262
8324
int
8263
8325
innodb_file_format_name_validate(
8264
8326
/*=============================*/
8265
 
        Session*                        ,       /*!< in: thread handle */
8266
 
        drizzle_sys_var*        ,       /*!< in: pointer to system
8267
 
                                                variable */
8268
 
        void*                           save,   /*!< out: immediate result
8269
 
                                                for update function */
8270
 
        drizzle_value*          value)  /*!< in: incoming string */
 
8327
  Session*      , /*!< in: thread handle */
 
8328
  drizzle_sys_var*  , /*!< in: pointer to system
 
8329
            variable */
 
8330
  void*       save, /*!< out: immediate result
 
8331
            for update function */
 
8332
  drizzle_value*    value)  /*!< in: incoming string */
8271
8333
{
8272
 
        const char*     file_format_input;
8273
 
        char            buff[STRING_BUFFER_USUAL_SIZE];
8274
 
        int             len = sizeof(buff);
8275
 
 
8276
 
        ut_a(save != NULL);
8277
 
        ut_a(value != NULL);
8278
 
 
8279
 
        file_format_input = value->val_str(value, buff, &len);
8280
 
 
8281
 
        if (file_format_input != NULL) {
8282
 
                uint    format_id;
8283
 
 
8284
 
                format_id = innobase_file_format_name_lookup(
8285
 
                        file_format_input);
8286
 
 
8287
 
                if (format_id <= DICT_TF_FORMAT_MAX) {
8288
 
 
8289
 
                        *static_cast<const char**>(save) = file_format_input;
8290
 
                        return(0);
8291
 
                }
8292
 
        }
8293
 
 
8294
 
        *static_cast<const char**>(save) = NULL;
8295
 
        return(1);
 
8334
  const char* file_format_input;
 
8335
  char    buff[STRING_BUFFER_USUAL_SIZE];
 
8336
  int   len = sizeof(buff);
 
8337
 
 
8338
  ut_a(save != NULL);
 
8339
  ut_a(value != NULL);
 
8340
 
 
8341
  file_format_input = value->val_str(value, buff, &len);
 
8342
 
 
8343
  if (file_format_input != NULL) {
 
8344
    uint  format_id;
 
8345
 
 
8346
    format_id = innobase_file_format_name_lookup(
 
8347
      file_format_input);
 
8348
 
 
8349
    if (format_id <= DICT_TF_FORMAT_MAX) {
 
8350
 
 
8351
      *static_cast<const char**>(save) = file_format_input;
 
8352
      return(0);
 
8353
    }
 
8354
  }
 
8355
 
 
8356
  *static_cast<const char**>(save) = NULL;
 
8357
  return(1);
8296
8358
}
8297
8359
 
8298
8360
/****************************************************************//**
8302
8364
void
8303
8365
innodb_file_format_name_update(
8304
8366
/*===========================*/
8305
 
        Session*                        ,               /*!< in: thread handle */
8306
 
        drizzle_sys_var*        ,               /*!< in: pointer to
8307
 
                                                        system variable */
8308
 
        void*                           var_ptr,        /*!< out: where the
8309
 
                                                        formal string goes */
8310
 
        const void*                     save)           /*!< in: immediate result
8311
 
                                                        from check function */
 
8367
  Session*      ,   /*!< in: thread handle */
 
8368
  drizzle_sys_var*  ,   /*!< in: pointer to
 
8369
              system variable */
 
8370
  void*       var_ptr,  /*!< out: where the
 
8371
              formal string goes */
 
8372
  const void*     save)   /*!< in: immediate result
 
8373
              from check function */
8312
8374
{
8313
 
        const char* format_name;
8314
 
 
8315
 
        ut_a(var_ptr != NULL);
8316
 
        ut_a(save != NULL);
8317
 
 
8318
 
        format_name = *static_cast<const char*const*>(save);
8319
 
 
8320
 
        if (format_name) {
8321
 
                uint    format_id;
8322
 
 
8323
 
                format_id = innobase_file_format_name_lookup(format_name);
8324
 
 
8325
 
                if (format_id <= DICT_TF_FORMAT_MAX) {
8326
 
                        srv_file_format = format_id;
8327
 
                }
8328
 
        }
8329
 
 
8330
 
        *static_cast<const char**>(var_ptr)
8331
 
                = trx_sys_file_format_id_to_name(srv_file_format);
 
8375
  const char* format_name;
 
8376
 
 
8377
  ut_a(var_ptr != NULL);
 
8378
  ut_a(save != NULL);
 
8379
 
 
8380
  format_name = *static_cast<const char*const*>(save);
 
8381
 
 
8382
  if (format_name) {
 
8383
    uint  format_id;
 
8384
 
 
8385
    format_id = innobase_file_format_name_lookup(format_name);
 
8386
 
 
8387
    if (format_id <= DICT_TF_FORMAT_MAX) {
 
8388
      srv_file_format = format_id;
 
8389
    }
 
8390
  }
 
8391
 
 
8392
  *static_cast<const char**>(var_ptr)
 
8393
    = trx_sys_file_format_id_to_name(srv_file_format);
8332
8394
}
8333
8395
 
8334
8396
/*************************************************************//**
8335
8397
Check if valid argument to innodb_file_format_check. This
8336
8398
function is registered as a callback with MySQL.
8337
 
@return 0 for valid file format */
 
8399
@return 0 for valid file format */
8338
8400
static
8339
8401
int
8340
8402
innodb_file_format_check_validate(
8341
8403
/*==============================*/
8342
 
        Session*                        ,       /*!< in: thread handle */
8343
 
        drizzle_sys_var*        ,       /*!< in: pointer to system
8344
 
                                                variable */
8345
 
        void*                           save,   /*!< out: immediate result
8346
 
                                                for update function */
8347
 
        drizzle_value*          value)  /*!< in: incoming string */
 
8404
  Session*      , /*!< in: thread handle */
 
8405
  drizzle_sys_var*  , /*!< in: pointer to system
 
8406
            variable */
 
8407
  void*       save, /*!< out: immediate result
 
8408
            for update function */
 
8409
  drizzle_value*    value)  /*!< in: incoming string */
8348
8410
{
8349
 
        const char*     file_format_input;
8350
 
        char            buff[STRING_BUFFER_USUAL_SIZE];
8351
 
        int             len = sizeof(buff);
8352
 
 
8353
 
        ut_a(save != NULL);
8354
 
        ut_a(value != NULL);
8355
 
 
8356
 
        file_format_input = value->val_str(value, buff, &len);
8357
 
 
8358
 
        if (file_format_input != NULL) {
8359
 
 
8360
 
                /* Check if user set on/off, we want to print a suitable
8361
 
                message if they did so. */
8362
 
 
8363
 
                if (innobase_file_format_check_on_off(file_format_input)) {
8364
 
                        errmsg_printf(ERRMSG_LVL_WARN, 
8365
 
                                "InnoDB: invalid innodb_file_format_check "
8366
 
                                "value; on/off can only be set at startup or "
8367
 
                                "in the configuration file");
8368
 
                } else if (innobase_file_format_check_validate(
8369
 
                                file_format_input)) {
8370
 
 
8371
 
                        *static_cast<const char**>(save) = file_format_input;
8372
 
 
8373
 
                        return(0);
8374
 
 
8375
 
                } else {
8376
 
                        errmsg_printf(ERRMSG_LVL_WARN, 
8377
 
                                "InnoDB: invalid innodb_file_format_check "
8378
 
                                "value; can be any format up to %s "
8379
 
                                "or its equivalent numeric id",
8380
 
                                trx_sys_file_format_id_to_name(
8381
 
                                        DICT_TF_FORMAT_MAX));
8382
 
                }
8383
 
        }
8384
 
 
8385
 
        *static_cast<const char**>(save) = NULL;
8386
 
        return(1);
 
8411
  const char* file_format_input;
 
8412
  char    buff[STRING_BUFFER_USUAL_SIZE];
 
8413
  int   len = sizeof(buff);
 
8414
 
 
8415
  ut_a(save != NULL);
 
8416
  ut_a(value != NULL);
 
8417
 
 
8418
  file_format_input = value->val_str(value, buff, &len);
 
8419
 
 
8420
  if (file_format_input != NULL) {
 
8421
 
 
8422
    /* Check if user set on/off, we want to print a suitable
 
8423
    message if they did so. */
 
8424
 
 
8425
    if (innobase_file_format_check_on_off(file_format_input)) {
 
8426
      errmsg_printf(ERRMSG_LVL_WARN, 
 
8427
        "InnoDB: invalid innodb_file_format_check "
 
8428
        "value; on/off can only be set at startup or "
 
8429
        "in the configuration file");
 
8430
    } else if (innobase_file_format_check_validate(
 
8431
        file_format_input)) {
 
8432
 
 
8433
      *static_cast<const char**>(save) = file_format_input;
 
8434
 
 
8435
      return(0);
 
8436
 
 
8437
    } else {
 
8438
      errmsg_printf(ERRMSG_LVL_WARN, 
 
8439
        "InnoDB: invalid innodb_file_format_check "
 
8440
        "value; can be any format up to %s "
 
8441
        "or its equivalent numeric id",
 
8442
        trx_sys_file_format_id_to_name(
 
8443
          DICT_TF_FORMAT_MAX));
 
8444
    }
 
8445
  }
 
8446
 
 
8447
  *static_cast<const char**>(save) = NULL;
 
8448
  return(1);
8387
8449
}
8388
8450
 
8389
8451
/****************************************************************//**
8393
8455
void
8394
8456
innodb_file_format_check_update(
8395
8457
/*============================*/
8396
 
        Session*                        session,        /*!< in: thread handle */
8397
 
        drizzle_sys_var*        ,               /*!< in: pointer to
8398
 
                                                        system variable */
8399
 
        void*                           var_ptr,        /*!< out: where the
8400
 
                                                        formal string goes */
8401
 
        const void*                     save)           /*!< in: immediate result
8402
 
                                                        from check function */
 
8458
  Session*      session,  /*!< in: thread handle */
 
8459
  drizzle_sys_var*  ,   /*!< in: pointer to
 
8460
              system variable */
 
8461
  void*       var_ptr,  /*!< out: where the
 
8462
              formal string goes */
 
8463
  const void*     save)   /*!< in: immediate result
 
8464
              from check function */
8403
8465
{
8404
 
        const char*     format_name_in;
8405
 
        const char**    format_name_out;
8406
 
        uint            format_id;
8407
 
 
8408
 
        ut_a(save != NULL);
8409
 
        ut_a(var_ptr != NULL);
8410
 
 
8411
 
        format_name_in = *static_cast<const char*const*>(save);
8412
 
 
8413
 
        if (!format_name_in) {
8414
 
 
8415
 
                return;
8416
 
        }
8417
 
 
8418
 
        format_id = innobase_file_format_name_lookup(format_name_in);
8419
 
 
8420
 
        if (format_id > DICT_TF_FORMAT_MAX) {
8421
 
                /* DEFAULT is "on", which is invalid at runtime. */
8422
 
                push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
8423
 
                                    ER_WRONG_ARGUMENTS,
8424
 
                                    "Ignoring SET innodb_file_format=%s",
8425
 
                                    format_name_in);
8426
 
                return;
8427
 
        }
8428
 
 
8429
 
        format_name_out = static_cast<const char**>(var_ptr);
8430
 
 
8431
 
        /* Update the max format id in the system tablespace. */
8432
 
        if (trx_sys_file_format_max_set(format_id, format_name_out)) {
8433
 
                ut_print_timestamp(stderr);
8434
 
                fprintf(stderr,
8435
 
                        " [Info] InnoDB: the file format in the system "
8436
 
                        "tablespace is now set to %s.\n", *format_name_out);
8437
 
        }
 
8466
  const char* format_name_in;
 
8467
  const char**  format_name_out;
 
8468
  uint    format_id;
 
8469
 
 
8470
  ut_a(save != NULL);
 
8471
  ut_a(var_ptr != NULL);
 
8472
 
 
8473
  format_name_in = *static_cast<const char*const*>(save);
 
8474
 
 
8475
  if (!format_name_in) {
 
8476
 
 
8477
    return;
 
8478
  }
 
8479
 
 
8480
  format_id = innobase_file_format_name_lookup(format_name_in);
 
8481
 
 
8482
  if (format_id > DICT_TF_FORMAT_MAX) {
 
8483
    /* DEFAULT is "on", which is invalid at runtime. */
 
8484
    push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
8485
            ER_WRONG_ARGUMENTS,
 
8486
            "Ignoring SET innodb_file_format=%s",
 
8487
            format_name_in);
 
8488
    return;
 
8489
  }
 
8490
 
 
8491
  format_name_out = static_cast<const char**>(var_ptr);
 
8492
 
 
8493
  /* Update the max format id in the system tablespace. */
 
8494
  if (trx_sys_file_format_max_set(format_id, format_name_out)) {
 
8495
    ut_print_timestamp(stderr);
 
8496
    fprintf(stderr,
 
8497
      " [Info] InnoDB: the file format in the system "
 
8498
      "tablespace is now set to %s.\n", *format_name_out);
 
8499
  }
8438
8500
}
8439
8501
 
8440
8502
/****************************************************************//**
8444
8506
void
8445
8507
innodb_adaptive_hash_index_update(
8446
8508
/*==============================*/
8447
 
        Session*                        ,               /*!< in: thread handle */
8448
 
        drizzle_sys_var*        ,               /*!< in: pointer to
8449
 
                                                        system variable */
8450
 
        void*                           ,       /*!< out: where the
8451
 
                                                        formal string goes */
8452
 
        const void*                     save)           /*!< in: immediate result
8453
 
                                                        from check function */
 
8509
  Session*      ,   /*!< in: thread handle */
 
8510
  drizzle_sys_var*  ,   /*!< in: pointer to
 
8511
              system variable */
 
8512
  void*       , /*!< out: where the
 
8513
              formal string goes */
 
8514
  const void*     save)   /*!< in: immediate result
 
8515
              from check function */
8454
8516
{
8455
 
        if (*(bool*) save) {
8456
 
                btr_search_enable();
8457
 
        } else {
8458
 
                btr_search_disable();
8459
 
        }
 
8517
  if (*(bool*) save) {
 
8518
    btr_search_enable();
 
8519
  } else {
 
8520
    btr_search_disable();
 
8521
  }
8460
8522
}
8461
8523
 
8462
8524
/*************************************************************//**
8463
8525
Check if it is a valid value of innodb_change_buffering.  This function is
8464
8526
registered as a callback with MySQL.
8465
 
@return 0 for valid innodb_change_buffering */
 
8527
@return 0 for valid innodb_change_buffering */
8466
8528
static
8467
8529
int
8468
8530
innodb_change_buffering_validate(
8469
8531
/*=============================*/
8470
 
        Session*                        ,       /*!< in: thread handle */
8471
 
        drizzle_sys_var*        ,       /*!< in: pointer to system
8472
 
                                                variable */
8473
 
        void*                           save,   /*!< out: immediate result
8474
 
                                                for update function */
8475
 
        drizzle_value*          value)  /*!< in: incoming string */
 
8532
  Session*      , /*!< in: thread handle */
 
8533
  drizzle_sys_var*  , /*!< in: pointer to system
 
8534
            variable */
 
8535
  void*       save, /*!< out: immediate result
 
8536
            for update function */
 
8537
  drizzle_value*    value)  /*!< in: incoming string */
8476
8538
{
8477
 
        const char*     change_buffering_input;
8478
 
        char            buff[STRING_BUFFER_USUAL_SIZE];
8479
 
        int             len = sizeof(buff);
8480
 
 
8481
 
        ut_a(save != NULL);
8482
 
        ut_a(value != NULL);
8483
 
 
8484
 
        change_buffering_input = value->val_str(value, buff, &len);
8485
 
 
8486
 
        if (change_buffering_input != NULL) {
8487
 
                ulint   use;
8488
 
 
8489
 
                for (use = 0; use < UT_ARR_SIZE(innobase_change_buffering_values);
8490
 
                     use++) {
8491
 
                        if (!innobase_strcasecmp(
8492
 
                                    change_buffering_input,
8493
 
                                    innobase_change_buffering_values[use])) {
8494
 
                                *(ibuf_use_t*) save = (ibuf_use_t) use;
8495
 
                                return(0);
8496
 
                        }
8497
 
                }
8498
 
        }
8499
 
 
8500
 
        return(1);
 
8539
  const char* change_buffering_input;
 
8540
  char    buff[STRING_BUFFER_USUAL_SIZE];
 
8541
  int   len = sizeof(buff);
 
8542
 
 
8543
  ut_a(save != NULL);
 
8544
  ut_a(value != NULL);
 
8545
 
 
8546
  change_buffering_input = value->val_str(value, buff, &len);
 
8547
 
 
8548
  if (change_buffering_input != NULL) {
 
8549
    ulint use;
 
8550
 
 
8551
    for (use = 0; use < UT_ARR_SIZE(innobase_change_buffering_values);
 
8552
         use++) {
 
8553
      if (!innobase_strcasecmp(
 
8554
            change_buffering_input,
 
8555
            innobase_change_buffering_values[use])) {
 
8556
        *(ibuf_use_t*) save = (ibuf_use_t) use;
 
8557
        return(0);
 
8558
      }
 
8559
    }
 
8560
  }
 
8561
 
 
8562
  return(1);
8501
8563
}
8502
8564
 
8503
8565
/****************************************************************//**
8507
8569
void
8508
8570
innodb_change_buffering_update(
8509
8571
/*===========================*/
8510
 
        Session*                        ,               /*!< in: thread handle */
8511
 
        drizzle_sys_var*        ,               /*!< in: pointer to
8512
 
                                                        system variable */
8513
 
        void*                           var_ptr,        /*!< out: where the
8514
 
                                                        formal string goes */
8515
 
        const void*                     save)           /*!< in: immediate result
8516
 
                                                        from check function */
 
8572
  Session*      ,   /*!< in: thread handle */
 
8573
  drizzle_sys_var*  ,   /*!< in: pointer to
 
8574
              system variable */
 
8575
  void*       var_ptr,  /*!< out: where the
 
8576
              formal string goes */
 
8577
  const void*     save)   /*!< in: immediate result
 
8578
              from check function */
8517
8579
{
8518
 
        ut_a(var_ptr != NULL);
8519
 
        ut_a(save != NULL);
8520
 
        ut_a((*(ibuf_use_t*) save) < IBUF_USE_COUNT);
8521
 
 
8522
 
        ibuf_use = *(const ibuf_use_t*) save;
8523
 
 
8524
 
        *(const char**) var_ptr = innobase_change_buffering_values[ibuf_use];
 
8580
  ut_a(var_ptr != NULL);
 
8581
  ut_a(save != NULL);
 
8582
  ut_a((*(ibuf_use_t*) save) < IBUF_USE_COUNT);
 
8583
 
 
8584
  ibuf_use = *(const ibuf_use_t*) save;
 
8585
 
 
8586
  *(const char**) var_ptr = innobase_change_buffering_values[ibuf_use];
8525
8587
}
8526
8588
 
8527
8589
/* plugin options */
8584
8646
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
8585
8647
  "With which method to flush data.", NULL, NULL, NULL);
8586
8648
 
8587
 
static DRIZZLE_SYSVAR_BOOL(locks_unsafe_for_binlog, innobase_locks_unsafe_for_binlog,
8588
 
  PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
8589
 
  "Force InnoDB to not use next-key locking, to use only row-level locking.",
8590
 
  NULL, NULL, TRUE);
8591
 
 
8592
8649
#ifdef UNIV_LOG_ARCHIVE
8593
8650
static DRIZZLE_SYSVAR_STR(log_arch_dir, innobase_log_arch_dir,
8594
8651
  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
8753
8810
  "1 => New style AUTOINC locking                            "
8754
8811
  "2 => No AUTOINC locking (unsafe for SBR)",
8755
8812
  NULL, NULL,
8756
 
  AUTOINC_NO_LOCKING,   /* Default setting */
8757
 
  AUTOINC_OLD_STYLE_LOCKING,    /* Minimum value */
8758
 
  AUTOINC_NO_LOCKING, 0);       /* Maximum value */
 
8813
  AUTOINC_NO_LOCKING, /* Default setting */
 
8814
  AUTOINC_OLD_STYLE_LOCKING,  /* Minimum value */
 
8815
  AUTOINC_NO_LOCKING, 0); /* Maximum value */
8759
8816
 
8760
8817
static DRIZZLE_SYSVAR_STR(version, innodb_version_str,
8761
8818
  PLUGIN_VAR_NOCMDOPT | PLUGIN_VAR_READONLY,
8799
8856
  DRIZZLE_SYSVAR(flush_log_at_trx_commit),
8800
8857
  DRIZZLE_SYSVAR(flush_method),
8801
8858
  DRIZZLE_SYSVAR(force_recovery),
8802
 
  DRIZZLE_SYSVAR(locks_unsafe_for_binlog),
8803
8859
  DRIZZLE_SYSVAR(lock_wait_timeout),
8804
8860
#ifdef UNIV_LOG_ARCHIVE
8805
8861
  DRIZZLE_SYSVAR(log_arch_dir),
8845
8901
  "Supports transactions, row-level locking, and foreign keys",
8846
8902
  PLUGIN_LICENSE_GPL,
8847
8903
  innobase_init, /* Plugin Init */
8848
 
  innobase_deinit, /* Plugin Deinit */
8849
8904
  innobase_system_variables, /* system variables */
8850
8905
  NULL /* reserved */
8851
8906
}
8852
8907
DRIZZLE_DECLARE_PLUGIN_END;
8853
8908
 
8854
8909
int ha_innobase::read_range_first(const key_range *start_key,
8855
 
                                  const key_range *end_key,
8856
 
                                  bool eq_range_arg,
8857
 
                                  bool sorted)
 
8910
          const key_range *end_key,
 
8911
          bool eq_range_arg,
 
8912
          bool sorted)
8858
8913
{
8859
8914
  int res;
8860
8915
  //if (!eq_range_arg)
8888
8943
innobase_commit_concurrency_init_default(void)
8889
8944
/*==========================================*/
8890
8945
{
8891
 
        DRIZZLE_SYSVAR_NAME(commit_concurrency).def_val
8892
 
                = innobase_commit_concurrency;
 
8946
  DRIZZLE_SYSVAR_NAME(commit_concurrency).def_val
 
8947
    = innobase_commit_concurrency;
8893
8948
}
8894
8949
 
8895
8950
#ifdef UNIV_COMPILE_TEST_FUNCS
8896
8951
 
8897
8952
typedef struct innobase_convert_name_test_struct {
8898
 
        char*           buf;
8899
 
        ulint           buflen;
8900
 
        const char*     id;
8901
 
        ulint           idlen;
8902
 
        void*           session;
8903
 
        ibool           file_id;
 
8953
  char*   buf;
 
8954
  ulint   buflen;
 
8955
  const char* id;
 
8956
  ulint   idlen;
 
8957
  void*   session;
 
8958
  ibool   file_id;
8904
8959
 
8905
 
        const char*     expected;
 
8960
  const char* expected;
8906
8961
} innobase_convert_name_test_t;
8907
8962
 
8908
8963
void
8909
8964
test_innobase_convert_name()
8910
8965
{
8911
 
        char    buf[1024];
8912
 
        ulint   i;
8913
 
 
8914
 
        innobase_convert_name_test_t test_input[] = {
8915
 
                {buf, sizeof(buf), "abcd", 4, NULL, TRUE, "\"abcd\""},
8916
 
                {buf, 7, "abcd", 4, NULL, TRUE, "\"abcd\""},
8917
 
                {buf, 6, "abcd", 4, NULL, TRUE, "\"abcd\""},
8918
 
                {buf, 5, "abcd", 4, NULL, TRUE, "\"abc\""},
8919
 
                {buf, 4, "abcd", 4, NULL, TRUE, "\"ab\""},
8920
 
 
8921
 
                {buf, sizeof(buf), "ab@0060cd", 9, NULL, TRUE, "\"ab`cd\""},
8922
 
                {buf, 9, "ab@0060cd", 9, NULL, TRUE, "\"ab`cd\""},
8923
 
                {buf, 8, "ab@0060cd", 9, NULL, TRUE, "\"ab`cd\""},
8924
 
                {buf, 7, "ab@0060cd", 9, NULL, TRUE, "\"ab`cd\""},
8925
 
                {buf, 6, "ab@0060cd", 9, NULL, TRUE, "\"ab`c\""},
8926
 
                {buf, 5, "ab@0060cd", 9, NULL, TRUE, "\"ab`\""},
8927
 
                {buf, 4, "ab@0060cd", 9, NULL, TRUE, "\"ab\""},
8928
 
 
8929
 
                {buf, sizeof(buf), "ab\"cd", 5, NULL, TRUE,
8930
 
                        "\"#mysql50#ab\"\"cd\""},
8931
 
                {buf, 17, "ab\"cd", 5, NULL, TRUE,
8932
 
                        "\"#mysql50#ab\"\"cd\""},
8933
 
                {buf, 16, "ab\"cd", 5, NULL, TRUE,
8934
 
                        "\"#mysql50#ab\"\"c\""},
8935
 
                {buf, 15, "ab\"cd", 5, NULL, TRUE,
8936
 
                        "\"#mysql50#ab\"\"\""},
8937
 
                {buf, 14, "ab\"cd", 5, NULL, TRUE,
8938
 
                        "\"#mysql50#ab\""},
8939
 
                {buf, 13, "ab\"cd", 5, NULL, TRUE,
8940
 
                        "\"#mysql50#ab\""},
8941
 
                {buf, 12, "ab\"cd", 5, NULL, TRUE,
8942
 
                        "\"#mysql50#a\""},
8943
 
                {buf, 11, "ab\"cd", 5, NULL, TRUE,
8944
 
                        "\"#mysql50#\""},
8945
 
                {buf, 10, "ab\"cd", 5, NULL, TRUE,
8946
 
                        "\"#mysql50\""},
8947
 
 
8948
 
                {buf, sizeof(buf), "ab/cd", 5, NULL, TRUE, "\"ab\".\"cd\""},
8949
 
                {buf, 9, "ab/cd", 5, NULL, TRUE, "\"ab\".\"cd\""},
8950
 
                {buf, 8, "ab/cd", 5, NULL, TRUE, "\"ab\".\"c\""},
8951
 
                {buf, 7, "ab/cd", 5, NULL, TRUE, "\"ab\".\"\""},
8952
 
                {buf, 6, "ab/cd", 5, NULL, TRUE, "\"ab\"."},
8953
 
                {buf, 5, "ab/cd", 5, NULL, TRUE, "\"ab\"."},
8954
 
                {buf, 4, "ab/cd", 5, NULL, TRUE, "\"ab\""},
8955
 
                {buf, 3, "ab/cd", 5, NULL, TRUE, "\"a\""},
8956
 
                {buf, 2, "ab/cd", 5, NULL, TRUE, "\"\""},
8957
 
                /* XXX probably "" is a better result in this case
8958
 
                {buf, 1, "ab/cd", 5, NULL, TRUE, "."},
8959
 
                */
8960
 
                {buf, 0, "ab/cd", 5, NULL, TRUE, ""},
8961
 
        };
8962
 
 
8963
 
        for (i = 0; i < sizeof(test_input) / sizeof(test_input[0]); i++) {
8964
 
 
8965
 
                char*   end;
8966
 
                ibool   ok = TRUE;
8967
 
                size_t  res_len;
8968
 
 
8969
 
                fprintf(stderr, "TESTING %lu, %s, %lu, %s\n",
8970
 
                        test_input[i].buflen,
8971
 
                        test_input[i].id,
8972
 
                        test_input[i].idlen,
8973
 
                        test_input[i].expected);
8974
 
 
8975
 
                end = innobase_convert_name(
8976
 
                        test_input[i].buf,
8977
 
                        test_input[i].buflen,
8978
 
                        test_input[i].id,
8979
 
                        test_input[i].idlen,
8980
 
                        test_input[i].session,
8981
 
                        test_input[i].file_id);
8982
 
 
8983
 
                res_len = (size_t) (end - test_input[i].buf);
8984
 
 
8985
 
                if (res_len != strlen(test_input[i].expected)) {
8986
 
 
8987
 
                        fprintf(stderr, "unexpected len of the result: %u, "
8988
 
                                "expected: %u\n", (unsigned) res_len,
8989
 
                                (unsigned) strlen(test_input[i].expected));
8990
 
                        ok = FALSE;
8991
 
                }
8992
 
 
8993
 
                if (memcmp(test_input[i].buf,
8994
 
                           test_input[i].expected,
8995
 
                           strlen(test_input[i].expected)) != 0
8996
 
                    || !ok) {
8997
 
 
8998
 
                        fprintf(stderr, "unexpected result: %.*s, "
8999
 
                                "expected: %s\n", (int) res_len,
9000
 
                                test_input[i].buf,
9001
 
                                test_input[i].expected);
9002
 
                        ok = FALSE;
9003
 
                }
9004
 
 
9005
 
                if (ok) {
9006
 
                        fprintf(stderr, "OK: res: %.*s\n\n", (int) res_len,
9007
 
                                buf);
9008
 
                } else {
9009
 
                        fprintf(stderr, "FAILED\n\n");
9010
 
                        return;
9011
 
                }
9012
 
        }
 
8966
  char  buf[1024];
 
8967
  ulint i;
 
8968
 
 
8969
  innobase_convert_name_test_t test_input[] = {
 
8970
    {buf, sizeof(buf), "abcd", 4, NULL, TRUE, "\"abcd\""},
 
8971
    {buf, 7, "abcd", 4, NULL, TRUE, "\"abcd\""},
 
8972
    {buf, 6, "abcd", 4, NULL, TRUE, "\"abcd\""},
 
8973
    {buf, 5, "abcd", 4, NULL, TRUE, "\"abc\""},
 
8974
    {buf, 4, "abcd", 4, NULL, TRUE, "\"ab\""},
 
8975
 
 
8976
    {buf, sizeof(buf), "ab@0060cd", 9, NULL, TRUE, "\"ab`cd\""},
 
8977
    {buf, 9, "ab@0060cd", 9, NULL, TRUE, "\"ab`cd\""},
 
8978
    {buf, 8, "ab@0060cd", 9, NULL, TRUE, "\"ab`cd\""},
 
8979
    {buf, 7, "ab@0060cd", 9, NULL, TRUE, "\"ab`cd\""},
 
8980
    {buf, 6, "ab@0060cd", 9, NULL, TRUE, "\"ab`c\""},
 
8981
    {buf, 5, "ab@0060cd", 9, NULL, TRUE, "\"ab`\""},
 
8982
    {buf, 4, "ab@0060cd", 9, NULL, TRUE, "\"ab\""},
 
8983
 
 
8984
    {buf, sizeof(buf), "ab\"cd", 5, NULL, TRUE,
 
8985
      "\"#mysql50#ab\"\"cd\""},
 
8986
    {buf, 17, "ab\"cd", 5, NULL, TRUE,
 
8987
      "\"#mysql50#ab\"\"cd\""},
 
8988
    {buf, 16, "ab\"cd", 5, NULL, TRUE,
 
8989
      "\"#mysql50#ab\"\"c\""},
 
8990
    {buf, 15, "ab\"cd", 5, NULL, TRUE,
 
8991
      "\"#mysql50#ab\"\"\""},
 
8992
    {buf, 14, "ab\"cd", 5, NULL, TRUE,
 
8993
      "\"#mysql50#ab\""},
 
8994
    {buf, 13, "ab\"cd", 5, NULL, TRUE,
 
8995
      "\"#mysql50#ab\""},
 
8996
    {buf, 12, "ab\"cd", 5, NULL, TRUE,
 
8997
      "\"#mysql50#a\""},
 
8998
    {buf, 11, "ab\"cd", 5, NULL, TRUE,
 
8999
      "\"#mysql50#\""},
 
9000
    {buf, 10, "ab\"cd", 5, NULL, TRUE,
 
9001
      "\"#mysql50\""},
 
9002
 
 
9003
    {buf, sizeof(buf), "ab/cd", 5, NULL, TRUE, "\"ab\".\"cd\""},
 
9004
    {buf, 9, "ab/cd", 5, NULL, TRUE, "\"ab\".\"cd\""},
 
9005
    {buf, 8, "ab/cd", 5, NULL, TRUE, "\"ab\".\"c\""},
 
9006
    {buf, 7, "ab/cd", 5, NULL, TRUE, "\"ab\".\"\""},
 
9007
    {buf, 6, "ab/cd", 5, NULL, TRUE, "\"ab\"."},
 
9008
    {buf, 5, "ab/cd", 5, NULL, TRUE, "\"ab\"."},
 
9009
    {buf, 4, "ab/cd", 5, NULL, TRUE, "\"ab\""},
 
9010
    {buf, 3, "ab/cd", 5, NULL, TRUE, "\"a\""},
 
9011
    {buf, 2, "ab/cd", 5, NULL, TRUE, "\"\""},
 
9012
    /* XXX probably "" is a better result in this case
 
9013
    {buf, 1, "ab/cd", 5, NULL, TRUE, "."},
 
9014
    */
 
9015
    {buf, 0, "ab/cd", 5, NULL, TRUE, ""},
 
9016
  };
 
9017
 
 
9018
  for (i = 0; i < sizeof(test_input) / sizeof(test_input[0]); i++) {
 
9019
 
 
9020
    char* end;
 
9021
    ibool ok = TRUE;
 
9022
    size_t  res_len;
 
9023
 
 
9024
    fprintf(stderr, "TESTING %lu, %s, %lu, %s\n",
 
9025
      test_input[i].buflen,
 
9026
      test_input[i].id,
 
9027
      test_input[i].idlen,
 
9028
      test_input[i].expected);
 
9029
 
 
9030
    end = innobase_convert_name(
 
9031
      test_input[i].buf,
 
9032
      test_input[i].buflen,
 
9033
      test_input[i].id,
 
9034
      test_input[i].idlen,
 
9035
      test_input[i].session,
 
9036
      test_input[i].file_id);
 
9037
 
 
9038
    res_len = (size_t) (end - test_input[i].buf);
 
9039
 
 
9040
    if (res_len != strlen(test_input[i].expected)) {
 
9041
 
 
9042
      fprintf(stderr, "unexpected len of the result: %u, "
 
9043
        "expected: %u\n", (unsigned) res_len,
 
9044
        (unsigned) strlen(test_input[i].expected));
 
9045
      ok = FALSE;
 
9046
    }
 
9047
 
 
9048
    if (memcmp(test_input[i].buf,
 
9049
         test_input[i].expected,
 
9050
         strlen(test_input[i].expected)) != 0
 
9051
        || !ok) {
 
9052
 
 
9053
      fprintf(stderr, "unexpected result: %.*s, "
 
9054
        "expected: %s\n", (int) res_len,
 
9055
        test_input[i].buf,
 
9056
        test_input[i].expected);
 
9057
      ok = FALSE;
 
9058
    }
 
9059
 
 
9060
    if (ok) {
 
9061
      fprintf(stderr, "OK: res: %.*s\n\n", (int) res_len,
 
9062
        buf);
 
9063
    } else {
 
9064
      fprintf(stderr, "FAILED\n\n");
 
9065
      return;
 
9066
    }
 
9067
  }
9013
9068
}
9014
9069
 
9015
9070
#endif /* UNIV_COMPILE_TEST_FUNCS */