My Project
handler.h
00001 #ifndef HANDLER_INCLUDED
00002 #define HANDLER_INCLUDED
00003 
00004 /*
00005    Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
00006 
00007    This program is free software; you can redistribute it and/or
00008    modify it under the terms of the GNU General Public License
00009    as published by the Free Software Foundation; version 2 of
00010    the License.
00011 
00012    This program is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00015    GNU General Public License for more details.
00016 
00017    You should have received a copy of the GNU General Public License
00018    along with this program; if not, write to the Free Software
00019    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
00020 */
00021 
00022 /* Definitions for parameters to do with handler-routines */
00023 
00024 #include "my_pthread.h"
00025 #include <algorithm>
00026 #include "sql_const.h"
00027 #include "mysqld.h"                             /* server_id */
00028 #include "sql_plugin.h"        /* plugin_ref, st_plugin_int, plugin */
00029 #include "thr_lock.h"          /* thr_lock_type, THR_LOCK_DATA */
00030 #include "sql_cache.h"
00031 #include "structs.h"                            /* SHOW_COMP_OPTION */
00032 
00033 #include <my_global.h>
00034 #include <my_compare.h>
00035 #include <ft_global.h>
00036 #include <keycache.h>
00037 
00038 class Alter_info;
00039 
00040 // the following is for checking tables
00041 
00042 #define HA_ADMIN_ALREADY_DONE     1
00043 #define HA_ADMIN_OK               0
00044 #define HA_ADMIN_NOT_IMPLEMENTED -1
00045 #define HA_ADMIN_FAILED          -2
00046 #define HA_ADMIN_CORRUPT         -3
00047 #define HA_ADMIN_INTERNAL_ERROR  -4
00048 #define HA_ADMIN_INVALID         -5
00049 #define HA_ADMIN_REJECT          -6
00050 #define HA_ADMIN_TRY_ALTER       -7
00051 #define HA_ADMIN_WRONG_CHECKSUM  -8
00052 #define HA_ADMIN_NOT_BASE_TABLE  -9
00053 #define HA_ADMIN_NEEDS_UPGRADE  -10
00054 #define HA_ADMIN_NEEDS_ALTER    -11
00055 #define HA_ADMIN_NEEDS_CHECK    -12
00056 
00063 enum enum_alter_inplace_result {
00064   HA_ALTER_ERROR,
00065   HA_ALTER_INPLACE_NOT_SUPPORTED,
00066   HA_ALTER_INPLACE_EXCLUSIVE_LOCK,
00067   HA_ALTER_INPLACE_SHARED_LOCK_AFTER_PREPARE,
00068   HA_ALTER_INPLACE_SHARED_LOCK,
00069   HA_ALTER_INPLACE_NO_LOCK_AFTER_PREPARE,
00070   HA_ALTER_INPLACE_NO_LOCK
00071 };
00072 
00073 /* Bits in table_flags() to show what database can do */
00074 
00075 #define HA_NO_TRANSACTIONS     (1 << 0) /* Doesn't support transactions */
00076 #define HA_PARTIAL_COLUMN_READ (1 << 1) /* read may not return all columns */
00077 #define HA_TABLE_SCAN_ON_INDEX (1 << 2) /* No separate data/index file */
00078 /*
00079   The following should be set if the following is not true when scanning
00080   a table with rnd_next()
00081   - We will see all rows (including deleted ones)
00082   - Row positions are 'table->s->db_record_offset' apart
00083   If this flag is not set, filesort will do a position() call for each matched
00084   row to be able to find the row later.
00085 */
00086 #define HA_REC_NOT_IN_SEQ      (1 << 3)
00087 #define HA_CAN_GEOMETRY        (1 << 4)
00088 /*
00089   Reading keys in random order is as fast as reading keys in sort order
00090   (Used in records.cc to decide if we should use a record cache and by
00091   filesort to decide if we should sort key + data or key + pointer-to-row
00092 */
00093 #define HA_FAST_KEY_READ       (1 << 5)
00094 /*
00095   Set the following flag if we on delete should force all key to be read
00096   and on update read all keys that changes
00097 */
00098 #define HA_REQUIRES_KEY_COLUMNS_FOR_DELETE (1 << 6)
00099 #define HA_NULL_IN_KEY         (1 << 7) /* One can have keys with NULL */
00100 #define HA_DUPLICATE_POS       (1 << 8)    /* position() gives dup row */
00101 #define HA_NO_BLOBS            (1 << 9) /* Doesn't support blobs */
00102 #define HA_CAN_INDEX_BLOBS     (1 << 10)
00103 #define HA_AUTO_PART_KEY       (1 << 11) /* auto-increment in multi-part key */
00104 #define HA_REQUIRE_PRIMARY_KEY (1 << 12) /* .. and can't create a hidden one */
00105 #define HA_STATS_RECORDS_IS_EXACT (1 << 13) /* stats.records is exact */
00106 /*
00107   INSERT_DELAYED only works with handlers that uses MySQL internal table
00108   level locks
00109 */
00110 #define HA_CAN_INSERT_DELAYED  (1 << 14)
00111 /*
00112   If we get the primary key columns for free when we do an index read
00113   (usually, it also implies that HA_PRIMARY_KEY_REQUIRED_FOR_POSITION
00114   flag is set).
00115 */
00116 #define HA_PRIMARY_KEY_IN_READ_INDEX (1 << 15)
00117 /*
00118   If HA_PRIMARY_KEY_REQUIRED_FOR_POSITION is set, it means that to position()
00119   uses a primary key given by the record argument.
00120   Without primary key, we can't call position().
00121   If not set, the position is returned as the current rows position
00122   regardless of what argument is given.
00123 */ 
00124 #define HA_PRIMARY_KEY_REQUIRED_FOR_POSITION (1 << 16) 
00125 #define HA_CAN_RTREEKEYS       (1 << 17)
00126 #define HA_NOT_DELETE_WITH_CACHE (1 << 18)
00127 /*
00128   The following is we need to a primary key to delete (and update) a row.
00129   If there is no primary key, all columns needs to be read on update and delete
00130 */
00131 #define HA_PRIMARY_KEY_REQUIRED_FOR_DELETE (1 << 19)
00132 #define HA_NO_PREFIX_CHAR_KEYS (1 << 20)
00133 #define HA_CAN_FULLTEXT        (1 << 21)
00134 #define HA_CAN_SQL_HANDLER     (1 << 22)
00135 #define HA_NO_AUTO_INCREMENT   (1 << 23)
00136 #define HA_HAS_CHECKSUM        (1 << 24)
00137 /* Table data are stored in separate files (for lower_case_table_names) */
00138 #define HA_FILE_BASED          (1 << 26)
00139 #define HA_NO_VARCHAR          (1 << 27)
00140 #define HA_CAN_BIT_FIELD       (1 << 28) /* supports bit fields */
00141 #define HA_ANY_INDEX_MAY_BE_UNIQUE (1 << 30)
00142 #define HA_NO_COPY_ON_ALTER    (LL(1) << 31)
00143 #define HA_HAS_RECORDS         (LL(1) << 32) /* records() gives exact count*/
00144 /* Has it's own method of binlog logging */
00145 #define HA_HAS_OWN_BINLOGGING  (LL(1) << 33)
00146 /*
00147   Engine is capable of row-format and statement-format logging,
00148   respectively
00149 */
00150 #define HA_BINLOG_ROW_CAPABLE  (LL(1) << 34)
00151 #define HA_BINLOG_STMT_CAPABLE (LL(1) << 35)
00152 /*
00153     When a multiple key conflict happens in a REPLACE command mysql
00154     expects the conflicts to be reported in the ascending order of
00155     key names.
00156 
00157     For e.g.
00158 
00159     CREATE TABLE t1 (a INT, UNIQUE (a), b INT NOT NULL, UNIQUE (b), c INT NOT
00160                      NULL, INDEX(c));
00161 
00162     REPLACE INTO t1 VALUES (1,1,1),(2,2,2),(2,1,3);
00163 
00164     MySQL expects the conflict with 'a' to be reported before the conflict with
00165     'b'.
00166 
00167     If the underlying storage engine does not report the conflicting keys in
00168     ascending order, it causes unexpected errors when the REPLACE command is
00169     executed.
00170 
00171     This flag helps the underlying SE to inform the server that the keys are not
00172     ordered.
00173 */
00174 #define HA_DUPLICATE_KEY_NOT_IN_ORDER    (LL(1) << 36)
00175 /*
00176   Engine supports REPAIR TABLE. Used by CHECK TABLE FOR UPGRADE if an
00177   incompatible table is detected. If this flag is set, CHECK TABLE FOR UPGRADE
00178   will report ER_TABLE_NEEDS_UPGRADE, otherwise ER_TABLE_NEED_REBUILD.
00179 */
00180 #define HA_CAN_REPAIR                    (LL(1) << 37)
00181 
00182 /*
00183   Set of all binlog flags. Currently only contain the capabilities
00184   flags.
00185  */
00186 #define HA_BINLOG_FLAGS (HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE)
00187 
00220 #define HA_READ_BEFORE_WRITE_REMOVAL  (LL(1) << 38)
00221 
00222 /*
00223   Engine supports extended fulltext API
00224  */
00225 #define HA_CAN_FULLTEXT_EXT              (LL(1) << 39)
00226 
00227 /*
00228   Storage engine doesn't synchronize result set with expected table contents.
00229   Used by replication slave to check if it is possible to retrieve rows from
00230   the table when deciding whether to do a full table scan, index scan or hash
00231   scan while applying a row event.
00232  */
00233 #define HA_READ_OUT_OF_SYNC              (LL(1) << 40)
00234 
00235 /*
00236   Storage engine supports table export using the
00237   FLUSH TABLE <table_list> FOR EXPORT statement.
00238  */
00239 #define HA_CAN_EXPORT                 (LL(1) << 41)
00240 
00241 /*
00242   The handler don't want accesses to this table to 
00243   be const-table optimized
00244 */
00245 #define HA_BLOCK_CONST_TABLE          (LL(1) << 42)
00246 
00247 /* bits in index_flags(index_number) for what you can do with index */
00248 #define HA_READ_NEXT            1       /* TODO really use this flag */
00249 #define HA_READ_PREV            2       /* supports ::index_prev */
00250 #define HA_READ_ORDER           4       /* index_next/prev follow sort order */
00251 #define HA_READ_RANGE           8       /* can find all records in a range */
00252 #define HA_ONLY_WHOLE_INDEX     16      /* Can't use part key searches */
00253 #define HA_KEYREAD_ONLY         64      /* Support HA_EXTRA_KEYREAD */
00254 /*
00255   Index scan will not return records in rowid order. Not guaranteed to be
00256   set for unordered (e.g. HASH) indexes.
00257 */
00258 #define HA_KEY_SCAN_NOT_ROR     128 
00259 #define HA_DO_INDEX_COND_PUSHDOWN  256 /* Supports Index Condition Pushdown */
00260 
00261 
00262 
00290 #define HA_PARTITION_FUNCTION_SUPPORTED         (1L << 0)
00291 #define HA_FAST_CHANGE_PARTITION                (1L << 1)
00292 #define HA_PARTITION_ONE_PHASE                  (1L << 2)
00293 
00294 /* operations for disable/enable indexes */
00295 #define HA_KEY_SWITCH_NONUNIQ      0
00296 #define HA_KEY_SWITCH_ALL          1
00297 #define HA_KEY_SWITCH_NONUNIQ_SAVE 2
00298 #define HA_KEY_SWITCH_ALL_SAVE     3
00299 
00300 /*
00301   Note: the following includes binlog and closing 0.
00302   so: innodb + bdb + ndb + binlog + myisam + myisammrg + archive +
00303       example + csv + heap + blackhole + federated + 0
00304   (yes, the sum is deliberately inaccurate)
00305   TODO remove the limit, use dynarrays
00306 */
00307 #define MAX_HA 15
00308 
00309 /*
00310   Use this instead of 0 as the initial value for the slot number of
00311   handlerton, so that we can distinguish uninitialized slot number
00312   from slot 0.
00313 */
00314 #define HA_SLOT_UNDEF ((uint)-1)
00315 
00316 /*
00317   Parameters for open() (in register form->filestat)
00318   HA_GET_INFO does an implicit HA_ABORT_IF_LOCKED
00319 */
00320 
00321 #define HA_OPEN_KEYFILE         1
00322 #define HA_OPEN_RNDFILE         2
00323 #define HA_GET_INDEX            4
00324 #define HA_GET_INFO             8       /* do a ha_info() after open */
00325 #define HA_READ_ONLY            16      /* File opened as readonly */
00326 /* Try readonly if can't open with read and write */
00327 #define HA_TRY_READ_ONLY        32
00328 #define HA_WAIT_IF_LOCKED       64      /* Wait if locked on open */
00329 #define HA_ABORT_IF_LOCKED      128     /* skip if locked on open.*/
00330 #define HA_BLOCK_LOCK           256     /* unlock when reading some records */
00331 #define HA_OPEN_TEMPORARY       512
00332 
00333         /* Some key definitions */
00334 #define HA_KEY_NULL_LENGTH      1
00335 #define HA_KEY_BLOB_LENGTH      2
00336 
00337 #define HA_LEX_CREATE_TMP_TABLE 1
00338 #define HA_LEX_CREATE_IF_NOT_EXISTS 2
00339 #define HA_LEX_CREATE_TABLE_LIKE 4
00340 #define HA_OPTION_NO_CHECKSUM   (1L << 17)
00341 #define HA_OPTION_NO_DELAY_KEY_WRITE (1L << 18)
00342 #define HA_MAX_REC_LENGTH       65535U
00343 
00344 /* Table caching type */
00345 #define HA_CACHE_TBL_NONTRANSACT 0
00346 #define HA_CACHE_TBL_NOCACHE     1
00347 #define HA_CACHE_TBL_ASKTRANSACT 2
00348 #define HA_CACHE_TBL_TRANSACT    4
00349 
00362 // WITH CONSISTENT SNAPSHOT option
00363 static const uint MYSQL_START_TRANS_OPT_WITH_CONS_SNAPSHOT = 1;
00364 // READ ONLY option
00365 static const uint MYSQL_START_TRANS_OPT_READ_ONLY          = 2;
00366 // READ WRITE option
00367 static const uint MYSQL_START_TRANS_OPT_READ_WRITE         = 4;
00368 
00369 /* Flags for method is_fatal_error */
00370 #define HA_CHECK_DUP_KEY 1
00371 #define HA_CHECK_DUP_UNIQUE 2
00372 #define HA_CHECK_DUP (HA_CHECK_DUP_KEY + HA_CHECK_DUP_UNIQUE)
00373 
00374 enum legacy_db_type
00375 {
00376   DB_TYPE_UNKNOWN=0,DB_TYPE_DIAB_ISAM=1,
00377   DB_TYPE_HASH,DB_TYPE_MISAM,DB_TYPE_PISAM,
00378   DB_TYPE_RMS_ISAM, DB_TYPE_HEAP, DB_TYPE_ISAM,
00379   DB_TYPE_MRG_ISAM, DB_TYPE_MYISAM, DB_TYPE_MRG_MYISAM,
00380   DB_TYPE_BERKELEY_DB, DB_TYPE_INNODB,
00381   DB_TYPE_GEMINI, DB_TYPE_NDBCLUSTER,
00382   DB_TYPE_EXAMPLE_DB, DB_TYPE_ARCHIVE_DB, DB_TYPE_CSV_DB,
00383   DB_TYPE_FEDERATED_DB,
00384   DB_TYPE_BLACKHOLE_DB,
00385   DB_TYPE_PARTITION_DB,
00386   DB_TYPE_BINLOG,
00387   DB_TYPE_SOLID,
00388   DB_TYPE_PBXT,
00389   DB_TYPE_TABLE_FUNCTION,
00390   DB_TYPE_MEMCACHE,
00391   DB_TYPE_FALCON,
00392   DB_TYPE_MARIA,
00394   DB_TYPE_PERFORMANCE_SCHEMA,
00395   DB_TYPE_FIRST_DYNAMIC=42,
00396   DB_TYPE_DEFAULT=127 // Must be last
00397 };
00398 
00399 enum row_type { ROW_TYPE_NOT_USED=-1, ROW_TYPE_DEFAULT, ROW_TYPE_FIXED,
00400                 ROW_TYPE_DYNAMIC, ROW_TYPE_COMPRESSED,
00401                 ROW_TYPE_REDUNDANT, ROW_TYPE_COMPACT,
00403                 ROW_TYPE_PAGE };
00404 
00405 /* Specifies data storage format for individual columns */
00406 enum column_format_type {
00407   COLUMN_FORMAT_TYPE_DEFAULT=   0, /* Not specified (use engine default) */
00408   COLUMN_FORMAT_TYPE_FIXED=     1, /* FIXED format */
00409   COLUMN_FORMAT_TYPE_DYNAMIC=   2  /* DYNAMIC format */
00410 };
00411 
00412 enum enum_binlog_func {
00413   BFN_RESET_LOGS=        1,
00414   BFN_RESET_SLAVE=       2,
00415   BFN_BINLOG_WAIT=       3,
00416   BFN_BINLOG_END=        4,
00417   BFN_BINLOG_PURGE_FILE= 5
00418 };
00419 
00420 enum enum_binlog_command {
00421   LOGCOM_CREATE_TABLE,
00422   LOGCOM_ALTER_TABLE,
00423   LOGCOM_RENAME_TABLE,
00424   LOGCOM_DROP_TABLE,
00425   LOGCOM_CREATE_DB,
00426   LOGCOM_ALTER_DB,
00427   LOGCOM_DROP_DB
00428 };
00429 
00430 /* struct to hold information about the table that should be created */
00431 
00432 /* Bits in used_fields */
00433 #define HA_CREATE_USED_AUTO             (1L << 0)
00434 #define HA_CREATE_USED_RAID             (1L << 1) //RAID is no longer availble
00435 #define HA_CREATE_USED_UNION            (1L << 2)
00436 #define HA_CREATE_USED_INSERT_METHOD    (1L << 3)
00437 #define HA_CREATE_USED_MIN_ROWS         (1L << 4)
00438 #define HA_CREATE_USED_MAX_ROWS         (1L << 5)
00439 #define HA_CREATE_USED_AVG_ROW_LENGTH   (1L << 6)
00440 #define HA_CREATE_USED_PACK_KEYS        (1L << 7)
00441 #define HA_CREATE_USED_CHARSET          (1L << 8)
00442 #define HA_CREATE_USED_DEFAULT_CHARSET  (1L << 9)
00443 #define HA_CREATE_USED_DATADIR          (1L << 10)
00444 #define HA_CREATE_USED_INDEXDIR         (1L << 11)
00445 #define HA_CREATE_USED_ENGINE           (1L << 12)
00446 #define HA_CREATE_USED_CHECKSUM         (1L << 13)
00447 #define HA_CREATE_USED_DELAY_KEY_WRITE  (1L << 14)
00448 #define HA_CREATE_USED_ROW_FORMAT       (1L << 15)
00449 #define HA_CREATE_USED_COMMENT          (1L << 16)
00450 #define HA_CREATE_USED_PASSWORD         (1L << 17)
00451 #define HA_CREATE_USED_CONNECTION       (1L << 18)
00452 #define HA_CREATE_USED_KEY_BLOCK_SIZE   (1L << 19)
00453 
00454 #define HA_CREATE_USED_TRANSACTIONAL    (1L << 20)
00455 
00456 #define HA_CREATE_USED_PAGE_CHECKSUM    (1L << 21)
00457 
00462 #define HA_CREATE_USED_STATS_PERSISTENT (1L << 22)
00463 
00469 #define HA_CREATE_USED_STATS_AUTO_RECALC (1L << 23)
00470 
00476 #define HA_CREATE_USED_STATS_SAMPLE_PAGES (1L << 24)
00477 
00478 
00479 /*
00480   This is master database for most of system tables. However there
00481   can be other databases which can hold system tables. Respective
00482   storage engines define their own system database names.
00483 */
00484 extern const char *mysqld_system_database;
00485 
00486 /*
00487   Structure to hold list of system_database.system_table.
00488   This is used at both mysqld and storage engine layer.
00489 */
00490 struct st_system_tablename
00491 {
00492   const char *db;
00493   const char *tablename;
00494 };
00495 
00496 
00497 typedef ulonglong my_xid; // this line is the same as in log_event.h
00498 #define MYSQL_XID_PREFIX "MySQLXid"
00499 #define MYSQL_XID_PREFIX_LEN 8 // must be a multiple of 8
00500 #define MYSQL_XID_OFFSET (MYSQL_XID_PREFIX_LEN+sizeof(server_id))
00501 #define MYSQL_XID_GTRID_LEN (MYSQL_XID_OFFSET+sizeof(my_xid))
00502 
00503 #define XIDDATASIZE MYSQL_XIDDATASIZE
00504 #define MAXGTRIDSIZE 64
00505 #define MAXBQUALSIZE 64
00506 
00507 #define COMPATIBLE_DATA_YES 0
00508 #define COMPATIBLE_DATA_NO  1
00509 
00510 namespace AQP {
00511   class Join_plan;
00512 };
00513 
00522 struct xid_t {
00523   long formatID;
00524   long gtrid_length;
00525   long bqual_length;
00526   char data[XIDDATASIZE];  // not \0-terminated !
00527 
00528   xid_t() {}                                /* Remove gcc warning */  
00529   bool eq(struct xid_t *xid)
00530   { return eq(xid->gtrid_length, xid->bqual_length, xid->data); }
00531   bool eq(long g, long b, const char *d)
00532   { return g == gtrid_length && b == bqual_length && !memcmp(d, data, g+b); }
00533   void set(struct xid_t *xid)
00534   { memcpy(this, xid, xid->length()); }
00535   void set(long f, const char *g, long gl, const char *b, long bl)
00536   {
00537     formatID= f;
00538     memcpy(data, g, gtrid_length= gl);
00539     memcpy(data+gl, b, bqual_length= bl);
00540   }
00541   void set(ulonglong xid)
00542   {
00543     my_xid tmp;
00544     formatID= 1;
00545     set(MYSQL_XID_PREFIX_LEN, 0, MYSQL_XID_PREFIX);
00546     memcpy(data+MYSQL_XID_PREFIX_LEN, &server_id, sizeof(server_id));
00547     tmp= xid;
00548     memcpy(data+MYSQL_XID_OFFSET, &tmp, sizeof(tmp));
00549     gtrid_length=MYSQL_XID_GTRID_LEN;
00550   }
00551   void set(long g, long b, const char *d)
00552   {
00553     formatID= 1;
00554     gtrid_length= g;
00555     bqual_length= b;
00556     memcpy(data, d, g+b);
00557   }
00558   bool is_null() { return formatID == -1; }
00559   void null() { formatID= -1; }
00560   my_xid quick_get_my_xid()
00561   {
00562     my_xid tmp;
00563     memcpy(&tmp, data+MYSQL_XID_OFFSET, sizeof(tmp));
00564     return tmp;
00565   }
00566   my_xid get_my_xid()
00567   {
00568     return gtrid_length == MYSQL_XID_GTRID_LEN && bqual_length == 0 &&
00569            !memcmp(data, MYSQL_XID_PREFIX, MYSQL_XID_PREFIX_LEN) ?
00570            quick_get_my_xid() : 0;
00571   }
00572   uint length()
00573   {
00574     return sizeof(formatID)+sizeof(gtrid_length)+sizeof(bqual_length)+
00575            gtrid_length+bqual_length;
00576   }
00577   uchar *key()
00578   {
00579     return (uchar *)&gtrid_length;
00580   }
00581   uint key_length()
00582   {
00583     return sizeof(gtrid_length)+sizeof(bqual_length)+gtrid_length+bqual_length;
00584   }
00585 };
00586 typedef struct xid_t XID;
00587 
00588 /* for recover() handlerton call */
00589 #define MIN_XID_LIST_SIZE  128
00590 #define MAX_XID_LIST_SIZE  (1024*128)
00591 
00592 /*
00593   These structures are used to pass information from a set of SQL commands
00594   on add/drop/change tablespace definitions to the proper hton.
00595 */
00596 #define UNDEF_NODEGROUP 65535
00597 enum ts_command_type
00598 {
00599   TS_CMD_NOT_DEFINED = -1,
00600   CREATE_TABLESPACE = 0,
00601   ALTER_TABLESPACE = 1,
00602   CREATE_LOGFILE_GROUP = 2,
00603   ALTER_LOGFILE_GROUP = 3,
00604   DROP_TABLESPACE = 4,
00605   DROP_LOGFILE_GROUP = 5,
00606   CHANGE_FILE_TABLESPACE = 6,
00607   ALTER_ACCESS_MODE_TABLESPACE = 7
00608 };
00609 
00610 enum ts_alter_tablespace_type
00611 {
00612   TS_ALTER_TABLESPACE_TYPE_NOT_DEFINED = -1,
00613   ALTER_TABLESPACE_ADD_FILE = 1,
00614   ALTER_TABLESPACE_DROP_FILE = 2
00615 };
00616 
00617 enum tablespace_access_mode
00618 {
00619   TS_NOT_DEFINED= -1,
00620   TS_READ_ONLY = 0,
00621   TS_READ_WRITE = 1,
00622   TS_NOT_ACCESSIBLE = 2
00623 };
00624 
00625 struct handlerton;
00626 class st_alter_tablespace : public Sql_alloc
00627 {
00628   public:
00629   const char *tablespace_name;
00630   const char *logfile_group_name;
00631   enum ts_command_type ts_cmd_type;
00632   enum ts_alter_tablespace_type ts_alter_tablespace_type;
00633   const char *data_file_name;
00634   const char *undo_file_name;
00635   const char *redo_file_name;
00636   ulonglong extent_size;
00637   ulonglong undo_buffer_size;
00638   ulonglong redo_buffer_size;
00639   ulonglong initial_size;
00640   ulonglong autoextend_size;
00641   ulonglong max_size;
00642   uint nodegroup_id;
00643   handlerton *storage_engine;
00644   bool wait_until_completed;
00645   const char *ts_comment;
00646   enum tablespace_access_mode ts_access_mode;
00647   st_alter_tablespace()
00648   {
00649     tablespace_name= NULL;
00650     logfile_group_name= "DEFAULT_LG"; //Default log file group
00651     ts_cmd_type= TS_CMD_NOT_DEFINED;
00652     data_file_name= NULL;
00653     undo_file_name= NULL;
00654     redo_file_name= NULL;
00655     extent_size= 1024*1024;        //Default 1 MByte
00656     undo_buffer_size= 8*1024*1024; //Default 8 MByte
00657     redo_buffer_size= 8*1024*1024; //Default 8 MByte
00658     initial_size= 128*1024*1024;   //Default 128 MByte
00659     autoextend_size= 0;            //No autoextension as default
00660     max_size= 0;                   //Max size == initial size => no extension
00661     storage_engine= NULL;
00662     nodegroup_id= UNDEF_NODEGROUP;
00663     wait_until_completed= TRUE;
00664     ts_comment= NULL;
00665     ts_access_mode= TS_NOT_DEFINED;
00666   }
00667 };
00668 
00669 /* The handler for a table type.  Will be included in the TABLE structure */
00670 
00671 struct TABLE;
00672 
00673 /*
00674   Make sure that the order of schema_tables and enum_schema_tables are the same.
00675 */
00676 enum enum_schema_tables
00677 {
00678   SCH_CHARSETS= 0,
00679   SCH_COLLATIONS,
00680   SCH_COLLATION_CHARACTER_SET_APPLICABILITY,
00681   SCH_COLUMNS,
00682   SCH_COLUMN_PRIVILEGES,
00683   SCH_ENGINES,
00684   SCH_EVENTS,
00685   SCH_FILES,
00686   SCH_GLOBAL_STATUS,
00687   SCH_GLOBAL_VARIABLES,
00688   SCH_KEY_COLUMN_USAGE,
00689   SCH_OPEN_TABLES,
00690   SCH_OPTIMIZER_TRACE,
00691   SCH_PARAMETERS,
00692   SCH_PARTITIONS,
00693   SCH_PLUGINS,
00694   SCH_PROCESSLIST,
00695   SCH_PROFILES,
00696   SCH_REFERENTIAL_CONSTRAINTS,
00697   SCH_PROCEDURES,
00698   SCH_SCHEMATA,
00699   SCH_SCHEMA_PRIVILEGES,
00700   SCH_SESSION_STATUS,
00701   SCH_SESSION_VARIABLES,
00702   SCH_STATISTICS,
00703   SCH_STATUS,
00704   SCH_TABLES,
00705   SCH_TABLESPACES,
00706   SCH_TABLE_CONSTRAINTS,
00707   SCH_TABLE_NAMES,
00708   SCH_TABLE_PRIVILEGES,
00709   SCH_TRIGGERS,
00710   SCH_USER_PRIVILEGES,
00711   SCH_VARIABLES,
00712   SCH_VIEWS
00713 };
00714 
00715 struct TABLE_SHARE;
00716 struct st_foreign_key_info;
00717 typedef struct st_foreign_key_info FOREIGN_KEY_INFO;
00718 typedef bool (stat_print_fn)(THD *thd, const char *type, uint type_len,
00719                              const char *file, uint file_len,
00720                              const char *status, uint status_len);
00721 enum ha_stat_type { HA_ENGINE_STATUS, HA_ENGINE_LOGS, HA_ENGINE_MUTEX };
00722 extern st_plugin_int *hton2plugin[MAX_HA];
00723 
00724 /* Transaction log maintains type definitions */
00725 enum log_status
00726 {
00727   HA_LOG_STATUS_FREE= 0,      /* log is free and can be deleted */
00728   HA_LOG_STATUS_INUSE= 1,     /* log can't be deleted because it is in use */
00729   HA_LOG_STATUS_NOSUCHLOG= 2  /* no such log (can't be returned by
00730                                 the log iterator status) */
00731 };
00732 /*
00733   Function for signaling that the log file changed its state from
00734   LOG_STATUS_INUSE to LOG_STATUS_FREE
00735 
00736   Now it do nothing, will be implemented as part of new transaction
00737   log management for engines.
00738   TODO: implement the function.
00739 */
00740 void signal_log_not_needed(struct handlerton, char *log_file);
00741 /*
00742   Data of transaction log iterator.
00743 */
00744 struct handler_log_file_data {
00745   LEX_STRING filename;
00746   enum log_status status;
00747 };
00748 
00749 
00750 enum handler_iterator_type
00751 {
00752   /* request of transaction log iterator */
00753   HA_TRANSACTLOG_ITERATOR= 1
00754 };
00755 enum handler_create_iterator_result
00756 {
00757   HA_ITERATOR_OK,          /* iterator created */
00758   HA_ITERATOR_UNSUPPORTED, /* such type of iterator is not supported */
00759   HA_ITERATOR_ERROR        /* error during iterator creation */
00760 };
00761 
00762 /*
00763   Iterator structure. Can be used by handler/handlerton for different purposes.
00764 
00765   Iterator should be created in the way to point "before" the first object
00766   it iterate, so next() call move it to the first object or return !=0 if
00767   there is nothing to iterate through.
00768 */
00769 struct handler_iterator {
00770   /*
00771     Moves iterator to next record and return 0 or return !=0
00772     if there is no records.
00773     iterator_object will be filled by this function if next() returns 0.
00774     Content of the iterator_object depend on iterator type.
00775   */
00776   int (*next)(struct handler_iterator *, void *iterator_object);
00777   /*
00778     Free resources allocated by iterator, after this call iterator
00779     is not usable.
00780   */
00781   void (*destroy)(struct handler_iterator *);
00782   /*
00783     Pointer to buffer for the iterator to use.
00784     Should be allocated by function which created the iterator and
00785     destroied by freed by above "destroy" call
00786   */
00787   void *buffer;
00788 };
00789 
00790 class handler;
00791 /*
00792   handlerton is a singleton structure - one instance per storage engine -
00793   to provide access to storage engine functionality that works on the
00794   "global" level (unlike handler class that works on a per-table basis)
00795 
00796   usually handlerton instance is defined statically in ha_xxx.cc as
00797 
00798   static handlerton { ... } xxx_hton;
00799 
00800   savepoint_*, prepare, recover, and *_by_xid pointers can be 0.
00801 */
00802 struct handlerton
00803 {
00804   /*
00805     Historical marker for if the engine is available of not
00806   */
00807   SHOW_COMP_OPTION state;
00808 
00809   /*
00810     Historical number used for frm file to determine the correct storage engine.
00811     This is going away and new engines will just use "name" for this.
00812   */
00813   enum legacy_db_type db_type;
00814   /*
00815     each storage engine has it's own memory area (actually a pointer)
00816     in the thd, for storing per-connection information.
00817     It is accessed as
00818 
00819       thd->ha_data[xxx_hton.slot]
00820 
00821    slot number is initialized by MySQL after xxx_init() is called.
00822    */
00823    uint slot;
00824    /*
00825      to store per-savepoint data storage engine is provided with an area
00826      of a requested size (0 is ok here).
00827      savepoint_offset must be initialized statically to the size of
00828      the needed memory to store per-savepoint information.
00829      After xxx_init it is changed to be an offset to savepoint storage
00830      area and need not be used by storage engine.
00831      see binlog_hton and binlog_savepoint_set/rollback for an example.
00832    */
00833    uint savepoint_offset;
00834    /*
00835      handlerton methods:
00836 
00837      close_connection is only called if
00838      thd->ha_data[xxx_hton.slot] is non-zero, so even if you don't need
00839      this storage area - set it to something, so that MySQL would know
00840      this storage engine was accessed in this connection
00841    */
00842    int  (*close_connection)(handlerton *hton, THD *thd);
00843    /*
00844      sv points to an uninitialized storage area of requested size
00845      (see savepoint_offset description)
00846    */
00847    int  (*savepoint_set)(handlerton *hton, THD *thd, void *sv);
00848    /*
00849      sv points to a storage area, that was earlier passed
00850      to the savepoint_set call
00851    */
00852    int  (*savepoint_rollback)(handlerton *hton, THD *thd, void *sv);
00859    bool (*savepoint_rollback_can_release_mdl)(handlerton *hton, THD *thd);
00860    int  (*savepoint_release)(handlerton *hton, THD *thd, void *sv);
00861    /*
00862      'all' is true if it's a real commit, that makes persistent changes
00863      'all' is false if it's not in fact a commit but an end of the
00864      statement that is part of the transaction.
00865      NOTE 'all' is also false in auto-commit mode where 'end of statement'
00866      and 'real commit' mean the same event.
00867    */
00868    int  (*commit)(handlerton *hton, THD *thd, bool all);
00869    int  (*rollback)(handlerton *hton, THD *thd, bool all);
00870    int  (*prepare)(handlerton *hton, THD *thd, bool all);
00871    int  (*recover)(handlerton *hton, XID *xid_list, uint len);
00872    int  (*commit_by_xid)(handlerton *hton, XID *xid);
00873    int  (*rollback_by_xid)(handlerton *hton, XID *xid);
00874    void *(*create_cursor_read_view)(handlerton *hton, THD *thd);
00875    void (*set_cursor_read_view)(handlerton *hton, THD *thd, void *read_view);
00876    void (*close_cursor_read_view)(handlerton *hton, THD *thd, void *read_view);
00877    handler *(*create)(handlerton *hton, TABLE_SHARE *table, MEM_ROOT *mem_root);
00878    void (*drop_database)(handlerton *hton, char* path);
00879    int (*panic)(handlerton *hton, enum ha_panic_function flag);
00880    int (*start_consistent_snapshot)(handlerton *hton, THD *thd);
00881    bool (*flush_logs)(handlerton *hton);
00882    bool (*show_status)(handlerton *hton, THD *thd, stat_print_fn *print, enum ha_stat_type stat);
00883    uint (*partition_flags)();
00884    uint (*alter_table_flags)(uint flags);
00885    int (*alter_tablespace)(handlerton *hton, THD *thd, st_alter_tablespace *ts_info);
00886    int (*fill_is_table)(handlerton *hton, THD *thd, TABLE_LIST *tables, 
00887                         class Item *cond, 
00888                         enum enum_schema_tables);
00889    uint32 flags;                                /* global handler flags */
00890    /*
00891       Those handlerton functions below are properly initialized at handler
00892       init.
00893    */
00894    int (*binlog_func)(handlerton *hton, THD *thd, enum_binlog_func fn, void *arg);
00895    void (*binlog_log_query)(handlerton *hton, THD *thd, 
00896                             enum_binlog_command binlog_command,
00897                             const char *query, uint query_length,
00898                             const char *db, const char *table_name);
00899    int (*release_temporary_latches)(handlerton *hton, THD *thd);
00900 
00901    /*
00902      Get log status.
00903      If log_status is null then the handler do not support transaction
00904      log information (i.e. log iterator can't be created).
00905      (see example of implementation in handler.cc, TRANS_LOG_MGM_EXAMPLE_CODE)
00906 
00907    */
00908    enum log_status (*get_log_status)(handlerton *hton, char *log);
00909 
00910    /*
00911      Iterators creator.
00912      Presence of the pointer should be checked before using
00913    */
00914    enum handler_create_iterator_result
00915      (*create_iterator)(handlerton *hton, enum handler_iterator_type type,
00916                         struct handler_iterator *fill_this_in);
00917    int (*discover)(handlerton *hton, THD* thd, const char *db, 
00918                    const char *name,
00919                    uchar **frmblob, 
00920                    size_t *frmlen);
00921    int (*find_files)(handlerton *hton, THD *thd,
00922                      const char *db,
00923                      const char *path,
00924                      const char *wild, bool dir, List<LEX_STRING> *files);
00925    int (*table_exists_in_engine)(handlerton *hton, THD* thd, const char *db,
00926                                  const char *name);
00927    int (*make_pushed_join)(handlerton *hton, THD* thd, 
00928                            const AQP::Join_plan* plan);
00929 
00941   const char* (*system_database)();
00942 
00958   bool (*is_supported_system_table)(const char *db,
00959                                     const char *table_name,
00960                                     bool is_sql_layer_system_table);
00961 
00962    uint32 license; /* Flag for Engine License */
00963    void *data; /* Location for engines to keep personal structures */
00964 };
00965 
00966 
00967 /* Possible flags of a handlerton (there can be 32 of them) */
00968 #define HTON_NO_FLAGS                 0
00969 #define HTON_CLOSE_CURSORS_AT_COMMIT (1 << 0)
00970 #define HTON_ALTER_NOT_SUPPORTED     (1 << 1) //Engine does not support alter
00971 #define HTON_CAN_RECREATE            (1 << 2) //Delete all is used fro truncate
00972 #define HTON_HIDDEN                  (1 << 3) //Engine does not appear in lists
00973 #define HTON_FLUSH_AFTER_RENAME      (1 << 4)
00974 #define HTON_NOT_USER_SELECTABLE     (1 << 5)
00975 #define HTON_TEMPORARY_NOT_SUPPORTED (1 << 6) //Having temporary tables not supported
00976 #define HTON_SUPPORT_LOG_TABLES      (1 << 7) //Engine supports log tables
00977 #define HTON_NO_PARTITION            (1 << 8) //You can not partition these tables
00978 
00979 /*
00980   This flag should be set when deciding that the engine does not allow row based
00981   binary logging (RBL) optimizations.
00982 
00983   Currently, setting this flag, means that table's read/write_set will be left 
00984   untouched when logging changes to tables in this engine. In practice this 
00985   means that the server will not mess around with table->write_set and/or 
00986   table->read_set when using RBL and deciding whether to log full or minimal rows.
00987 
00988   It's valuable for instance for virtual tables, eg: Performance Schema which have
00989   no meaning for replication.
00990 */
00991 #define HTON_NO_BINLOG_ROW_OPT       (1 << 9)
00992 
01001 #define HTON_SUPPORTS_EXTENDED_KEYS  (1 << 10)
01002 // Engine supports foreign key constraint.
01003 #define HTON_SUPPORTS_FOREIGN_KEYS   (1 << 11)
01004 
01005 
01006 enum enum_tx_isolation { ISO_READ_UNCOMMITTED, ISO_READ_COMMITTED,
01007                          ISO_REPEATABLE_READ, ISO_SERIALIZABLE};
01008 
01009 
01010 typedef struct {
01011   ulonglong data_file_length;
01012   ulonglong max_data_file_length;
01013   ulonglong index_file_length;
01014   ulonglong delete_length;
01015   ha_rows records;
01016   ulong mean_rec_length;
01017   ulong create_time;
01018   ulong check_time;
01019   ulong update_time;
01020   ulonglong check_sum;
01021 } PARTITION_STATS;
01022 
01023 #define UNDEF_NODEGROUP 65535
01024 class Item;
01025 struct st_table_log_memory_entry;
01026 
01027 class partition_info;
01028 
01029 struct st_partition_iter;
01030 
01031 enum enum_ha_unused { HA_CHOICE_UNDEF, HA_CHOICE_NO, HA_CHOICE_YES };
01032 
01033 enum enum_stats_auto_recalc { HA_STATS_AUTO_RECALC_DEFAULT= 0,
01034                               HA_STATS_AUTO_RECALC_ON,
01035                               HA_STATS_AUTO_RECALC_OFF };
01036 
01037 typedef struct st_ha_create_information
01038 {
01039   const CHARSET_INFO *table_charset, *default_table_charset;
01040   LEX_STRING connect_string;
01041   const char *password, *tablespace;
01042   LEX_STRING comment;
01043   const char *data_file_name, *index_file_name;
01044   const char *alias;
01045   ulonglong max_rows,min_rows;
01046   ulonglong auto_increment_value;
01047   ulong table_options;
01048   ulong avg_row_length;
01049   ulong used_fields;
01050   ulong key_block_size;
01051   uint stats_sample_pages;              /* number of pages to sample during
01052                                         stats estimation, if used, otherwise 0. */
01053   enum_stats_auto_recalc stats_auto_recalc;
01054   SQL_I_List<TABLE_LIST> merge_list;
01055   handlerton *db_type;
01065   enum row_type row_type;
01066   uint null_bits;                       /* NULL bits at start of record */
01067   uint options;                         /* OR of HA_CREATE_ options */
01068   uint merge_insert_method;
01069   uint extra_size;                      /* length of extra data segment */
01070   bool varchar;                         /* 1 if table has a VARCHAR */
01071   enum ha_storage_media storage_media;  /* DEFAULT, DISK or MEMORY */
01072 } HA_CREATE_INFO;
01073 
01089 class inplace_alter_handler_ctx : public Sql_alloc
01090 {
01091 public:
01092   inplace_alter_handler_ctx() {}
01093 
01094   virtual ~inplace_alter_handler_ctx() {}
01095 };
01096 
01097 
01106 class Alter_inplace_info
01107 {
01108 public:
01123   typedef ulong HA_ALTER_FLAGS;
01124 
01125   // Add non-unique, non-primary index
01126   static const HA_ALTER_FLAGS ADD_INDEX                  = 1L << 0;
01127 
01128   // Drop non-unique, non-primary index
01129   static const HA_ALTER_FLAGS DROP_INDEX                 = 1L << 1;
01130 
01131   // Add unique, non-primary index
01132   static const HA_ALTER_FLAGS ADD_UNIQUE_INDEX           = 1L << 2;
01133 
01134   // Drop unique, non-primary index
01135   static const HA_ALTER_FLAGS DROP_UNIQUE_INDEX          = 1L << 3;
01136 
01137   // Add primary index
01138   static const HA_ALTER_FLAGS ADD_PK_INDEX               = 1L << 4;
01139 
01140   // Drop primary index
01141   static const HA_ALTER_FLAGS DROP_PK_INDEX              = 1L << 5;
01142 
01143   // Add column
01144   static const HA_ALTER_FLAGS ADD_COLUMN                 = 1L << 6;
01145 
01146   // Drop column
01147   static const HA_ALTER_FLAGS DROP_COLUMN                = 1L << 7;
01148 
01149   // Rename column
01150   static const HA_ALTER_FLAGS ALTER_COLUMN_NAME          = 1L << 8;
01151 
01152   // Change column datatype
01153   static const HA_ALTER_FLAGS ALTER_COLUMN_TYPE          = 1L << 9;
01154 
01161   static const HA_ALTER_FLAGS ALTER_COLUMN_EQUAL_PACK_LENGTH = 1L << 10;
01162 
01163   // Reorder column
01164   static const HA_ALTER_FLAGS ALTER_COLUMN_ORDER         = 1L << 11;
01165 
01166   // Change column from NOT NULL to NULL
01167   static const HA_ALTER_FLAGS ALTER_COLUMN_NULLABLE      = 1L << 12;
01168 
01169   // Change column from NULL to NOT NULL
01170   static const HA_ALTER_FLAGS ALTER_COLUMN_NOT_NULLABLE  = 1L << 13;
01171 
01172   // Set or remove default column value
01173   static const HA_ALTER_FLAGS ALTER_COLUMN_DEFAULT       = 1L << 14;
01174 
01175   // Add foreign key
01176   static const HA_ALTER_FLAGS ADD_FOREIGN_KEY            = 1L << 15;
01177 
01178   // Drop foreign key
01179   static const HA_ALTER_FLAGS DROP_FOREIGN_KEY           = 1L << 16;
01180 
01181   // table_options changed, see HA_CREATE_INFO::used_fields for details.
01182   static const HA_ALTER_FLAGS CHANGE_CREATE_OPTION       = 1L << 17;
01183 
01184   // Table is renamed
01185   static const HA_ALTER_FLAGS ALTER_RENAME               = 1L << 18;
01186 
01187   // Change the storage type of column 
01188   static const HA_ALTER_FLAGS ALTER_COLUMN_STORAGE_TYPE = 1L << 19;
01189 
01190   // Change the column format of column
01191   static const HA_ALTER_FLAGS ALTER_COLUMN_COLUMN_FORMAT = 1L << 20;
01192 
01193   // Add partition
01194   static const HA_ALTER_FLAGS ADD_PARTITION              = 1L << 21;
01195 
01196   // Drop partition
01197   static const HA_ALTER_FLAGS DROP_PARTITION             = 1L << 22;
01198 
01199   // Changing partition options
01200   static const HA_ALTER_FLAGS ALTER_PARTITION            = 1L << 23;
01201 
01202   // Coalesce partition
01203   static const HA_ALTER_FLAGS COALESCE_PARTITION         = 1L << 24;
01204 
01205   // Reorganize partition ... into
01206   static const HA_ALTER_FLAGS REORGANIZE_PARTITION       = 1L << 25;
01207 
01208   // Reorganize partition
01209   static const HA_ALTER_FLAGS ALTER_TABLE_REORG          = 1L << 26;
01210 
01211   // Remove partitioning
01212   static const HA_ALTER_FLAGS ALTER_REMOVE_PARTITIONING  = 1L << 27;
01213 
01214   // Partition operation with ALL keyword
01215   static const HA_ALTER_FLAGS ALTER_ALL_PARTITION        = 1L << 28;
01216 
01221   static const HA_ALTER_FLAGS RECREATE_TABLE             = 1L << 29;
01222 
01232   HA_CREATE_INFO *create_info;
01233 
01245   Alter_info *alter_info;
01246 
01262   KEY  *key_info_buffer;
01263 
01265   uint key_count;
01266 
01268   uint index_drop_count;
01269 
01274   KEY  **index_drop_buffer;
01275 
01277   uint index_add_count;
01278 
01283   uint *index_add_buffer;
01284 
01291   inplace_alter_handler_ctx *handler_ctx;
01292 
01303   inplace_alter_handler_ctx **group_commit_ctx;
01304 
01308   HA_ALTER_FLAGS handler_flags;
01309 
01316   partition_info *modified_part_info;
01317 
01319   const bool ignore;
01320 
01322   bool online;
01323 
01336   const char *unsupported_reason;
01337 
01338   Alter_inplace_info(HA_CREATE_INFO *create_info_arg,
01339                      Alter_info *alter_info_arg,
01340                      KEY *key_info_arg, uint key_count_arg,
01341                      partition_info *modified_part_info_arg,
01342                      bool ignore_arg)
01343     : create_info(create_info_arg),
01344     alter_info(alter_info_arg),
01345     key_info_buffer(key_info_arg),
01346     key_count(key_count_arg),
01347     index_drop_count(0),
01348     index_drop_buffer(NULL),
01349     index_add_count(0),
01350     index_add_buffer(NULL),
01351     handler_ctx(NULL),
01352     group_commit_ctx(NULL),
01353     handler_flags(0),
01354     modified_part_info(modified_part_info_arg),
01355     ignore(ignore_arg),
01356     online(false),
01357     unsupported_reason(NULL)
01358   {}
01359 
01360   ~Alter_inplace_info()
01361   {
01362     delete handler_ctx;
01363   }
01364 
01374   void report_unsupported_error(const char *not_supported,
01375                                 const char *try_instead);
01376 };
01377 
01378 
01379 typedef struct st_key_create_information
01380 {
01381   enum ha_key_alg algorithm;
01382   ulong block_size;
01383   LEX_STRING parser_name;
01384   LEX_STRING comment;
01391   bool check_for_duplicate_indexes;
01392 } KEY_CREATE_INFO;
01393 
01394 
01395 /*
01396   Class for maintaining hooks used inside operations on tables such
01397   as: create table functions, delete table functions, and alter table
01398   functions.
01399 
01400   Class is using the Template Method pattern to separate the public
01401   usage interface from the private inheritance interface.  This
01402   imposes no overhead, since the public non-virtual function is small
01403   enough to be inlined.
01404 
01405   The hooks are usually used for functions that does several things,
01406   e.g., create_table_from_items(), which both create a table and lock
01407   it.
01408  */
01409 class TABLEOP_HOOKS
01410 {
01411 public:
01412   TABLEOP_HOOKS() {}
01413   virtual ~TABLEOP_HOOKS() {}
01414 
01415   inline void prelock(TABLE **tables, uint count)
01416   {
01417     do_prelock(tables, count);
01418   }
01419 
01420   inline int postlock(TABLE **tables, uint count)
01421   {
01422     return do_postlock(tables, count);
01423   }
01424 private:
01425   /* Function primitive that is called prior to locking tables */
01426   virtual void do_prelock(TABLE **tables, uint count)
01427   {
01428     /* Default is to do nothing */
01429   }
01430 
01439   virtual int do_postlock(TABLE **tables, uint count)
01440   {
01441     return 0;                           /* Default is to do nothing */
01442   }
01443 };
01444 
01445 typedef struct st_savepoint SAVEPOINT;
01446 extern ulong savepoint_alloc_size;
01447 extern KEY_CREATE_INFO default_key_create_info;
01448 
01449 typedef struct st_ha_check_opt
01450 {
01451   st_ha_check_opt() {}                        /* Remove gcc warning */
01452   uint flags;       /* isam layer flags (e.g. for myisamchk) */
01453   uint sql_flags;   /* sql layer flags - for something myisamchk cannot do */
01454   KEY_CACHE *key_cache; /* new key cache when changing key cache */
01455   void init();
01456 } HA_CHECK_OPT;
01457 
01458 
01459 
01460 /*
01461   This is a buffer area that the handler can use to store rows.
01462   'end_of_used_area' should be kept updated after calls to
01463   read-functions so that other parts of the code can use the
01464   remaining area (until next read calls is issued).
01465 */
01466 
01467 typedef struct st_handler_buffer
01468 {
01469   uchar *buffer;         /* Buffer one can start using */
01470   uchar *buffer_end;     /* End of buffer */
01471   uchar *end_of_used_area;     /* End of area that was used by handler */
01472 } HANDLER_BUFFER;
01473 
01474 typedef struct system_status_var SSV;
01475 
01476 
01477 typedef void *range_seq_t;
01478 
01479 typedef struct st_range_seq_if
01480 {
01481   /*
01482     Initialize the traversal of range sequence
01483     
01484     SYNOPSIS
01485       init()
01486         init_params  The seq_init_param parameter 
01487         n_ranges     The number of ranges obtained 
01488         flags        A combination of HA_MRR_SINGLE_POINT, HA_MRR_FIXED_KEY
01489 
01490     RETURN
01491       An opaque value to be used as RANGE_SEQ_IF::next() parameter
01492   */
01493   range_seq_t (*init)(void *init_params, uint n_ranges, uint flags);
01494 
01495 
01496   /*
01497     Get the next range in the range sequence
01498 
01499     SYNOPSIS
01500       next()
01501         seq    The value returned by RANGE_SEQ_IF::init()
01502         range  OUT Information about the next range
01503     
01504     RETURN
01505       0 - Ok, the range structure filled with info about the next range
01506       1 - No more ranges
01507   */
01508   uint (*next) (range_seq_t seq, KEY_MULTI_RANGE *range);
01509 
01510   /*
01511     Check whether range_info orders to skip the next record
01512 
01513     SYNOPSIS
01514       skip_record()
01515         seq         The value returned by RANGE_SEQ_IF::init()
01516         range_info  Information about the next range 
01517                     (Ignored if MRR_NO_ASSOCIATION is set)
01518         rowid       Rowid of the record to be checked (ignored if set to 0)
01519     
01520     RETURN
01521       1 - Record with this range_info and/or this rowid shall be filtered
01522           out from the stream of records returned by multi_range_read_next()
01523       0 - The record shall be left in the stream
01524   */ 
01525   bool (*skip_record) (range_seq_t seq, char *range_info, uchar *rowid);
01526 
01527   /*
01528     Check if the record combination matches the index condition
01529     SYNOPSIS
01530       skip_index_tuple()
01531         seq         The value returned by RANGE_SEQ_IF::init()
01532         range_info  Information about the next range 
01533     
01534     RETURN
01535       0 - The record combination satisfies the index condition
01536       1 - Otherwise
01537   */ 
01538   bool (*skip_index_tuple) (range_seq_t seq, char *range_info);
01539 } RANGE_SEQ_IF;
01540 
01541 uint16 &mrr_persistent_flag_storage(range_seq_t seq, uint idx);
01542 char* &mrr_get_ptr_by_idx(range_seq_t seq, uint idx);
01543 
01550 class Cost_estimate
01551 { 
01552 private:
01553   double io_cost;                               
01554   double cpu_cost;                              
01555   double import_cost;                           
01556   double mem_cost;                              
01557   
01558 public:
01559 
01561   static double IO_BLOCK_READ_COST() { return  1.0; } 
01562 
01563   Cost_estimate() :
01564     io_cost(0),
01565     cpu_cost(0),
01566     import_cost(0),
01567     mem_cost(0)
01568   {}
01569 
01571   double total_cost()      const { return io_cost + cpu_cost + import_cost; }
01572   double get_io_cost()     const { return io_cost; }
01573   double get_cpu_cost()    const { return cpu_cost; }
01574   double get_import_cost() const { return import_cost; }
01575   double get_mem_cost()    const { return mem_cost; }
01576 
01582   bool is_zero() const
01583   { 
01584     return !(io_cost || cpu_cost || import_cost || mem_cost);
01585   }
01586 
01588   void reset()
01589   {
01590     io_cost= cpu_cost= import_cost= mem_cost= 0;
01591   }
01592 
01594   void multiply(double m)
01595   {
01596     io_cost *= m;
01597     cpu_cost *= m;
01598     import_cost *= m;
01599     /* Don't multiply mem_cost */
01600   }
01601 
01602   Cost_estimate& operator+= (const Cost_estimate &other)
01603   {
01604     io_cost+= other.io_cost;
01605     cpu_cost+= other.cpu_cost;
01606     import_cost+= other.import_cost;
01607     mem_cost+= other.mem_cost;
01608 
01609     return *this;
01610   }
01611 
01612   Cost_estimate operator+ (const Cost_estimate &other)
01613   {
01614     Cost_estimate result= *this;
01615     result+= other;
01616     return result;
01617   }
01618 
01620   void add_io(double add_io_cost) { io_cost+= add_io_cost; }
01621 
01623   void add_cpu(double add_cpu_cost) { cpu_cost+= add_cpu_cost; }
01624 
01626   void add_import(double add_import_cost) { import_cost+= add_import_cost; }
01627 
01629   void add_mem(double add_mem_cost) { mem_cost+= add_mem_cost; }
01630 };
01631 
01632 void get_sweep_read_cost(TABLE *table, ha_rows nrows, bool interrupted, 
01633                          Cost_estimate *cost);
01634 
01635 /*
01636   The below two are not used (and not handled) in this milestone of this WL
01637   entry because there seems to be no use for them at this stage of
01638   implementation.
01639 */
01640 #define HA_MRR_SINGLE_POINT 1
01641 #define HA_MRR_FIXED_KEY  2
01642 
01643 /* 
01644   Indicates that RANGE_SEQ_IF::next(&range) doesn't need to fill in the
01645   'range' parameter.
01646 */
01647 #define HA_MRR_NO_ASSOCIATION 4
01648 
01649 /* 
01650   The MRR user will provide ranges in key order, and MRR implementation
01651   must return rows in key order.
01652   Passing this flag to multi_read_range_init() may cause the
01653   default MRR handler to be used even if HA_MRR_USE_DEFAULT_IMPL
01654   was not specified.
01655   (If the native MRR impl. can not provide SORTED result)
01656 */
01657 #define HA_MRR_SORTED 8
01658 
01659 /* MRR implementation doesn't have to retrieve full records */
01660 #define HA_MRR_INDEX_ONLY 16
01661 
01662 /* 
01663   The passed memory buffer is of maximum possible size, the caller can't
01664   assume larger buffer.
01665 */
01666 #define HA_MRR_LIMITS 32
01667 
01668 
01669 /*
01670   Flag set <=> default MRR implementation is used
01671   (The choice is made by **_info[_const]() function which may set this
01672    flag. SQL layer remembers the flag value and then passes it to
01673    multi_read_range_init().
01674 */
01675 #define HA_MRR_USE_DEFAULT_IMPL 64
01676 
01677 /*
01678   Used only as parameter to multi_range_read_info():
01679   Flag set <=> the caller guarantees that the bounds of the scanned ranges
01680   will not have NULL values.
01681 */
01682 #define HA_MRR_NO_NULL_ENDPOINTS 128
01683 
01684 /*
01685   Set by the MRR implementation to signal that it will natively
01686   produced sorted result if multi_range_read_init() is called with
01687   the HA_MRR_SORTED flag - Else multi_range_read_init(HA_MRR_SORTED)
01688   will revert to use the default MRR implementation. 
01689 */
01690 #define HA_MRR_SUPPORT_SORTED 256
01691 
01692 
01693 class ha_statistics
01694 {
01695 public:
01696   ulonglong data_file_length;           /* Length off data file */
01697   ulonglong max_data_file_length;       /* Length off data file */
01698   ulonglong index_file_length;
01699   ulonglong max_index_file_length;
01700   ulonglong delete_length;              /* Free bytes */
01701   ulonglong auto_increment_value;
01702   /*
01703     The number of records in the table. 
01704       0    - means the table has exactly 0 rows
01705     other  - if (table_flags() & HA_STATS_RECORDS_IS_EXACT)
01706                the value is the exact number of records in the table
01707              else
01708                it is an estimate
01709   */
01710   ha_rows records;
01711   ha_rows deleted;                      /* Deleted records */
01712   ulong mean_rec_length;                /* physical reclength */
01713   ulong create_time;                    /* When table was created */
01714   ulong check_time;
01715   ulong update_time;
01716   uint block_size;                      /* index block size */
01717   
01718   /*
01719     number of buffer bytes that native mrr implementation needs,
01720   */
01721   uint mrr_length_per_rec; 
01722 
01723   ha_statistics():
01724     data_file_length(0), max_data_file_length(0),
01725     index_file_length(0), delete_length(0), auto_increment_value(0),
01726     records(0), deleted(0), mean_rec_length(0), create_time(0),
01727     check_time(0), update_time(0), block_size(0)
01728   {}
01729 };
01730 
01731 uint calculate_key_len(TABLE *, uint, const uchar *, key_part_map);
01732 /*
01733   bitmap with first N+1 bits set
01734   (keypart_map for a key prefix of [0..N] keyparts)
01735 */
01736 #define make_keypart_map(N) (((key_part_map)2 << (N)) - 1)
01737 /*
01738   bitmap with first N bits set
01739   (keypart_map for a key prefix of [0..N-1] keyparts)
01740 */
01741 #define make_prev_keypart_map(N) (((key_part_map)1 << (N)) - 1)
01742 
01743 
01745 class Handler_share
01746 {
01747 public:
01748   Handler_share() {}
01749   virtual ~Handler_share() {}
01750 };
01751 
01752 
01801 class handler :public Sql_alloc
01802 {
01803 public:
01804   typedef ulonglong Table_flags;
01805 protected:
01806   TABLE_SHARE *table_share;             /* The table definition */
01807   TABLE *table;                         /* The current open table */
01808   Table_flags cached_table_flags;       /* Set on init() and open() */
01809 
01810   ha_rows estimation_rows_to_insert;
01811 public:
01812   handlerton *ht;                 /* storage engine of this handler */
01813   uchar *ref;                           /* Pointer to current row */
01814   uchar *dup_ref;                       /* Pointer to duplicate row */
01815 
01816   ha_statistics stats;
01817   
01818   /* MultiRangeRead-related members: */
01819   range_seq_t mrr_iter;    /* Interator to traverse the range sequence */
01820   RANGE_SEQ_IF mrr_funcs;  /* Range sequence traversal functions */
01821   HANDLER_BUFFER *multi_range_buffer; /* MRR buffer info */
01822   uint ranges_in_seq; /* Total number of ranges in the traversed sequence */
01823   /* TRUE <=> source MRR ranges and the output are ordered */
01824   bool mrr_is_output_sorted;
01825   
01826   /* TRUE <=> we're currently traversing a range in mrr_cur_range. */
01827   bool mrr_have_range;
01828   /* Current range (the one we're now returning rows from) */
01829   KEY_MULTI_RANGE mrr_cur_range;
01830 
01831   /*
01832     The direction of the current range or index scan. This is used by
01833     the ICP implementation to determine if it has reached the end
01834     of the current range.
01835   */
01836   enum enum_range_scan_direction {
01837     RANGE_SCAN_ASC,
01838     RANGE_SCAN_DESC
01839   };
01840 private:
01841   /*
01842     Storage space for the end range value. Should only be accessed using
01843     the end_range pointer. The content is invalid when end_range is NULL.
01844   */
01845   key_range save_end_range;
01846   enum_range_scan_direction range_scan_direction;
01847   int key_compare_result_on_equal;
01848 
01849 protected:
01850   KEY_PART_INFO *range_key_part;
01851   bool eq_range;
01852   /* 
01853     TRUE <=> the engine guarantees that returned records are within the range
01854     being scanned.
01855   */
01856   bool in_range_check_pushed_down;
01857 
01858 public:  
01859   /*
01860     End value for a range scan. If this is NULL the range scan has no
01861     end value. Should also be NULL when there is no ongoing range scan.
01862     Used by the read_range() functions and also evaluated by pushed
01863     index conditions.
01864   */
01865   key_range *end_range;
01866   uint errkey;                          /* Last dup key */
01867   uint key_used_on_scan;
01868   uint active_index;
01870   uint ref_length;
01871   FT_INFO *ft_handler;
01872   enum {NONE=0, INDEX, RND} inited;
01873   bool implicit_emptied;                /* Can be !=0 only if HEAP */
01874   const Item *pushed_cond;
01875 
01876   Item *pushed_idx_cond;
01877   uint pushed_idx_cond_keyno;  /* The index which the above condition is for */
01878 
01888   ulonglong next_insert_id;
01895   ulonglong insert_id_for_cur_row;
01900   Discrete_interval auto_inc_interval_for_cur_row;
01907   uint auto_inc_intervals_count;
01908 
01921   PSI_table *m_psi;
01922 
01923   virtual void unbind_psi();
01924   virtual void rebind_psi();
01925 
01926 private:
01927   friend class DsMrr_impl;
01934   int m_lock_type;
01939   Handler_share **ha_share;
01940 
01941 public:
01942   handler(handlerton *ht_arg, TABLE_SHARE *share_arg)
01943     :table_share(share_arg), table(0),
01944     estimation_rows_to_insert(0), ht(ht_arg),
01945     ref(0), range_scan_direction(RANGE_SCAN_ASC),
01946     in_range_check_pushed_down(false), end_range(NULL),
01947     key_used_on_scan(MAX_KEY), active_index(MAX_KEY),
01948     ref_length(sizeof(my_off_t)),
01949     ft_handler(0), inited(NONE),
01950     implicit_emptied(0),
01951     pushed_cond(0), pushed_idx_cond(NULL), pushed_idx_cond_keyno(MAX_KEY),
01952     next_insert_id(0), insert_id_for_cur_row(0),
01953     auto_inc_intervals_count(0),
01954     m_psi(NULL), m_lock_type(F_UNLCK), ha_share(NULL)
01955     {
01956       DBUG_PRINT("info",
01957                  ("handler created F_UNLCK %d F_RDLCK %d F_WRLCK %d",
01958                   F_UNLCK, F_RDLCK, F_WRLCK));
01959     }
01960   virtual ~handler(void)
01961   {
01962     DBUG_ASSERT(m_lock_type == F_UNLCK);
01963     DBUG_ASSERT(inited == NONE);
01964   }
01965   virtual handler *clone(const char *name, MEM_ROOT *mem_root);
01967   void init()
01968   {
01969     cached_table_flags= table_flags();
01970   }
01971   /* ha_ methods: public wrappers for private virtual API */
01972 
01973   int ha_open(TABLE *table, const char *name, int mode, int test_if_locked);
01974   int ha_close(void);
01975   int ha_index_init(uint idx, bool sorted);
01976   int ha_index_end();
01977   int ha_rnd_init(bool scan);
01978   int ha_rnd_end();
01979   int ha_rnd_next(uchar *buf);
01980   int ha_rnd_pos(uchar * buf, uchar *pos);
01981   int ha_index_read_map(uchar *buf, const uchar *key,
01982                         key_part_map keypart_map,
01983                         enum ha_rkey_function find_flag);
01984   int ha_index_read_last_map(uchar * buf, const uchar * key,
01985                              key_part_map keypart_map);
01986   int ha_index_read_idx_map(uchar *buf, uint index, const uchar *key,
01987                            key_part_map keypart_map,
01988                            enum ha_rkey_function find_flag);
01989   int ha_index_next(uchar * buf);
01990   int ha_index_prev(uchar * buf);
01991   int ha_index_first(uchar * buf);
01992   int ha_index_last(uchar * buf);
01993   int ha_index_next_same(uchar *buf, const uchar *key, uint keylen);
01994   int ha_index_read(uchar *buf, const uchar *key, uint key_len,
01995                     enum ha_rkey_function find_flag);
01996   int ha_index_read_last(uchar *buf, const uchar *key, uint key_len);
01997   int ha_reset();
01998   /* this is necessary in many places, e.g. in HANDLER command */
01999   int ha_index_or_rnd_end()
02000   {
02001     return inited == INDEX ? ha_index_end() : inited == RND ? ha_rnd_end() : 0;
02002   }
02006   Table_flags ha_table_flags() const { return cached_table_flags; }
02013   int ha_external_lock(THD *thd, int lock_type);
02014   int ha_write_row(uchar * buf);
02015   int ha_update_row(const uchar * old_data, uchar * new_data);
02016   int ha_delete_row(const uchar * buf);
02017   void ha_release_auto_increment();
02018 
02019   int check_collation_compatibility();
02020   int ha_check_for_upgrade(HA_CHECK_OPT *check_opt);
02022   int ha_check(THD *thd, HA_CHECK_OPT *check_opt);
02023   int ha_repair(THD* thd, HA_CHECK_OPT* check_opt);
02024   void ha_start_bulk_insert(ha_rows rows);
02025   int ha_end_bulk_insert();
02026   int ha_bulk_update_row(const uchar *old_data, uchar *new_data,
02027                          uint *dup_key_found);
02028   int ha_delete_all_rows();
02029   int ha_truncate();
02030   int ha_reset_auto_increment(ulonglong value);
02031   int ha_optimize(THD* thd, HA_CHECK_OPT* check_opt);
02032   int ha_analyze(THD* thd, HA_CHECK_OPT* check_opt);
02033   bool ha_check_and_repair(THD *thd);
02034   int ha_disable_indexes(uint mode);
02035   int ha_enable_indexes(uint mode);
02036   int ha_discard_or_import_tablespace(my_bool discard);
02037   int ha_rename_table(const char *from, const char *to);
02038   int ha_delete_table(const char *name);
02039   void ha_drop_table(const char *name);
02040 
02041   int ha_create(const char *name, TABLE *form, HA_CREATE_INFO *info);
02042 
02043   int ha_create_handler_files(const char *name, const char *old_name,
02044                               int action_flag, HA_CREATE_INFO *info);
02045 
02046   int ha_change_partitions(HA_CREATE_INFO *create_info,
02047                            const char *path,
02048                            ulonglong * const copied,
02049                            ulonglong * const deleted,
02050                            const uchar *pack_frm_data,
02051                            size_t pack_frm_len);
02052   int ha_drop_partitions(const char *path);
02053   int ha_rename_partitions(const char *path);
02054 
02055   void adjust_next_insert_id_after_explicit_value(ulonglong nr);
02056   int update_auto_increment();
02057   virtual void print_error(int error, myf errflag);
02058   virtual bool get_error_message(int error, String *buf);
02059   uint get_dup_key(int error);
02078   virtual bool get_foreign_dup_key(char *child_table_name,
02079                                    uint child_table_name_len,
02080                                    char *child_key_name,
02081                                    uint child_key_name_len)
02082   { DBUG_ASSERT(false); return(false); }
02083   virtual void change_table_ptr(TABLE *table_arg, TABLE_SHARE *share)
02084   {
02085     table= table_arg;
02086     table_share= share;
02087   }
02088   /* Estimates calculation */
02089   virtual double scan_time()
02090   { return ulonglong2double(stats.data_file_length) / IO_SIZE + 2; }
02091 
02092 
02104   virtual double read_time(uint index, uint ranges, ha_rows rows)
02105   { return rows2double(ranges+rows); }
02106 
02107   virtual double index_only_read_time(uint keynr, double records);
02108   
02114   virtual longlong get_memory_buffer_size() const { return -1; }
02115 
02116   virtual ha_rows multi_range_read_info_const(uint keyno, RANGE_SEQ_IF *seq,
02117                                               void *seq_init_param, 
02118                                               uint n_ranges, uint *bufsz,
02119                                               uint *flags, 
02120                                               Cost_estimate *cost);
02121   virtual ha_rows multi_range_read_info(uint keyno, uint n_ranges, uint keys,
02122                                         uint *bufsz, uint *flags, 
02123                                         Cost_estimate *cost);
02124   virtual int multi_range_read_init(RANGE_SEQ_IF *seq, void *seq_init_param,
02125                                     uint n_ranges, uint mode,
02126                                     HANDLER_BUFFER *buf);
02127   virtual int multi_range_read_next(char **range_info);
02128 
02129 
02130   virtual const key_map *keys_to_use_for_scanning() { return &key_map_empty; }
02131   bool has_transactions()
02132   { return (ha_table_flags() & HA_NO_TRANSACTIONS) == 0; }
02133   virtual uint extra_rec_buf_length() const { return 0; }
02134 
02145   virtual bool is_fatal_error(int error, uint flags)
02146   {
02147     if (!error ||
02148         ((flags & HA_CHECK_DUP_KEY) &&
02149          (error == HA_ERR_FOUND_DUPP_KEY ||
02150           error == HA_ERR_FOUND_DUPP_UNIQUE)))
02151       return FALSE;
02152     return TRUE;
02153   }
02154 
02159   virtual ha_rows records() { return stats.records; }
02166   virtual ha_rows estimate_rows_upper_bound()
02167   { return stats.records+EXTRA_RECORDS; }
02168 
02173   virtual enum row_type get_row_type() const { return ROW_TYPE_NOT_USED; }
02174 
02175   virtual const char *index_type(uint key_number) { DBUG_ASSERT(0); return "";}
02176 
02177 
02185   virtual void column_bitmaps_signal();
02186   uint get_index(void) const { return active_index; }
02187 
02192   virtual bool start_bulk_update() { return 1; }
02197   virtual bool start_bulk_delete() { return 1; }
02209   virtual int exec_bulk_update(uint *dup_key_found)
02210   {
02211     DBUG_ASSERT(FALSE);
02212     return HA_ERR_WRONG_COMMAND;
02213   }
02218   virtual void end_bulk_update() { return; }
02225   virtual int end_bulk_delete()
02226   {
02227     DBUG_ASSERT(FALSE);
02228     return HA_ERR_WRONG_COMMAND;
02229   }
02230 protected:
02240   virtual int index_read_map(uchar * buf, const uchar * key,
02241                              key_part_map keypart_map,
02242                              enum ha_rkey_function find_flag)
02243   {
02244     uint key_len= calculate_key_len(table, active_index, key, keypart_map);
02245     return  index_read(buf, key, key_len, find_flag);
02246   }
02254   virtual int index_read_idx_map(uchar * buf, uint index, const uchar * key,
02255                                  key_part_map keypart_map,
02256                                  enum ha_rkey_function find_flag);
02258   virtual int index_next(uchar * buf)
02259    { return  HA_ERR_WRONG_COMMAND; }
02261   virtual int index_prev(uchar * buf)
02262    { return  HA_ERR_WRONG_COMMAND; }
02264   virtual int index_first(uchar * buf)
02265    { return  HA_ERR_WRONG_COMMAND; }
02267   virtual int index_last(uchar * buf)
02268    { return  HA_ERR_WRONG_COMMAND; }
02270   virtual int index_next_same(uchar *buf, const uchar *key, uint keylen);
02277   virtual int index_read_last_map(uchar * buf, const uchar * key,
02278                                   key_part_map keypart_map)
02279   {
02280     uint key_len= calculate_key_len(table, active_index, key, keypart_map);
02281     return index_read_last(buf, key, key_len);
02282   }
02283 public:
02284   virtual int read_range_first(const key_range *start_key,
02285                                const key_range *end_key,
02286                                bool eq_range, bool sorted);
02287   virtual int read_range_next();
02288 
02297   void set_end_range(const key_range* range,
02298                      enum_range_scan_direction direction);
02299   int compare_key(key_range *range);
02300   int compare_key_icp(const key_range *range) const;
02301   virtual int ft_init() { return HA_ERR_WRONG_COMMAND; }
02302   void ft_end() { ft_handler=NULL; }
02303   virtual FT_INFO *ft_init_ext(uint flags, uint inx,String *key)
02304     { return NULL; }
02305   virtual int ft_read(uchar *buf) { return HA_ERR_WRONG_COMMAND; }
02306 protected:
02308   virtual int rnd_next(uchar *buf)=0;
02310   virtual int rnd_pos(uchar * buf, uchar *pos)=0;
02311 public:
02317   virtual int rnd_pos_by_record(uchar *record)
02318     {
02319       DBUG_ASSERT(table_flags() & HA_PRIMARY_KEY_REQUIRED_FOR_POSITION);
02320       position(record);
02321       return ha_rnd_pos(record, ref);
02322     }
02323   virtual int read_first_row(uchar *buf, uint primary_key);
02328   virtual int restart_rnd_next(uchar *buf, uchar *pos)
02329     { return HA_ERR_WRONG_COMMAND; }
02330   virtual int rnd_same(uchar *buf, uint inx)
02331     { return HA_ERR_WRONG_COMMAND; }
02332   virtual ha_rows records_in_range(uint inx, key_range *min_key, key_range *max_key)
02333     { return (ha_rows) 10; }
02334   /*
02335     If HA_PRIMARY_KEY_REQUIRED_FOR_POSITION is set, then it sets ref
02336     (reference to the row, aka position, with the primary key given in
02337     the record).
02338     Otherwise it set ref to the current row.
02339   */
02340   virtual void position(const uchar *record)=0;
02341   virtual int info(uint)=0; // see my_base.h for full description
02342   virtual void get_dynamic_partition_info(PARTITION_STATS *stat_info,
02343                                           uint part_id);
02344   virtual uint32 calculate_key_hash_value(Field **field_array)
02345   { DBUG_ASSERT(0); return 0; }
02346   virtual int extra(enum ha_extra_function operation)
02347   { return 0; }
02348   virtual int extra_opt(enum ha_extra_function operation, ulong cache_size)
02349   { return extra(operation); }
02350 
02355   virtual bool start_read_removal(void)
02356   { DBUG_ASSERT(0); return false; }
02357 
02363   virtual ha_rows end_read_removal(void)
02364   { DBUG_ASSERT(0); return (ha_rows) 0; }
02365 
02378   virtual bool was_semi_consistent_read() { return 0; }
02385   virtual void try_semi_consistent_read(bool) {}
02386   virtual void unlock_row() {}
02387   virtual int start_stmt(THD *thd, thr_lock_type lock_type) {return 0;}
02388   virtual void get_auto_increment(ulonglong offset, ulonglong increment,
02389                                   ulonglong nb_desired_values,
02390                                   ulonglong *first_value,
02391                                   ulonglong *nb_reserved_values);
02392   void set_next_insert_id(ulonglong id)
02393   {
02394     DBUG_PRINT("info",("auto_increment: next value %lu", (ulong)id));
02395     next_insert_id= id;
02396   }
02397   void restore_auto_increment(ulonglong prev_insert_id)
02398   {
02399     /*
02400       Insertion of a row failed, re-use the lastly generated auto_increment
02401       id, for the next row. This is achieved by resetting next_insert_id to
02402       what it was before the failed insertion (that old value is provided by
02403       the caller). If that value was 0, it was the first row of the INSERT;
02404       then if insert_id_for_cur_row contains 0 it means no id was generated
02405       for this first row, so no id was generated since the INSERT started, so
02406       we should set next_insert_id to 0; if insert_id_for_cur_row is not 0, it
02407       is the generated id of the first and failed row, so we use it.
02408     */
02409     next_insert_id= (prev_insert_id > 0) ? prev_insert_id :
02410       insert_id_for_cur_row;
02411   }
02412 
02413   virtual void update_create_info(HA_CREATE_INFO *create_info) {}
02414   int check_old_types();
02415   virtual int assign_to_keycache(THD* thd, HA_CHECK_OPT* check_opt)
02416   { return HA_ADMIN_NOT_IMPLEMENTED; }
02417   virtual int preload_keys(THD* thd, HA_CHECK_OPT* check_opt)
02418   { return HA_ADMIN_NOT_IMPLEMENTED; }
02419   /* end of the list of admin commands */
02420 
02421   virtual int indexes_are_disabled(void) {return 0;}
02422   virtual char *update_table_comment(const char * comment)
02423   { return (char*) comment;}
02424   virtual void append_create_info(String *packet) {}
02435   virtual bool is_fk_defined_on_table_or_index(uint index)
02436   { return FALSE; }
02437   virtual char* get_foreign_key_create_info()
02438   { return(NULL);}  /* gets foreign key create string from InnoDB */
02447   virtual bool can_switch_engines() { return true; }
02459   virtual int
02460   get_foreign_key_list(THD *thd, List<FOREIGN_KEY_INFO> *f_key_list)
02461   { return 0; }
02473   virtual int
02474   get_parent_foreign_key_list(THD *thd, List<FOREIGN_KEY_INFO> *f_key_list)
02475   { return 0; }
02476   virtual uint referenced_by_foreign_key() { return 0;}
02477   virtual void init_table_handle_for_HANDLER()
02478   { return; }       /* prepare InnoDB for HANDLER */
02479   virtual void free_foreign_key_create_info(char* str) {}
02481   virtual const char *table_type() const =0;
02493   virtual const char **bas_ext() const =0;
02494 
02495   virtual int get_default_no_partitions(HA_CREATE_INFO *info) { return 1;}
02496   virtual void set_auto_partitions(partition_info *part_info) { return; }
02497 
02508   virtual bool get_no_parts(const char *name,
02509                             uint *no_parts)
02510   {
02511     *no_parts= 0;
02512     return 0;
02513   }
02514   virtual void set_part_info(partition_info *part_info, bool early) {return;}
02515 
02516   virtual ulong index_flags(uint idx, uint part, bool all_parts) const =0;
02517 
02518   uint max_record_length() const
02519   {
02520     using std::min;
02521     return min(HA_MAX_REC_LENGTH, max_supported_record_length());
02522   }
02523   uint max_keys() const
02524   {
02525     using std::min;
02526     return min(MAX_KEY, max_supported_keys());
02527   }
02528   uint max_key_parts() const
02529   {
02530     using std::min;
02531     return min(MAX_REF_PARTS, max_supported_key_parts());
02532   }
02533   uint max_key_length() const
02534   {
02535     using std::min;
02536     return min(MAX_KEY_LENGTH, max_supported_key_length());
02537   }
02538   uint max_key_part_length() const
02539   {
02540     using std::min;
02541     return min(MAX_KEY_LENGTH, max_supported_key_part_length());
02542   }
02543 
02544   virtual uint max_supported_record_length() const { return HA_MAX_REC_LENGTH; }
02545   virtual uint max_supported_keys() const { return 0; }
02546   virtual uint max_supported_key_parts() const { return MAX_REF_PARTS; }
02547   virtual uint max_supported_key_length() const { return MAX_KEY_LENGTH; }
02548   virtual uint max_supported_key_part_length() const { return 255; }
02549   virtual uint min_record_length(uint options) const { return 1; }
02550 
02551   virtual bool low_byte_first() const { return 1; }
02552   virtual uint checksum() const { return 0; }
02553   virtual bool is_crashed() const  { return 0; }
02554   virtual bool auto_repair() const { return 0; }
02555 
02556 
02557 #define CHF_CREATE_FLAG 0
02558 #define CHF_DELETE_FLAG 1
02559 #define CHF_RENAME_FLAG 2
02560 #define CHF_INDEX_FLAG  3
02561 
02562 
02566   virtual uint lock_count(void) const { return 1; }
02580   virtual THR_LOCK_DATA **store_lock(THD *thd,
02581                                      THR_LOCK_DATA **to,
02582                                      enum thr_lock_type lock_type)=0;
02583 
02585   virtual uint8 table_cache_type() { return HA_CACHE_TBL_NONTRANSACT; }
02586 
02587 
02618   virtual my_bool register_query_cache_table(THD *thd, char *table_key,
02619                                              uint key_length,
02620                                              qc_engine_callback
02621                                              *engine_callback,
02622                                              ulonglong *engine_data)
02623   {
02624     *engine_callback= 0;
02625     return TRUE;
02626   }
02627 
02628 
02629  /*
02630    @retval TRUE   Primary key (if there is one) is clustered
02631                   key covering all fields
02632    @retval FALSE  otherwise
02633  */
02634  virtual bool primary_key_is_clustered() { return FALSE; }
02635  virtual int cmp_ref(const uchar *ref1, const uchar *ref2)
02636  {
02637    return memcmp(ref1, ref2, ref_length);
02638  }
02639 
02640  /*
02641    Condition pushdown to storage engines
02642  */
02643 
02666  virtual const Item *cond_push(const Item *cond) { return cond; };
02672  virtual void cond_pop() { return; }
02673 
02699  virtual Item *idx_cond_push(uint keyno, Item* idx_cond) { return idx_cond; }
02700 
02702  virtual void cancel_pushed_idx_cond()
02703  {
02704    pushed_idx_cond= NULL;
02705    pushed_idx_cond_keyno= MAX_KEY;
02706    in_range_check_pushed_down= false;
02707  }
02708 
02713   virtual uint number_of_pushed_joins() const
02714   { return 0; }
02715 
02720   virtual const TABLE* root_of_pushed_join() const
02721   { return NULL; }
02722 
02727   virtual const TABLE* parent_of_pushed_join() const
02728   { return NULL; }
02729 
02730   virtual int index_read_pushed(uchar * buf, const uchar * key,
02731                              key_part_map keypart_map)
02732   { return  HA_ERR_WRONG_COMMAND; }
02733 
02734   virtual int index_next_pushed(uchar * buf)
02735   { return  HA_ERR_WRONG_COMMAND; }
02736 
02740  virtual bool check_if_incompatible_data(HA_CREATE_INFO *create_info,
02741                                          uint table_changes)
02742  { return COMPATIBLE_DATA_NO; }
02743 
02744  /* On-line/in-place ALTER TABLE interface. */
02745 
02746  /*
02747    Here is an outline of on-line/in-place ALTER TABLE execution through
02748    this interface.
02749 
02750    Phase 1 : Initialization
02751    ========================
02752    During this phase we determine which algorithm should be used
02753    for execution of ALTER TABLE and what level concurrency it will
02754    require.
02755 
02756    *) This phase starts by opening the table and preparing description
02757       of the new version of the table.
02758    *) Then we check if it is impossible even in theory to carry out
02759       this ALTER TABLE using the in-place algorithm. For example, because
02760       we need to change storage engine or the user has explicitly requested
02761       usage of the "copy" algorithm.
02762    *) If in-place ALTER TABLE is theoretically possible, we continue
02763       by compiling differences between old and new versions of the table
02764       in the form of HA_ALTER_FLAGS bitmap. We also build a few
02765       auxiliary structures describing requested changes and store
02766       all these data in the Alter_inplace_info object.
02767    *) Then the handler::check_if_supported_inplace_alter() method is called
02768       in order to find if the storage engine can carry out changes requested
02769       by this ALTER TABLE using the in-place algorithm. To determine this,
02770       the engine can rely on data in HA_ALTER_FLAGS/Alter_inplace_info
02771       passed to it as well as on its own checks. If the in-place algorithm
02772       can be used for this ALTER TABLE, the level of required concurrency for
02773       its execution is also returned.
02774       If any errors occur during the handler call, ALTER TABLE is aborted
02775       and no further handler functions are called.
02776    *) Locking requirements of the in-place algorithm are compared to any
02777       concurrency requirements specified by user. If there is a conflict
02778       between them, we either switch to the copy algorithm or emit an error.
02779 
02780    Phase 2 : Execution
02781    ===================
02782 
02783    In this phase the operations are executed.
02784 
02785    *) As the first step, we acquire a lock corresponding to the concurrency
02786       level which was returned by handler::check_if_supported_inplace_alter()
02787       and requested by the user. This lock is held for most of the
02788       duration of in-place ALTER (if HA_ALTER_INPLACE_SHARED_LOCK_AFTER_PREPARE
02789       or HA_ALTER_INPLACE_NO_LOCK_AFTER_PREPARE were returned we acquire an
02790       exclusive lock for duration of the next step only).
02791    *) After that we call handler::ha_prepare_inplace_alter_table() to give the
02792       storage engine a chance to update its internal structures with a higher
02793       lock level than the one that will be used for the main step of algorithm.
02794       After that we downgrade the lock if it is necessary.
02795    *) After that, the main step of this phase and algorithm is executed.
02796       We call the handler::ha_inplace_alter_table() method, which carries out the
02797       changes requested by ALTER TABLE but does not makes them visible to other
02798       connections yet.
02799    *) We ensure that no other connection uses the table by upgrading our
02800       lock on it to exclusive.
02801    *) a) If the previous step succeeds, handler::ha_commit_inplace_alter_table() is
02802          called to allow the storage engine to do any final updates to its structures,
02803          to make all earlier changes durable and visible to other connections.
02804       b) If we have failed to upgrade lock or any errors have occured during the
02805          handler functions calls (including commit), we call
02806          handler::ha_commit_inplace_alter_table()
02807          to rollback all changes which were done during previous steps.
02808 
02809   Phase 3 : Final
02810   ===============
02811 
02812   In this phase we:
02813 
02814   *) Update SQL-layer data-dictionary by installing .FRM file for the new version
02815      of the table.
02816   *) Inform the storage engine about this change by calling the
02817      handler::ha_notify_table_changed() method.
02818   *) Destroy the Alter_inplace_info and handler_ctx objects.
02819 
02820  */
02821 
02850  virtual enum_alter_inplace_result
02851  check_if_supported_inplace_alter(TABLE *altered_table,
02852                                   Alter_inplace_info *ha_alter_info);
02853 
02854 
02859  bool ha_prepare_inplace_alter_table(TABLE *altered_table,
02860                                      Alter_inplace_info *ha_alter_info);
02861 
02862 
02867  bool ha_inplace_alter_table(TABLE *altered_table,
02868                              Alter_inplace_info *ha_alter_info)
02869  {
02870    return inplace_alter_table(altered_table, ha_alter_info);
02871  }
02872 
02873 
02879  bool ha_commit_inplace_alter_table(TABLE *altered_table,
02880                                     Alter_inplace_info *ha_alter_info,
02881                                     bool commit);
02882 
02883 
02888  void ha_notify_table_changed()
02889  {
02890    notify_table_changed();
02891  }
02892 
02893 
02894 protected:
02923  virtual bool prepare_inplace_alter_table(TABLE *altered_table,
02924                                           Alter_inplace_info *ha_alter_info)
02925  { return false; }
02926 
02927 
02947  virtual bool inplace_alter_table(TABLE *altered_table,
02948                                   Alter_inplace_info *ha_alter_info)
02949  { return false; }
02950 
02951 
02984  virtual bool commit_inplace_alter_table(TABLE *altered_table,
02985                                          Alter_inplace_info *ha_alter_info,
02986                                          bool commit)
02987 {
02988   /* Nothing to commit/rollback, mark all handlers committed! */
02989   ha_alter_info->group_commit_ctx= NULL;
02990   return false;
02991 }
02992 
02993 
02999  virtual void notify_table_changed();
03000 
03001 public:
03002  /* End of On-line/in-place ALTER TABLE interface. */
03003 
03004 
03010   virtual void use_hidden_primary_key();
03011   virtual uint alter_table_flags(uint flags)
03012   {
03013     if (ht->alter_table_flags)
03014       return ht->alter_table_flags(flags);
03015     return 0;
03016   }
03017 
03018 protected:
03019   /* Service methods for use by storage engines. */
03020   void ha_statistic_increment(ulonglong SSV::*offset) const;
03021   void **ha_data(THD *) const;
03022   THD *ha_thd(void) const;
03023 
03029   PSI_table_share *ha_table_share_psi(const TABLE_SHARE *share) const;
03030 
03038   virtual int rename_table(const char *from, const char *to);
03043   virtual int delete_table(const char *name);
03044 private:
03045   /* Private helpers */
03046   inline void mark_trx_read_write();
03047   /*
03048     Low-level primitives for storage engines.  These should be
03049     overridden by the storage engine class. To call these methods, use
03050     the corresponding 'ha_*' method above.
03051   */
03052 
03053   virtual int open(const char *name, int mode, uint test_if_locked)=0;
03054   virtual int close(void)=0;
03055   virtual int index_init(uint idx, bool sorted) { active_index= idx; return 0; }
03056   virtual int index_end() { active_index= MAX_KEY; return 0; }
03064   virtual int rnd_init(bool scan)= 0;
03065   virtual int rnd_end() { return 0; }
03066   virtual int write_row(uchar *buf __attribute__((unused)))
03067   {
03068     return HA_ERR_WRONG_COMMAND;
03069   }
03070 
03079   virtual int update_row(const uchar *old_data __attribute__((unused)),
03080                          uchar *new_data __attribute__((unused)))
03081   {
03082     return HA_ERR_WRONG_COMMAND;
03083   }
03084 
03085   virtual int delete_row(const uchar *buf __attribute__((unused)))
03086   {
03087     return HA_ERR_WRONG_COMMAND;
03088   }
03094   virtual int reset() { return 0; }
03095   virtual Table_flags table_flags(void) const= 0;
03118   virtual int external_lock(THD *thd __attribute__((unused)),
03119                             int lock_type __attribute__((unused)))
03120   {
03121     return 0;
03122   }
03123   virtual void release_auto_increment() { return; };
03125   virtual int check_for_upgrade(HA_CHECK_OPT *check_opt)
03126   { return 0; }
03127   virtual int check(THD* thd, HA_CHECK_OPT* check_opt)
03128   { return HA_ADMIN_NOT_IMPLEMENTED; }
03129 
03135   virtual int repair(THD* thd, HA_CHECK_OPT* check_opt)
03136   {
03137     DBUG_ASSERT(!(ha_table_flags() & HA_CAN_REPAIR));
03138     return HA_ADMIN_NOT_IMPLEMENTED;
03139   }
03140   virtual void start_bulk_insert(ha_rows rows) {}
03141   virtual int end_bulk_insert() { return 0; }
03142 protected:
03143   virtual int index_read(uchar * buf, const uchar * key, uint key_len,
03144                          enum ha_rkey_function find_flag)
03145    { return  HA_ERR_WRONG_COMMAND; }
03146   virtual int index_read_last(uchar * buf, const uchar * key, uint key_len)
03147    { return (my_errno= HA_ERR_WRONG_COMMAND); }
03148 public:
03165   virtual int bulk_update_row(const uchar *old_data, uchar *new_data,
03166                               uint *dup_key_found)
03167   {
03168     DBUG_ASSERT(FALSE);
03169     return HA_ERR_WRONG_COMMAND;
03170   }
03177   virtual int delete_all_rows()
03178   { return (my_errno=HA_ERR_WRONG_COMMAND); }
03197   virtual int truncate()
03198   { return HA_ERR_WRONG_COMMAND; }
03204   virtual int reset_auto_increment(ulonglong value)
03205   { return HA_ERR_WRONG_COMMAND; }
03206   virtual int optimize(THD* thd, HA_CHECK_OPT* check_opt)
03207   { return HA_ADMIN_NOT_IMPLEMENTED; }
03208   virtual int analyze(THD* thd, HA_CHECK_OPT* check_opt)
03209   { return HA_ADMIN_NOT_IMPLEMENTED; }
03210   virtual bool check_and_repair(THD *thd) { return TRUE; }
03211   virtual int disable_indexes(uint mode) { return HA_ERR_WRONG_COMMAND; }
03212   virtual int enable_indexes(uint mode) { return HA_ERR_WRONG_COMMAND; }
03213   virtual int discard_or_import_tablespace(my_bool discard)
03214   { return (my_errno=HA_ERR_WRONG_COMMAND); }
03215   virtual void drop_table(const char *name);
03216   virtual int create(const char *name, TABLE *form, HA_CREATE_INFO *info)=0;
03217 
03218   virtual int create_handler_files(const char *name, const char *old_name,
03219                                    int action_flag, HA_CREATE_INFO *info)
03220   { return FALSE; }
03221 
03222   virtual int change_partitions(HA_CREATE_INFO *create_info,
03223                                 const char *path,
03224                                 ulonglong * const copied,
03225                                 ulonglong * const deleted,
03226                                 const uchar *pack_frm_data,
03227                                 size_t pack_frm_len)
03228   { return HA_ERR_WRONG_COMMAND; }
03229   virtual int drop_partitions(const char *path)
03230   { return HA_ERR_WRONG_COMMAND; }
03231   virtual int rename_partitions(const char *path)
03232   { return HA_ERR_WRONG_COMMAND; }
03233   virtual bool set_ha_share_ref(Handler_share **arg_ha_share)
03234   {
03235     DBUG_ASSERT(!ha_share);
03236     DBUG_ASSERT(arg_ha_share);
03237     if (ha_share || !arg_ha_share)
03238       return true;
03239     ha_share= arg_ha_share;
03240     return false;
03241   }
03242   int get_lock_type() const { return m_lock_type; }
03243 protected:
03244   Handler_share *get_ha_share_ptr();
03245   void set_ha_share_ptr(Handler_share *arg_ha_share);
03246   void lock_shared_ha_data();
03247   void unlock_shared_ha_data();
03248 };
03249 
03250 
03251 bool key_uses_partial_cols(TABLE *table, uint keyno);
03252 
03253 /*
03254   A Disk-Sweep MRR interface implementation
03255 
03256   This implementation makes range (and, in the future, 'ref') scans to read
03257   table rows in disk sweeps. 
03258   
03259   Currently it is used by MyISAM and InnoDB. Potentially it can be used with
03260   any table handler that has non-clustered indexes and on-disk rows.
03261 */
03262 
03263 class DsMrr_impl
03264 {
03265 public:
03266   typedef void (handler::*range_check_toggle_func_t)(bool on);
03267 
03268   DsMrr_impl()
03269     : h2(NULL) {};
03270   ~DsMrr_impl() { DBUG_ASSERT(h2 == NULL); }
03271   
03272   /*
03273     The "owner" handler object (the one that calls dsmrr_XXX functions.
03274     It is used to retrieve full table rows by calling rnd_pos().
03275   */
03276   handler *h;
03277   TABLE *table; /* Always equal to h->table */
03278 private:
03279   /* Secondary handler object.  It is used for scanning the index */
03280   handler *h2;
03281 
03282   /* Buffer to store rowids, or (rowid, range_id) pairs */
03283   uchar *rowids_buf;
03284   uchar *rowids_buf_cur;   /* Current position when reading/writing */
03285   uchar *rowids_buf_last;  /* When reading: end of used buffer space */
03286   uchar *rowids_buf_end;   /* End of the buffer */
03287 
03288   bool dsmrr_eof; /* TRUE <=> We have reached EOF when reading index tuples */
03289 
03290   /* TRUE <=> need range association, buffer holds {rowid, range_id} pairs */
03291   bool is_mrr_assoc;
03292 
03293   bool use_default_impl; /* TRUE <=> shortcut all calls to default MRR impl */
03294 public:
03295   void init(handler *h_arg, TABLE *table_arg)
03296   {
03297     h= h_arg; 
03298     table= table_arg;
03299   }
03300   int dsmrr_init(handler *h, RANGE_SEQ_IF *seq_funcs, void *seq_init_param, 
03301                  uint n_ranges, uint mode, HANDLER_BUFFER *buf);
03302   void dsmrr_close();
03303 
03314   void reset();
03315   int dsmrr_fill_buffer();
03316   int dsmrr_next(char **range_info);
03317 
03318   ha_rows dsmrr_info(uint keyno, uint n_ranges, uint keys, uint *bufsz,
03319                      uint *flags, Cost_estimate *cost);
03320 
03321   ha_rows dsmrr_info_const(uint keyno, RANGE_SEQ_IF *seq, 
03322                             void *seq_init_param, uint n_ranges, uint *bufsz,
03323                             uint *flags, Cost_estimate *cost);
03324 private:
03325   bool choose_mrr_impl(uint keyno, ha_rows rows, uint *flags, uint *bufsz, 
03326                        Cost_estimate *cost);
03327   bool get_disk_sweep_mrr_cost(uint keynr, ha_rows rows, uint flags, 
03328                                uint *buffer_size, Cost_estimate *cost);
03329 };
03330         /* Some extern variables used with handlers */
03331 
03332 extern const char *ha_row_type[];
03333 extern MYSQL_PLUGIN_IMPORT const char *tx_isolation_names[];
03334 extern MYSQL_PLUGIN_IMPORT const char *binlog_format_names[];
03335 extern TYPELIB tx_isolation_typelib;
03336 extern const char *myisam_stats_method_names[];
03337 extern ulong total_ha, total_ha_2pc;
03338 
03339 /* lookups */
03340 handlerton *ha_default_handlerton(THD *thd);
03341 handlerton *ha_default_temp_handlerton(THD *thd);
03342 plugin_ref ha_resolve_by_name(THD *thd, const LEX_STRING *name, 
03343                               bool is_temp_table);
03344 plugin_ref ha_lock_engine(THD *thd, const handlerton *hton);
03345 handlerton *ha_resolve_by_legacy_type(THD *thd, enum legacy_db_type db_type);
03346 handler *get_new_handler(TABLE_SHARE *share, MEM_ROOT *alloc,
03347                          handlerton *db_type);
03348 handlerton *ha_checktype(THD *thd, enum legacy_db_type database_type,
03349                           bool no_substitute, bool report_error);
03350 
03351 
03352 static inline enum legacy_db_type ha_legacy_type(const handlerton *db_type)
03353 {
03354   return (db_type == NULL) ? DB_TYPE_UNKNOWN : db_type->db_type;
03355 }
03356 
03357 static inline const char *ha_resolve_storage_engine_name(const handlerton *db_type)
03358 {
03359   return db_type == NULL ? "UNKNOWN" : hton2plugin[db_type->slot]->name.str;
03360 }
03361 
03362 static inline bool ha_check_storage_engine_flag(const handlerton *db_type, uint32 flag)
03363 {
03364   return db_type == NULL ? FALSE : MY_TEST(db_type->flags & flag);
03365 }
03366 
03367 static inline bool ha_storage_engine_is_enabled(const handlerton *db_type)
03368 {
03369   return (db_type && db_type->create) ?
03370          (db_type->state == SHOW_OPTION_YES) : FALSE;
03371 }
03372 
03373 /* basic stuff */
03374 int ha_init_errors(void);
03375 int ha_init(void);
03376 int ha_end(void);
03377 int ha_initialize_handlerton(st_plugin_int *plugin);
03378 int ha_finalize_handlerton(st_plugin_int *plugin);
03379 
03380 TYPELIB* ha_known_exts();
03381 int ha_panic(enum ha_panic_function flag);
03382 void ha_close_connection(THD* thd);
03383 bool ha_flush_logs(handlerton *db_type);
03384 void ha_drop_database(char* path);
03385 int ha_create_table(THD *thd, const char *path,
03386                     const char *db, const char *table_name,
03387                     HA_CREATE_INFO *create_info,
03388                                 bool update_create_info,
03389                     bool is_temp_table= false);
03390 
03391 int ha_delete_table(THD *thd, handlerton *db_type, const char *path,
03392                     const char *db, const char *alias, bool generate_warning);
03393 
03394 /* statistics and info */
03395 bool ha_show_status(THD *thd, handlerton *db_type, enum ha_stat_type stat);
03396 
03397 /* discovery */
03398 int ha_create_table_from_engine(THD* thd, const char *db, const char *name);
03399 bool ha_check_if_table_exists(THD* thd, const char *db, const char *name,
03400                              bool *exists);
03401 int ha_discover(THD* thd, const char* dbname, const char* name,
03402                 uchar** frmblob, size_t* frmlen);
03403 int ha_find_files(THD *thd,const char *db,const char *path,
03404                   const char *wild, bool dir, List<LEX_STRING>* files);
03405 int ha_table_exists_in_engine(THD* thd, const char* db, const char* name);
03406 bool ha_check_if_supported_system_table(handlerton *hton, const char* db, 
03407                                         const char* table_name);
03408 
03409 /* key cache */
03410 extern "C" int ha_init_key_cache(const char *name, KEY_CACHE *key_cache);
03411 int ha_resize_key_cache(KEY_CACHE *key_cache);
03412 int ha_change_key_cache_param(KEY_CACHE *key_cache);
03413 int ha_change_key_cache(KEY_CACHE *old_key_cache, KEY_CACHE *new_key_cache);
03414 
03415 /* report to InnoDB that control passes to the client */
03416 int ha_release_temporary_latches(THD *thd);
03417 
03418 /* transactions: interface to handlerton functions */
03419 int ha_start_consistent_snapshot(THD *thd);
03420 int ha_commit_or_rollback_by_xid(THD *thd, XID *xid, bool commit);
03421 int ha_commit_trans(THD *thd, bool all, bool ignore_global_read_lock= false);
03422 int ha_rollback_trans(THD *thd, bool all);
03423 int ha_prepare(THD *thd);
03424 int ha_recover(HASH *commit_list);
03425 
03426 /*
03427  transactions: interface to low-level handlerton functions. These are
03428  intended to be used by the transaction coordinators to
03429  commit/prepare/rollback transactions in the engines.
03430 */
03431 int ha_commit_low(THD *thd, bool all, bool run_after_commit= true);
03432 int ha_prepare_low(THD *thd, bool all);
03433 int ha_rollback_low(THD *thd, bool all);
03434 
03435 /* transactions: these functions never call handlerton functions directly */
03436 int ha_enable_transaction(THD *thd, bool on);
03437 
03438 /* savepoints */
03439 int ha_rollback_to_savepoint(THD *thd, SAVEPOINT *sv);
03440 bool ha_rollback_to_savepoint_can_release_mdl(THD *thd);
03441 int ha_savepoint(THD *thd, SAVEPOINT *sv);
03442 int ha_release_savepoint(THD *thd, SAVEPOINT *sv);
03443 
03444 /* Build pushed joins in handlers implementing this feature */
03445 int ha_make_pushed_joins(THD *thd, const AQP::Join_plan* plan);
03446 
03447 /* these are called by storage engines */
03448 void trans_register_ha(THD *thd, bool all, handlerton *ht);
03449 
03450 /*
03451   Storage engine has to assume the transaction will end up with 2pc if
03452    - there is more than one 2pc-capable storage engine available
03453    - in the current transaction 2pc was not disabled yet
03454 */
03455 #define trans_need_2pc(thd, all)                   ((total_ha_2pc > 1) && \
03456         !((all ? &thd->transaction.all : &thd->transaction.stmt)->no_2pc))
03457 
03458 #ifdef HAVE_NDB_BINLOG
03459 int ha_reset_logs(THD *thd);
03460 int ha_binlog_index_purge_file(THD *thd, const char *file);
03461 void ha_reset_slave(THD *thd);
03462 void ha_binlog_log_query(THD *thd, handlerton *db_type,
03463                          enum_binlog_command binlog_command,
03464                          const char *query, uint query_length,
03465                          const char *db, const char *table_name);
03466 void ha_binlog_wait(THD *thd);
03467 #else
03468 #define ha_reset_logs(a) do {} while (0)
03469 #define ha_binlog_index_purge_file(a,b) do {} while (0)
03470 #define ha_reset_slave(a) do {} while (0)
03471 #define ha_binlog_log_query(a,b,c,d,e,f,g) do {} while (0)
03472 #define ha_binlog_wait(a) do {} while (0)
03473 #endif
03474 
03475 /* It is required by basic binlog features on both MySQL server and libmysqld */
03476 int ha_binlog_end(THD *thd);
03477 
03478 const char *ha_legacy_type_name(legacy_db_type legacy_type);
03479 const char *get_canonical_filename(handler *file, const char *path,
03480                                    char *tmp_path);
03481 bool mysql_xa_recover(THD *thd);
03482 
03483 
03484 inline const char *table_case_name(HA_CREATE_INFO *info, const char *name)
03485 {
03486   return ((lower_case_table_names == 2 && info->alias) ? info->alias : name);
03487 }
03488 
03489 void print_keydup_error(TABLE *table, KEY *key, const char *msg, myf errflag);
03490 void print_keydup_error(TABLE *table, KEY *key, myf errflag);
03491 
03492 #endif /* HANDLER_INCLUDED */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines