summaryrefslogtreecommitdiff
path: root/sql/handler.h
diff options
context:
space:
mode:
Diffstat (limited to 'sql/handler.h')
-rw-r--r--sql/handler.h598
1 files changed, 518 insertions, 80 deletions
diff --git a/sql/handler.h b/sql/handler.h
index b1d64a1114b..bbdc38eba4d 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -1,6 +1,6 @@
#ifndef HANDLER_INCLUDED
#define HANDLER_INCLUDED
-
+#error don't forget to merge mysql_priv.h!
/* Copyright 2000-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc.
This program is free software; you can redistribute it and/or modify
@@ -33,6 +33,10 @@
#include <ft_global.h>
#include <keycache.h>
+#if MAX_KEY > 128
+#error MAX_KEY is too large. Values up to 128 are supported.
+#endif
+
// the following is for checking tables
#define HA_ADMIN_ALREADY_DONE 1
@@ -113,7 +117,8 @@
#define HA_CAN_FULLTEXT (1 << 21)
#define HA_CAN_SQL_HANDLER (1 << 22)
#define HA_NO_AUTO_INCREMENT (1 << 23)
-#define HA_HAS_CHECKSUM (1 << 24)
+/* Has automatic checksums and uses the old checksum format */
+#define HA_HAS_OLD_CHECKSUM (1 << 24)
/* Table data are stored in separate files (for lower_case_table_names) */
#define HA_FILE_BASED (1 << 26)
#define HA_NO_VARCHAR (1 << 27)
@@ -153,6 +158,10 @@
ordered.
*/
#define HA_DUPLICATE_KEY_NOT_IN_ORDER (LL(1) << 36)
+/* Has automatic checksums and uses the new checksum format */
+#define HA_HAS_NEW_CHECKSUM (LL(1) << 37)
+
+#define HA_MRR_CANT_SORT (LL(1) << 38)
/*
Set of all binlog flags. Currently only contain the capabilities
@@ -169,6 +178,15 @@
#define HA_KEYREAD_ONLY 64 /* Support HA_EXTRA_KEYREAD */
/*
+ Index scan will not return records in rowid order. Not guaranteed to be
+ set for unordered (e.g. HASH) indexes.
+*/
+#define HA_KEY_SCAN_NOT_ROR 128
+#define HA_DO_INDEX_COND_PUSHDOWN 256 /* Supports Index Condition Pushdown */
+
+
+
+/*
bits in alter_table_flags:
*/
/*
@@ -221,12 +239,6 @@
#define HA_FAST_CHANGE_PARTITION (1L << 13)
#define HA_PARTITION_ONE_PHASE (1L << 14)
-/*
- Index scan will not return records in rowid order. Not guaranteed to be
- set for unordered (e.g. HASH) indexes.
-*/
-#define HA_KEY_SCAN_NOT_ROR 128
-
/* operations for disable/enable indexes */
#define HA_KEY_SWITCH_NONUNIQ 0
#define HA_KEY_SWITCH_ALL 1
@@ -273,8 +285,6 @@
#define HA_LEX_CREATE_TMP_TABLE 1
#define HA_LEX_CREATE_IF_NOT_EXISTS 2
#define HA_LEX_CREATE_TABLE_LIKE 4
-#define HA_OPTION_NO_CHECKSUM (1L << 17)
-#define HA_OPTION_NO_DELAY_KEY_WRITE (1L << 18)
#define HA_MAX_REC_LENGTH 65535
/* Table caching type */
@@ -315,6 +325,11 @@ enum legacy_db_type
DB_TYPE_FIRST_DYNAMIC=42,
DB_TYPE_DEFAULT=127 // Must be last
};
+/*
+ Better name for DB_TYPE_UNKNOWN. Should be used for engines that do not have
+ a hard-coded type value here.
+ */
+#define DB_TYPE_AUTOASSIGN DB_TYPE_UNKNOWN
enum row_type { ROW_TYPE_NOT_USED=-1, ROW_TYPE_DEFAULT, ROW_TYPE_FIXED,
ROW_TYPE_DYNAMIC, ROW_TYPE_COMPRESSED,
@@ -363,9 +378,8 @@ enum enum_binlog_command {
#define HA_CREATE_USED_PASSWORD (1L << 17)
#define HA_CREATE_USED_CONNECTION (1L << 18)
#define HA_CREATE_USED_KEY_BLOCK_SIZE (1L << 19)
-/** Unused. Reserved for future versions. */
+/* The following two are used by Maria engine: */
#define HA_CREATE_USED_TRANSACTIONAL (1L << 20)
-/** Unused. Reserved for future versions. */
#define HA_CREATE_USED_PAGE_CHECKSUM (1L << 21)
typedef ulonglong my_xid; // this line is the same as in log_event.h
@@ -546,6 +560,7 @@ struct TABLE;
enum enum_schema_tables
{
SCH_CHARSETS= 0,
+ SCH_CLIENT_STATS,
SCH_COLLATIONS,
SCH_COLLATION_CHARACTER_SET_APPLICABILITY,
SCH_COLUMNS,
@@ -555,15 +570,17 @@ enum enum_schema_tables
SCH_FILES,
SCH_GLOBAL_STATUS,
SCH_GLOBAL_VARIABLES,
+ SCH_INDEX_STATS,
+ SCH_KEY_CACHES,
SCH_KEY_COLUMN_USAGE,
SCH_OPEN_TABLES,
SCH_PARAMETERS,
SCH_PARTITIONS,
SCH_PLUGINS,
+ SCH_PROCEDURES,
SCH_PROCESSLIST,
SCH_PROFILES,
SCH_REFERENTIAL_CONSTRAINTS,
- SCH_PROCEDURES,
SCH_SCHEMATA,
SCH_SCHEMA_PRIVILEGES,
SCH_SESSION_STATUS,
@@ -575,8 +592,10 @@ enum enum_schema_tables
SCH_TABLE_CONSTRAINTS,
SCH_TABLE_NAMES,
SCH_TABLE_PRIVILEGES,
+ SCH_TABLE_STATS,
SCH_TRIGGERS,
SCH_USER_PRIVILEGES,
+ SCH_USER_STATS,
SCH_VARIABLES,
SCH_VIEWS
};
@@ -615,6 +634,103 @@ struct handler_log_file_data {
enum log_status status;
};
+/*
+ Definitions for engine-specific table/field/index options in the CREATE TABLE.
+
+ Options are declared with HA_*OPTION_* macros (HA_TOPTION_NUMBER,
+ HA_FOPTION_ENUM, HA_IOPTION_STRING, etc).
+
+ Every macros takes the option name, and the name of the underlying field of
+ the appropriate C structure. The "appropriate C structure" is
+ ha_table_option_struct for table level options,
+ ha_field_option_struct for field level options,
+ ha_index_option_struct for key level options. The engine either
+ defines a structure of this name, or uses #define's to map
+ these "appropriate" names to the actual structure type name.
+
+ ULL options use a ulonglong as the backing store.
+ HA_*OPTION_NUMBER() takes the option name, the structure field name,
+ the default value for the option, min, max, and blk_siz values.
+
+ STRING options use a char* as a backing store.
+ HA_*OPTION_STRING takes the option name and the structure field name.
+ The default value will be 0.
+
+ ENUM options use a uint as a backing store (not enum!!!).
+ HA_*OPTION_ENUM takes the option name, the structure field name,
+ the default value for the option as a number, and a string with the
+ permitted values for this enum - one string with comma separated values,
+ for example: "gzip,bzip2,lzma"
+
+ BOOL options use a bool as a backing store.
+ HA_*OPTION_BOOL takes the option name, the structure field name,
+ and the default value for the option.
+ From the SQL, BOOL options accept YES/NO, ON/OFF, and 1/0.
+
+ The name of the option is limited to 255 bytes,
+ the value (for string options) - to the 32767 bytes.
+
+ See ha_example.cc for an example.
+*/
+enum ha_option_type { HA_OPTION_TYPE_ULL, /* unsigned long long */
+ HA_OPTION_TYPE_STRING, /* char * */
+ HA_OPTION_TYPE_ENUM, /* uint */
+ HA_OPTION_TYPE_BOOL}; /* bool */
+
+#define HA_xOPTION_NUMBER(name, struc, field, def, min, max, blk_siz) \
+ { HA_OPTION_TYPE_ULL, name, sizeof(name)-1, \
+ offsetof(struc, field), def, min, max, blk_siz, 0 }
+#define HA_xOPTION_STRING(name, struc, field) \
+ { HA_OPTION_TYPE_STRING, name, sizeof(name)-1, \
+ offsetof(struc, field), 0, 0, 0, 0, 0 }
+#define HA_xOPTION_ENUM(name, struc, field, values, def) \
+ { HA_OPTION_TYPE_ENUM, name, sizeof(name)-1, \
+ offsetof(struc, field), def, 0, \
+ sizeof(values)-1, 0, values }
+#define HA_xOPTION_BOOL(name, struc, field, def) \
+ { HA_OPTION_TYPE_BOOL, name, sizeof(name)-1, \
+ offsetof(struc, field), def, 0, 1, 0, 0 }
+#define HA_xOPTION_END { HA_OPTION_TYPE_ULL, 0, 0, 0, 0, 0, 0, 0, 0 }
+
+#define HA_TOPTION_NUMBER(name, field, def, min, max, blk_siz) \
+ HA_xOPTION_NUMBER(name, ha_table_option_struct, field, def, min, max, blk_siz)
+#define HA_TOPTION_STRING(name, field) \
+ HA_xOPTION_STRING(name, ha_table_option_struct, field)
+#define HA_TOPTION_ENUM(name, field, values, def) \
+ HA_xOPTION_ENUM(name, ha_table_option_struct, field, values, def)
+#define HA_TOPTION_BOOL(name, field, def) \
+ HA_xOPTION_BOOL(name, ha_table_option_struct, field, def)
+#define HA_TOPTION_END HA_xOPTION_END
+
+#define HA_FOPTION_NUMBER(name, field, def, min, max, blk_siz) \
+ HA_xOPTION_NUMBER(name, ha_field_option_struct, field, def, min, max, blk_siz)
+#define HA_FOPTION_STRING(name, field) \
+ HA_xOPTION_STRING(name, ha_field_option_struct, field)
+#define HA_FOPTION_ENUM(name, field, values, def) \
+ HA_xOPTION_ENUM(name, ha_field_option_struct, field, values, def)
+#define HA_FOPTION_BOOL(name, field, def) \
+ HA_xOPTION_BOOL(name, ha_field_option_struct, field, def)
+#define HA_FOPTION_END HA_xOPTION_END
+
+#define HA_IOPTION_NUMBER(name, field, def, min, max, blk_siz) \
+ HA_xOPTION_NUMBER(name, ha_index_option_struct, field, def, min, max, blk_siz)
+#define HA_IOPTION_STRING(name, field) \
+ HA_xOPTION_STRING(name, ha_index_option_struct, field)
+#define HA_IOPTION_ENUM(name, field, values, def) \
+ HA_xOPTION_ENUM(name, ha_index_option_struct, field, values, def)
+#define HA_IOPTION_BOOL(name, field, values, def) \
+ HA_xOPTION_BOOL(name, ha_index_option_struct, field, values, def)
+#define HA_IOPTION_END HA_xOPTION_END
+
+typedef struct st_ha_create_table_option {
+ enum ha_option_type type;
+ const char *name;
+ size_t name_length;
+ ptrdiff_t offset;
+ ulonglong def_value;
+ ulonglong min_value, max_value, block_size;
+ const char *values;
+} ha_create_table_option;
enum handler_iterator_type
{
@@ -676,8 +792,9 @@ struct handlerton
SHOW_COMP_OPTION state;
/*
- Historical number used for frm file to determine the correct storage engine.
- This is going away and new engines will just use "name" for this.
+ Historical number used for frm file to determine the correct
+ storage engine. This is going away and new engines will just use
+ "name" for this.
*/
enum legacy_db_type db_type;
/*
@@ -787,17 +904,28 @@ struct handlerton
int (*table_exists_in_engine)(handlerton *hton, THD* thd, const char *db,
const char *name);
uint32 license; /* Flag for Engine License */
- void *data; /* Location for engines to keep personal structures */
+ /*
+ Optional clauses in the CREATE/ALTER TABLE
+ */
+ ha_create_table_option *table_options; // table level options
+ ha_create_table_option *field_options; // these are specified per field
+ ha_create_table_option *index_options; // these are specified per index
+
};
+inline LEX_STRING *hton_name(const handlerton *hton)
+{
+ return &(hton2plugin[hton->slot]->name);
+}
+
+
/* Possible flags of a handlerton (there can be 32 of them) */
#define HTON_NO_FLAGS 0
#define HTON_CLOSE_CURSORS_AT_COMMIT (1 << 0)
#define HTON_ALTER_NOT_SUPPORTED (1 << 1) //Engine does not support alter
#define HTON_CAN_RECREATE (1 << 2) //Delete all is used fro truncate
#define HTON_HIDDEN (1 << 3) //Engine does not appear in lists
-#define HTON_FLUSH_AFTER_RENAME (1 << 4)
#define HTON_NOT_USER_SELECTABLE (1 << 5)
#define HTON_TEMPORARY_NOT_SUPPORTED (1 << 6) //Having temporary tables not supported
#define HTON_SUPPORT_LOG_TABLES (1 << 7) //Engine supports log tables
@@ -843,6 +971,7 @@ struct THD_TRANS
void reset() { no_2pc= FALSE; modified_non_trans_table= FALSE; }
bool is_empty() const { return ha_list == NULL; }
+ THD_TRANS() {} /* Remove gcc warning */
};
@@ -953,9 +1082,9 @@ typedef struct {
ulonglong delete_length;
ha_rows records;
ulong mean_rec_length;
- ulong create_time;
- ulong check_time;
- ulong update_time;
+ time_t create_time;
+ time_t check_time;
+ time_t update_time;
ulonglong check_sum;
} PARTITION_STATS;
@@ -968,7 +1097,7 @@ class partition_info;
struct st_partition_iter;
#define NOT_A_PARTITION_ID ((uint32)-1)
-enum enum_ha_unused { HA_CHOICE_UNDEF, HA_CHOICE_NO, HA_CHOICE_YES };
+enum ha_choice { HA_CHOICE_UNDEF, HA_CHOICE_NO, HA_CHOICE_YES };
typedef struct st_ha_create_information
{
@@ -1000,11 +1129,16 @@ typedef struct st_ha_create_information
uint options; /* OR of HA_CREATE_ options */
uint merge_insert_method;
uint extra_size; /* length of extra data segment */
- enum enum_ha_unused unused1;
- bool frm_only; /* 1 if no ha_create_table() */
- bool varchar; /* 1 if table has a VARCHAR */
- enum ha_storage_media storage_media; /* DEFAULT, DISK or MEMORY */
- enum enum_ha_unused unused2;
+ enum ha_choice transactional;
+ bool frm_only; ///< 1 if no ha_create_table()
+ bool varchar; ///< 1 if table has a VARCHAR
+ enum ha_storage_media storage_media; ///< DEFAULT, DISK or MEMORY
+ enum ha_choice page_checksum; ///< If we have page_checksums
+ engine_option_value *option_list; ///< list of table create options
+ /* the following three are only for ALTER TABLE, check_if_incompatible_data() */
+ void *option_struct; ///< structure with parsed table options
+ void **fileds_option_struct; ///< array of field option structures
+ void **indexes_option_struct; ///< array of index option structures
} HA_CREATE_INFO;
@@ -1079,11 +1213,191 @@ typedef struct st_ha_check_opt
st_ha_check_opt() {} /* Remove gcc warning */
uint flags; /* isam layer flags (e.g. for myisamchk) */
uint sql_flags; /* sql layer flags - for something myisamchk cannot do */
- KEY_CACHE *key_cache; /* new key cache when changing key cache */
+ KEY_CACHE *key_cache; /* new key cache when changing key cache */
void init();
} HA_CHECK_OPT;
+/********************************************************************************
+ * MRR
+ ********************************************************************************/
+
+typedef void *range_seq_t;
+
+typedef struct st_range_seq_if
+{
+ /*
+ Initialize the traversal of range sequence
+
+ SYNOPSIS
+ init()
+ init_params The seq_init_param parameter
+ n_ranges The number of ranges obtained
+ flags A combination of HA_MRR_SINGLE_POINT, HA_MRR_FIXED_KEY
+
+ RETURN
+ An opaque value to be used as RANGE_SEQ_IF::next() parameter
+ */
+ range_seq_t (*init)(void *init_params, uint n_ranges, uint flags);
+
+
+ /*
+ Get the next range in the range sequence
+
+ SYNOPSIS
+ next()
+ seq The value returned by RANGE_SEQ_IF::init()
+ range OUT Information about the next range
+
+ RETURN
+ 0 - Ok, the range structure filled with info about the next range
+ 1 - No more ranges
+ */
+ uint (*next) (range_seq_t seq, KEY_MULTI_RANGE *range);
+
+ /*
+ Check whether range_info orders to skip the next record
+
+ SYNOPSIS
+ skip_record()
+ seq The value returned by RANGE_SEQ_IF::init()
+ range_info Information about the next range
+ (Ignored if MRR_NO_ASSOCIATION is set)
+ rowid Rowid of the record to be checked (ignored if set to 0)
+
+ RETURN
+ 1 - Record with this range_info and/or this rowid shall be filtered
+ out from the stream of records returned by multi_range_read_next()
+ 0 - The record shall be left in the stream
+ */
+ bool (*skip_record) (range_seq_t seq, char *range_info, uchar *rowid);
+
+ /*
+ Check if the record combination matches the index condition
+ SYNOPSIS
+ skip_index_tuple()
+ seq The value returned by RANGE_SEQ_IF::init()
+ range_info Information about the next range
+
+ RETURN
+ 0 - The record combination satisfies the index condition
+ 1 - Otherwise
+ */
+ bool (*skip_index_tuple) (range_seq_t seq, char *range_info);
+} RANGE_SEQ_IF;
+
+class COST_VECT
+{
+public:
+ double io_count; /* number of I/O */
+ double avg_io_cost; /* cost of an average I/O oper. */
+ double cpu_cost; /* cost of operations in CPU */
+ double mem_cost; /* cost of used memory */
+ double import_cost; /* cost of remote operations */
+
+ enum { IO_COEFF=1 };
+ enum { CPU_COEFF=1 };
+ enum { MEM_COEFF=1 };
+ enum { IMPORT_COEFF=1 };
+
+ COST_VECT() {} // keep gcc happy
+
+ double total_cost()
+ {
+ return IO_COEFF*io_count*avg_io_cost + CPU_COEFF * cpu_cost +
+ MEM_COEFF*mem_cost + IMPORT_COEFF*import_cost;
+ }
+
+ void zero()
+ {
+ avg_io_cost= 1.0;
+ io_count= cpu_cost= mem_cost= import_cost= 0.0;
+ }
+
+ void multiply(double m)
+ {
+ io_count *= m;
+ cpu_cost *= m;
+ import_cost *= m;
+ /* Don't multiply mem_cost */
+ }
+
+ void add(const COST_VECT* cost)
+ {
+ double io_count_sum= io_count + cost->io_count;
+ add_io(cost->io_count, cost->avg_io_cost);
+ io_count= io_count_sum;
+ cpu_cost += cost->cpu_cost;
+ }
+ void add_io(double add_io_cnt, double add_avg_cost)
+ {
+ double io_count_sum= io_count + add_io_cnt;
+ avg_io_cost= (io_count * avg_io_cost +
+ add_io_cnt * add_avg_cost) / io_count_sum;
+ io_count= io_count_sum;
+ }
+
+ /*
+ To be used when we go from old single value-based cost calculations to
+ the new COST_VECT-based.
+ */
+ void convert_from_cost(double cost)
+ {
+ zero();
+ avg_io_cost= 1.0;
+ io_count= cost;
+ }
+};
+
+void get_sweep_read_cost(TABLE *table, ha_rows nrows, bool interrupted,
+ COST_VECT *cost);
+
+/*
+ The below two are not used (and not handled) in this milestone of this WL
+ entry because there seems to be no use for them at this stage of
+ implementation.
+*/
+#define HA_MRR_SINGLE_POINT 1
+#define HA_MRR_FIXED_KEY 2
+
+/*
+ Indicates that RANGE_SEQ_IF::next(&range) doesn't need to fill in the
+ 'range' parameter.
+*/
+#define HA_MRR_NO_ASSOCIATION 4
+
+/*
+ The MRR user will provide ranges in key order, and MRR implementation
+ must return rows in key order.
+*/
+#define HA_MRR_SORTED 8
+
+/* MRR implementation doesn't have to retrieve full records */
+#define HA_MRR_INDEX_ONLY 16
+
+/*
+ The passed memory buffer is of maximum possible size, the caller can't
+ assume larger buffer.
+*/
+#define HA_MRR_LIMITS 32
+
+
+/*
+ Flag set <=> default MRR implementation is used
+ (The choice is made by **_info[_const]() function which may set this
+ flag. SQL layer remembers the flag value and then passes it to
+ multi_read_range_init().
+*/
+#define HA_MRR_USE_DEFAULT_IMPL 64
+
+/*
+ Used only as parameter to multi_range_read_info():
+ Flag set <=> the caller guarantees that the bounds of the scanned ranges
+ will not have NULL values.
+*/
+#define HA_MRR_NO_NULL_ENDPOINTS 128
+
+
/*
This is a buffer area that the handler can use to store rows.
@@ -1094,8 +1408,8 @@ typedef struct st_ha_check_opt
typedef struct st_handler_buffer
{
- const uchar *buffer; /* Buffer one can start using */
- const uchar *buffer_end; /* End of buffer */
+ /* const? */uchar *buffer; /* Buffer one can start using */
+ /* const? */uchar *buffer_end; /* End of buffer */
uchar *end_of_used_area; /* End of area that was used by handler */
} HANDLER_BUFFER;
@@ -1121,16 +1435,21 @@ public:
ha_rows records;
ha_rows deleted; /* Deleted records */
ulong mean_rec_length; /* physical reclength */
- ulong create_time; /* When table was created */
- ulong check_time;
- ulong update_time;
+ time_t create_time; /* When table was created */
+ time_t check_time;
+ time_t update_time;
uint block_size; /* index block size */
+ /*
+ number of buffer bytes that native mrr implementation needs,
+ */
+ uint mrr_length_per_rec;
+
ha_statistics():
data_file_length(0), max_data_file_length(0),
index_file_length(0), delete_length(0), auto_increment_value(0),
records(0), deleted(0), mean_rec_length(0), create_time(0),
- check_time(0), update_time(0), block_size(0)
+ check_time(0), update_time(0), block_size(0), mrr_length_per_rec(0)
{}
};
@@ -1169,11 +1488,18 @@ public:
ha_statistics stats;
- /** The following are for read_multi_range */
- bool multi_range_sorted;
- KEY_MULTI_RANGE *multi_range_curr;
- KEY_MULTI_RANGE *multi_range_end;
- HANDLER_BUFFER *multi_range_buffer;
+ /** MultiRangeRead-related members: */
+ range_seq_t mrr_iter; /* Interator to traverse the range sequence */
+ RANGE_SEQ_IF mrr_funcs; /* Range sequence traversal functions */
+ HANDLER_BUFFER *multi_range_buffer; /* MRR buffer info */
+ uint ranges_in_seq; /* Total number of ranges in the traversed sequence */
+ /* TRUE <=> source MRR ranges and the output are ordered */
+ bool mrr_is_output_sorted;
+
+ /** TRUE <=> we're currently traversing a range in mrr_cur_range. */
+ bool mrr_have_range;
+ /** Current range (the one we're now returning rows from) */
+ KEY_MULTI_RANGE mrr_cur_range;
/** The following are for read_range() */
key_range save_end_range, *end_range;
@@ -1184,12 +1510,20 @@ public:
uint errkey; /* Last dup key */
uint key_used_on_scan;
uint active_index;
+ /*
+ TRUE <=> the engine guarantees that returned records are within the range
+ being scanned.
+ */
+ bool in_range_check_pushed_down;
+
/** Length of ref (1-8 or the clustered key length) */
uint ref_length;
FT_INFO *ft_handler;
enum {NONE=0, INDEX, RND} inited;
bool locked;
bool implicit_emptied; /* Can be !=0 only if HEAP */
+ bool mark_trx_done;
+ bool cloned; /* 1 if this was created with clone */
const COND *pushed_cond;
/**
next_insert_id is the next value which should be inserted into the
@@ -1212,6 +1546,15 @@ public:
Interval returned by get_auto_increment() and being consumed by the
inserter.
*/
+ /* Statistics variables */
+ ulonglong rows_read;
+ ulonglong rows_changed;
+ /* One bigger than needed to avoid to test if key == MAX_KEY */
+ ulonglong index_rows_read[MAX_KEY+1];
+
+ Item *pushed_idx_cond;
+ uint pushed_idx_cond_keyno; /* The index which the above condition is for */
+
Discrete_interval auto_inc_interval_for_cur_row;
/**
Number of reserved auto-increment intervals. Serves as a heuristic
@@ -1239,13 +1582,18 @@ public:
:table_share(share_arg), table(0),
estimation_rows_to_insert(0), ht(ht_arg),
ref(0), key_used_on_scan(MAX_KEY), active_index(MAX_KEY),
+ in_range_check_pushed_down(FALSE),
ref_length(sizeof(my_off_t)),
ft_handler(0), inited(NONE),
- locked(FALSE), implicit_emptied(0),
+ locked(FALSE), implicit_emptied(0), mark_trx_done(FALSE), cloned(0),
pushed_cond(0), next_insert_id(0), insert_id_for_cur_row(0),
+ pushed_idx_cond(NULL),
+ pushed_idx_cond_keyno(MAX_KEY),
auto_inc_intervals_count(0),
m_psi(NULL)
- {}
+ {
+ reset_statistics();
+ }
virtual ~handler(void)
{
DBUG_ASSERT(locked == FALSE);
@@ -1267,6 +1615,7 @@ public:
DBUG_ASSERT(inited==NONE);
if (!(result= index_init(idx, sorted)))
inited=INDEX;
+ end_range= NULL;
DBUG_RETURN(result);
}
int ha_index_end()
@@ -1274,9 +1623,12 @@ public:
DBUG_ENTER("ha_index_end");
DBUG_ASSERT(inited==INDEX);
inited=NONE;
+ end_range= NULL;
DBUG_RETURN(index_end());
}
- int ha_rnd_init(bool scan)
+ /* This is called after index_init() if we need to do a index scan */
+ virtual int prepare_index_scan() { return 0; }
+ int ha_rnd_init(bool scan) __attribute__ ((warn_unused_result))
{
int result;
DBUG_ENTER("ha_rnd_init");
@@ -1291,7 +1643,15 @@ public:
inited=NONE;
DBUG_RETURN(rnd_end());
}
+ int ha_rnd_init_with_error(bool scan) __attribute__ ((warn_unused_result));
int ha_reset();
+ /* Tell handler (not storage engine) this is start of a new statement */
+ void ha_start_of_new_statement()
+ {
+ ft_handler= 0;
+ mark_trx_done= FALSE;
+ }
+
/* this is necessary in many places, e.g. in HANDLER command */
int ha_index_or_rnd_end()
{
@@ -1363,15 +1723,31 @@ public:
virtual void print_error(int error, myf errflag);
virtual bool get_error_message(int error, String *buf);
uint get_dup_key(int error);
+ void reset_statistics()
+ {
+ rows_read= rows_changed= 0;
+ bzero(index_rows_read, sizeof(index_rows_read));
+ }
virtual void change_table_ptr(TABLE *table_arg, TABLE_SHARE *share)
{
table= table_arg;
table_share= share;
+ reset_statistics();
}
virtual double scan_time()
{ return ulonglong2double(stats.data_file_length) / IO_SIZE + 2; }
virtual double read_time(uint index, uint ranges, ha_rows rows)
{ return rows2double(ranges+rows); }
+
+ /**
+ Calculate cost of 'keyread' scan for given index and number of records.
+
+ @param index index to read
+ @param ranges #of ranges to read
+ @param rows #of records to read
+ */
+ virtual double keyread_time(uint index, uint ranges, ha_rows rows);
+
virtual const key_map *keys_to_use_for_scanning() { return &key_map_empty; }
bool has_transactions()
{ return (ha_table_flags() & HA_NO_TRANSACTIONS) == 0; }
@@ -1475,22 +1851,23 @@ public:
}
/**
@brief
- Positions an index cursor to the index specified in the handle. Fetches the
- row if available. If the key value is null, begin at the first key of the
- index.
+ Positions an index cursor to the index specified in the
+ handle. Fetches the row if available. If the key value is null,
+ begin at the first key of the index.
*/
+protected:
virtual int index_read_map(uchar * buf, const uchar * key,
key_part_map keypart_map,
enum ha_rkey_function find_flag)
{
uint key_len= calculate_key_len(table, active_index, key, keypart_map);
- return index_read(buf, key, key_len, find_flag);
+ return index_read(buf, key, key_len, find_flag);
}
/**
@brief
- Positions an index cursor to the index specified in the handle. Fetches the
- row if available. If the key value is null, begin at the first key of the
- index.
+ Positions an index cursor to the index specified in the
+ handle. Fetches the row if available. If the key value is null,
+ begin at the first key of the index.
*/
virtual int index_read_idx_map(uchar * buf, uint index, const uchar * key,
key_part_map keypart_map,
@@ -1504,30 +1881,46 @@ public:
virtual int index_last(uchar * buf)
{ return HA_ERR_WRONG_COMMAND; }
virtual int index_next_same(uchar *buf, const uchar *key, uint keylen);
- /**
- @brief
- The following functions works like index_read, but it find the last
- row with the current key value or prefix.
- */
- virtual int index_read_last_map(uchar * buf, const uchar * key,
- key_part_map keypart_map)
+ inline void update_index_statistics()
{
- uint key_len= calculate_key_len(table, active_index, key, keypart_map);
- return index_read_last(buf, key, key_len);
+ index_rows_read[active_index]++;
+ rows_read++;
}
- virtual int read_multi_range_first(KEY_MULTI_RANGE **found_range_p,
- KEY_MULTI_RANGE *ranges, uint range_count,
- bool sorted, HANDLER_BUFFER *buffer);
- virtual int read_multi_range_next(KEY_MULTI_RANGE **found_range_p);
+public:
+
+ /* Similar functions like the above, but does statistics counting */
+ inline int ha_index_read_map(uchar * buf, const uchar * key,
+ key_part_map keypart_map,
+ enum ha_rkey_function find_flag);
+ inline int ha_index_read_idx_map(uchar * buf, uint index, const uchar * key,
+ key_part_map keypart_map,
+ enum ha_rkey_function find_flag);
+ inline int ha_index_next(uchar * buf);
+ inline int ha_index_prev(uchar * buf);
+ inline int ha_index_first(uchar * buf);
+ inline int ha_index_last(uchar * buf);
+ inline int ha_index_next_same(uchar *buf, const uchar *key, uint keylen);
+ virtual ha_rows multi_range_read_info_const(uint keyno, RANGE_SEQ_IF *seq,
+ void *seq_init_param,
+ uint n_ranges, uint *bufsz,
+ uint *flags, COST_VECT *cost);
+ virtual ha_rows multi_range_read_info(uint keyno, uint n_ranges, uint keys,
+ uint *bufsz, uint *flags, COST_VECT *cost);
+ virtual int multi_range_read_init(RANGE_SEQ_IF *seq, void *seq_init_param,
+ uint n_ranges, uint mode,
+ HANDLER_BUFFER *buf);
+ virtual int multi_range_read_next(char **range_info);
virtual int read_range_first(const key_range *start_key,
const key_range *end_key,
bool eq_range, bool sorted);
virtual int read_range_next();
int compare_key(key_range *range);
+ int compare_key2(key_range *range);
virtual int ft_init() { return HA_ERR_WRONG_COMMAND; }
void ft_end() { ft_handler=NULL; }
virtual FT_INFO *ft_init_ext(uint flags, uint inx,String *key)
{ return NULL; }
+private:
virtual int ft_read(uchar *buf) { return HA_ERR_WRONG_COMMAND; }
virtual int rnd_next(uchar *buf)=0;
virtual int rnd_pos(uchar * buf, uchar *pos)=0;
@@ -1537,20 +1930,33 @@ public:
It will return the row with the PK given in the record argument.
*/
virtual int rnd_pos_by_record(uchar *record)
- {
- position(record);
- return rnd_pos(record, ref);
- }
+ {
+ position(record);
+ return rnd_pos(record, ref);
+ }
virtual int read_first_row(uchar *buf, uint primary_key);
+public:
+
+ /* Same as above, but with statistics */
+ inline int ha_ft_read(uchar *buf);
+ inline int ha_rnd_next(uchar *buf);
+ inline int ha_rnd_pos(uchar *buf, uchar *pos);
+ inline int ha_rnd_pos_by_record(uchar *buf);
+ inline int ha_read_first_row(uchar *buf, uint primary_key);
+
/**
- The following function is only needed for tables that may be temporary
- tables during joins.
+ The following 3 function is only needed for tables that may be
+ internal temporary tables during joins.
*/
- virtual int restart_rnd_next(uchar *buf, uchar *pos)
+ virtual int remember_rnd_pos()
+ { return HA_ERR_WRONG_COMMAND; }
+ virtual int restart_rnd_next(uchar *buf)
{ return HA_ERR_WRONG_COMMAND; }
virtual int rnd_same(uchar *buf, uint inx)
{ return HA_ERR_WRONG_COMMAND; }
- virtual ha_rows records_in_range(uint inx, key_range *min_key, key_range *max_key)
+
+ virtual ha_rows records_in_range(uint inx, key_range *min_key,
+ key_range *max_key)
{ return (ha_rows) 10; }
/*
If HA_PRIMARY_KEY_REQUIRED_FOR_POSITION is set, then it sets ref
@@ -1666,7 +2072,8 @@ public:
*/
virtual const char **bas_ext() const =0;
- virtual int get_default_no_partitions(HA_CREATE_INFO *info) { return 1;}
+ virtual int get_default_no_partitions(HA_CREATE_INFO *create_info)
+ { return 1;}
virtual void set_auto_partitions(partition_info *part_info) { return; }
virtual bool get_no_parts(const char *name,
uint *no_parts)
@@ -1709,13 +2116,14 @@ public:
virtual bool is_crashed() const { return 0; }
virtual bool auto_repair() const { return 0; }
+ void update_global_table_stats();
+ void update_global_index_stats();
#define CHF_CREATE_FLAG 0
#define CHF_DELETE_FLAG 1
#define CHF_RENAME_FLAG 2
#define CHF_INDEX_FLAG 3
-
/**
@note lock_count() can return > 1 if the table is MERGE or partitioned.
*/
@@ -1826,6 +2234,7 @@ public:
Pops the top if condition stack, if stack is not empty.
*/
virtual void cond_pop() { return; };
+ virtual Item *idx_cond_push(uint keyno, Item* idx_cond) { return idx_cond; }
virtual bool check_if_incompatible_data(HA_CREATE_INFO *create_info,
uint table_changes)
{ return COMPATIBLE_DATA_NO; }
@@ -1843,9 +2252,24 @@ public:
return 0;
}
+ LEX_STRING *engine_name() { return hton_name(ht); }
+
+ /*
+ @brief
+ Check whether the engine supports virtual columns
+
+ @retval
+ FALSE if the engine does not support virtual columns
+ @retval
+ TRUE if the engine supports virtual columns
+ */
+ virtual bool check_if_supported_virtual_columns(void) { return FALSE;}
+
protected:
+ /* deprecated, don't use in new engines */
+ inline void ha_statistic_increment(ulong SSV::*offset) const { }
+
/* Service methods for use by storage engines. */
- void ha_statistic_increment(ulong SSV::*offset) const;
void **ha_data(THD *) const;
THD *ha_thd(void) const;
@@ -1895,10 +2319,18 @@ protected:
tables.
*/
virtual int delete_table(const char *name);
+
private:
/* Private helpers */
- inline void mark_trx_read_write();
-private:
+ void mark_trx_read_write_part2();
+ inline void mark_trx_read_write()
+ {
+ if (!mark_trx_done)
+ mark_trx_read_write_part2();
+ }
+ inline void increment_statistics(ulong SSV::*offset) const;
+ inline void decrement_statistics(ulong SSV::*offset) const;
+
/*
Low-level primitives for storage engines. These should be
overridden by the storage engine class. To call these methods, use
@@ -1985,8 +2417,6 @@ private:
virtual int index_read(uchar * buf, const uchar * key, uint key_len,
enum ha_rkey_function find_flag)
{ return HA_ERR_WRONG_COMMAND; }
- virtual int index_read_last(uchar * buf, const uchar * key, uint key_len)
- { return (my_errno= HA_ERR_WRONG_COMMAND); }
/**
This method is similar to update_row, however the handler doesn't need
to execute the updates at this point in time. The handler can be certain
@@ -2051,8 +2481,17 @@ private:
{ return HA_ERR_WRONG_COMMAND; }
virtual int rename_partitions(const char *path)
{ return HA_ERR_WRONG_COMMAND; }
+ friend class ha_partition;
+ friend class DsMrr_impl;
+public:
+ /* XXX to be removed, see ha_partition::partition_ht() */
+ virtual handlerton *partition_ht() const
+ { return ht; }
};
+#include "multi_range_read.h"
+
+bool key_uses_partial_cols(TABLE *table, uint keyno);
/* Some extern variables used with handlers */
@@ -2081,7 +2520,7 @@ static inline enum legacy_db_type ha_legacy_type(const handlerton *db_type)
static inline const char *ha_resolve_storage_engine_name(const handlerton *db_type)
{
- return db_type == NULL ? "UNKNOWN" : hton2plugin[db_type->slot]->name.str;
+ return db_type == NULL ? "UNKNOWN" : hton_name(db_type)->str;
}
static inline bool ha_check_storage_engine_flag(const handlerton *db_type, uint32 flag)
@@ -2131,6 +2570,7 @@ int ha_table_exists_in_engine(THD* thd, const char* db, const char* name);
extern "C" int ha_init_key_cache(const char *name, KEY_CACHE *key_cache);
int ha_resize_key_cache(KEY_CACHE *key_cache);
int ha_change_key_cache_param(KEY_CACHE *key_cache);
+int ha_repartition_key_cache(KEY_CACHE *key_cache);
int ha_change_key_cache(KEY_CACHE *old_key_cache, KEY_CACHE *new_key_cache);
/* report to InnoDB that control passes to the client */
@@ -2187,10 +2627,8 @@ const char *get_canonical_filename(handler *file, const char *path,
char *tmp_path);
bool mysql_xa_recover(THD *thd);
-
inline const char *table_case_name(HA_CREATE_INFO *info, const char *name)
{
return ((lower_case_table_names == 2 && info->alias) ? info->alias : name);
}
-
-#endif /* HANDLER_INCLUDED */
+#endif