~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-03-15 14:05:26 UTC
  • mfrom: (1237.9.99 staging)
  • Revision ID: osullivan.padraig@gmail.com-20100315140526-opbgwdwn6tfecdkq
MergeĀ fromĀ trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
50
50
***********************************************************************/
51
51
 
52
52
/* TODO list for the InnoDB Cursor in 5.0:
53
 
  - Remove the flag trx->active_trans and look at trx->conc_state
54
53
  - fix savepoint functions to use savepoint storage area
55
54
  - Find out what kind of problems the OS X case-insensitivity causes to
56
55
    table and database names; should we 'normalize' the names like we do
80
79
#include "drizzled/field/blob.h"
81
80
#include "drizzled/field/varstring.h"
82
81
#include "drizzled/field/timestamp.h"
83
 
#include "drizzled/plugin/storage_engine.h"
84
 
#include "drizzled/plugin/info_schema_table.h"
 
82
#include "drizzled/plugin/xa_storage_engine.h"
85
83
#include "drizzled/memory/multi_malloc.h"
86
84
#include "drizzled/pthread_globals.h"
87
85
#include "drizzled/named_savepoint.h"
124
122
}
125
123
 
126
124
#include "ha_innodb.h"
127
 
#include "i_s.h"
 
125
#include "data_dictionary.h"
128
126
#include "handler0vars.h"
129
127
 
 
128
#include <iostream>
 
129
#include <sstream>
130
130
#include <string>
131
131
 
 
132
#include "plugin/innobase/handler/status_function.h"
 
133
 
132
134
using namespace std;
133
135
using namespace drizzled;
134
136
 
161
163
# define EQ_CURRENT_SESSION(session) ((session) == current_session)
162
164
#endif /* MYSQL_DYNAMIC_PLUGIN && __WIN__ */
163
165
 
164
 
static plugin::StorageEngine* innodb_engine_ptr= NULL;
 
166
static plugin::XaStorageEngine* innodb_engine_ptr= NULL;
 
167
static plugin::TableFunction* status_table_function_ptr= NULL;
 
168
static plugin::TableFunction* cmp_tool= NULL;
 
169
static plugin::TableFunction* cmp_reset_tool= NULL;
 
170
static plugin::TableFunction* cmp_mem_tool= NULL;
 
171
static plugin::TableFunction* cmp_mem_reset_tool= NULL;
 
172
static plugin::TableFunction* innodb_trx_tool= NULL;
 
173
static plugin::TableFunction* innodb_locks_tool= NULL;
 
174
static plugin::TableFunction* innodb_lock_waits_tool= NULL;
165
175
 
166
176
static const long AUTOINC_OLD_STYLE_LOCKING = 0;
167
177
static const long AUTOINC_NEW_STYLE_LOCKING = 1;
248
258
static INNOBASE_SHARE *get_share(const char *table_name);
249
259
static void free_share(INNOBASE_SHARE *share);
250
260
 
251
 
class InnobaseEngine : public plugin::StorageEngine
 
