diff options
Diffstat (limited to 'innobase/include/row0sel.h')
-rw-r--r-- | innobase/include/row0sel.h | 330 |
1 files changed, 330 insertions, 0 deletions
diff --git a/innobase/include/row0sel.h b/innobase/include/row0sel.h new file mode 100644 index 00000000000..a64d3f8e425 --- /dev/null +++ b/innobase/include/row0sel.h @@ -0,0 +1,330 @@ +/****************************************************** +Select + +(c) 1997 Innobase Oy + +Created 12/19/1997 Heikki Tuuri +*******************************************************/ + +#ifndef row0sel_h +#define row0sel_h + +#include "univ.i" +#include "data0data.h" +#include "que0types.h" +#include "dict0types.h" +#include "trx0types.h" +#include "row0types.h" +#include "que0types.h" +#include "pars0sym.h" +#include "btr0pcur.h" +#include "read0read.h" +#include "row0mysql.h" + +/************************************************************************* +Creates a select node struct. */ + +sel_node_t* +sel_node_create( +/*============*/ + /* out, own: select node struct */ + mem_heap_t* heap); /* in: memory heap where created */ +/************************************************************************* +Frees the memory private to a select node when a query graph is freed, +does not free the heap where the node was originally created. */ + +void +sel_node_free_private( +/*==================*/ + sel_node_t* node); /* in: select node struct */ +/************************************************************************* +Frees a prefetch buffer for a column, including the dynamically allocated +memory for data stored there. */ + +void +sel_col_prefetch_buf_free( +/*======================*/ + sel_buf_t* prefetch_buf); /* in, own: prefetch buffer */ +/************************************************************************* +Gets the plan node for the nth table in a join. */ +UNIV_INLINE +plan_t* +sel_node_get_nth_plan( +/*==================*/ + sel_node_t* node, + ulint i); +/************************************************************************** +Performs a select step. This is a high-level function used in SQL execution +graphs. */ + +que_thr_t* +row_sel_step( +/*=========*/ + /* out: query thread to run next or NULL */ + que_thr_t* thr); /* in: query thread */ +/************************************************************************** +Performs an execution step of an open or close cursor statement node. */ +UNIV_INLINE +que_thr_t* +open_step( +/*======*/ + /* out: query thread to run next or NULL */ + que_thr_t* thr); /* in: query thread */ +/************************************************************************** +Performs a fetch for a cursor. */ + +que_thr_t* +fetch_step( +/*=======*/ + /* out: query thread to run next or NULL */ + que_thr_t* thr); /* in: query thread */ +/*************************************************************** +Prints a row in a select result. */ + +que_thr_t* +row_printf_step( +/*============*/ + /* out: query thread to run next or NULL */ + que_thr_t* thr); /* in: query thread */ +/******************************************************************** +Converts a key value stored in MySQL format to an Innobase dtuple. +The last field of the key value may be just a prefix of a fixed length +field: hence the parameter key_len. */ + +void +row_sel_convert_mysql_key_to_innobase( +/*==================================*/ + dtuple_t* tuple, /* in: tuple where to build; + NOTE: we assume that the type info + in the tuple is already according + to index! */ + byte* buf, /* in: buffer to use in field + conversions */ + dict_index_t* index, /* in: index of the key value */ + byte* key_ptr, /* in: MySQL key value */ + ulint key_len); /* in: MySQL key value length */ +/************************************************************************ +Searches for rows in the database. This is used in the interface to +MySQL. This function opens a cursor, and also implements fetch next +and fetch prev. NOTE that if we do a search with a full key value +from a unique index (ROW_SEL_EXACT), then we will not store the cursor +position and fetch next or fetch prev must not be tried to the cursor! */ + +ulint +row_search_for_mysql( +/*=================*/ + /* out: DB_SUCCESS, + DB_RECORD_NOT_FOUND, + DB_END_OF_INDEX, or DB_DEADLOCK */ + byte* buf, /* in/out: buffer for the fetched + row in the MySQL format */ + ulint mode, /* in: search mode PAGE_CUR_L, ... */ + row_prebuilt_t* prebuilt, /* in: prebuilt struct for the + table handle; this contains the info + of search_tuple, index; if search + tuple contains 0 fields then we + position the cursor at the start or + the end of the index, depending on + 'mode' */ + ulint match_mode, /* in: 0 or ROW_SEL_EXACT or + ROW_SEL_EXACT_PREFIX */ + ulint direction); /* in: 0 or ROW_SEL_NEXT or + ROW_SEL_PREV; NOTE: if this is != 0, + then prebuilt must have a pcur + with stored position! In opening of a + cursor 'direction' should be 0. */ + + +/* A structure for caching column values for prefetched rows */ +struct sel_buf_struct{ + byte* data; /* data, or NULL; if not NULL, this field + has allocated memory which must be explicitly + freed; can be != NULL even when len is + UNIV_SQL_NULL */ + ulint len; /* data length or UNIV_SQL_NULL */ + ulint val_buf_size; + /* size of memory buffer allocated for data: + this can be more than len; this is defined + when data != NULL */ +}; + +struct plan_struct{ + dict_table_t* table; /* table struct in the dictionary + cache */ + dict_index_t* index; /* table index used in the search */ + btr_pcur_t pcur; /* persistent cursor used to search + the index */ + ibool asc; /* TRUE if cursor traveling upwards */ + ibool pcur_is_open; /* TRUE if pcur has been positioned + and we can try to fetch new rows */ + ibool cursor_at_end; /* TRUE if the cursor is open but + we know that there are no more + qualifying rows left to retrieve from + the index tree; NOTE though, that + there may still be unprocessed rows in + the prefetch stack; always FALSE when + pcur_is_open is FALSE */ + ibool stored_cursor_rec_processed; + /* TRUE if the pcur position has been + stored and the record it is positioned + on has already been processed */ + que_node_t** tuple_exps; /* array of expressions which are used + to calculate the field values in the + search tuple: there is one expression + for each field in the search tuple */ + dtuple_t* tuple; /* search tuple */ + ulint mode; /* search mode: PAGE_CUR_G, ... */ + ulint n_exact_match; /* number of first fields in the search + tuple which must be exactly matched */ + ibool unique_search; /* TRUE if we are searching an + index record with a unique key */ + ulint n_rows_fetched; /* number of rows fetched using pcur + after it was opened */ + ulint n_rows_prefetched;/* number of prefetched rows cached + for fetch: fetching several rows in + the same mtr saves CPU time */ + ulint first_prefetched;/* index of the first cached row in + select buffer arrays for each column */ + ibool no_prefetch; /* no prefetch for this table */ + ibool mixed_index; /* TRUE if index is a clustered index + in a mixed cluster */ + sym_node_list_t columns; /* symbol table nodes for the columns + to retrieve from the table */ + UT_LIST_BASE_NODE_T(func_node_t) + end_conds; /* conditions which determine the + fetch limit of the index segment we + have to look at: when one of these + fails, the result set has been + exhausted for the cursor in this + index; these conditions are normalized + so that in a comparison the column + for this table is the first argument */ + UT_LIST_BASE_NODE_T(func_node_t) + other_conds; /* the rest of search conditions we can + test at this table in a join */ + ibool must_get_clust; /* TRUE if index is a non-clustered + index and we must also fetch the + clustered index record; this is the + case if the non-clustered record does + not contain all the needed columns, or + if this is a single-table explicit + cursor, or a searched update or + delete */ + ulint* clust_map; /* map telling how clust_ref is built + from the fields of a non-clustered + record */ + dtuple_t* clust_ref; /* the reference to the clustered + index entry is built here if index is + a non-clustered index */ + btr_pcur_t clust_pcur; /* if index is non-clustered, we use + this pcur to search the clustered + index */ + mem_heap_t* old_vers_heap; /* memory heap used in building an old + version of a row, or NULL */ +}; + +struct sel_node_struct{ + que_common_t common; /* node type: QUE_NODE_SELECT */ + ulint state; /* node state */ + que_node_t* select_list; /* select list */ + sym_node_t* into_list; /* variables list or NULL */ + sym_node_t* table_list; /* table list */ + ibool asc; /* TRUE if the rows should be fetched + in an ascending order */ + ibool set_x_locks; /* TRUE if the cursor is for update or + delete, which means that a row x-lock + should be placed on the cursor row */ + ibool select_will_do_update; + /* TRUE if the select is for a searched + update which can be performed in-place: + in this case the select will take care + of the update */ + ulint latch_mode; /* BTR_SEARCH_LEAF, or BTR_MODIFY_LEAF + if select_will_do_update is TRUE */ + ulint row_lock_mode; /* LOCK_X or LOCK_S */ + ulint n_tables; /* number of tables */ + ulint fetch_table; /* number of the next table to access + in the join */ + plan_t* plans; /* array of n_tables many plan nodes + containing the search plan and the + search data structures */ + que_node_t* search_cond; /* search condition */ + read_view_t* read_view; /* if the query is a non-locking + consistent read, its read view is + placed here, otherwise NULL */ + ibool consistent_read;/* TRUE if the select is a consistent, + non-locking read */ + order_node_t* order_by; /* order by column definition, or + NULL */ + ibool is_aggregate; /* TRUE if the select list consists of + aggregate functions */ + ibool aggregate_already_fetched; + /* TRUE if the aggregate row has + already been fetched for the current + cursor */ + ibool can_get_updated;/* this is TRUE if the select is in a + single-table explicit cursor which can + get updated within the stored procedure, + or in a searched update or delete; + NOTE that to determine of an explicit + cursor if it can get updated, the + parser checks from a stored procedure + if it contains positioned update or + delete statements */ + sym_node_t* explicit_cursor;/* not NULL if an explicit cursor */ + UT_LIST_BASE_NODE_T(sym_node_t) + copy_variables; /* variables whose values we have to + copy when an explicit cursor is opened, + so that they do not change between + fetches */ +}; + +/* Select node states */ +#define SEL_NODE_CLOSED 0 /* it is a declared cursor which is not + currently open */ +#define SEL_NODE_OPEN 1 /* intention locks not yet set on + tables */ +#define SEL_NODE_FETCH 2 /* intention locks have been set */ +#define SEL_NODE_NO_MORE_ROWS 3 /* cursor has reached the result set + end */ + +/* Fetch statement node */ +struct fetch_node_struct{ + que_common_t common; /* type: QUE_NODE_FETCH */ + sel_node_t* cursor_def; /* cursor definition */ + sym_node_t* into_list; /* variables to set */ +}; + +/* Open or close cursor statement node */ +struct open_node_struct{ + que_common_t common; /* type: QUE_NODE_OPEN */ + ulint op_type; /* ROW_SEL_OPEN_CURSOR or + ROW_SEL_CLOSE_CURSOR */ + sel_node_t* cursor_def; /* cursor definition */ +}; + +/* Row printf statement node */ +struct row_printf_node_struct{ + que_common_t common; /* type: QUE_NODE_ROW_PRINTF */ + sel_node_t* sel_node; /* select */ +}; + +#define ROW_SEL_OPEN_CURSOR 0 +#define ROW_SEL_CLOSE_CURSOR 1 + +/* Flags for the MySQL interface */ +#define ROW_SEL_NEXT 1 +#define ROW_SEL_PREV 2 + +#define ROW_SEL_EXACT 1 /* search using a complete key value */ +#define ROW_SEL_EXACT_PREFIX 2 /* search using a key prefix which + must match to rows: the prefix may + contain an incomplete field (the + last field in prefix may be just + a prefix of a fixed length column) */ + +#ifndef UNIV_NONINL +#include "row0sel.ic" +#endif + +#endif |