MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
handler.h
1 #ifndef HANDLER_INCLUDED
2 #define HANDLER_INCLUDED
3 
4 /*
5  Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
6 
7  This program is free software; you can redistribute it and/or
8  modify it under the terms of the GNU General Public License
9  as published by the Free Software Foundation; version 2 of
10  the License.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21 
22 /* Definitions for parameters to do with handler-routines */
23 
24 #include "my_pthread.h"
25 #include <algorithm>
26 #include "sql_const.h"
27 #include "mysqld.h" /* server_id */
28 #include "sql_plugin.h" /* plugin_ref, st_plugin_int, plugin */
29 #include "thr_lock.h" /* thr_lock_type, THR_LOCK_DATA */
30 #include "sql_cache.h"
31 #include "structs.h" /* SHOW_COMP_OPTION */
32 
33 #include <my_global.h>
34 #include <my_compare.h>
35 #include <ft_global.h>
36 #include <keycache.h>
37 
38 class Alter_info;
39 
40 // the following is for checking tables
41 
42 #define HA_ADMIN_ALREADY_DONE 1
43 #define HA_ADMIN_OK 0
44 #define HA_ADMIN_NOT_IMPLEMENTED -1
45 #define HA_ADMIN_FAILED -2
46 #define HA_ADMIN_CORRUPT -3
47 #define HA_ADMIN_INTERNAL_ERROR -4
48 #define HA_ADMIN_INVALID -5
49 #define HA_ADMIN_REJECT -6
50 #define HA_ADMIN_TRY_ALTER -7
51 #define HA_ADMIN_WRONG_CHECKSUM -8
52 #define HA_ADMIN_NOT_BASE_TABLE -9
53 #define HA_ADMIN_NEEDS_UPGRADE -10
54 #define HA_ADMIN_NEEDS_ALTER -11
55 #define HA_ADMIN_NEEDS_CHECK -12
56 
63 enum enum_alter_inplace_result {
64  HA_ALTER_ERROR,
65  HA_ALTER_INPLACE_NOT_SUPPORTED,
66  HA_ALTER_INPLACE_EXCLUSIVE_LOCK,
67  HA_ALTER_INPLACE_SHARED_LOCK_AFTER_PREPARE,
68  HA_ALTER_INPLACE_SHARED_LOCK,
69  HA_ALTER_INPLACE_NO_LOCK_AFTER_PREPARE,
70  HA_ALTER_INPLACE_NO_LOCK
71 };
72 
73 /* Bits in table_flags() to show what database can do */
74 
75 #define HA_NO_TRANSACTIONS (1 << 0) /* Doesn't support transactions */
76 #define HA_PARTIAL_COLUMN_READ (1 << 1) /* read may not return all columns */
77 #define HA_TABLE_SCAN_ON_INDEX (1 << 2) /* No separate data/index file */
78 /*
79  The following should be set if the following is not true when scanning
80  a table with rnd_next()
81  - We will see all rows (including deleted ones)
82  - Row positions are 'table->s->db_record_offset' apart
83  If this flag is not set, filesort will do a position() call for each matched
84  row to be able to find the row later.
85 */
86 #define HA_REC_NOT_IN_SEQ (1 << 3)
87 #define HA_CAN_GEOMETRY (1 << 4)
88 /*
89  Reading keys in random order is as fast as reading keys in sort order
90  (Used in records.cc to decide if we should use a record cache and by
91  filesort to decide if we should sort key + data or key + pointer-to-row
92 */
93 #define HA_FAST_KEY_READ (1 << 5)
94 /*
95  Set the following flag if we on delete should force all key to be read
96  and on update read all keys that changes
97 */
98 #define HA_REQUIRES_KEY_COLUMNS_FOR_DELETE (1 << 6)
99 #define HA_NULL_IN_KEY (1 << 7) /* One can have keys with NULL */
100 #define HA_DUPLICATE_POS (1 << 8) /* position() gives dup row */
101 #define HA_NO_BLOBS (1 << 9) /* Doesn't support blobs */
102 #define HA_CAN_INDEX_BLOBS (1 << 10)
103 #define HA_AUTO_PART_KEY (1 << 11) /* auto-increment in multi-part key */
104 #define HA_REQUIRE_PRIMARY_KEY (1 << 12) /* .. and can't create a hidden one */
105 #define HA_STATS_RECORDS_IS_EXACT (1 << 13) /* stats.records is exact */
106 /*
107  INSERT_DELAYED only works with handlers that uses MySQL internal table
108  level locks
109 */
110 #define HA_CAN_INSERT_DELAYED (1 << 14)
111 /*
112  If we get the primary key columns for free when we do an index read
113  (usually, it also implies that HA_PRIMARY_KEY_REQUIRED_FOR_POSITION
114  flag is set).
115 */
116 #define HA_PRIMARY_KEY_IN_READ_INDEX (1 << 15)
117 /*
118  If HA_PRIMARY_KEY_REQUIRED_FOR_POSITION is set, it means that to position()
119  uses a primary key given by the record argument.
120  Without primary key, we can't call position().
121  If not set, the position is returned as the current rows position
122  regardless of what argument is given.
123 */
124 #define HA_PRIMARY_KEY_REQUIRED_FOR_POSITION (1 << 16)
125 #define HA_CAN_RTREEKEYS (1 << 17)
126 #define HA_NOT_DELETE_WITH_CACHE (1 << 18)
127 /*
128  The following is we need to a primary key to delete (and update) a row.
129  If there is no primary key, all columns needs to be read on update and delete
130 */
131 #define HA_PRIMARY_KEY_REQUIRED_FOR_DELETE (1 << 19)
132 #define HA_NO_PREFIX_CHAR_KEYS (1 << 20)
133 #define HA_CAN_FULLTEXT (1 << 21)
134 #define HA_CAN_SQL_HANDLER (1 << 22)
135 #define HA_NO_AUTO_INCREMENT (1 << 23)
136 #define HA_HAS_CHECKSUM (1 << 24)
137 /* Table data are stored in separate files (for lower_case_table_names) */
138 #define HA_FILE_BASED (1 << 26)
139 #define HA_NO_VARCHAR (1 << 27)
140 #define HA_CAN_BIT_FIELD (1 << 28) /* supports bit fields */
141 #define HA_ANY_INDEX_MAY_BE_UNIQUE (1 << 30)
142 #define HA_NO_COPY_ON_ALTER (LL(1) << 31)
143 #define HA_HAS_RECORDS (LL(1) << 32) /* records() gives exact count*/
144 /* Has it's own method of binlog logging */
145 #define HA_HAS_OWN_BINLOGGING (LL(1) << 33)
146 /*
147  Engine is capable of row-format and statement-format logging,
148  respectively
149 */
150 #define HA_BINLOG_ROW_CAPABLE (LL(1) << 34)
151 #define HA_BINLOG_STMT_CAPABLE (LL(1) << 35)
152 /*
153  When a multiple key conflict happens in a REPLACE command mysql
154  expects the conflicts to be reported in the ascending order of
155  key names.
156 
157  For e.g.
158 
159  CREATE TABLE t1 (a INT, UNIQUE (a), b INT NOT NULL, UNIQUE (b), c INT NOT
160  NULL, INDEX(c));
161 
162  REPLACE INTO t1 VALUES (1,1,1),(2,2,2),(2,1,3);
163 
164  MySQL expects the conflict with 'a' to be reported before the conflict with
165  'b'.
166 
167  If the underlying storage engine does not report the conflicting keys in
168  ascending order, it causes unexpected errors when the REPLACE command is
169  executed.
170 
171  This flag helps the underlying SE to inform the server that the keys are not
172  ordered.
173 */
174 #define HA_DUPLICATE_KEY_NOT_IN_ORDER (LL(1) << 36)
175 /*
176  Engine supports REPAIR TABLE. Used by CHECK TABLE FOR UPGRADE if an
177  incompatible table is detected. If this flag is set, CHECK TABLE FOR UPGRADE
178  will report ER_TABLE_NEEDS_UPGRADE, otherwise ER_TABLE_NEED_REBUILD.
179 */
180 #define HA_CAN_REPAIR (LL(1) << 37)
181 
182 /*
183  Set of all binlog flags. Currently only contain the capabilities
184  flags.
185  */
186 #define HA_BINLOG_FLAGS (HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE)
187 
220 #define HA_READ_BEFORE_WRITE_REMOVAL (LL(1) << 38)
221 
222 /*
223  Engine supports extended fulltext API
224  */
225 #define HA_CAN_FULLTEXT_EXT (LL(1) << 39)
226 
227 /*
228  Storage engine doesn't synchronize result set with expected table contents.
229  Used by replication slave to check if it is possible to retrieve rows from
230  the table when deciding whether to do a full table scan, index scan or hash
231  scan while applying a row event.
232  */
233 #define HA_READ_OUT_OF_SYNC (LL(1) << 40)
234 
235 /*
236  Storage engine supports table export using the
237  FLUSH TABLE <table_list> FOR EXPORT statement.
238  */
239 #define HA_CAN_EXPORT (LL(1) << 41)
240 
241 /*
242  The handler don't want accesses to this table to
243  be const-table optimized
244 */
245 #define HA_BLOCK_CONST_TABLE (LL(1) << 42)
246 
247 /* bits in index_flags(index_number) for what you can do with index */
248 #define HA_READ_NEXT 1 /* TODO really use this flag */
249 #define HA_READ_PREV 2 /* supports ::index_prev */
250 #define HA_READ_ORDER 4 /* index_next/prev follow sort order */
251 #define HA_READ_RANGE 8 /* can find all records in a range */
252 #define HA_ONLY_WHOLE_INDEX 16 /* Can't use part key searches */
253 #define HA_KEYREAD_ONLY 64 /* Support HA_EXTRA_KEYREAD */
254 /*
255  Index scan will not return records in rowid order. Not guaranteed to be
256  set for unordered (e.g. HASH) indexes.
257 */
258 #define HA_KEY_SCAN_NOT_ROR 128
259 #define HA_DO_INDEX_COND_PUSHDOWN 256 /* Supports Index Condition Pushdown */
260 
261 
262 
290 #define HA_PARTITION_FUNCTION_SUPPORTED (1L << 0)
291 #define HA_FAST_CHANGE_PARTITION (1L << 1)
292 #define HA_PARTITION_ONE_PHASE (1L << 2)
293 
294 /* operations for disable/enable indexes */
295 #define HA_KEY_SWITCH_NONUNIQ 0
296 #define HA_KEY_SWITCH_ALL 1
297 #define HA_KEY_SWITCH_NONUNIQ_SAVE 2
298 #define HA_KEY_SWITCH_ALL_SAVE 3
299 
300 /*
301  Note: the following includes binlog and closing 0.
302  so: innodb + bdb + ndb + binlog + myisam + myisammrg + archive +
303  example + csv + heap + blackhole + federated + 0
304  (yes, the sum is deliberately inaccurate)
305  TODO remove the limit, use dynarrays
306 */
307 #define MAX_HA 15
308 
309 /*
310  Use this instead of 0 as the initial value for the slot number of
311  handlerton, so that we can distinguish uninitialized slot number
312  from slot 0.
313 */
314 #define HA_SLOT_UNDEF ((uint)-1)
315 
316 /*
317  Parameters for open() (in register form->filestat)
318  HA_GET_INFO does an implicit HA_ABORT_IF_LOCKED
319 */
320 
321 #define HA_OPEN_KEYFILE 1
322 #define HA_OPEN_RNDFILE 2
323 #define HA_GET_INDEX 4
324 #define HA_GET_INFO 8 /* do a ha_info() after open */
325 #define HA_READ_ONLY 16 /* File opened as readonly */
326 /* Try readonly if can't open with read and write */
327 #define HA_TRY_READ_ONLY 32
328 #define HA_WAIT_IF_LOCKED 64 /* Wait if locked on open */
329 #define HA_ABORT_IF_LOCKED 128 /* skip if locked on open.*/
330 #define HA_BLOCK_LOCK 256 /* unlock when reading some records */
331 #define HA_OPEN_TEMPORARY 512
332 
333  /* Some key definitions */
334 #define HA_KEY_NULL_LENGTH 1
335 #define HA_KEY_BLOB_LENGTH 2
336 
337 #define HA_LEX_CREATE_TMP_TABLE 1
338 #define HA_LEX_CREATE_IF_NOT_EXISTS 2
339 #define HA_LEX_CREATE_TABLE_LIKE 4
340 #define HA_OPTION_NO_CHECKSUM (1L << 17)
341 #define HA_OPTION_NO_DELAY_KEY_WRITE (1L << 18)
342 #define HA_MAX_REC_LENGTH 65535U
343 
344 /* Table caching type */
345 #define HA_CACHE_TBL_NONTRANSACT 0
346 #define HA_CACHE_TBL_NOCACHE 1
347 #define HA_CACHE_TBL_ASKTRANSACT 2
348 #define HA_CACHE_TBL_TRANSACT 4
349 
362 // WITH CONSISTENT SNAPSHOT option
363 static const uint MYSQL_START_TRANS_OPT_WITH_CONS_SNAPSHOT = 1;
364 // READ ONLY option
365 static const uint MYSQL_START_TRANS_OPT_READ_ONLY = 2;
366 // READ WRITE option
367 static const uint MYSQL_START_TRANS_OPT_READ_WRITE = 4;
368 
369 /* Flags for method is_fatal_error */
370 #define HA_CHECK_DUP_KEY 1
371 #define HA_CHECK_DUP_UNIQUE 2
372 #define HA_CHECK_DUP (HA_CHECK_DUP_KEY + HA_CHECK_DUP_UNIQUE)
373 
374 enum legacy_db_type
375 {
376  DB_TYPE_UNKNOWN=0,DB_TYPE_DIAB_ISAM=1,
377  DB_TYPE_HASH,DB_TYPE_MISAM,DB_TYPE_PISAM,
378  DB_TYPE_RMS_ISAM, DB_TYPE_HEAP, DB_TYPE_ISAM,
379  DB_TYPE_MRG_ISAM, DB_TYPE_MYISAM, DB_TYPE_MRG_MYISAM,
380  DB_TYPE_BERKELEY_DB, DB_TYPE_INNODB,
381  DB_TYPE_GEMINI, DB_TYPE_NDBCLUSTER,
382  DB_TYPE_EXAMPLE_DB, DB_TYPE_ARCHIVE_DB, DB_TYPE_CSV_DB,
383  DB_TYPE_FEDERATED_DB,
384  DB_TYPE_BLACKHOLE_DB,
385  DB_TYPE_PARTITION_DB,
386  DB_TYPE_BINLOG,
387  DB_TYPE_SOLID,
388  DB_TYPE_PBXT,
389  DB_TYPE_TABLE_FUNCTION,
390  DB_TYPE_MEMCACHE,
391  DB_TYPE_FALCON,
392  DB_TYPE_MARIA,
394  DB_TYPE_PERFORMANCE_SCHEMA,
395  DB_TYPE_FIRST_DYNAMIC=42,
396  DB_TYPE_DEFAULT=127 // Must be last
397 };
398 
399 enum row_type { ROW_TYPE_NOT_USED=-1, ROW_TYPE_DEFAULT, ROW_TYPE_FIXED,
400  ROW_TYPE_DYNAMIC, ROW_TYPE_COMPRESSED,
401  ROW_TYPE_REDUNDANT, ROW_TYPE_COMPACT,
403  ROW_TYPE_PAGE };
404 
405 /* Specifies data storage format for individual columns */
406 enum column_format_type {
407  COLUMN_FORMAT_TYPE_DEFAULT= 0, /* Not specified (use engine default) */
408  COLUMN_FORMAT_TYPE_FIXED= 1, /* FIXED format */
409  COLUMN_FORMAT_TYPE_DYNAMIC= 2 /* DYNAMIC format */
410 };
411 
412 enum enum_binlog_func {
413  BFN_RESET_LOGS= 1,
414  BFN_RESET_SLAVE= 2,
415  BFN_BINLOG_WAIT= 3,
416  BFN_BINLOG_END= 4,
417  BFN_BINLOG_PURGE_FILE= 5
418 };
419 
420 enum enum_binlog_command {
421  LOGCOM_CREATE_TABLE,
422  LOGCOM_ALTER_TABLE,
423  LOGCOM_RENAME_TABLE,
424  LOGCOM_DROP_TABLE,
425  LOGCOM_CREATE_DB,
426  LOGCOM_ALTER_DB,
427  LOGCOM_DROP_DB
428 };
429 
430 /* struct to hold information about the table that should be created */
431 
432 /* Bits in used_fields */
433 #define HA_CREATE_USED_AUTO (1L << 0)
434 #define HA_CREATE_USED_RAID (1L << 1) //RAID is no longer availble
435 #define HA_CREATE_USED_UNION (1L << 2)
436 #define HA_CREATE_USED_INSERT_METHOD (1L << 3)
437 #define HA_CREATE_USED_MIN_ROWS (1L << 4)
438 #define HA_CREATE_USED_MAX_ROWS (1L << 5)
439 #define HA_CREATE_USED_AVG_ROW_LENGTH (1L << 6)
440 #define HA_CREATE_USED_PACK_KEYS (1L << 7)
441 #define HA_CREATE_USED_CHARSET (1L << 8)
442 #define HA_CREATE_USED_DEFAULT_CHARSET (1L << 9)
443 #define HA_CREATE_USED_DATADIR (1L << 10)
444 #define HA_CREATE_USED_INDEXDIR (1L << 11)
445 #define HA_CREATE_USED_ENGINE (1L << 12)
446 #define HA_CREATE_USED_CHECKSUM (1L << 13)
447 #define HA_CREATE_USED_DELAY_KEY_WRITE (1L << 14)
448 #define HA_CREATE_USED_ROW_FORMAT (1L << 15)
449 #define HA_CREATE_USED_COMMENT (1L << 16)
450 #define HA_CREATE_USED_PASSWORD (1L << 17)
451 #define HA_CREATE_USED_CONNECTION (1L << 18)
452 #define HA_CREATE_USED_KEY_BLOCK_SIZE (1L << 19)
453 
454 #define HA_CREATE_USED_TRANSACTIONAL (1L << 20)
455 
456 #define HA_CREATE_USED_PAGE_CHECKSUM (1L << 21)
457 
462 #define HA_CREATE_USED_STATS_PERSISTENT (1L << 22)
463 
469 #define HA_CREATE_USED_STATS_AUTO_RECALC (1L << 23)
470 
476 #define HA_CREATE_USED_STATS_SAMPLE_PAGES (1L << 24)
477 
478 
479 /*
480  This is master database for most of system tables. However there
481  can be other databases which can hold system tables. Respective
482  storage engines define their own system database names.
483 */
484 extern const char *mysqld_system_database;
485 
486 /*
487  Structure to hold list of system_database.system_table.
488  This is used at both mysqld and storage engine layer.
489 */
491 {
492  const char *db;
493  const char *tablename;
494 };
495 
496 
497 typedef ulonglong my_xid; // this line is the same as in log_event.h
498 #define MYSQL_XID_PREFIX "MySQLXid"
499 #define MYSQL_XID_PREFIX_LEN 8 // must be a multiple of 8
500 #define MYSQL_XID_OFFSET (MYSQL_XID_PREFIX_LEN+sizeof(server_id))
501 #define MYSQL_XID_GTRID_LEN (MYSQL_XID_OFFSET+sizeof(my_xid))
502 
503 #define XIDDATASIZE MYSQL_XIDDATASIZE
504 #define MAXGTRIDSIZE 64
505 #define MAXBQUALSIZE 64
506 
507 #define COMPATIBLE_DATA_YES 0
508 #define COMPATIBLE_DATA_NO 1
509 
510 namespace AQP {
511  class Join_plan;
512 };
513 
522 struct xid_t {
523  long formatID;
526  char data[XIDDATASIZE]; // not \0-terminated !
527 
528  xid_t() {} /* Remove gcc warning */
529  bool eq(struct xid_t *xid)
530  { return eq(xid->gtrid_length, xid->bqual_length, xid->data); }
531  bool eq(long g, long b, const char *d)
532  { return g == gtrid_length && b == bqual_length && !memcmp(d, data, g+b); }
533  void set(struct xid_t *xid)
534  { memcpy(this, xid, xid->length()); }
535  void set(long f, const char *g, long gl, const char *b, long bl)
536  {
537  formatID= f;
538  memcpy(data, g, gtrid_length= gl);
539  memcpy(data+gl, b, bqual_length= bl);
540  }
541  void set(ulonglong xid)
542  {
543  my_xid tmp;
544  formatID= 1;
545  set(MYSQL_XID_PREFIX_LEN, 0, MYSQL_XID_PREFIX);
546  memcpy(data+MYSQL_XID_PREFIX_LEN, &server_id, sizeof(server_id));
547  tmp= xid;
548  memcpy(data+MYSQL_XID_OFFSET, &tmp, sizeof(tmp));
549  gtrid_length=MYSQL_XID_GTRID_LEN;
550  }
551  void set(long g, long b, const char *d)
552  {
553  formatID= 1;
554  gtrid_length= g;
555  bqual_length= b;
556  memcpy(data, d, g+b);
557  }
558  bool is_null() { return formatID == -1; }
559  void null() { formatID= -1; }
560  my_xid quick_get_my_xid()
561  {
562  my_xid tmp;
563  memcpy(&tmp, data+MYSQL_XID_OFFSET, sizeof(tmp));
564  return tmp;
565  }
566  my_xid get_my_xid()
567  {
568  return gtrid_length == MYSQL_XID_GTRID_LEN && bqual_length == 0 &&
569  !memcmp(data, MYSQL_XID_PREFIX, MYSQL_XID_PREFIX_LEN) ?
570  quick_get_my_xid() : 0;
571  }
572  uint length()
573  {
574  return sizeof(formatID)+sizeof(gtrid_length)+sizeof(bqual_length)+
575  gtrid_length+bqual_length;
576  }
577  uchar *key()
578  {
579  return (uchar *)&gtrid_length;
580  }
581  uint key_length()
582  {
583  return sizeof(gtrid_length)+sizeof(bqual_length)+gtrid_length+bqual_length;
584  }
585 };
586 typedef struct xid_t XID;
587 
588 /* for recover() handlerton call */
589 #define MIN_XID_LIST_SIZE 128
590 #define MAX_XID_LIST_SIZE (1024*128)
591 
592 /*
593  These structures are used to pass information from a set of SQL commands
594  on add/drop/change tablespace definitions to the proper hton.
595 */
596 #define UNDEF_NODEGROUP 65535
597 enum ts_command_type
598 {
599  TS_CMD_NOT_DEFINED = -1,
600  CREATE_TABLESPACE = 0,
601  ALTER_TABLESPACE = 1,
602  CREATE_LOGFILE_GROUP = 2,
603  ALTER_LOGFILE_GROUP = 3,
604  DROP_TABLESPACE = 4,
605  DROP_LOGFILE_GROUP = 5,
606  CHANGE_FILE_TABLESPACE = 6,
607  ALTER_ACCESS_MODE_TABLESPACE = 7
608 };
609 
610 enum ts_alter_tablespace_type
611 {
612  TS_ALTER_TABLESPACE_TYPE_NOT_DEFINED = -1,
613  ALTER_TABLESPACE_ADD_FILE = 1,
614  ALTER_TABLESPACE_DROP_FILE = 2
615 };
616 
617 enum tablespace_access_mode
618 {
619  TS_NOT_DEFINED= -1,
620  TS_READ_ONLY = 0,
621  TS_READ_WRITE = 1,
622  TS_NOT_ACCESSIBLE = 2
623 };
624 
625 struct handlerton;
627 {
628  public:
629  const char *tablespace_name;
630  const char *logfile_group_name;
631  enum ts_command_type ts_cmd_type;
632  enum ts_alter_tablespace_type ts_alter_tablespace_type;
633  const char *data_file_name;
634  const char *undo_file_name;
635  const char *redo_file_name;
636  ulonglong extent_size;
637  ulonglong undo_buffer_size;
638  ulonglong redo_buffer_size;
639  ulonglong initial_size;
640  ulonglong autoextend_size;
641  ulonglong max_size;
642  uint nodegroup_id;
643  handlerton *storage_engine;
644  bool wait_until_completed;
645  const char *ts_comment;
646  enum tablespace_access_mode ts_access_mode;
648  {
649  tablespace_name= NULL;
650  logfile_group_name= "DEFAULT_LG"; //Default log file group
651  ts_cmd_type= TS_CMD_NOT_DEFINED;
652  data_file_name= NULL;
653  undo_file_name= NULL;
654  redo_file_name= NULL;
655  extent_size= 1024*1024; //Default 1 MByte
656  undo_buffer_size= 8*1024*1024; //Default 8 MByte
657  redo_buffer_size= 8*1024*1024; //Default 8 MByte
658  initial_size= 128*1024*1024; //Default 128 MByte
659  autoextend_size= 0; //No autoextension as default
660  max_size= 0; //Max size == initial size => no extension
661  storage_engine= NULL;
662  nodegroup_id= UNDEF_NODEGROUP;
663  wait_until_completed= TRUE;
664  ts_comment= NULL;
665  ts_access_mode= TS_NOT_DEFINED;
666  }
667 };
668 
669 /* The handler for a table type. Will be included in the TABLE structure */
670 
671 struct TABLE;
672 
673 /*
674  Make sure that the order of schema_tables and enum_schema_tables are the same.
675 */
676 enum enum_schema_tables
677 {
678  SCH_CHARSETS= 0,
679  SCH_COLLATIONS,
680  SCH_COLLATION_CHARACTER_SET_APPLICABILITY,
681  SCH_COLUMNS,
682  SCH_COLUMN_PRIVILEGES,
683  SCH_ENGINES,
684  SCH_EVENTS,
685  SCH_FILES,
686  SCH_GLOBAL_STATUS,
687  SCH_GLOBAL_VARIABLES,
688  SCH_KEY_COLUMN_USAGE,
689  SCH_OPEN_TABLES,
690  SCH_OPTIMIZER_TRACE,
691  SCH_PARAMETERS,
692  SCH_PARTITIONS,
693  SCH_PLUGINS,
694  SCH_PROCESSLIST,
695  SCH_PROFILES,
696  SCH_REFERENTIAL_CONSTRAINTS,
697  SCH_PROCEDURES,
698  SCH_SCHEMATA,
699  SCH_SCHEMA_PRIVILEGES,
700  SCH_SESSION_STATUS,
701  SCH_SESSION_VARIABLES,
702  SCH_STATISTICS,
703  SCH_STATUS,
704  SCH_TABLES,
705  SCH_TABLESPACES,
706  SCH_TABLE_CONSTRAINTS,
707  SCH_TABLE_NAMES,
708  SCH_TABLE_PRIVILEGES,
709  SCH_TRIGGERS,
710  SCH_USER_PRIVILEGES,
711  SCH_VARIABLES,
712  SCH_VIEWS
713 };
714 
715 struct TABLE_SHARE;
716 struct st_foreign_key_info;
718 typedef bool (stat_print_fn)(THD *thd, const char *type, uint type_len,
719  const char *file, uint file_len,
720  const char *status, uint status_len);
721 enum ha_stat_type { HA_ENGINE_STATUS, HA_ENGINE_LOGS, HA_ENGINE_MUTEX };
722 extern st_plugin_int *hton2plugin[MAX_HA];
723 
724 /* Transaction log maintains type definitions */
725 enum log_status
726 {
727  HA_LOG_STATUS_FREE= 0, /* log is free and can be deleted */
728  HA_LOG_STATUS_INUSE= 1, /* log can't be deleted because it is in use */
729  HA_LOG_STATUS_NOSUCHLOG= 2 /* no such log (can't be returned by
730  the log iterator status) */
731 };
732 /*
733  Function for signaling that the log file changed its state from
734  LOG_STATUS_INUSE to LOG_STATUS_FREE
735 
736  Now it do nothing, will be implemented as part of new transaction
737  log management for engines.
738  TODO: implement the function.
739 */
740 void signal_log_not_needed(struct handlerton, char *log_file);
741 /*
742  Data of transaction log iterator.
743 */
745  LEX_STRING filename;
746  enum log_status status;
747 };
748 
749 
750 enum handler_iterator_type
751 {
752  /* request of transaction log iterator */
753  HA_TRANSACTLOG_ITERATOR= 1
754 };
755 enum handler_create_iterator_result
756 {
757  HA_ITERATOR_OK, /* iterator created */
758  HA_ITERATOR_UNSUPPORTED, /* such type of iterator is not supported */
759  HA_ITERATOR_ERROR /* error during iterator creation */
760 };
761 
762 /*
763  Iterator structure. Can be used by handler/handlerton for different purposes.
764 
765  Iterator should be created in the way to point "before" the first object
766  it iterate, so next() call move it to the first object or return !=0 if
767  there is nothing to iterate through.
768 */
770  /*
771  Moves iterator to next record and return 0 or return !=0
772  if there is no records.
773  iterator_object will be filled by this function if next() returns 0.
774  Content of the iterator_object depend on iterator type.
775  */
776  int (*next)(struct handler_iterator *, void *iterator_object);
777  /*
778  Free resources allocated by iterator, after this call iterator
779  is not usable.
780  */
781  void (*destroy)(struct handler_iterator *);
782  /*
783  Pointer to buffer for the iterator to use.
784  Should be allocated by function which created the iterator and
785  destroied by freed by above "destroy" call
786  */
787  void *buffer;
788 };
789 
790 class handler;
791 /*
792  handlerton is a singleton structure - one instance per storage engine -
793  to provide access to storage engine functionality that works on the
794  "global" level (unlike handler class that works on a per-table basis)
795 
796  usually handlerton instance is defined statically in ha_xxx.cc as
797 
798  static handlerton { ... } xxx_hton;
799 
800  savepoint_*, prepare, recover, and *_by_xid pointers can be 0.
801 */
803 {
804  /*
805  Historical marker for if the engine is available of not
806  */
807  SHOW_COMP_OPTION state;
808 
809  /*
810  Historical number used for frm file to determine the correct storage engine.
811  This is going away and new engines will just use "name" for this.
812  */
813  enum legacy_db_type db_type;
814  /*
815  each storage engine has it's own memory area (actually a pointer)
816  in the thd, for storing per-connection information.
817  It is accessed as
818 
819  thd->ha_data[xxx_hton.slot]
820 
821  slot number is initialized by MySQL after xxx_init() is called.
822  */
823  uint slot;
824  /*
825  to store per-savepoint data storage engine is provided with an area
826  of a requested size (0 is ok here).
827  savepoint_offset must be initialized statically to the size of
828  the needed memory to store per-savepoint information.
829  After xxx_init it is changed to be an offset to savepoint storage
830  area and need not be used by storage engine.
831  see binlog_hton and binlog_savepoint_set/rollback for an example.
832  */
833  uint savepoint_offset;
834  /*
835  handlerton methods:
836 
837  close_connection is only called if
838  thd->ha_data[xxx_hton.slot] is non-zero, so even if you don't need
839  this storage area - set it to something, so that MySQL would know
840  this storage engine was accessed in this connection
841  */
842  int (*close_connection)(handlerton *hton, THD *thd);
843  /*
844  sv points to an uninitialized storage area of requested size
845  (see savepoint_offset description)
846  */
847  int (*savepoint_set)(handlerton *hton, THD *thd, void *sv);
848  /*
849  sv points to a storage area, that was earlier passed
850  to the savepoint_set call
851  */
852  int (*savepoint_rollback)(handlerton *hton, THD *thd, void *sv);
853  int (*savepoint_release)(handlerton *hton, THD *thd, void *sv);
854  /*
855  'all' is true if it's a real commit, that makes persistent changes
856  'all' is false if it's not in fact a commit but an end of the
857  statement that is part of the transaction.
858  NOTE 'all' is also false in auto-commit mode where 'end of statement'
859  and 'real commit' mean the same event.
860  */
861  int (*commit)(handlerton *hton, THD *thd, bool all);
862  int (*rollback)(handlerton *hton, THD *thd, bool all);
863  int (*prepare)(handlerton *hton, THD *thd, bool all);
864  int (*recover)(handlerton *hton, XID *xid_list, uint len);
865  int (*commit_by_xid)(handlerton *hton, XID *xid);
866  int (*rollback_by_xid)(handlerton *hton, XID *xid);
867  void *(*create_cursor_read_view)(handlerton *hton, THD *thd);
868  void (*set_cursor_read_view)(handlerton *hton, THD *thd, void *read_view);
869  void (*close_cursor_read_view)(handlerton *hton, THD *thd, void *read_view);
870  handler *(*create)(handlerton *hton, TABLE_SHARE *table, MEM_ROOT *mem_root);
871  void (*drop_database)(handlerton *hton, char* path);
872  int (*panic)(handlerton *hton, enum ha_panic_function flag);
873  int (*start_consistent_snapshot)(handlerton *hton, THD *thd);
874  bool (*flush_logs)(handlerton *hton);
875  bool (*show_status)(handlerton *hton, THD *thd, stat_print_fn *print, enum ha_stat_type stat);
876  uint (*partition_flags)();
877  uint (*alter_table_flags)(uint flags);
878  int (*alter_tablespace)(handlerton *hton, THD *thd, st_alter_tablespace *ts_info);
879  int (*fill_is_table)(handlerton *hton, THD *thd, TABLE_LIST *tables,
880  class Item *cond,
881  enum enum_schema_tables);
882  uint32 flags; /* global handler flags */
883  /*
884  Those handlerton functions below are properly initialized at handler
885  init.
886  */
887  int (*binlog_func)(handlerton *hton, THD *thd, enum_binlog_func fn, void *arg);
888  void (*binlog_log_query)(handlerton *hton, THD *thd,
889  enum_binlog_command binlog_command,
890  const char *query, uint query_length,
891  const char *db, const char *table_name);
892  int (*release_temporary_latches)(handlerton *hton, THD *thd);
893 
894  /*
895  Get log status.
896  If log_status is null then the handler do not support transaction
897  log information (i.e. log iterator can't be created).
898  (see example of implementation in handler.cc, TRANS_LOG_MGM_EXAMPLE_CODE)
899 
900  */
901  enum log_status (*get_log_status)(handlerton *hton, char *log);
902 
903  /*
904  Iterators creator.
905  Presence of the pointer should be checked before using
906  */
907  enum handler_create_iterator_result
908  (*create_iterator)(handlerton *hton, enum handler_iterator_type type,
909  struct handler_iterator *fill_this_in);
910  int (*discover)(handlerton *hton, THD* thd, const char *db,
911  const char *name,
912  uchar **frmblob,
913  size_t *frmlen);
914  int (*find_files)(handlerton *hton, THD *thd,
915  const char *db,
916  const char *path,
917  const char *wild, bool dir, List<LEX_STRING> *files);
918  int (*table_exists_in_engine)(handlerton *hton, THD* thd, const char *db,
919  const char *name);
920  int (*make_pushed_join)(handlerton *hton, THD* thd,
921  const AQP::Join_plan* plan);
922 
934  const char* (*system_database)();
935 
951  bool (*is_supported_system_table)(const char *db,
952  const char *table_name,
953  bool is_sql_layer_system_table);
954 
955  uint32 license; /* Flag for Engine License */
956  void *data; /* Location for engines to keep personal structures */
957 };
958 
959 
960 /* Possible flags of a handlerton (there can be 32 of them) */
961 #define HTON_NO_FLAGS 0
962 #define HTON_CLOSE_CURSORS_AT_COMMIT (1 << 0)
963 #define HTON_ALTER_NOT_SUPPORTED (1 << 1) //Engine does not support alter
964 #define HTON_CAN_RECREATE (1 << 2) //Delete all is used fro truncate
965 #define HTON_HIDDEN (1 << 3) //Engine does not appear in lists
966 #define HTON_FLUSH_AFTER_RENAME (1 << 4)
967 #define HTON_NOT_USER_SELECTABLE (1 << 5)
968 #define HTON_TEMPORARY_NOT_SUPPORTED (1 << 6) //Having temporary tables not supported
969 #define HTON_SUPPORT_LOG_TABLES (1 << 7) //Engine supports log tables
970 #define HTON_NO_PARTITION (1 << 8) //You can not partition these tables
971 
972 /*
973  This flag should be set when deciding that the engine does not allow row based
974  binary logging (RBL) optimizations.
975 
976  Currently, setting this flag, means that table's read/write_set will be left
977  untouched when logging changes to tables in this engine. In practice this
978  means that the server will not mess around with table->write_set and/or
979  table->read_set when using RBL and deciding whether to log full or minimal rows.
980 
981  It's valuable for instance for virtual tables, eg: Performance Schema which have
982  no meaning for replication.
983 */
984 #define HTON_NO_BINLOG_ROW_OPT (1 << 9)
985 
994 #define HTON_SUPPORTS_EXTENDED_KEYS (1 << 10)
995 
996 
997 enum enum_tx_isolation { ISO_READ_UNCOMMITTED, ISO_READ_COMMITTED,
998  ISO_REPEATABLE_READ, ISO_SERIALIZABLE};
999 
1000 
1001 typedef struct {
1002  ulonglong data_file_length;
1003  ulonglong max_data_file_length;
1004  ulonglong index_file_length;
1005  ulonglong delete_length;
1006  ha_rows records;
1007  ulong mean_rec_length;
1008  ulong create_time;
1009  ulong check_time;
1010  ulong update_time;
1011  ulonglong check_sum;
1012 } PARTITION_STATS;
1013 
1014 #define UNDEF_NODEGROUP 65535
1015 class Item;
1016 struct st_table_log_memory_entry;
1017 
1018 class partition_info;
1019 
1020 struct st_partition_iter;
1021 
1022 enum enum_ha_unused { HA_CHOICE_UNDEF, HA_CHOICE_NO, HA_CHOICE_YES };
1023 
1024 enum enum_stats_auto_recalc { HA_STATS_AUTO_RECALC_DEFAULT= 0,
1025  HA_STATS_AUTO_RECALC_ON,
1026  HA_STATS_AUTO_RECALC_OFF };
1027 
1029 {
1030  const CHARSET_INFO *table_charset, *default_table_charset;
1031  LEX_STRING connect_string;
1032  const char *password, *tablespace;
1033  LEX_STRING comment;
1034  const char *data_file_name, *index_file_name;
1035  const char *alias;
1036  ulonglong max_rows,min_rows;
1037  ulonglong auto_increment_value;
1038  ulong table_options;
1039  ulong avg_row_length;
1040  ulong used_fields;
1041  ulong key_block_size;
1042  uint stats_sample_pages; /* number of pages to sample during
1043  stats estimation, if used, otherwise 0. */
1044  enum_stats_auto_recalc stats_auto_recalc;
1045  SQL_I_List<TABLE_LIST> merge_list;
1046  handlerton *db_type;
1056  enum row_type row_type;
1057  uint null_bits; /* NULL bits at start of record */
1058  uint options; /* OR of HA_CREATE_ options */
1059  uint merge_insert_method;
1060  uint extra_size; /* length of extra data segment */
1061  bool varchar; /* 1 if table has a VARCHAR */
1062  enum ha_storage_media storage_media; /* DEFAULT, DISK or MEMORY */
1063 } HA_CREATE_INFO;
1064 
1081 {
1082 public:
1084 
1085  virtual ~inplace_alter_handler_ctx() {}
1086 };
1087 
1088 
1098 {
1099 public:
1115  typedef ulong HA_ALTER_FLAGS;
1116 
1117  // Add non-unique, non-primary index
1118  static const HA_ALTER_FLAGS ADD_INDEX = 1L << 0;
1119 
1120  // Drop non-unique, non-primary index
1121  static const HA_ALTER_FLAGS DROP_INDEX = 1L << 1;
1122 
1123  // Add unique, non-primary index
1124  static const HA_ALTER_FLAGS ADD_UNIQUE_INDEX = 1L << 2;
1125 
1126  // Drop unique, non-primary index
1127  static const HA_ALTER_FLAGS DROP_UNIQUE_INDEX = 1L << 3;
1128 
1129  // Add primary index
1130  static const HA_ALTER_FLAGS ADD_PK_INDEX = 1L << 4;
1131 
1132  // Drop primary index
1133  static const HA_ALTER_FLAGS DROP_PK_INDEX = 1L << 5;
1134 
1135  // Add column
1136  static const HA_ALTER_FLAGS ADD_COLUMN = 1L << 6;
1137 
1138  // Drop column
1139  static const HA_ALTER_FLAGS DROP_COLUMN = 1L << 7;
1140 
1141  // Rename column
1142  static const HA_ALTER_FLAGS ALTER_COLUMN_NAME = 1L << 8;
1143 
1144  // Change column datatype
1145  static const HA_ALTER_FLAGS ALTER_COLUMN_TYPE = 1L << 9;
1146 
1154 
1155  // Reorder column
1156  static const HA_ALTER_FLAGS ALTER_COLUMN_ORDER = 1L << 11;
1157 
1158  // Change column from NOT NULL to NULL
1159  static const HA_ALTER_FLAGS ALTER_COLUMN_NULLABLE = 1L << 12;
1160 
1161  // Change column from NULL to NOT NULL
1162  static const HA_ALTER_FLAGS ALTER_COLUMN_NOT_NULLABLE = 1L << 13;
1163 
1164  // Set or remove default column value
1165  static const HA_ALTER_FLAGS ALTER_COLUMN_DEFAULT = 1L << 14;
1166 
1167  // Add foreign key
1168  static const HA_ALTER_FLAGS ADD_FOREIGN_KEY = 1L << 15;
1169 
1170  // Drop foreign key
1171  static const HA_ALTER_FLAGS DROP_FOREIGN_KEY = 1L << 16;
1172 
1173  // table_options changed, see HA_CREATE_INFO::used_fields for details.
1174  static const HA_ALTER_FLAGS CHANGE_CREATE_OPTION = 1L << 17;
1175 
1176  // Table is renamed
1177  static const HA_ALTER_FLAGS ALTER_RENAME = 1L << 18;
1178 
1179  // Change the storage type of column
1180  static const HA_ALTER_FLAGS ALTER_COLUMN_STORAGE_TYPE = 1L << 19;
1181 
1182  // Change the column format of column
1183  static const HA_ALTER_FLAGS ALTER_COLUMN_COLUMN_FORMAT = 1L << 20;
1184 
1185  // Add partition
1186  static const HA_ALTER_FLAGS ADD_PARTITION = 1L << 21;
1187 
1188  // Drop partition
1189  static const HA_ALTER_FLAGS DROP_PARTITION = 1L << 22;
1190 
1191  // Changing partition options
1192  static const HA_ALTER_FLAGS ALTER_PARTITION = 1L << 23;
1193 
1194  // Coalesce partition
1195  static const HA_ALTER_FLAGS COALESCE_PARTITION = 1L << 24;
1196 
1197  // Reorganize partition ... into
1198  static const HA_ALTER_FLAGS REORGANIZE_PARTITION = 1L << 25;
1199 
1200  // Reorganize partition
1201  static const HA_ALTER_FLAGS ALTER_TABLE_REORG = 1L << 26;
1202 
1203  // Remove partitioning
1204  static const HA_ALTER_FLAGS ALTER_REMOVE_PARTITIONING = 1L << 27;
1205 
1206  // Partition operation with ALL keyword
1207  static const HA_ALTER_FLAGS ALTER_ALL_PARTITION = 1L << 28;
1208 
1219 
1232 
1249 
1252 
1255 
1261 
1264 
1270 
1278 
1290 
1295 
1303 
1305  const bool ignore;
1306 
1308  bool online;
1309 
1322  const char *unsupported_reason;
1323 
1324  Alter_inplace_info(HA_CREATE_INFO *create_info_arg,
1325  Alter_info *alter_info_arg,
1326  KEY *key_info_arg, uint key_count_arg,
1327  partition_info *modified_part_info_arg,
1328  bool ignore_arg)
1329  : create_info(create_info_arg),
1330  alter_info(alter_info_arg),
1331  key_info_buffer(key_info_arg),
1332  key_count(key_count_arg),
1333  index_drop_count(0),
1334  index_drop_buffer(NULL),
1335  index_add_count(0),
1336  index_add_buffer(NULL),
1337  handler_ctx(NULL),
1338  group_commit_ctx(NULL),
1339  handler_flags(0),
1340  modified_part_info(modified_part_info_arg),
1341  ignore(ignore_arg),
1342  online(false),
1343  unsupported_reason(NULL)
1344  {}
1345 
1347  {
1348  delete handler_ctx;
1349  }
1350 
1360  void report_unsupported_error(const char *not_supported,
1361  const char *try_instead);
1362 };
1363 
1364 
1366 {
1367  enum ha_key_alg algorithm;
1368  ulong block_size;
1369  LEX_STRING parser_name;
1370  LEX_STRING comment;
1378 } KEY_CREATE_INFO;
1379 
1380 
1381 /*
1382  Class for maintaining hooks used inside operations on tables such
1383  as: create table functions, delete table functions, and alter table
1384  functions.
1385 
1386  Class is using the Template Method pattern to separate the public
1387  usage interface from the private inheritance interface. This
1388  imposes no overhead, since the public non-virtual function is small
1389  enough to be inlined.
1390 
1391  The hooks are usually used for functions that does several things,
1392  e.g., create_table_from_items(), which both create a table and lock
1393  it.
1394  */
1396 {
1397 public:
1398  TABLEOP_HOOKS() {}
1399  virtual ~TABLEOP_HOOKS() {}
1400 
1401  inline void prelock(TABLE **tables, uint count)
1402  {
1403  do_prelock(tables, count);
1404  }
1405 
1406  inline int postlock(TABLE **tables, uint count)
1407  {
1408  return do_postlock(tables, count);
1409  }
1410 private:
1411  /* Function primitive that is called prior to locking tables */
1412  virtual void do_prelock(TABLE **tables, uint count)
1413  {
1414  /* Default is to do nothing */
1415  }
1416 
1425  virtual int do_postlock(TABLE **tables, uint count)
1426  {
1427  return 0; /* Default is to do nothing */
1428  }
1429 };
1430 
1431 typedef struct st_savepoint SAVEPOINT;
1432 extern ulong savepoint_alloc_size;
1433 extern KEY_CREATE_INFO default_key_create_info;
1434 
1435 typedef struct st_ha_check_opt
1436 {
1437  st_ha_check_opt() {} /* Remove gcc warning */
1438  uint flags; /* isam layer flags (e.g. for myisamchk) */
1439  uint sql_flags; /* sql layer flags - for something myisamchk cannot do */
1440  KEY_CACHE *key_cache; /* new key cache when changing key cache */
1441  void init();
1442 } HA_CHECK_OPT;
1443 
1444 
1445 
1446 /*
1447  This is a buffer area that the handler can use to store rows.
1448  'end_of_used_area' should be kept updated after calls to
1449  read-functions so that other parts of the code can use the
1450  remaining area (until next read calls is issued).
1451 */
1452 
1453 typedef struct st_handler_buffer
1454 {
1455  uchar *buffer; /* Buffer one can start using */
1456  uchar *buffer_end; /* End of buffer */
1457  uchar *end_of_used_area; /* End of area that was used by handler */
1458 } HANDLER_BUFFER;
1459 
1460 typedef struct system_status_var SSV;
1461 
1462 
1463 typedef void *range_seq_t;
1464 
1465 typedef struct st_range_seq_if
1466 {
1467  /*
1468  Initialize the traversal of range sequence
1469 
1470  SYNOPSIS
1471  init()
1472  init_params The seq_init_param parameter
1473  n_ranges The number of ranges obtained
1474  flags A combination of HA_MRR_SINGLE_POINT, HA_MRR_FIXED_KEY
1475 
1476  RETURN
1477  An opaque value to be used as RANGE_SEQ_IF::next() parameter
1478  */
1479  range_seq_t (*init)(void *init_params, uint n_ranges, uint flags);
1480 
1481 
1482  /*
1483  Get the next range in the range sequence
1484 
1485  SYNOPSIS
1486  next()
1487  seq The value returned by RANGE_SEQ_IF::init()
1488  range OUT Information about the next range
1489 
1490  RETURN
1491  0 - Ok, the range structure filled with info about the next range
1492  1 - No more ranges
1493  */
1494  uint (*next) (range_seq_t seq, KEY_MULTI_RANGE *range);
1495 
1496  /*
1497  Check whether range_info orders to skip the next record
1498 
1499  SYNOPSIS
1500  skip_record()
1501  seq The value returned by RANGE_SEQ_IF::init()
1502  range_info Information about the next range
1503  (Ignored if MRR_NO_ASSOCIATION is set)
1504  rowid Rowid of the record to be checked (ignored if set to 0)
1505 
1506  RETURN
1507  1 - Record with this range_info and/or this rowid shall be filtered
1508  out from the stream of records returned by multi_range_read_next()
1509  0 - The record shall be left in the stream
1510  */
1511  bool (*skip_record) (range_seq_t seq, char *range_info, uchar *rowid);
1512 
1513  /*
1514  Check if the record combination matches the index condition
1515  SYNOPSIS
1516  skip_index_tuple()
1517  seq The value returned by RANGE_SEQ_IF::init()
1518  range_info Information about the next range
1519 
1520  RETURN
1521  0 - The record combination satisfies the index condition
1522  1 - Otherwise
1523  */
1524  bool (*skip_index_tuple) (range_seq_t seq, char *range_info);
1525 } RANGE_SEQ_IF;
1526 
1527 uint16 &mrr_persistent_flag_storage(range_seq_t seq, uint idx);
1528 char* &mrr_get_ptr_by_idx(range_seq_t seq, uint idx);
1529 
1537 {
1538 private:
1539  double io_cost;
1540  double cpu_cost;
1541  double import_cost;
1542  double mem_cost;
1543 
1544 public:
1545 
1547  static double IO_BLOCK_READ_COST() { return 1.0; }
1548 
1549  Cost_estimate() :
1550  io_cost(0),
1551  cpu_cost(0),
1552  import_cost(0),
1553  mem_cost(0)
1554  {}
1555 
1557  double total_cost() const { return io_cost + cpu_cost + import_cost; }
1558  double get_io_cost() const { return io_cost; }
1559  double get_cpu_cost() const { return cpu_cost; }
1560  double get_import_cost() const { return import_cost; }
1561  double get_mem_cost() const { return mem_cost; }
1562 
1568  bool is_zero() const
1569  {
1570  return !(io_cost || cpu_cost || import_cost || mem_cost);
1571  }
1572 
1574  void reset()
1575  {
1576  io_cost= cpu_cost= import_cost= mem_cost= 0;
1577  }
1578 
1580  void multiply(double m)
1581  {
1582  io_cost *= m;
1583  cpu_cost *= m;
1584  import_cost *= m;
1585  /* Don't multiply mem_cost */
1586  }
1587 
1588  Cost_estimate& operator+= (const Cost_estimate &other)
1589  {
1590  io_cost+= other.io_cost;
1591  cpu_cost+= other.cpu_cost;
1592  import_cost+= other.import_cost;
1593  mem_cost+= other.mem_cost;
1594 
1595  return *this;
1596  }
1597 
1598  Cost_estimate operator+ (const Cost_estimate &other)
1599  {
1600  Cost_estimate result= *this;
1601  result+= other;
1602  return result;
1603  }
1604 
1606  void add_io(double add_io_cost) { io_cost+= add_io_cost; }
1607 
1609  void add_cpu(double add_cpu_cost) { cpu_cost+= add_cpu_cost; }
1610 
1612  void add_import(double add_import_cost) { import_cost+= add_import_cost; }
1613 
1615  void add_mem(double add_mem_cost) { mem_cost+= add_mem_cost; }
1616 };
1617 
1618 void get_sweep_read_cost(TABLE *table, ha_rows nrows, bool interrupted,
1619  Cost_estimate *cost);
1620 
1621 /*
1622  The below two are not used (and not handled) in this milestone of this WL
1623  entry because there seems to be no use for them at this stage of
1624  implementation.
1625 */
1626 #define HA_MRR_SINGLE_POINT 1
1627 #define HA_MRR_FIXED_KEY 2
1628 
1629 /*
1630  Indicates that RANGE_SEQ_IF::next(&range) doesn't need to fill in the
1631  'range' parameter.
1632 */
1633 #define HA_MRR_NO_ASSOCIATION 4
1634 
1635 /*
1636  The MRR user will provide ranges in key order, and MRR implementation
1637  must return rows in key order.
1638  Passing this flag to multi_read_range_init() may cause the
1639  default MRR handler to be used even if HA_MRR_USE_DEFAULT_IMPL
1640  was not specified.
1641  (If the native MRR impl. can not provide SORTED result)
1642 */
1643 #define HA_MRR_SORTED 8
1644 
1645 /* MRR implementation doesn't have to retrieve full records */
1646 #define HA_MRR_INDEX_ONLY 16
1647 
1648 /*
1649  The passed memory buffer is of maximum possible size, the caller can't
1650  assume larger buffer.
1651 */
1652 #define HA_MRR_LIMITS 32
1653 
1654 
1655 /*
1656  Flag set <=> default MRR implementation is used
1657  (The choice is made by **_info[_const]() function which may set this
1658  flag. SQL layer remembers the flag value and then passes it to
1659  multi_read_range_init().
1660 */
1661 #define HA_MRR_USE_DEFAULT_IMPL 64
1662 
1663 /*
1664  Used only as parameter to multi_range_read_info():
1665  Flag set <=> the caller guarantees that the bounds of the scanned ranges
1666  will not have NULL values.
1667 */
1668 #define HA_MRR_NO_NULL_ENDPOINTS 128
1669 
1670 /*
1671  Set by the MRR implementation to signal that it will natively
1672  produced sorted result if multi_range_read_init() is called with
1673  the HA_MRR_SORTED flag - Else multi_range_read_init(HA_MRR_SORTED)
1674  will revert to use the default MRR implementation.
1675 */
1676 #define HA_MRR_SUPPORT_SORTED 256
1677 
1678 
1680 {
1681 public:
1682  ulonglong data_file_length; /* Length off data file */
1683  ulonglong max_data_file_length; /* Length off data file */
1684  ulonglong index_file_length;
1685  ulonglong max_index_file_length;
1686  ulonglong delete_length; /* Free bytes */
1687  ulonglong auto_increment_value;
1688  /*
1689  The number of records in the table.
1690  0 - means the table has exactly 0 rows
1691  other - if (table_flags() & HA_STATS_RECORDS_IS_EXACT)
1692  the value is the exact number of records in the table
1693  else
1694  it is an estimate
1695  */
1696  ha_rows records;
1697  ha_rows deleted; /* Deleted records */
1698  ulong mean_rec_length; /* physical reclength */
1699  ulong create_time; /* When table was created */
1700  ulong check_time;
1701  ulong update_time;
1702  uint block_size; /* index block size */
1703 
1704  /*
1705  number of buffer bytes that native mrr implementation needs,
1706  */
1707  uint mrr_length_per_rec;
1708 
1709  ha_statistics():
1710  data_file_length(0), max_data_file_length(0),
1711  index_file_length(0), delete_length(0), auto_increment_value(0),
1712  records(0), deleted(0), mean_rec_length(0), create_time(0),
1713  check_time(0), update_time(0), block_size(0)
1714  {}
1715 };
1716 
1717 uint calculate_key_len(TABLE *, uint, const uchar *, key_part_map);
1718 /*
1719  bitmap with first N+1 bits set
1720  (keypart_map for a key prefix of [0..N] keyparts)
1721 */
1722 #define make_keypart_map(N) (((key_part_map)2 << (N)) - 1)
1723 /*
1724  bitmap with first N bits set
1725  (keypart_map for a key prefix of [0..N-1] keyparts)
1726 */
1727 #define make_prev_keypart_map(N) (((key_part_map)1 << (N)) - 1)
1728 
1729 
1732 {
1733 public:
1734  Handler_share() {}
1735  virtual ~Handler_share() {}
1736 };
1737 
1738 
1787 class handler :public Sql_alloc
1788 {
1789 public:
1790  typedef ulonglong Table_flags;
1791 protected:
1792  TABLE_SHARE *table_share; /* The table definition */
1793  TABLE *table; /* The current open table */
1794  Table_flags cached_table_flags; /* Set on init() and open() */
1795 
1796  ha_rows estimation_rows_to_insert;
1797 public:
1798  handlerton *ht; /* storage engine of this handler */
1799  uchar *ref; /* Pointer to current row */
1800  uchar *dup_ref; /* Pointer to duplicate row */
1801 
1803 
1804  /* MultiRangeRead-related members: */
1805  range_seq_t mrr_iter; /* Interator to traverse the range sequence */
1806  RANGE_SEQ_IF mrr_funcs; /* Range sequence traversal functions */
1807  HANDLER_BUFFER *multi_range_buffer; /* MRR buffer info */
1808  uint ranges_in_seq; /* Total number of ranges in the traversed sequence */
1809  /* TRUE <=> source MRR ranges and the output are ordered */
1810  bool mrr_is_output_sorted;
1811 
1812  /* TRUE <=> we're currently traversing a range in mrr_cur_range. */
1813  bool mrr_have_range;
1814  /* Current range (the one we're now returning rows from) */
1815  KEY_MULTI_RANGE mrr_cur_range;
1816 
1817  /*
1818  The direction of the current range or index scan. This is used by
1819  the ICP implementation to determine if it has reached the end
1820  of the current range.
1821  */
1822  enum enum_range_scan_direction {
1823  RANGE_SCAN_ASC,
1824  RANGE_SCAN_DESC
1825  };
1826 private:
1827  /*
1828  Storage space for the end range value. Should only be accessed using
1829  the end_range pointer. The content is invalid when end_range is NULL.
1830  */
1831  key_range save_end_range;
1832  enum_range_scan_direction range_scan_direction;
1833  int key_compare_result_on_equal;
1834 
1835 protected:
1836  KEY_PART_INFO *range_key_part;
1837  bool eq_range;
1838  /*
1839  TRUE <=> the engine guarantees that returned records are within the range
1840  being scanned.
1841  */
1842  bool in_range_check_pushed_down;
1843 
1844 public:
1845  /*
1846  End value for a range scan. If this is NULL the range scan has no
1847  end value. Should also be NULL when there is no ongoing range scan.
1848  Used by the read_range() functions and also evaluated by pushed
1849  index conditions.
1850  */
1851  key_range *end_range;
1852  uint errkey; /* Last dup key */
1853  uint key_used_on_scan;
1854  uint active_index;
1857  FT_INFO *ft_handler;
1858  enum {NONE=0, INDEX, RND} inited;
1859  bool implicit_emptied; /* Can be !=0 only if HEAP */
1860  const Item *pushed_cond;
1861 
1862  Item *pushed_idx_cond;
1863  uint pushed_idx_cond_keyno; /* The index which the above condition is for */
1864 
1874  ulonglong next_insert_id;
1894 
1907  PSI_table *m_psi;
1908 
1909  virtual void unbind_psi();
1910  virtual void rebind_psi();
1911 
1912 private:
1913  friend class DsMrr_impl;
1920  int m_lock_type;
1925  Handler_share **ha_share;
1926 
1927 public:
1928  handler(handlerton *ht_arg, TABLE_SHARE *share_arg)
1929  :table_share(share_arg), table(0),
1930  estimation_rows_to_insert(0), ht(ht_arg),
1931  ref(0), range_scan_direction(RANGE_SCAN_ASC),
1932  in_range_check_pushed_down(false), end_range(NULL),
1933  key_used_on_scan(MAX_KEY), active_index(MAX_KEY),
1934  ref_length(sizeof(my_off_t)),
1935  ft_handler(0), inited(NONE),
1936  implicit_emptied(0),
1937  pushed_cond(0), pushed_idx_cond(NULL), pushed_idx_cond_keyno(MAX_KEY),
1940  m_psi(NULL), m_lock_type(F_UNLCK), ha_share(NULL)
1941  {
1942  DBUG_PRINT("info",
1943  ("handler created F_UNLCK %d F_RDLCK %d F_WRLCK %d",
1944  F_UNLCK, F_RDLCK, F_WRLCK));
1945  }
1946  virtual ~handler(void)
1947  {
1948  DBUG_ASSERT(m_lock_type == F_UNLCK);
1949  DBUG_ASSERT(inited == NONE);
1950  }
1951  virtual handler *clone(const char *name, MEM_ROOT *mem_root);
1953  void init()
1954  {
1955  cached_table_flags= table_flags();
1956  }
1957  /* ha_ methods: public wrappers for private virtual API */
1958 
1959  int ha_open(TABLE *table, const char *name, int mode, int test_if_locked);
1960  int ha_close(void);
1961  int ha_index_init(uint idx, bool sorted);
1962  int ha_index_end();
1963  int ha_rnd_init(bool scan);
1964  int ha_rnd_end();
1965  int ha_rnd_next(uchar *buf);
1966  int ha_rnd_pos(uchar * buf, uchar *pos);
1967  int ha_index_read_map(uchar *buf, const uchar *key,
1968  key_part_map keypart_map,
1969  enum ha_rkey_function find_flag);
1970  int ha_index_read_last_map(uchar * buf, const uchar * key,
1971  key_part_map keypart_map);
1972  int ha_index_read_idx_map(uchar *buf, uint index, const uchar *key,
1973  key_part_map keypart_map,
1974  enum ha_rkey_function find_flag);
1975  int ha_index_next(uchar * buf);
1976  int ha_index_prev(uchar * buf);
1977  int ha_index_first(uchar * buf);
1978  int ha_index_last(uchar * buf);
1979  int ha_index_next_same(uchar *buf, const uchar *key, uint keylen);
1980  int ha_index_read(uchar *buf, const uchar *key, uint key_len,
1981  enum ha_rkey_function find_flag);
1982  int ha_index_read_last(uchar *buf, const uchar *key, uint key_len);
1983  int ha_reset();
1984  /* this is necessary in many places, e.g. in HANDLER command */
1985  int ha_index_or_rnd_end()
1986  {
1987  return inited == INDEX ? ha_index_end() : inited == RND ? ha_rnd_end() : 0;
1988  }
1992  Table_flags ha_table_flags() const { return cached_table_flags; }
1999  int ha_external_lock(THD *thd, int lock_type);
2000  int ha_write_row(uchar * buf);
2001  int ha_update_row(const uchar * old_data, uchar * new_data);
2002  int ha_delete_row(const uchar * buf);
2003  void ha_release_auto_increment();
2004 
2006  int ha_check_for_upgrade(HA_CHECK_OPT *check_opt);
2008  int ha_check(THD *thd, HA_CHECK_OPT *check_opt);
2009  int ha_repair(THD* thd, HA_CHECK_OPT* check_opt);
2010  void ha_start_bulk_insert(ha_rows rows);
2011  int ha_end_bulk_insert();
2012  int ha_bulk_update_row(const uchar *old_data, uchar *new_data,
2013  uint *dup_key_found);
2014  int ha_delete_all_rows();
2015  int ha_truncate();
2016  int ha_reset_auto_increment(ulonglong value);
2017  int ha_optimize(THD* thd, HA_CHECK_OPT* check_opt);
2018  int ha_analyze(THD* thd, HA_CHECK_OPT* check_opt);
2019  bool ha_check_and_repair(THD *thd);
2020  int ha_disable_indexes(uint mode);
2021  int ha_enable_indexes(uint mode);
2022  int ha_discard_or_import_tablespace(my_bool discard);
2023  int ha_rename_table(const char *from, const char *to);
2024  int ha_delete_table(const char *name);
2025  void ha_drop_table(const char *name);
2026 
2027  int ha_create(const char *name, TABLE *form, HA_CREATE_INFO *info);
2028 
2029  int ha_create_handler_files(const char *name, const char *old_name,
2030  int action_flag, HA_CREATE_INFO *info);
2031 
2032  int ha_change_partitions(HA_CREATE_INFO *create_info,
2033  const char *path,
2034  ulonglong * const copied,
2035  ulonglong * const deleted,
2036  const uchar *pack_frm_data,
2037  size_t pack_frm_len);
2038  int ha_drop_partitions(const char *path);
2039  int ha_rename_partitions(const char *path);
2040 
2041  void adjust_next_insert_id_after_explicit_value(ulonglong nr);
2042  int update_auto_increment();
2043  virtual void print_error(int error, myf errflag);
2044  virtual bool get_error_message(int error, String *buf);
2045  uint get_dup_key(int error);
2064  virtual bool get_foreign_dup_key(char *child_table_name,
2065  uint child_table_name_len,
2066  char *child_key_name,
2067  uint child_key_name_len)
2068  { DBUG_ASSERT(false); return(false); }
2069  virtual void change_table_ptr(TABLE *table_arg, TABLE_SHARE *share)
2070  {
2071  table= table_arg;
2072  table_share= share;
2073  }
2074  /* Estimates calculation */
2075  virtual double scan_time()
2076  { return ulonglong2double(stats.data_file_length) / IO_SIZE + 2; }
2077 
2078 
2090  virtual double read_time(uint index, uint ranges, ha_rows rows)
2091  { return rows2double(ranges+rows); }
2092 
2093  virtual double index_only_read_time(uint keynr, double records);
2094 
2100  virtual longlong get_memory_buffer_size() const { return -1; }
2101 
2102  virtual ha_rows multi_range_read_info_const(uint keyno, RANGE_SEQ_IF *seq,
2103  void *seq_init_param,
2104  uint n_ranges, uint *bufsz,
2105  uint *flags,
2106  Cost_estimate *cost);
2107  virtual ha_rows multi_range_read_info(uint keyno, uint n_ranges, uint keys,
2108  uint *bufsz, uint *flags,
2109  Cost_estimate *cost);
2110  virtual int multi_range_read_init(RANGE_SEQ_IF *seq, void *seq_init_param,
2111  uint n_ranges, uint mode,
2112  HANDLER_BUFFER *buf);
2113  virtual int multi_range_read_next(char **range_info);
2114 
2115 
2116  virtual const key_map *keys_to_use_for_scanning() { return &key_map_empty; }
2117  bool has_transactions()
2118  { return (ha_table_flags() & HA_NO_TRANSACTIONS) == 0; }
2119  virtual uint extra_rec_buf_length() const { return 0; }
2120 
2131  virtual bool is_fatal_error(int error, uint flags)
2132  {
2133  if (!error ||
2134  ((flags & HA_CHECK_DUP_KEY) &&
2135  (error == HA_ERR_FOUND_DUPP_KEY ||
2136  error == HA_ERR_FOUND_DUPP_UNIQUE)))
2137  return FALSE;
2138  return TRUE;
2139  }
2140 
2145  virtual ha_rows records() { return stats.records; }
2152  virtual ha_rows estimate_rows_upper_bound()
2153  { return stats.records+EXTRA_RECORDS; }
2154 
2159  virtual enum row_type get_row_type() const { return ROW_TYPE_NOT_USED; }
2160 
2161  virtual const char *index_type(uint key_number) { DBUG_ASSERT(0); return "";}
2162 
2163 
2171  virtual void column_bitmaps_signal();
2172  uint get_index(void) const { return active_index; }
2173 
2178  virtual bool start_bulk_update() { return 1; }
2183  virtual bool start_bulk_delete() { return 1; }
2195  virtual int exec_bulk_update(uint *dup_key_found)
2196  {
2197  DBUG_ASSERT(FALSE);
2198  return HA_ERR_WRONG_COMMAND;
2199  }
2204  virtual void end_bulk_update() { return; }
2211  virtual int end_bulk_delete()
2212  {
2213  DBUG_ASSERT(FALSE);
2214  return HA_ERR_WRONG_COMMAND;
2215  }
2216 protected:
2226  virtual int index_read_map(uchar * buf, const uchar * key,
2227  key_part_map keypart_map,
2228  enum ha_rkey_function find_flag)
2229  {
2230  uint key_len= calculate_key_len(table, active_index, key, keypart_map);
2231  return index_read(buf, key, key_len, find_flag);
2232  }
2240  virtual int index_read_idx_map(uchar * buf, uint index, const uchar * key,
2241  key_part_map keypart_map,
2242  enum ha_rkey_function find_flag);
2244  virtual int index_next(uchar * buf)
2245  { return HA_ERR_WRONG_COMMAND; }
2247  virtual int index_prev(uchar * buf)
2248  { return HA_ERR_WRONG_COMMAND; }
2250  virtual int index_first(uchar * buf)
2251  { return HA_ERR_WRONG_COMMAND; }
2253  virtual int index_last(uchar * buf)
2254  { return HA_ERR_WRONG_COMMAND; }
2256  virtual int index_next_same(uchar *buf, const uchar *key, uint keylen);
2263  virtual int index_read_last_map(uchar * buf, const uchar * key,
2264  key_part_map keypart_map)
2265  {
2266  uint key_len= calculate_key_len(table, active_index, key, keypart_map);
2267  return index_read_last(buf, key, key_len);
2268  }
2269 public:
2270  virtual int read_range_first(const key_range *start_key,
2271  const key_range *end_key,
2272  bool eq_range, bool sorted);
2273  virtual int read_range_next();
2274 
2283  void set_end_range(const key_range* range,
2284  enum_range_scan_direction direction);
2285  int compare_key(key_range *range);
2286  int compare_key_icp(const key_range *range) const;
2287  virtual int ft_init() { return HA_ERR_WRONG_COMMAND; }
2288  void ft_end() { ft_handler=NULL; }
2289  virtual FT_INFO *ft_init_ext(uint flags, uint inx,String *key)
2290  { return NULL; }
2291  virtual int ft_read(uchar *buf) { return HA_ERR_WRONG_COMMAND; }
2292 protected:
2294  virtual int rnd_next(uchar *buf)=0;
2296  virtual int rnd_pos(uchar * buf, uchar *pos)=0;
2297 public:
2303  virtual int rnd_pos_by_record(uchar *record)
2304  {
2305  DBUG_ASSERT(table_flags() & HA_PRIMARY_KEY_REQUIRED_FOR_POSITION);
2306  position(record);
2307  return ha_rnd_pos(record, ref);
2308  }
2309  virtual int read_first_row(uchar *buf, uint primary_key);
2314  virtual int restart_rnd_next(uchar *buf, uchar *pos)
2315  { return HA_ERR_WRONG_COMMAND; }
2316  virtual int rnd_same(uchar *buf, uint inx)
2317  { return HA_ERR_WRONG_COMMAND; }
2318  virtual ha_rows records_in_range(uint inx, key_range *min_key, key_range *max_key)
2319  { return (ha_rows) 10; }
2320  /*
2321  If HA_PRIMARY_KEY_REQUIRED_FOR_POSITION is set, then it sets ref
2322  (reference to the row, aka position, with the primary key given in
2323  the record).
2324  Otherwise it set ref to the current row.
2325  */
2326  virtual void position(const uchar *record)=0;
2327  virtual int info(uint)=0; // see my_base.h for full description
2328  virtual void get_dynamic_partition_info(PARTITION_STATS *stat_info,
2329  uint part_id);
2330  virtual uint32 calculate_key_hash_value(Field **field_array)
2331  { DBUG_ASSERT(0); return 0; }
2332  virtual int extra(enum ha_extra_function operation)
2333  { return 0; }
2334  virtual int extra_opt(enum ha_extra_function operation, ulong cache_size)
2335  { return extra(operation); }
2336 
2341  virtual bool start_read_removal(void)
2342  { DBUG_ASSERT(0); return false; }
2343 
2349  virtual ha_rows end_read_removal(void)
2350  { DBUG_ASSERT(0); return (ha_rows) 0; }
2351 
2364  virtual bool was_semi_consistent_read() { return 0; }
2371  virtual void try_semi_consistent_read(bool) {}
2372  virtual void unlock_row() {}
2373  virtual int start_stmt(THD *thd, thr_lock_type lock_type) {return 0;}
2374  virtual void get_auto_increment(ulonglong offset, ulonglong increment,
2375  ulonglong nb_desired_values,
2376  ulonglong *first_value,
2377  ulonglong *nb_reserved_values);
2378  void set_next_insert_id(ulonglong id)
2379  {
2380  DBUG_PRINT("info",("auto_increment: next value %lu", (ulong)id));
2381  next_insert_id= id;
2382  }
2383  void restore_auto_increment(ulonglong prev_insert_id)
2384  {
2385  /*
2386  Insertion of a row failed, re-use the lastly generated auto_increment
2387  id, for the next row. This is achieved by resetting next_insert_id to
2388  what it was before the failed insertion (that old value is provided by
2389  the caller). If that value was 0, it was the first row of the INSERT;
2390  then if insert_id_for_cur_row contains 0 it means no id was generated
2391  for this first row, so no id was generated since the INSERT started, so
2392  we should set next_insert_id to 0; if insert_id_for_cur_row is not 0, it
2393  is the generated id of the first and failed row, so we use it.
2394  */
2395  next_insert_id= (prev_insert_id > 0) ? prev_insert_id :
2397  }
2398 
2399  virtual void update_create_info(HA_CREATE_INFO *create_info) {}
2400  int check_old_types();
2401  virtual int assign_to_keycache(THD* thd, HA_CHECK_OPT* check_opt)
2402  { return HA_ADMIN_NOT_IMPLEMENTED; }
2403  virtual int preload_keys(THD* thd, HA_CHECK_OPT* check_opt)
2404  { return HA_ADMIN_NOT_IMPLEMENTED; }
2405  /* end of the list of admin commands */
2406 
2407  virtual int indexes_are_disabled(void) {return 0;}
2408  virtual char *update_table_comment(const char * comment)
2409  { return (char*) comment;}
2410  virtual void append_create_info(String *packet) {}
2422  { return FALSE; }
2423  virtual char* get_foreign_key_create_info()
2424  { return(NULL);} /* gets foreign key create string from InnoDB */
2433  virtual bool can_switch_engines() { return true; }
2445  virtual int
2447  { return 0; }
2459  virtual int
2461  { return 0; }
2462  virtual uint referenced_by_foreign_key() { return 0;}
2463  virtual void init_table_handle_for_HANDLER()
2464  { return; } /* prepare InnoDB for HANDLER */
2465  virtual void free_foreign_key_create_info(char* str) {}
2467  virtual const char *table_type() const =0;
2479  virtual const char **bas_ext() const =0;
2480 
2481  virtual int get_default_no_partitions(HA_CREATE_INFO *info) { return 1;}
2482  virtual void set_auto_partitions(partition_info *part_info) { return; }
2483 
2494  virtual bool get_no_parts(const char *name,
2495  uint *no_parts)
2496  {
2497  *no_parts= 0;
2498  return 0;
2499  }
2500  virtual void set_part_info(partition_info *part_info, bool early) {return;}
2501 
2502  virtual ulong index_flags(uint idx, uint part, bool all_parts) const =0;
2503 
2504  uint max_record_length() const
2505  {
2506  using std::min;
2507  return min(HA_MAX_REC_LENGTH, max_supported_record_length());
2508  }
2509  uint max_keys() const
2510  {
2511  using std::min;
2512  return min(MAX_KEY, max_supported_keys());
2513  }
2514  uint max_key_parts() const
2515  {
2516  using std::min;
2517  return min(MAX_REF_PARTS, max_supported_key_parts());
2518  }
2519  uint max_key_length() const
2520  {
2521  using std::min;
2522  return min(MAX_KEY_LENGTH, max_supported_key_length());
2523  }
2524  uint max_key_part_length() const
2525  {
2526  using std::min;
2527  return min(MAX_KEY_LENGTH, max_supported_key_part_length());
2528  }
2529 
2530  virtual uint max_supported_record_length() const { return HA_MAX_REC_LENGTH; }
2531  virtual uint max_supported_keys() const { return 0; }
2532  virtual uint max_supported_key_parts() const { return MAX_REF_PARTS; }
2533  virtual uint max_supported_key_length() const { return MAX_KEY_LENGTH; }
2534  virtual uint max_supported_key_part_length() const { return 255; }
2535  virtual uint min_record_length(uint options) const { return 1; }
2536 
2537  virtual bool low_byte_first() const { return 1; }
2538  virtual uint checksum() const { return 0; }
2539  virtual bool is_crashed() const { return 0; }
2540  virtual bool auto_repair() const { return 0; }
2541 
2542 
2543 #define CHF_CREATE_FLAG 0
2544 #define CHF_DELETE_FLAG 1
2545 #define CHF_RENAME_FLAG 2
2546 #define CHF_INDEX_FLAG 3
2547 
2548 
2552  virtual uint lock_count(void) const { return 1; }
2566  virtual THR_LOCK_DATA **store_lock(THD *thd,
2567  THR_LOCK_DATA **to,
2568  enum thr_lock_type lock_type)=0;
2569 
2571  virtual uint8 table_cache_type() { return HA_CACHE_TBL_NONTRANSACT; }
2572 
2573 
2604  virtual my_bool register_query_cache_table(THD *thd, char *table_key,
2605  uint key_length,
2606  qc_engine_callback
2607  *engine_callback,
2608  ulonglong *engine_data)
2609  {
2610  *engine_callback= 0;
2611  return TRUE;
2612  }
2613 
2614 
2615  /*
2616  @retval TRUE Primary key (if there is one) is clustered
2617  key covering all fields
2618  @retval FALSE otherwise
2619  */
2620  virtual bool primary_key_is_clustered() { return FALSE; }
2621  virtual int cmp_ref(const uchar *ref1, const uchar *ref2)
2622  {
2623  return memcmp(ref1, ref2, ref_length);
2624  }
2625 
2626  /*
2627  Condition pushdown to storage engines
2628  */
2629 
2652  virtual const Item *cond_push(const Item *cond) { return cond; };
2658  virtual void cond_pop() { return; }
2659 
2685  virtual Item *idx_cond_push(uint keyno, Item* idx_cond) { return idx_cond; }
2686 
2688  virtual void cancel_pushed_idx_cond()
2689  {
2690  pushed_idx_cond= NULL;
2691  pushed_idx_cond_keyno= MAX_KEY;
2692  in_range_check_pushed_down= false;
2693  }
2694 
2699  virtual uint number_of_pushed_joins() const
2700  { return 0; }
2701 
2706  virtual const TABLE* root_of_pushed_join() const
2707  { return NULL; }
2708 
2713  virtual const TABLE* parent_of_pushed_join() const
2714  { return NULL; }
2715 
2716  virtual int index_read_pushed(uchar * buf, const uchar * key,
2717  key_part_map keypart_map)
2718  { return HA_ERR_WRONG_COMMAND; }
2719 
2720  virtual int index_next_pushed(uchar * buf)
2721  { return HA_ERR_WRONG_COMMAND; }
2722 
2726  virtual bool check_if_incompatible_data(HA_CREATE_INFO *create_info,
2727  uint table_changes)
2728  { return COMPATIBLE_DATA_NO; }
2729 
2730  /* On-line/in-place ALTER TABLE interface. */
2731 
2732  /*
2733  Here is an outline of on-line/in-place ALTER TABLE execution through
2734  this interface.
2735 
2736  Phase 1 : Initialization
2737  ========================
2738  During this phase we determine which algorithm should be used
2739  for execution of ALTER TABLE and what level concurrency it will
2740  require.
2741 
2742  *) This phase starts by opening the table and preparing description
2743  of the new version of the table.
2744  *) Then we check if it is impossible even in theory to carry out
2745  this ALTER TABLE using the in-place algorithm. For example, because
2746  we need to change storage engine or the user has explicitly requested
2747  usage of the "copy" algorithm.
2748  *) If in-place ALTER TABLE is theoretically possible, we continue
2749  by compiling differences between old and new versions of the table
2750  in the form of HA_ALTER_FLAGS bitmap. We also build a few
2751  auxiliary structures describing requested changes and store
2752  all these data in the Alter_inplace_info object.
2753  *) Then the handler::check_if_supported_inplace_alter() method is called
2754  in order to find if the storage engine can carry out changes requested
2755  by this ALTER TABLE using the in-place algorithm. To determine this,
2756  the engine can rely on data in HA_ALTER_FLAGS/Alter_inplace_info
2757  passed to it as well as on its own checks. If the in-place algorithm
2758  can be used for this ALTER TABLE, the level of required concurrency for
2759  its execution is also returned.
2760  If any errors occur during the handler call, ALTER TABLE is aborted
2761  and no further handler functions are called.
2762  *) Locking requirements of the in-place algorithm are compared to any
2763  concurrency requirements specified by user. If there is a conflict
2764  between them, we either switch to the copy algorithm or emit an error.
2765 
2766  Phase 2 : Execution
2767  ===================
2768 
2769  In this phase the operations are executed.
2770 
2771  *) As the first step, we acquire a lock corresponding to the concurrency
2772  level which was returned by handler::check_if_supported_inplace_alter()
2773  and requested by the user. This lock is held for most of the
2774  duration of in-place ALTER (if HA_ALTER_INPLACE_SHARED_LOCK_AFTER_PREPARE
2775  or HA_ALTER_INPLACE_NO_LOCK_AFTER_PREPARE were returned we acquire an
2776  exclusive lock for duration of the next step only).
2777  *) After that we call handler::ha_prepare_inplace_alter_table() to give the
2778  storage engine a chance to update its internal structures with a higher
2779  lock level than the one that will be used for the main step of algorithm.
2780  After that we downgrade the lock if it is necessary.
2781  *) After that, the main step of this phase and algorithm is executed.
2782  We call the handler::ha_inplace_alter_table() method, which carries out the
2783  changes requested by ALTER TABLE but does not makes them visible to other
2784  connections yet.
2785  *) We ensure that no other connection uses the table by upgrading our
2786  lock on it to exclusive.
2787  *) a) If the previous step succeeds, handler::ha_commit_inplace_alter_table() is
2788  called to allow the storage engine to do any final updates to its structures,
2789  to make all earlier changes durable and visible to other connections.
2790  b) If we have failed to upgrade lock or any errors have occured during the
2791  handler functions calls (including commit), we call
2792  handler::ha_commit_inplace_alter_table()
2793  to rollback all changes which were done during previous steps.
2794 
2795  Phase 3 : Final
2796  ===============
2797 
2798  In this phase we:
2799 
2800  *) Update SQL-layer data-dictionary by installing .FRM file for the new version
2801  of the table.
2802  *) Inform the storage engine about this change by calling the
2803  handler::ha_notify_table_changed() method.
2804  *) Destroy the Alter_inplace_info and handler_ctx objects.
2805 
2806  */
2807 
2836  virtual enum_alter_inplace_result
2837  check_if_supported_inplace_alter(TABLE *altered_table,
2838  Alter_inplace_info *ha_alter_info);
2839 
2840 
2845  bool ha_prepare_inplace_alter_table(TABLE *altered_table,
2846  Alter_inplace_info *ha_alter_info);
2847 
2848 
2853  bool ha_inplace_alter_table(TABLE *altered_table,
2854  Alter_inplace_info *ha_alter_info)
2855  {
2856  return inplace_alter_table(altered_table, ha_alter_info);
2857  }
2858 
2859 
2865  bool ha_commit_inplace_alter_table(TABLE *altered_table,
2866  Alter_inplace_info *ha_alter_info,
2867  bool commit);
2868 
2869 
2875  {
2877  }
2878 
2879 
2880 protected:
2909  virtual bool prepare_inplace_alter_table(TABLE *altered_table,
2910  Alter_inplace_info *ha_alter_info)
2911  { return false; }
2912 
2913 
2933  virtual bool inplace_alter_table(TABLE *altered_table,
2934  Alter_inplace_info *ha_alter_info)
2935  { return false; }
2936 
2937 
2970  virtual bool commit_inplace_alter_table(TABLE *altered_table,
2971  Alter_inplace_info *ha_alter_info,
2972  bool commit)
2973 {
2974  /* Nothing to commit/rollback, mark all handlers committed! */
2975  ha_alter_info->group_commit_ctx= NULL;
2976  return false;
2977 }
2978 
2979 
2985  virtual void notify_table_changed();
2986 
2987 public:
2988  /* End of On-line/in-place ALTER TABLE interface. */
2989 
2990 
2996  virtual void use_hidden_primary_key();
2997  virtual uint alter_table_flags(uint flags)
2998  {
2999  if (ht->alter_table_flags)
3000  return ht->alter_table_flags(flags);
3001  return 0;
3002  }
3003 
3004 protected:
3005  /* Service methods for use by storage engines. */
3006  void ha_statistic_increment(ulonglong SSV::*offset) const;
3007  void **ha_data(THD *) const;
3008  THD *ha_thd(void) const;
3009 
3015  PSI_table_share *ha_table_share_psi(const TABLE_SHARE *share) const;
3016 
3024  virtual int rename_table(const char *from, const char *to);
3029  virtual int delete_table(const char *name);
3030 private:
3031  /* Private helpers */
3032  inline void mark_trx_read_write();
3033  /*
3034  Low-level primitives for storage engines. These should be
3035  overridden by the storage engine class. To call these methods, use
3036  the corresponding 'ha_*' method above.
3037  */
3038 
3039  virtual int open(const char *name, int mode, uint test_if_locked)=0;
3040  virtual int close(void)=0;
3041  virtual int index_init(uint idx, bool sorted) { active_index= idx; return 0; }
3042  virtual int index_end() { active_index= MAX_KEY; return 0; }
3050  virtual int rnd_init(bool scan)= 0;
3051  virtual int rnd_end() { return 0; }
3052  virtual int write_row(uchar *buf __attribute__((unused)))
3053  {
3054  return HA_ERR_WRONG_COMMAND;
3055  }
3056 
3065  virtual int update_row(const uchar *old_data __attribute__((unused)),
3066  uchar *new_data __attribute__((unused)))
3067  {
3068  return HA_ERR_WRONG_COMMAND;
3069  }
3070 
3071  virtual int delete_row(const uchar *buf __attribute__((unused)))
3072  {
3073  return HA_ERR_WRONG_COMMAND;
3074  }
3080  virtual int reset() { return 0; }
3081  virtual Table_flags table_flags(void) const= 0;
3104  virtual int external_lock(THD *thd __attribute__((unused)),
3105  int lock_type __attribute__((unused)))
3106  {
3107  return 0;
3108  }
3109  virtual void release_auto_increment() { return; };
3111  virtual int check_for_upgrade(HA_CHECK_OPT *check_opt)
3112  { return 0; }
3113  virtual int check(THD* thd, HA_CHECK_OPT* check_opt)
3114  { return HA_ADMIN_NOT_IMPLEMENTED; }
3115 
3121  virtual int repair(THD* thd, HA_CHECK_OPT* check_opt)
3122  {
3123  DBUG_ASSERT(!(ha_table_flags() & HA_CAN_REPAIR));
3124  return HA_ADMIN_NOT_IMPLEMENTED;
3125  }
3126  virtual void start_bulk_insert(ha_rows rows) {}
3127  virtual int end_bulk_insert() { return 0; }
3128 protected:
3129  virtual int index_read(uchar * buf, const uchar * key, uint key_len,
3130  enum ha_rkey_function find_flag)
3131  { return HA_ERR_WRONG_COMMAND; }
3132  virtual int index_read_last(uchar * buf, const uchar * key, uint key_len)
3133  { return (my_errno= HA_ERR_WRONG_COMMAND); }
3134 public:
3151  virtual int bulk_update_row(const uchar *old_data, uchar *new_data,
3152  uint *dup_key_found)
3153  {
3154  DBUG_ASSERT(FALSE);
3155  return HA_ERR_WRONG_COMMAND;
3156  }
3163  virtual int delete_all_rows()
3164  { return (my_errno=HA_ERR_WRONG_COMMAND); }
3183  virtual int truncate()
3184  { return HA_ERR_WRONG_COMMAND; }
3190  virtual int reset_auto_increment(ulonglong value)
3191  { return HA_ERR_WRONG_COMMAND; }
3192  virtual int optimize(THD* thd, HA_CHECK_OPT* check_opt)
3193  { return HA_ADMIN_NOT_IMPLEMENTED; }
3194  virtual int analyze(THD* thd, HA_CHECK_OPT* check_opt)
3195  { return HA_ADMIN_NOT_IMPLEMENTED; }
3196  virtual bool check_and_repair(THD *thd) { return TRUE; }
3197  virtual int disable_indexes(uint mode) { return HA_ERR_WRONG_COMMAND; }
3198  virtual int enable_indexes(uint mode) { return HA_ERR_WRONG_COMMAND; }
3199  virtual int discard_or_import_tablespace(my_bool discard)
3200  { return (my_errno=HA_ERR_WRONG_COMMAND); }
3201  virtual void drop_table(const char *name);
3202  virtual int create(const char *name, TABLE *form, HA_CREATE_INFO *info)=0;
3203 
3204  virtual int create_handler_files(const char *name, const char *old_name,
3205  int action_flag, HA_CREATE_INFO *info)
3206  { return FALSE; }
3207 
3208  virtual int change_partitions(HA_CREATE_INFO *create_info,
3209  const char *path,
3210  ulonglong * const copied,
3211  ulonglong * const deleted,
3212  const uchar *pack_frm_data,
3213  size_t pack_frm_len)
3214  { return HA_ERR_WRONG_COMMAND; }
3215  virtual int drop_partitions(const char *path)
3216  { return HA_ERR_WRONG_COMMAND; }
3217  virtual int rename_partitions(const char *path)
3218  { return HA_ERR_WRONG_COMMAND; }
3219  virtual bool set_ha_share_ref(Handler_share **arg_ha_share)
3220  {
3221  DBUG_ASSERT(!ha_share);
3222  DBUG_ASSERT(arg_ha_share);
3223  if (ha_share || !arg_ha_share)
3224  return true;
3225  ha_share= arg_ha_share;
3226  return false;
3227  }
3228  int get_lock_type() const { return m_lock_type; }
3229 protected:
3231  void set_ha_share_ptr(Handler_share *arg_ha_share);
3232  void lock_shared_ha_data();
3233  void unlock_shared_ha_data();
3234 };
3235 
3236 
3237 bool key_uses_partial_cols(TABLE *table, uint keyno);
3238 
3239 /*
3240  A Disk-Sweep MRR interface implementation
3241 
3242  This implementation makes range (and, in the future, 'ref') scans to read
3243  table rows in disk sweeps.
3244 
3245  Currently it is used by MyISAM and InnoDB. Potentially it can be used with
3246  any table handler that has non-clustered indexes and on-disk rows.
3247 */
3248 
3250 {
3251 public:
3252  typedef void (handler::*range_check_toggle_func_t)(bool on);
3253 
3254  DsMrr_impl()
3255  : h2(NULL) {};
3256  ~DsMrr_impl() { DBUG_ASSERT(h2 == NULL); }
3257 
3258  /*
3259  The "owner" handler object (the one that calls dsmrr_XXX functions.
3260  It is used to retrieve full table rows by calling rnd_pos().
3261  */
3262  handler *h;
3263  TABLE *table; /* Always equal to h->table */
3264 private:
3265  /* Secondary handler object. It is used for scanning the index */
3266  handler *h2;
3267 
3268  /* Buffer to store rowids, or (rowid, range_id) pairs */
3269  uchar *rowids_buf;
3270  uchar *rowids_buf_cur; /* Current position when reading/writing */
3271  uchar *rowids_buf_last; /* When reading: end of used buffer space */
3272  uchar *rowids_buf_end; /* End of the buffer */
3273 
3274  bool dsmrr_eof; /* TRUE <=> We have reached EOF when reading index tuples */
3275 
3276  /* TRUE <=> need range association, buffer holds {rowid, range_id} pairs */
3277  bool is_mrr_assoc;
3278 
3279  bool use_default_impl; /* TRUE <=> shortcut all calls to default MRR impl */
3280 public:
3281  void init(handler *h_arg, TABLE *table_arg)
3282  {
3283  h= h_arg;
3284  table= table_arg;
3285  }
3286  int dsmrr_init(handler *h, RANGE_SEQ_IF *seq_funcs, void *seq_init_param,
3287  uint n_ranges, uint mode, HANDLER_BUFFER *buf);
3288  void dsmrr_close();
3289 
3300  void reset();
3301  int dsmrr_fill_buffer();
3302  int dsmrr_next(char **range_info);
3303 
3304  ha_rows dsmrr_info(uint keyno, uint n_ranges, uint keys, uint *bufsz,
3305  uint *flags, Cost_estimate *cost);
3306 
3307  ha_rows dsmrr_info_const(uint keyno, RANGE_SEQ_IF *seq,
3308  void *seq_init_param, uint n_ranges, uint *bufsz,
3309  uint *flags, Cost_estimate *cost);
3310 private:
3311  bool choose_mrr_impl(uint keyno, ha_rows rows, uint *flags, uint *bufsz,
3312  Cost_estimate *cost);
3313  bool get_disk_sweep_mrr_cost(uint keynr, ha_rows rows, uint flags,
3314  uint *buffer_size, Cost_estimate *cost);
3315 };
3316  /* Some extern variables used with handlers */
3317 
3318 extern const char *ha_row_type[];
3319 extern MYSQL_PLUGIN_IMPORT const char *tx_isolation_names[];
3320 extern MYSQL_PLUGIN_IMPORT const char *binlog_format_names[];
3321 extern TYPELIB tx_isolation_typelib;
3322 extern const char *myisam_stats_method_names[];
3323 extern ulong total_ha, total_ha_2pc;
3324 
3325 /* lookups */
3328 plugin_ref ha_resolve_by_name(THD *thd, const LEX_STRING *name,
3329  bool is_temp_table);
3330 plugin_ref ha_lock_engine(THD *thd, const handlerton *hton);
3331 handlerton *ha_resolve_by_legacy_type(THD *thd, enum legacy_db_type db_type);
3332 handler *get_new_handler(TABLE_SHARE *share, MEM_ROOT *alloc,
3333  handlerton *db_type);
3334 handlerton *ha_checktype(THD *thd, enum legacy_db_type database_type,
3335  bool no_substitute, bool report_error);
3336 
3337 
3338 static inline enum legacy_db_type ha_legacy_type(const handlerton *db_type)
3339 {
3340  return (db_type == NULL) ? DB_TYPE_UNKNOWN : db_type->db_type;
3341 }
3342 
3343 static inline const char *ha_resolve_storage_engine_name(const handlerton *db_type)
3344 {
3345  return db_type == NULL ? "UNKNOWN" : hton2plugin[db_type->slot]->name.str;
3346 }
3347 
3348 static inline bool ha_check_storage_engine_flag(const handlerton *db_type, uint32 flag)
3349 {
3350  return db_type == NULL ? FALSE : test(db_type->flags & flag);
3351 }
3352 
3353 static inline bool ha_storage_engine_is_enabled(const handlerton *db_type)
3354 {
3355  return (db_type && db_type->create) ?
3356  (db_type->state == SHOW_OPTION_YES) : FALSE;
3357 }
3358 
3359 /* basic stuff */
3360 int ha_init_errors(void);
3361 int ha_init(void);
3362 int ha_end(void);
3363 int ha_initialize_handlerton(st_plugin_int *plugin);
3364 int ha_finalize_handlerton(st_plugin_int *plugin);
3365 
3366 TYPELIB* ha_known_exts();
3367 int ha_panic(enum ha_panic_function flag);
3368 void ha_close_connection(THD* thd);
3369 bool ha_flush_logs(handlerton *db_type);
3370 void ha_drop_database(char* path);
3371 int ha_create_table(THD *thd, const char *path,
3372  const char *db, const char *table_name,
3373  HA_CREATE_INFO *create_info,
3374  bool update_create_info,
3375  bool is_temp_table= false);
3376 
3377 int ha_delete_table(THD *thd, handlerton *db_type, const char *path,
3378  const char *db, const char *alias, bool generate_warning);
3379 
3380 /* statistics and info */
3381 bool ha_show_status(THD *thd, handlerton *db_type, enum ha_stat_type stat);
3382 
3383 /* discovery */
3384 int ha_create_table_from_engine(THD* thd, const char *db, const char *name);
3385 bool ha_check_if_table_exists(THD* thd, const char *db, const char *name,
3386  bool *exists);
3387 int ha_discover(THD* thd, const char* dbname, const char* name,
3388  uchar** frmblob, size_t* frmlen);
3389 int ha_find_files(THD *thd,const char *db,const char *path,
3390  const char *wild, bool dir, List<LEX_STRING>* files);
3391 int ha_table_exists_in_engine(THD* thd, const char* db, const char* name);
3392 bool ha_check_if_supported_system_table(handlerton *hton, const char* db,
3393  const char* table_name);
3394 
3395 /* key cache */
3396 extern "C" int ha_init_key_cache(const char *name, KEY_CACHE *key_cache);
3397 int ha_resize_key_cache(KEY_CACHE *key_cache);
3398 int ha_change_key_cache_param(KEY_CACHE *key_cache);
3399 int ha_change_key_cache(KEY_CACHE *old_key_cache, KEY_CACHE *new_key_cache);
3400 
3401 /* report to InnoDB that control passes to the client */
3402 int ha_release_temporary_latches(THD *thd);
3403 
3404 /* transactions: interface to handlerton functions */
3405 int ha_start_consistent_snapshot(THD *thd);
3406 int ha_commit_or_rollback_by_xid(THD *thd, XID *xid, bool commit);
3407 int ha_commit_trans(THD *thd, bool all, bool ignore_global_read_lock= false);
3408 int ha_rollback_trans(THD *thd, bool all);
3409 int ha_prepare(THD *thd);
3410 int ha_recover(HASH *commit_list);
3411 
3412 /*
3413  transactions: interface to low-level handlerton functions. These are
3414  intended to be used by the transaction coordinators to
3415  commit/prepare/rollback transactions in the engines.
3416 */
3417 int ha_commit_low(THD *thd, bool all, bool run_after_commit= true);
3418 int ha_prepare_low(THD *thd, bool all);
3419 int ha_rollback_low(THD *thd, bool all);
3420 
3421 /* transactions: these functions never call handlerton functions directly */
3422 int ha_enable_transaction(THD *thd, bool on);
3423 
3424 /* savepoints */
3425 int ha_rollback_to_savepoint(THD *thd, SAVEPOINT *sv);
3426 int ha_savepoint(THD *thd, SAVEPOINT *sv);
3427 int ha_release_savepoint(THD *thd, SAVEPOINT *sv);
3428 
3429 /* Build pushed joins in handlers implementing this feature */
3430 int ha_make_pushed_joins(THD *thd, const AQP::Join_plan* plan);
3431 
3432 /* these are called by storage engines */
3433 void trans_register_ha(THD *thd, bool all, handlerton *ht);
3434 
3435 /*
3436  Storage engine has to assume the transaction will end up with 2pc if
3437  - there is more than one 2pc-capable storage engine available
3438  - in the current transaction 2pc was not disabled yet
3439 */
3440 #define trans_need_2pc(thd, all) ((total_ha_2pc > 1) && \
3441  !((all ? &thd->transaction.all : &thd->transaction.stmt)->no_2pc))
3442 
3443 #ifdef HAVE_NDB_BINLOG
3444 int ha_reset_logs(THD *thd);
3445 int ha_binlog_index_purge_file(THD *thd, const char *file);
3446 void ha_reset_slave(THD *thd);
3447 void ha_binlog_log_query(THD *thd, handlerton *db_type,
3448  enum_binlog_command binlog_command,
3449  const char *query, uint query_length,
3450  const char *db, const char *table_name);
3451 void ha_binlog_wait(THD *thd);
3452 #else
3453 #define ha_reset_logs(a) do {} while (0)
3454 #define ha_binlog_index_purge_file(a,b) do {} while (0)
3455 #define ha_reset_slave(a) do {} while (0)
3456 #define ha_binlog_log_query(a,b,c,d,e,f,g) do {} while (0)
3457 #define ha_binlog_wait(a) do {} while (0)
3458 #endif
3459 
3460 /* It is required by basic binlog features on both MySQL server and libmysqld */
3461 int ha_binlog_end(THD *thd);
3462 
3463 const char *ha_legacy_type_name(legacy_db_type legacy_type);
3464 const char *get_canonical_filename(handler *file, const char *path,
3465  char *tmp_path);
3466 bool mysql_xa_recover(THD *thd);
3467 
3468 
3469 inline const char *table_case_name(HA_CREATE_INFO *info, const char *name)
3470 {
3471  return ((lower_case_table_names == 2 && info->alias) ? info->alias : name);
3472 }
3473 
3474 void print_keydup_error(TABLE *table, KEY *key, const char *msg, myf errflag);
3475 void print_keydup_error(TABLE *table, KEY *key, myf errflag);
3476 
3477 #endif /* HANDLER_INCLUDED */