261
class InnobaseEngine : public plugin::XaStorageEngine
252
262
{
253
263
public:
254
264
  InnobaseEngine(string name_arg) :
255
 
    plugin::StorageEngine(name_arg,
 
265
    plugin::XaStorageEngine(name_arg,
256
266
                          HTON_NULL_IN_KEY |
257
267
                          HTON_CAN_INDEX_BLOBS |
258
268
                          HTON_PRIMARY_KEY_REQUIRED_FOR_POSITION |
264
274
    table_definition_ext= plugin::DEFAULT_DEFINITION_FILE_EXT;
265
275
    addAlias("INNOBASE");
266
276
  }
267
 
 
 
277
private:
 
278
  virtual int doStartTransaction(Session *session, start_transaction_option_t options);
 
279
  virtual void doStartStatement(Session *session);
 
280
  virtual void doEndStatement(Session *session);
 
281
public:
268
282
  virtual
269
283
  int
270
284
  close_connection(
273
287
        Session*        session);       /* in: handle to the MySQL thread of the user
274
288
                        whose resources should be free'd */
275
289
 
276
 
  virtual int savepoint_set_hook(Session* session,
 
290
  virtual int doSetSavepoint(Session* session,
277
291
                                 drizzled::NamedSavepoint &savepoint);
278
 
  virtual int savepoint_rollback_hook(Session* session,
279
 
                                     drizzled::NamedSavepoint &savepoint);
280
 
  virtual int savepoint_release_hook(Session* session,
281
 
                                     drizzled::NamedSavepoint &savepoint);
282
 
  virtual int commit(Session* session, bool all);
283
 
  virtual int rollback(Session* session, bool all);
 
292
  virtual int doRollbackToSavepoint(Session* session,
 
293
                                     drizzled::NamedSavepoint &savepoint);
 
294
  virtual int doReleaseSavepoint(Session* session,
 
295
                                     drizzled::NamedSavepoint &savepoint);
 
296
  virtual int doXaCommit(Session* session, bool all)
 
297
  {
 
298
    return doCommit(session, all); /* XA commit just does a SQL COMMIT */
 
299
  }
 
300
  virtual int doXaRollback(Session *session, bool all)
 
301
  {
 
302
    return doRollback(session, all); /* XA rollback just does a SQL ROLLBACK */
 
303
  }
 
304
  virtual int doCommit(Session* session, bool all);
 
305
  virtual int doRollback(Session* session, bool all);
284
306
 
285
307
  /***********************************************************************
286
308
  This function is used to prepare X/Open XA distributed transaction   */
287
309
  virtual
288
310
  int
289
 
  prepare(
 
311
  doXaPrepare(
290
312
  /*================*/
291
313
                        /* out: 0 or error number */
292
314
        Session*        session,        /* in: handle to the MySQL thread of the user
297
319
  This function is used to recover X/Open XA distributed transactions   */
298
320
  virtual
299
321
  int
300
 
  recover(
 
322
  doXaRecover(
301
323
  /*================*/
302
324
                                /* out: number of prepared transactions
303
325
                                stored in xid_list */
304
326
        ::drizzled::XID*        xid_list,       /* in/out: prepared transactions */
305
 
        uint    len);           /* in: number of slots in xid_list */
 
327
        size_t len);            /* in: number of slots in xid_list */
306
328
  /***********************************************************************
307
329
  This function is used to commit one X/Open XA distributed transaction
308
330
  which is in the prepared state */
309
331
  virtual
310
332
  int
311
 
  commit_by_xid(
 
333
  doXaCommitXid(
312
334
  /*===================*/
313
335
                        /* out: 0 or error number */
314
336
        ::drizzled::XID*        xid);   /* in: X/Open XA transaction identification */
317
339
  which is in the prepared state */
318
340
  virtual
319
341
  int
320
 
  rollback_by_xid(
 
342
  doXaRollbackXid(
321
343
  /*=====================*/
322
344
                        /* out: 0 or error number */
323
345
        ::drizzled::XID *xid);  /* in: X/Open XA transaction identification */
330
352
 
331
353
  /*********************************************************************
332
354
  Removes all tables in the named database inside InnoDB. */
333
 
  virtual
334
 
  void
335
 
  drop_database(
 
355
  bool
 
356
  doDropSchema(
336
357
  /*===================*/
337
358
                        /* out: error number */
338
 
        char*   path);  /* in: database path; inside InnoDB the name
 
359
        const std::string       &schema_name);  /* in: database path; inside InnoDB the name
339
360
                        of the last directory in the path is used as
340
361
                        the database name: for example, in 'mysql/data/test'
341
362
                        the database name is 'test' */
342
363
 
343
 
  /*********************************************************************
344
 
  Creates an InnoDB transaction struct for the session if it does not yet have one.
345
 
  Starts a new InnoDB transaction if a transaction is not yet started. And
346
 
  assigns a new snapshot for a consistent read if the transaction does not yet
347
 
  have one. */
348
 
  virtual
349
 
  int
350
 
  start_consistent_snapshot(
351
 
  /*====================================*/
352
 
                        /* out: 0 */
353
 
        Session*        session);       /* in: MySQL thread handle of the user for whom
354
 
                        the transaction should be committed */
355
364
  /********************************************************************
356
365
  Flushes InnoDB logs to disk and makes a checkpoint. Really, a commit flushes
357
366
  the logs, and the name of this function should be innobase_checkpoint. */
374
383
 
375
384
  virtual
376
385
  int
377
 
  release_temporary_latches(
 
386
  doReleaseTemporaryLatches(
378
387
  /*===============================*/
379
388
                                /* out: 0 */
380
389
        Session*                session);       /* in: MySQL thread */
391
400
  UNIV_INTERN int doRenameTable(Session* session,
392
401
                                const char* from,
393
402
                                const char* to);
394
 
  UNIV_INTERN int doDropTable(Session& session, const string table_path);
 
403
  UNIV_INTERN int doDropTable(Session& session, const string &table_path);
395
404
 
396
405
  UNIV_INTERN virtual bool get_error_message(int error, String *buf);
397
406
 
517
526
/*================*/
518
527
        trx_t*  trx);   /*!< in: transaction handle */
519
528
 
520
 
static SHOW_VAR innodb_status_variables[]= {
 
529
static drizzle_show_var innodb_status_variables[]= {
521
530
  {"buffer_pool_pages_data",
522
531
  (char*) &export_vars.innodb_buffer_pool_pages_data,     SHOW_LONG},
523
532
  {"buffer_pool_pages_dirty",
611
620
  {NULL, NULL, SHOW_LONG}
612
621
};
613
622
 
 
623
InnodbStatusTool::Generator::Generator(drizzled::Field **fields) :
 
624
  plugin::TableFunction::Generator(fields)
 
625
 
626
  srv_export_innodb_status();
 
627
  status_var_ptr= innodb_status_variables;
 
628
}
 
629
 
 
630
bool InnodbStatusTool::Generator::populate()
 
631
{
 
632
  if (status_var_ptr->name)
 
633
  {
 
634
    std::ostringstream oss;
 
635
    string return_value;
 
636
    const char *value= status_var_ptr->value;
 
637
 
 
638
    /* VARIABLE_NAME */
 
639
    push(status_var_ptr->name);
 
640
 
 
641
    switch (status_var_ptr->type)
 
642
    {
 
643
    case SHOW_LONG:
 
644
      oss << *(int64_t*) value;
 
645
      return_value= oss.str();
 
646
      break;
 
647
    case SHOW_LONGLONG:
 
648
      oss << *(int64_t*) value;
 
649
      return_value= oss.str();
 
650
      break;
 
651
    case SHOW_BOOL:
 
652
      return_value= *(bool*) value ? "ON" : "OFF";
 
653
      break;
 
654
    default:
 
655
      assert(0);
 
656
    }
 
657
 
 
658
    /* VARIABLE_VALUE */
 
659
    if (return_value.length())
 
660
      push(return_value);
 
661
    else 
 
662
      push(" ");
 
663
 
 
664
    status_var_ptr++;
 
665
 
 
666
    return true;
 
667
  }
 
668
  return false;
 
669
}
 
670
 
614
671
/* General functions */
615
672
 
616
673
/******************************************************************//**
765
822
documentation, see Cursor.cc.
766
823
@return 0 */
767
824
int
768
 
InnobaseEngine::release_temporary_latches(
 
825
InnobaseEngine::doReleaseTemporaryLatches(
769
826
/*===============================*/
770
827
        Session*                session)        /*!< in: MySQL thread */
771
828
{
981
1038
          session->getSecurityContext().getUser().c_str()
982
1039
  );
983
1040
  fprintf(f,
984
 
          "\n%s", session->getQueryString()
 
1041
          "\n%s", session->getQueryString().c_str()
985
1042
  );
986
1043
        putc('\n', f);
987
1044
}
1358
1415
        trx = trx_allocate_for_mysql();
1359
1416
 
1360
1417
        trx->mysql_thd = session;
1361
 
        trx->mysql_query_str = session_query(session);
 
1418
        trx->mysql_query_str = session->query.c_str();
1362
1419
 
1363
1420
        innobase_trx_init(session, trx);
1364
1421
 
1450
1507
        update_session(session);
1451
1508
}
1452
1509
 
1453
 
/*********************************************************************//**
1454
 
Registers that InnoDB takes part in an SQL statement, so that MySQL knows to
1455
 
roll back the statement if the statement results in an error. This MUST be
1456
 
called for every SQL statement that may be rolled back by MySQL. Calling this
1457
 
several times to register the same statement is allowed, too. */
1458
 
static inline
1459
 
void
1460
 
innobase_register_stmt(
1461
 
/*===================*/
1462
 
        plugin::StorageEngine*  engine, /*!< in: Innobase hton */
1463
 
        Session*        session)        /*!< in: MySQL thd (connection) object */
1464
 
{
1465
 
        assert(engine == innodb_engine_ptr);
1466
 
        /* Register the statement */
1467
 
  TransactionServices &transaction_services= TransactionServices::singleton();
1468
 
        transaction_services.trans_register_ha(session, FALSE, engine);
1469
 
}
1470
 
 
1471
 
/*********************************************************************//**
1472
 
Registers an InnoDB transaction in MySQL, so that the MySQL XA code knows
1473
 
to call the InnoDB prepare and commit, or rollback for the transaction. This
1474
 
MUST be called for every transaction for which the user may call commit or
1475
 
rollback. Calling this several times to register the same transaction is
1476
 
allowed, too.
1477
 
This function also registers the current SQL statement. */
1478
 
static inline
1479
 
void
1480
 
innobase_register_trx_and_stmt(
1481
 
/*===========================*/
1482
 
        plugin::StorageEngine *engine, /*!< in: Innobase StorageEngine */
1483
 
        Session*        session)        /*!< in: MySQL thd (connection) object */
1484
 
{
1485
 
        /* NOTE that actually innobase_register_stmt() registers also
1486
 
        the transaction in the AUTOCOMMIT=1 mode. */
1487
 
 
1488
 
        innobase_register_stmt(engine, session);
1489
 
 
1490
 
        if (session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
1491
 
 
1492
 
                /* No autocommit mode, register for a transaction */
1493
 
    TransactionServices &transaction_services= TransactionServices::singleton();
1494
 
    transaction_services.trans_register_ha(session, TRUE, engine);
1495
 
        }
1496
 
}
1497
 
 
1498
1510
/*****************************************************************//**
1499
1511
Convert an SQL identifier to the MySQL system_charset_info (UTF-8)
1500
1512
and quote it if needed.
1662
1674
        prebuilt->read_just_key = 0;
1663
1675
}
1664
1676
 
1665
 
/*****************************************************************//**
1666
 
Call this when you have opened a new table handle in HANDLER, before you
1667
 
call index_read_idx() etc. Actually, we can let the cursor stay open even
1668
 
over a transaction commit! Then you should call this before every operation,
1669
 
fetch next etc. This function inits the necessary things even after a
1670
 
transaction commit. */
1671
 
UNIV_INTERN
1672
 
void
1673
 
ha_innobase::init_table_handle_for_HANDLER(void)
1674
 
/*============================================*/
1675
 
{
1676
 
        /* If current session does not yet have a trx struct, create one.
1677
 
        If the current handle does not yet have a prebuilt struct, create
1678
 
        one. Update the trx pointers in the prebuilt struct. Normally
1679
 
        this operation is done in external_lock. */
1680
 
 
1681
 
        update_session(ha_session());
1682
 
 
1683
 
        /* Initialize the prebuilt struct much like it would be inited in
1684
 
        external_lock */
1685
 
 
1686
 
        innobase_release_stat_resources(prebuilt->trx);
1687
 
 
1688
 
        /* If the transaction is not started yet, start it */
1689
 
 
1690
 
        trx_start_if_not_started(prebuilt->trx);
1691
 
 
1692
 
        /* Assign a read view if the transaction does not have it yet */
1693
 
 
1694
 
        trx_assign_read_view(prebuilt->trx);
1695
 
 
1696
 
        /* Set the MySQL flag to mark that there is an active transaction */
1697
 
 
1698
 
        if (prebuilt->trx->active_trans == 0) {
1699
 
 
1700
 
                innobase_register_trx_and_stmt(engine, user_session);
1701
 
 
1702
 
                prebuilt->trx->active_trans = 1;
1703
 
        }
1704
 
 
1705
 
        /* We did the necessary inits in this function, no need to repeat them
1706
 
        in row_search_for_mysql */
1707
 
 
1708
 
        prebuilt->sql_stat_start = FALSE;
1709
 
 
1710
 
        /* We let HANDLER always to do the reads as consistent reads, even
1711
 
        if the trx isolation level would have been specified as SERIALIZABLE */
1712
 
 
1713
 
        prebuilt->select_lock_type = LOCK_NONE;
1714
 
        prebuilt->stored_select_lock_type = LOCK_NONE;
1715
 
 
1716
 
        /* Always fetch all columns in the index record */
1717
 
 
1718
 
        prebuilt->hint_need_to_fetch_extra_cols = ROW_RETRIEVE_ALL_COLS;
1719
 
 
1720
 
        /* We want always to fetch all columns in the whole row? Or do
1721
 
        we???? */
1722
 
 
1723
 
        prebuilt->used_in_HANDLER = TRUE;
1724
 
        reset_template(prebuilt);
1725
 
}
1726
 
 
1727
1677
/*********************************************************************//**
1728
1678
Opens an InnoDB database.
1729
1679
@return 0 on success, error code on failure */
2010
1960
        pthread_cond_init(&commit_cond, NULL);
2011
1961
        innodb_inited= 1;
2012
1962
 
2013
 
        if (innodb_locks_init() ||
2014
 
                innodb_trx_init() ||
2015
 
                innodb_lock_waits_init() ||
2016
 
                i_s_cmp_init() ||
2017
 
                i_s_cmp_reset_init() ||
2018
 
                i_s_cmpmem_init() ||
2019
 
                i_s_cmpmem_reset_init())
2020
 
                goto error;
 
1963
        status_table_function_ptr= new InnodbStatusTool;
2021
1964
 
2022
1965
        registry.add(innodb_engine_ptr);
2023
1966
 
2024
 
        registry.add(innodb_trx_schema_table);
2025
 
        registry.add(innodb_locks_schema_table);
2026
 
        registry.add(innodb_lock_waits_schema_table);   
2027
 
        registry.add(innodb_cmp_schema_table);
2028
 
        registry.add(innodb_cmp_reset_schema_table);
2029
 
        registry.add(innodb_cmpmem_schema_table);
2030
 
        registry.add(innodb_cmpmem_reset_schema_table);
 
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);
2031
1989
 
2032
1990
        /* Get the current high water mark format. */
2033
1991
        innobase_file_format_check = (char*) trx_sys_file_format_max_get();
2045
2003
innobase_deinit(plugin::Registry &registry)
2046
2004
{
2047
2005
        int     err= 0;
2048
 
        i_s_common_deinit(registry);
 
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
 
2049
2031
        registry.remove(innodb_engine_ptr);
2050
2032
        delete innodb_engine_ptr;
2051
2033
 
2111
2093
have one.
2112
2094
@return 0 */
2113
2095
int
2114
 
InnobaseEngine::start_consistent_snapshot(
 
2096
InnobaseEngine::doStartTransaction(
2115
2097
/*====================================*/
2116
 
        Session*        session)        /*!< in: MySQL thread handle of the user for whom
2117
 
                        the transaction should be committed */
 
2098
        Session*        session,        /*!< in: MySQL thread handle of the user for whom
 
2099
                                                 the transaction should be committed */
 
2100
  start_transaction_option_t options)
2118
2101
{
2119
 
        trx_t*  trx;
2120
 
 
2121
2102
        assert(this == innodb_engine_ptr);
2122
2103
 
2123
2104
        /* Create a new trx struct for session, if it does not yet have one */
2124
 
 
2125
 
        trx = check_trx_exists(session);
 
2105
        trx_t *trx = check_trx_exists(session);
2126
2106
 
2127
2107
        /* This is just to play safe: release a possible FIFO ticket and
2128
2108
        search latch. Since we will reserve the kernel mutex, we have to
2129
2109
        release the search system latch first to obey the latching order. */
2130
 
 
2131
2110
        innobase_release_stat_resources(trx);
2132
2111
 
2133
2112
        /* If the transaction is not started yet, start it */
2134
 
 
2135
2113
        trx_start_if_not_started(trx);
2136
2114
 
2137
2115
        /* Assign a read view if the transaction does not have it yet */
2138
 
 
2139
 
        trx_assign_read_view(trx);
2140
 
 
2141
 
        /* Set the MySQL flag to mark that there is an active transaction */
2142
 
 
2143
 
        if (trx->active_trans == 0) {
2144
 
                innobase_register_trx_and_stmt(this, current_session);
2145
 
                trx->active_trans = 1;
2146
 
        }
2147
 
 
2148
 
        return(0);
 
2116
  if (options == START_TRANS_OPT_WITH_CONS_SNAPSHOT)
 
2117
          trx_assign_read_view(trx);
 
2118
 
 
2119
        return 0;
2149
2120
}
2150
2121
 
2151
2122
/*****************************************************************//**
2153
2124
ended.
2154
2125
@return 0 */
2155
2126
int
2156
 
InnobaseEngine::commit(
 
2127
InnobaseEngine::doCommit(
2157
2128
/*============*/
2158
2129
        Session*        session,        /*!< in: MySQL thread handle of the user for whom
2159
2130
                        the transaction should be committed */
2173
2144
                trx_search_latch_release_if_reserved(trx);
2174
2145
        }
2175
2146
 
2176
 
        /* The flag trx->active_trans is set to 1 in
2177
 
 
2178
 
        1. ::external_lock(),
2179
 
        2. ::start_stmt(),
2180
 
        3. innobase_query_caching_of_table_permitted(),
2181
 
        4. InnobaseEngine::savepoint_set(),
2182
 
        5. ::init_table_handle_for_HANDLER(),
2183
 
        6. InnobaseEngine::start_consistent_snapshot(),
2184
 
 
2185
 
        and it is only set to 0 in a commit or a rollback. If it is 0 we know
2186
 
        there cannot be resources to be freed and we could return immediately.
2187
 
        For the time being, we play safe and do the cleanup though there should
2188
 
        be nothing to clean up. */
2189
 
 
2190
 
        if (trx->active_trans == 0
2191
 
                && trx->conc_state != TRX_NOT_STARTED) {
2192
 
 
2193
 
                errmsg_printf(ERRMSG_LVL_ERROR, "trx->active_trans == 0, but"
2194
 
                        " trx->conc_state != TRX_NOT_STARTED");
2195
 
        }
2196
2147
        if (all
2197
2148
                || (!session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
2198
2149
 
2239
2190
                        pthread_mutex_unlock(&commit_cond_m);
2240
2191
                }
2241
2192
 
2242
 
                if (trx->active_trans == 2) {
 
2193
                if (trx->conc_state == TRX_PREPARED) {
2243
2194
 
2244
2195
                        pthread_mutex_unlock(&prepare_commit_mutex);
2245
2196
                }
2246
2197
 
2247
2198
                /* Now do a write + flush of logs. */
2248
2199
                trx_commit_complete_for_mysql(trx);
2249
 
                trx->active_trans = 0;
2250
2200
 
2251
2201
        } else {
2252
2202
                /* We just mark the SQL statement ended and do not do a
2283
2233
Rolls back a transaction or the latest SQL statement.
2284
2234
@return 0 or error number */
2285
2235
int
2286
 
InnobaseEngine::rollback(
 
2236
InnobaseEngine::doRollback(
2287
2237
/*==============*/
2288
2238
        Session*        session,/*!< in: handle to the MySQL thread of the user
2289
2239
                        whose transaction should be rolled back */
2313
2263
                || !session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
2314
2264
 
2315
2265
                error = trx_rollback_for_mysql(trx);
2316
 
                trx->active_trans = 0;
2317
2266
        } else {
2318
2267
                error = trx_rollback_last_sql_stat_for_mysql(trx);
2319
2268
        }
2354
2303
@return 0 if success, HA_ERR_NO_SAVEPOINT if no savepoint with the
2355
2304
given name */
2356
2305
int
2357
 
InnobaseEngine::savepoint_rollback_hook(
 
2306
InnobaseEngine::doRollbackToSavepoint(
2358
2307
/*===========================*/
2359
2308
        Session*        session,                /*!< in: handle to the MySQL thread of the user
2360
2309
                                whose transaction should be rolled back */
2374
2323
 
2375
2324
        innobase_release_stat_resources(trx);
2376
2325
 
2377
 
        /* TODO: use provided savepoint data area to store savepoint data */
2378
2326
        error= (int)trx_rollback_to_savepoint_for_mysql(trx, named_savepoint.getName().c_str(),
2379
2327
                                                        &mysql_binlog_cache_pos);
2380
2328
        return(convert_error_code_to_mysql(error, 0, NULL));
2385
2333
@return 0 if success, HA_ERR_NO_SAVEPOINT if no savepoint with the
2386
2334
given name */
2387
2335
int
2388
 
InnobaseEngine::savepoint_release_hook(
 
2336
InnobaseEngine::doReleaseSavepoint(
2389
2337
/*=======================*/
2390
2338
        Session*        session,                /*!< in: handle to the MySQL thread of the user
2391
2339
                                whose transaction should be rolled back */
2398
2346
 
2399
2347
        trx = check_trx_exists(session);
2400
2348
 
2401
 
        /* TODO: use provided savepoint data area to store savepoint data */
2402
2349
        error = (int) trx_release_savepoint_for_mysql(trx, named_savepoint.getName().c_str());
2403
2350
 
2404
2351
        return(convert_error_code_to_mysql(error, 0, NULL));
2408
2355
Sets a transaction savepoint.
2409
2356
@return always 0, that is, always succeeds */
2410
2357
int
2411
 
InnobaseEngine::savepoint_set_hook(
 
2358
InnobaseEngine::doSetSavepoint(
2412
2359
/*===============*/
2413
2360
        Session*        session,/*!< in: handle to the MySQL thread */
2414
2361
        drizzled::NamedSavepoint &named_savepoint)      /*!< in: savepoint data */
2433
2380
        innobase_release_stat_resources(trx);
2434
2381
 
2435
2382
        /* cannot happen outside of transaction */
2436
 
        assert(trx->active_trans);
 
2383
        assert(trx->conc_state != TRX_NOT_STARTED);
2437
2384
 
2438
 
        /* TODO: use provided savepoint data area to store savepoint data */
2439
2385
        error = (int) trx_savepoint_for_mysql(trx, named_savepoint.getName().c_str(), (ib_int64_t)0);
2440
2386
 
2441
2387
        return(convert_error_code_to_mysql(error, 0, NULL));
2457
2403
 
2458
2404
        ut_a(trx);
2459
2405
 
2460
 
        if (trx->active_trans == 0
2461
 
                && trx->conc_state != TRX_NOT_STARTED) {
2462
 
 
2463
 
                errmsg_printf(ERRMSG_LVL_ERROR, "trx->active_trans == 0, but"
2464
 
                        " trx->conc_state != TRX_NOT_STARTED");
2465
 
        }
2466
 
 
2467
 
 
2468
 
        if (trx->conc_state != TRX_NOT_STARTED &&
2469
 
                global_system_variables.log_warnings) {
2470
 
                errmsg_printf(ERRMSG_LVL_WARN, 
2471
 
                        "MySQL is closing a connection that has an active "
2472
 
                        "InnoDB transaction.  %lu row modifications will "
2473
 
                        "roll back.",
2474
 
                        (ulong) trx->undo_no.low);
2475
 
        }
 
2406
  assert(session->killed != Session::NOT_KILLED ||
 
2407
         trx->conc_state == TRX_NOT_STARTED);
 
2408
 
 
2409
  /* Warn if rolling back some things... */
 
2410
        if (session->killed != Session::NOT_KILLED &&
 
2411
      trx->conc_state != TRX_NOT_STARTED &&
 
2412
      trx->undo_no.low > 0 &&
 
2413
      global_system_variables.log_warnings)
 
2414
  {
 
2415
      errmsg_printf(ERRMSG_LVL_WARN, 
 
2416
      "Drizzle is closing a connection during a KILL operation\n"
 
2417
      "that has an active InnoDB transaction.  %lu row modifications will "
 
2418
      "roll back.\n",
 
2419
      (ulong) trx->undo_no.low);
 
2420
  }
2476
2421
 
2477
2422
        innobase_rollback_trx(trx);
2478
2423
 
2713
2658
        holding btr_search_latch. This breaks the latching order as
2714
2659
        we acquire dict_sys->mutex below and leads to a deadlock. */
2715
2660
        if (session != NULL) {
2716
 
                engine->release_temporary_latches(session);
 
2661
                getTransactionalEngine()->releaseTemporaryLatches(session);
2717
2662
        }
2718
2663
 
2719
2664
        normalize_table_name(norm_name, name);
2928
2873
 
2929
2874
        session = ha_session();
2930
2875
        if (session != NULL) {
2931
 
                engine->release_temporary_latches(session);
 
2876
                getTransactionalEngine()->releaseTemporaryLatches(session);
2932
2877
        }
2933
2878
 
2934
2879
        row_prebuilt_free(prebuilt, FALSE);
3834
3779
                ut_error;
3835
3780
        }
3836
3781
 
3837
 
        ha_statistic_increment(&SSV::ha_write_count);
 
3782
        ha_statistic_increment(&system_status_var::ha_write_count);
3838
3783
 
3839
3784
        sql_command = session_sql_command(user_session);
3840
3785
 
3879
3824
                        no need to re-acquire locks on it. */
3880
3825
 
3881
3826
                        /* Altering to InnoDB format */
3882
 
                        engine->commit(user_session, 1);
3883
 
                        /* Note that this transaction is still active. */
3884
 
                        prebuilt->trx->active_trans = 1;
 
3827
                        getTransactionalEngine()->commit(user_session, 1);
3885
3828
                        /* We will need an IX lock on the destination table. */
3886
3829
                        prebuilt->sql_stat_start = TRUE;
3887
3830
                } else {
3895
3838
 
3896
3839
                        /* Commit the transaction.  This will release the table
3897
3840
                        locks, so they have to be acquired again. */
3898
 
                        engine->commit(user_session, 1);
3899
 
                        /* Note that this transaction is still active. */
3900
 
                        prebuilt->trx->active_trans = 1;
 
3841
                        getTransactionalEngine()->commit(user_session, 1);
3901
3842
                        /* Re-acquire the table lock on the source table. */
3902
3843
                        row_lock_table_for_mysql(prebuilt, src_table, mode);
3903
3844
                        /* We will need an IX lock on the destination table. */
4207
4148
 
4208
4149
        ut_a(prebuilt->trx == trx);
4209
4150
 
4210
 
        ha_statistic_increment(&SSV::ha_update_count);
 
4151
        ha_statistic_increment(&system_status_var::ha_update_count);
4211
4152
 
4212
4153
        if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
4213
4154
                table->timestamp_field->set_time();
4312
4253
 
4313
4254
        ut_a(prebuilt->trx == trx);
4314
4255
 
4315
 
        ha_statistic_increment(&SSV::ha_delete_count);
 
4256
        ha_statistic_increment(&system_status_var::ha_delete_count);
4316
4257
 
4317
4258
        if (!prebuilt->upd_node) {
4318
4259
                row_get_prebuilt_update_vector(prebuilt);
4500
4441
 
4501
4442
  A) if the user has not explicitly set any MySQL table level locks:
4502
4443
 
4503
 
  1) MySQL calls ::external_lock to set an 'intention' table level lock on
4504
 
the table of the handle instance. There we set
4505
 
prebuilt->sql_stat_start = TRUE. The flag sql_stat_start should be set
4506
 
true if we are taking this table handle instance to use in a new SQL
4507
 
statement issued by the user. We also increment trx->n_mysql_tables_in_use.
4508
 
 
4509
 
  2) If prebuilt->sql_stat_start == TRUE we 'pre-compile' the MySQL search
 
4444
  1) Drizzle calls StorageEngine::doStartStatement(), indicating to
 
4445
     InnoDB that a new SQL statement has begun.
 
4446
 
 
4447
  2a) For each InnoDB-managed table in the SELECT, Drizzle calls ::external_lock
 
4448
     to set an 'intention' table level lock on the table of the Cursor instance.
 
4449
     There we set prebuilt->sql_stat_start = TRUE. The flag sql_stat_start should 
 
4450
     be set true if we are taking this table handle instance to use in a new SQL
 
4451
     statement issued by the user.
 
4452
 
 
4453
  2b) If prebuilt->sql_stat_start == TRUE we 'pre-compile' the MySQL search
4510
4454
instructions to prebuilt->template of the table handle instance in
4511
4455
::index_read. The template is used to save CPU time in large joins.
4512
4456
 
4518
4462
  4) We do the SELECT. MySQL may repeatedly call ::index_read for the
4519
4463
same table handle instance, if it is a join.
4520
4464
 
4521
 
  5) When the SELECT ends, MySQL removes its intention table level locks
4522
 
in ::external_lock. When trx->n_mysql_tables_in_use drops to zero,
4523
 
 (a) we execute a COMMIT there if the autocommit is on,
 
4465
5) When the SELECT ends, the Drizzle kernel calls doEndStatement()
 
4466
 
 
4467
 (a) we execute a COMMIT there if the autocommit is on. The Drizzle interpreter 
 
4468
     does NOT execute autocommit for pure read transactions, though it should.
 
4469
     That is why we must execute the COMMIT in ::doEndStatement().
4524
4470
 (b) we also release possible 'SQL statement level resources' InnoDB may
4525
 
have for this SQL statement. The MySQL interpreter does NOT execute
4526
 
autocommit for pure read transactions, though it should. That is why the
4527
 
table Cursor in that case has to execute the COMMIT in ::external_lock.
 
4471
     have for this SQL statement.
 
4472
 
 
4473
  @todo
 
4474
 
 
4475
  Remove need for InnoDB to call autocommit for read-only trx
 
4476
 
 
4477
  @todo Check the below is still valid (I don't think it is...)
4528
4478
 
4529
4479
  B) If the user has explicitly set MySQL table level locks, then MySQL
4530
4480
does NOT call ::external_lock at the start of the statement. To determine
4566
4516
 
4567
4517
        ut_a(prebuilt->trx == session_to_trx(user_session));
4568
4518
 
4569
 
        ha_statistic_increment(&SSV::ha_read_key_count);
 
4519
        ha_statistic_increment(&system_status_var::ha_read_key_count);
4570
4520
 
4571
4521
        index = prebuilt->index;
4572
4522
 
4681
4631
        KEY*            key = 0;
4682
4632
        dict_index_t*   index = 0;
4683
4633
 
4684
 
        ha_statistic_increment(&SSV::ha_read_key_count);
 
4634
        ha_statistic_increment(&system_status_var::ha_read_key_count);
4685
4635
 
4686
4636
        ut_ad(user_session == ha_session());
4687
4637
        ut_a(prebuilt->trx == session_to_trx(user_session));
4846
4796
        unsigned char*  buf)    /*!< in/out: buffer for next row in MySQL
4847
4797
                                format */
4848
4798
{
4849
 
        ha_statistic_increment(&SSV::ha_read_next_count);
 
4799
        ha_statistic_increment(&system_status_var::ha_read_next_count);
4850
4800
 
4851
4801
        return(general_fetch(buf, ROW_SEL_NEXT, 0));
4852
4802
}
4862
4812
        const unsigned char*    ,       /*!< in: key value */
4863
4813
        uint            )       /*!< in: key value length */
4864
4814
{
4865
 
        ha_statistic_increment(&SSV::ha_read_next_count);
 
4815
        ha_statistic_increment(&system_status_var::ha_read_next_count);
4866
4816
 
4867
4817
        return(general_fetch(buf, ROW_SEL_NEXT, last_match_mode));
4868
4818
}
4877
4827
/*====================*/
4878
4828
        unsigned char*  buf)    /*!< in/out: buffer for previous row in MySQL format */
4879
4829
{
4880
 
        ha_statistic_increment(&SSV::ha_read_prev_count);
 
4830
        ha_statistic_increment(&system_status_var::ha_read_prev_count);
4881
4831
 
4882
4832
        return(general_fetch(buf, ROW_SEL_PREV, 0));
4883
4833
}
4894
4844
{
4895
4845
        int     error;
4896
4846
 
4897
 
        ha_statistic_increment(&SSV::ha_read_first_count);
 
4847
        ha_statistic_increment(&system_status_var::ha_read_first_count);
4898
4848
 
4899
4849
        error = index_read(buf, NULL, 0, HA_READ_AFTER_KEY);
4900
4850
 
4919
4869
{
4920
4870
        int     error;
4921
4871
 
4922
 
        ha_statistic_increment(&SSV::ha_read_last_count);
 
4872
        ha_statistic_increment(&system_status_var::ha_read_last_count);
4923
4873
 
4924
4874
        error = index_read(buf, NULL, 0, HA_READ_BEFORE_KEY);
4925
4875
 
4988
4938
{
4989
4939
        int     error;
4990
4940
 
4991
 
        ha_statistic_increment(&SSV::ha_read_rnd_next_count);
 
4941
        ha_statistic_increment(&system_status_var::ha_read_rnd_next_count);
4992
4942
 
4993
4943
        if (start_of_scan) {
4994
4944
                error = index_first(buf);
5021
4971
        int             error;
5022
4972
        uint            keynr   = active_index;
5023
4973
 
5024
 
        ha_statistic_increment(&SSV::ha_read_rnd_count);
 
4974
        ha_statistic_increment(&system_status_var::ha_read_rnd_count);
5025
4975
 
5026
4976
        ut_a(prebuilt->trx == session_to_trx(ha_session()));
5027
4977
 
5803
5753
                }
5804
5754
        }
5805
5755
 
5806
 
        if (*trx->mysql_query_str) {
 
5756
        if (trx->mysql_query_str) {
5807
5757
                error = row_table_add_foreign_constraints(trx,
5808
 
                        *trx->mysql_query_str, norm_name,
 
5758
                        trx->mysql_query_str, norm_name,
5809
5759
                        lex_identified_temp_table);
5810
5760
 
5811
5761
                error = convert_error_code_to_mysql(error, iflags, NULL);
5961
5911
InnobaseEngine::doDropTable(
5962
5912
/*======================*/
5963
5913
        Session& session,
5964
 
        const string table_path)        /* in: table name */
 
5914
        const string &table_path)       /* in: table name */
5965
5915
{
5966
5916
        int     error;
5967
5917
        trx_t*  parent_trx;
6017
5967
 
6018
5968
/*****************************************************************//**
6019
5969
Removes all tables in the named database inside InnoDB. */
6020
 
void
6021
 
InnobaseEngine::drop_database(
 
5970
bool
 
5971
InnobaseEngine::doDropSchema(
6022
5972
/*===================*/
6023
 
        char*   path)   /*!< in: database path; inside InnoDB the name
 
5973
                             const std::string &schema_name)
 
5974
                /*!< in: database path; inside InnoDB the name
6024
5975
                        of the last directory in the path is used as
6025
5976
                        the database name: for example, in 'mysql/data/test'
6026
5977
                        the database name is 'test' */
6027
5978
{
6028
 
        ulint   len             = 0;
6029
5979
        trx_t*  trx;
6030
 
        char*   ptr;
6031
5980
        int     error;
6032
 
        char*   namebuf;
 
5981
        string schema_path(schema_name);
6033
5982
        Session*        session         = current_session;
6034
5983
 
6035
5984
        /* Get the transaction associated with the current session, or create one
6048
5997
                trx_search_latch_release_if_reserved(parent_trx);
6049
5998
        }
6050
5999
 
6051
 
        ptr = strchr(path, '\0') - 2;
6052
 
 
6053
 
        while (ptr >= path && *ptr != '\\' && *ptr != '/') {
6054
 
                ptr--;
6055
 
                len++;
6056
 
        }
6057
 
 
6058
 
        ptr++;
6059
 
        namebuf = (char*) malloc((uint) len + 2);
6060
 
 
6061
 
        memcpy(namebuf, ptr, len);
6062
 
        namebuf[len] = '/';
6063
 
        namebuf[len + 1] = '\0';
6064
 
#ifdef  __WIN__
6065
 
        innobase_casedn_str(namebuf);
6066
 
#endif
6067
 
#if defined __WIN__ && !defined MYSQL_SERVER
6068
 
        /* In the Windows plugin, thd = current_thd is always NULL */
6069
 
        trx = trx_allocate_for_mysql();
6070
 
        trx->mysql_thd = NULL;
6071
 
        trx->mysql_query_str = NULL;
6072
 
#else
 
6000
        schema_path.append("/");
6073
6001
        trx = innobase_trx_allocate(session);
6074
 
#endif
6075
 
        error = row_drop_database_for_mysql(namebuf, trx);
6076
 
        free(namebuf);
 
6002
        error = row_drop_database_for_mysql(schema_path.c_str(), trx);
6077
6003
 
6078
6004
        /* Flush the log to reduce probability that the .frm files and
6079
6005
        the InnoDB data dictionary get out-of-sync if the user runs
6088
6014
 
6089
6015
        innobase_commit_low(trx);
6090
6016
        trx_free_for_mysql(trx);
 
6017
 
 
6018
        return false; // We are just a listener since we lack control over DDL, so we give no positive acknowledgement. 
6091
6019
}
6092
6020
/*********************************************************************//**
6093
6021
Renames an InnoDB table.
7116
7044
}
7117
7045
 
7118
7046
/******************************************************************//**
7119
 
MySQL calls this function at the start of each SQL statement inside LOCK
7120
 
TABLES. Inside LOCK TABLES the ::external_lock method does not work to
7121
 
mark SQL statement borders. Note also a special case: if a temporary table
7122
 
is created inside LOCK TABLES, MySQL has not called external_lock() at all
7123
 
on that table.
7124
 
MySQL-5.0 also calls this before each statement in an execution of a stored
7125
 
procedure. To make the execution more deterministic for binlogging, MySQL-5.0
7126
 
locks all tables involved in a stored procedure with full explicit table
7127
 
locks (session_in_lock_tables(session) holds in store_lock()) before executing
7128
 
the procedure.
7129
 
@return 0 or error code */
7130
 
UNIV_INTERN
7131
 
int
7132
 
ha_innobase::start_stmt(
7133
 
/*====================*/
7134
 
        Session*        session,        /*!< in: handle to the user thread */
7135
 
        thr_lock_type   lock_type)
7136
 
{
7137
 
        trx_t*          trx;
7138
 
 
7139
 
        update_session(session);
7140
 
 
7141
 
        trx = prebuilt->trx;
7142
 
 
7143
 
        /* Here we release the search latch and the InnoDB thread FIFO ticket
7144
 
        if they were reserved. They should have been released already at the
7145
 
        end of the previous statement, but because inside LOCK TABLES the
7146
 
        lock count method does not work to mark the end of a SELECT statement,
7147
 
        that may not be the case. We MUST release the search latch before an
7148
 
        INSERT, for example. */
7149
 
 
7150
 
        innobase_release_stat_resources(trx);
7151
 
 
7152
 
        /* Reset the AUTOINC statement level counter for multi-row INSERTs. */
7153
 
        trx->n_autoinc_rows = 0;
7154
 
 
7155
 
        prebuilt->sql_stat_start = TRUE;
7156
 
        prebuilt->hint_need_to_fetch_extra_cols = 0;
7157
 
        reset_template(prebuilt);
7158
 
 
7159
 
        if (!prebuilt->mysql_has_locked) {
7160
 
                /* This handle is for a temporary table created inside
7161
 
                this same LOCK TABLES; since MySQL does NOT call external_lock
7162
 
                in this case, we must use x-row locks inside InnoDB to be
7163
 
                prepared for an update of a row */
7164
 
 
7165
 
                prebuilt->select_lock_type = LOCK_X;
7166
 
        } else {
7167
 
                if (trx->isolation_level != TRX_ISO_SERIALIZABLE
7168
 
                        && session_sql_command(session) == SQLCOM_SELECT
7169
 
                        && lock_type == TL_READ) {
7170
 
 
7171
 
                        /* For other than temporary tables, we obtain
7172
 
                        no lock for consistent read (plain SELECT). */
7173
 
 
7174
 
                        prebuilt->select_lock_type = LOCK_NONE;
7175
 
                } else {
7176
 
                        /* Not a consistent read: restore the
7177
 
                        select_lock_type value. The value of
7178
 
                        stored_select_lock_type was decided in:
7179
 
                        1) ::store_lock(),
7180
 
                        2) ::external_lock(),
7181
 
                        3) ::init_table_handle_for_HANDLER(), and
7182
 
                      */
7183
 
 
7184
 
                        prebuilt->select_lock_type =
7185
 
                                prebuilt->stored_select_lock_type;
7186
 
                }
7187
 
        }
7188
 
 
7189
 
        trx->detailed_error[0] = '\0';
7190
 
 
7191
 
        /* Set the MySQL flag to mark that there is an active transaction */
7192
 
        if (trx->active_trans == 0) {
7193
 
 
7194
 
                innobase_register_trx_and_stmt(engine, session);
7195
 
                trx->active_trans = 1;
7196
 
        } else {
7197
 
                innobase_register_stmt(engine, session);
7198
 
        }
7199
 
 
7200
 
        return(0);
7201
 
}
7202
 
 
7203
 
/******************************************************************//**
7204
7047
Maps a MySQL trx isolation level code to the InnoDB isolation level code
7205
7048
@return InnoDB isolation level */
7206
7049
static inline
7220
7063
 
7221
7064
/******************************************************************//**
7222
7065
As MySQL will execute an external lock for every new table it uses when it
7223
 
starts to process an SQL statement (an exception is when MySQL calls
7224
 
start_stmt for the handle) we can use this function to store the pointer to
7225
 
the Session in the handle. We will also use this function to communicate
7226
 
to InnoDB that a new SQL statement has started and that we must store a
7227
 
savepoint to our transaction handle, so that we are able to roll back
7228
 
the SQL statement in case of an error.
 
7066
starts to process an SQL statement.  We can use this function to store the pointer to
 
7067
the Session in the handle.
7229
7068
@return 0 */
7230
7069
UNIV_INTERN
7231
7070
int
7234
7073
        Session*        session,        /*!< in: handle to the user thread */
7235
7074
        int     lock_type)      /*!< in: lock type */
7236
7075
{
7237
 
        trx_t*          trx;
7238
 
 
7239
 
 
7240
7076
        update_session(session);
7241
7077
 
7242
 
        trx = prebuilt->trx;
 
7078
  trx_t *trx= prebuilt->trx;
7243
7079
 
7244
7080
        prebuilt->sql_stat_start = TRUE;
7245
7081
        prebuilt->hint_need_to_fetch_extra_cols = 0;
7257
7093
        if (lock_type != F_UNLCK) {
7258
7094
                /* MySQL is setting a new table lock */
7259
7095
 
7260
 
                trx->detailed_error[0] = '\0';
7261
 
 
7262
 
                /* Set the MySQL flag to mark that there is an active
7263
 
                transaction */
7264
 
                if (trx->active_trans == 0) {
7265
 
 
7266
 
                        innobase_register_trx_and_stmt(engine, session);
7267
 
                        trx->active_trans = 1;
7268
 
                } else if (trx->n_mysql_tables_in_use == 0) {
7269
 
                        innobase_register_stmt(engine, session);
7270
 
                }
7271
 
 
7272
7096
                if (trx->isolation_level == TRX_ISO_SERIALIZABLE
7273
7097
                        && prebuilt->select_lock_type == LOCK_NONE
7274
7098
                        && session_test_options(session,
7301
7125
                        trx->mysql_n_tables_locked++;
7302
7126
                }
7303
7127
 
7304
 
                trx->n_mysql_tables_in_use++;
7305
7128
                prebuilt->mysql_has_locked = TRUE;
7306
7129
 
7307
7130
                return(0);
7308
7131
        }
7309
7132
 
7310
7133
        /* MySQL is releasing a table lock */
7311
 
 
7312
 
        trx->n_mysql_tables_in_use--;
7313
7134
        prebuilt->mysql_has_locked = FALSE;
7314
 
 
7315
 
        /* Release a possible FIFO ticket and search latch. Since we
7316
 
        may reserve the kernel mutex, we have to release the search
7317
 
        system latch first to obey the latching order. */
7318
 
 
7319
 
        innobase_release_stat_resources(trx);
7320
 
 
7321
 
        /* If the MySQL lock count drops to zero we know that the current SQL
7322
 
        statement has ended */
7323
 
 
7324
 
        if (trx->n_mysql_tables_in_use == 0) {
7325
 
 
7326
 
                trx->mysql_n_tables_locked = 0;
7327
 
                prebuilt->used_in_HANDLER = FALSE;
7328
 
 
7329
 
                if (!session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
7330
 
                        if (trx->active_trans != 0) {
7331
 
                                engine->commit(session, TRUE);
7332
 
                        }
7333
 
                } else {
7334
 
                        if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
7335
 
                                                && trx->global_read_view) {
7336
 
 
7337
 
                                /* At low transaction isolation levels we let
7338
 
                                each consistent read set its own snapshot */
7339
 
 
7340
 
                                read_view_close_for_mysql(trx);
7341
 
                        }
7342
 
                }
7343
 
        }
 
7135
        trx->mysql_n_tables_locked= 0;
7344
7136
 
7345
7137
        return(0);
7346
7138
}
7347
7139
 
7348
7140
/************************************************************************//**
7349
 
Here we export InnoDB status variables to MySQL. */
7350
 
static
7351
 
void
7352
 
innodb_export_status(void)
7353
 
/*======================*/
7354
 
{
7355
 
        if (innodb_inited) {
7356
 
                srv_export_innodb_status();
7357
 
        }
7358
 
}
7359
 
 
7360
 
/************************************************************************//**
7361
7141
Implements the SHOW INNODB STATUS command. Sends the output of the InnoDB
7362
7142
Monitor to the client. */
7363
7143
static
7695
7475
 
7696
7476
        trx = check_trx_exists(session);
7697
7477
 
7698
 
        /* NOTE: MySQL can call this function with lock 'type' TL_IGNORE!
7699
 
        Be careful to ignore TL_IGNORE if we are going to do something with
7700
 
        only 'real' locks! */
7701
 
 
7702
 
        /* If no MySQL table is in use, we need to set the isolation level
7703
 
        of the transaction. */
7704
 
 
7705
 
        if (lock_type != TL_IGNORE
7706
 
            && trx->n_mysql_tables_in_use == 0) {
7707
 
                trx->isolation_level = innobase_map_isolation_level(
7708
 
                        (enum_tx_isolation) session_tx_isolation(session));
7709
 
 
7710
 
                if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
7711
 
                    && trx->global_read_view) {
7712
 
 
7713
 
                        /* At low transaction isolation levels we let
7714
 
                        each consistent read set its own snapshot */
7715
 
 
7716
 
                        read_view_close_for_mysql(trx);
7717
 
                }
7718
 
        }
7719
 
 
7720
7478
        assert(EQ_CURRENT_SESSION(session));
7721
7479
        const uint32_t sql_command = session_sql_command(session);
7722
7480
 
7797
7555
                TABLESPACE or TRUNCATE TABLE then allow multiple
7798
7556
                writers. Note that ALTER TABLE uses a TL_WRITE_ALLOW_READ
7799
7557
                < TL_WRITE_CONCURRENT_INSERT.
7800
 
 
7801
 
                We especially allow multiple writers if MySQL is at the
7802
 
                start of a stored procedure call (SQLCOM_CALL) or a
7803
 
                stored function call (MySQL does have in_lock_tables
7804
 
                TRUE there). */
 
7558
                */
7805
7559
 
7806
7560
                if ((lock_type >= TL_WRITE_CONCURRENT_INSERT
7807
7561
                     && lock_type <= TL_WRITE)
7817
7571
                would conflict with TL_WRITE_ALLOW_WRITE, blocking all inserts
7818
7572
                to t2. Convert the lock to a normal read lock to allow
7819
7573
                concurrent inserts to t2.
7820
 
 
7821
 
                We especially allow concurrent inserts if MySQL is at the
7822
 
                start of a stored procedure call (SQLCOM_CALL)
7823
 
                (MySQL does have session_in_lock_tables() TRUE there). */
 
7574
    */
7824
7575
 
7825
7576
                if (lock_type == TL_READ_NO_INSERT) {
7826
7577
 
8195
7946
 
8196
7947
        return(char_length);
8197
7948
}
 
7949
/**
 
7950
 * We will also use this function to communicate
 
7951
 * to InnoDB that a new SQL statement has started and that we must store a
 
7952
 * savepoint to our transaction handle, so that we are able to roll back
 
7953
 * the SQL statement in case of an error.
 
7954
 */
 
7955
void
 
7956
InnobaseEngine::doStartStatement(
 
7957
        Session *session) /*!< in: handle to the Drizzle session */
 
7958
{
 
7959
  /* 
 
7960
   * Create the InnoDB transaction structure
 
7961
   * for the session
 
7962
   */
 
7963
        trx_t *trx= check_trx_exists(session);
 
7964
 
 
7965
  /* "reset" the error message for the transaction */
 
7966
  trx->detailed_error[0]= '\0';
 
7967
 
 
7968
        /* Set the isolation level of the transaction. */
 
7969
  trx->isolation_level= innobase_map_isolation_level((enum_tx_isolation) session_tx_isolation(session));
 
7970
}
 
7971
 
 
7972
void
 
7973
InnobaseEngine::doEndStatement(
 
7974
  Session *session)
 
7975
{
 
7976
  trx_t *trx= check_trx_exists(session);
 
7977
 
 
7978
  /* Release a possible FIFO ticket and search latch. Since we
 
7979
  may reserve the kernel mutex, we have to release the search
 
7980
  system latch first to obey the latching order. */
 
7981
 
 
7982
  innobase_release_stat_resources(trx);
 
7983
 
 
7984
  if (! session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
 
7985
  {
 
7986
    if (trx->conc_state != TRX_NOT_STARTED)
 
7987
    {
 
7988
      commit(session, TRUE);
 
7989
    }
 
7990
  }
 
7991
  else
 
7992
  {
 
7993
    if (trx->isolation_level <= TRX_ISO_READ_COMMITTED &&
 
7994
        trx->global_read_view)
 
7995
    {
 
7996
      /* At low transaction isolation levels we let
 
7997
      each consistent read set its own snapshot */
 
7998
      read_view_close_for_mysql(trx);
 
7999
    }
 
8000
  }
 
8001
}
8198
8002
 
8199
8003
/*******************************************************************//**
8200
8004
This function is used to prepare an X/Open XA distributed transaction.
8201
8005
@return 0 or error number */
8202
8006
int
8203
 
InnobaseEngine::prepare(
 
8007
InnobaseEngine::doXaPrepare(
8204
8008
/*================*/
8205
8009
        Session*        session,/*!< in: handle to the MySQL thread of
8206
8010
                                the user whose XA transaction should
8230
8034
 
8231
8035
        innobase_release_stat_resources(trx);
8232
8036
 
8233
 
        if (trx->active_trans == 0 && trx->conc_state != TRX_NOT_STARTED) {
8234
 
 
8235
 
          errmsg_printf(ERRMSG_LVL_ERROR,
8236
 
                        "trx->active_trans == 0, but trx->conc_state != "
8237
 
                        "TRX_NOT_STARTED");
8238
 
        }
8239
 
 
8240
8037
        if (all
8241
8038
                || (!session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
8242
8039
 
8243
8040
                /* We were instructed to prepare the whole transaction, or
8244
8041
                this is an SQL statement end and autocommit is on */
8245
8042
 
8246
 
                ut_ad(trx->active_trans);
 
8043
                ut_ad(trx->conc_state != TRX_NOT_STARTED);
8247
8044
 
8248
8045
                error = (int) trx_prepare_for_mysql(trx);
8249
8046
        } else {
8290
8087
                to block for undefined period of time.
8291
8088
                */
8292
8089
                pthread_mutex_lock(&prepare_commit_mutex);
8293
 
                trx->active_trans = 2;
 
8090
                trx->conc_state = TRX_PREPARED;
8294
8091
        }
8295
8092
        return(error);
8296
8093
}
8299
8096
This function is used to recover X/Open XA distributed transactions.
8300
8097
@return number of prepared transactions stored in xid_list */
8301
8098
int
8302
 
InnobaseEngine::recover(
 
8099
InnobaseEngine::doXaRecover(
8303
8100
/*================*/
8304
8101
        ::drizzled::XID*        xid_list,/*!< in/out: prepared transactions */
8305
 
        uint                    len)    /*!< in: number of slots in xid_list */
 
8102
        size_t len)     /*!< in: number of slots in xid_list */
8306
8103
{
8307
8104
        assert(this == innodb_engine_ptr);
8308
8105
 
8319
8116
which is in the prepared state
8320
8117
@return 0 or error number */
8321
8118
int
8322
 
InnobaseEngine::commit_by_xid(
 
8119
InnobaseEngine::doXaCommitXid(
8323
8120
/*===================*/
8324
8121
        ::drizzled::XID*        xid)    /*!< in: X/Open XA transaction identification */
8325
8122
{
8343
8140
which is in the prepared state
8344
8141
@return 0 or error number */
8345
8142
int
8346
 
InnobaseEngine::rollback_by_xid(
 
8143
InnobaseEngine::doXaRollbackXid(
8347
8144
/*=====================*/
8348
8145
        ::drizzled::XID*                xid)    /*!< in: X/Open XA transaction
8349
8146
                                identification */
8727
8524
        *(const char**) var_ptr = innobase_change_buffering_values[ibuf_use];
8728
8525
}
8729
8526
 
8730
 
static int show_innodb_vars(SHOW_VAR *var, char *)
8731
 
{
8732
 
  innodb_export_status();
8733
 
  var->type= SHOW_ARRAY;
8734
 
  var->value= (char *) &innodb_status_variables;
8735
 
  return 0;
8736
 
}
8737
 
 
8738
 
static st_show_var_func_container
8739
 
show_innodb_vars_cont = { &show_innodb_vars };
8740
 
 
8741
 
static SHOW_VAR innodb_status_variables_export[]= {
8742
 
  {"Innodb",                   (char*) &show_innodb_vars_cont, SHOW_FUNC},
8743
 
  {NULL, NULL, SHOW_LONG}
8744
 
};
8745
 
 
8746
 
 
8747
8527
/* plugin options */
8748
8528
static DRIZZLE_SYSVAR_BOOL(checksums, innobase_use_checksums,
8749
8529
  PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
9066
8846
  PLUGIN_LICENSE_GPL,
9067
8847
  innobase_init, /* Plugin Init */
9068
8848
  innobase_deinit, /* Plugin Deinit */
9069
 
  innodb_status_variables_export,/* status variables             */
9070
8849
  innobase_system_variables, /* system variables */
9071
8850
  NULL /* reserved */
9072
8851
}