/****************************************************** Interface between Innobase row operations and MySQL. Contains also create table and other data dictionary operations. (c) 2000 Innobase Oy Created 9/17/2000 Heikki Tuuri *******************************************************/ #ifndef row0mysql_h #define row0mysql_h #include "univ.i" #include "data0data.h" #include "que0types.h" #include "dict0types.h" #include "trx0types.h" #include "row0types.h" #include "btr0pcur.h" #include "trx0types.h" typedef struct row_prebuilt_struct row_prebuilt_t; /*********************************************************************** Stores a variable-length field (like VARCHAR) length to dest, in the MySQL format. */ UNIV_INLINE byte* row_mysql_store_var_len( /*====================*/ /* out: dest + 2 */ byte* dest, /* in: where to store */ ulint len); /* in: length, must fit in two bytes */ /*********************************************************************** Reads a MySQL format variable-length field (like VARCHAR) length and returns pointer to the field data. */ UNIV_INLINE byte* row_mysql_read_var_ref( /*===================*/ /* out: field + 2 */ ulint* len, /* out: variable-length field length */ byte* field); /* in: field */ /*********************************************************************** Reads a MySQL format variable-length field (like VARCHAR) length and returns pointer to the field data. */ byte* row_mysql_read_var_ref_noninline( /*=============================*/ /* out: field + 2 */ ulint* len, /* out: variable-length field length */ byte* field); /* in: field */ /*********************************************************************** Stores a reference to a BLOB in the MySQL format. */ void row_mysql_store_blob_ref( /*=====================*/ byte* dest, /* in: where to store */ ulint col_len, /* in: dest buffer size: determines into how many bytes the BLOB length is stored, this may vary from 1 to 4 bytes */ byte* data, /* in: BLOB data */ ulint len); /* in: BLOB length */ /*********************************************************************** Reads a reference to a BLOB in the MySQL format. */ byte* row_mysql_read_blob_ref( /*====================*/ /* out: pointer to BLOB data */ ulint* len, /* out: BLOB length */ byte* ref, /* in: BLOB reference in the MySQL format */ ulint col_len); /* in: BLOB reference length (not BLOB length) */ /****************************************************************** Stores a non-SQL-NULL field given in the MySQL format in the Innobase format. */ UNIV_INLINE void row_mysql_store_col_in_innobase_format( /*===================================*/ dfield_t* dfield, /* in/out: dfield */ byte* buf, /* in/out: buffer for the converted value */ byte* mysql_data, /* in: MySQL column value, not SQL NULL; NOTE that dfield may also get a pointer to mysql_data, therefore do not discard this as long as dfield is used! */ ulint col_len, /* in: MySQL column length */ ulint type, /* in: data type */ ulint is_unsigned); /* in: != 0 if unsigned integer type */ /******************************************************************** Handles user errors and lock waits detected by the database engine. */ ibool row_mysql_handle_errors( /*====================*/ /* out: TRUE if it was a lock wait and we should continue running the query thread */ ulint* new_err,/* out: possible new error encountered in rollback, or the old error which was during the function entry */ trx_t* trx, /* in: transaction */ que_thr_t* thr, /* in: query thread */ trx_savept_t* savept);/* in: savepoint */ /************************************************************************ Create a prebuilt struct for a MySQL table handle. */ row_prebuilt_t* row_create_prebuilt( /*================*/ /* out, own: a prebuilt struct */ dict_table_t* table); /* in: Innobase table handle */ /************************************************************************ Free a prebuilt struct for a MySQL table handle. */ void row_prebuilt_free( /*==============*/ row_prebuilt_t* prebuilt); /* in, own: prebuilt struct */ /************************************************************************* Updates the transaction pointers in query graphs stored in the prebuilt struct. */ void row_update_prebuilt_trx( /*====================*/ /* out: prebuilt dtuple */ row_prebuilt_t* prebuilt, /* in: prebuilt struct in MySQL handle */ trx_t* trx); /* in: transaction handle */ /************************************************************************* Does an insert for MySQL. */ int row_insert_for_mysql( /*=================*/ /* out: error code or DB_SUCCESS */ byte* mysql_rec, /* in: row in the MySQL format */ row_prebuilt_t* prebuilt); /* in: prebuilt struct in MySQL handle */ /************************************************************************* Builds a dummy query graph used in selects. */ void row_prebuild_sel_graph( /*===================*/ row_prebuilt_t* prebuilt); /* in: prebuilt struct in MySQL handle */ /************************************************************************* Gets pointer to a prebuilt update vector used in updates. If the update graph has not yet been built in the prebuilt struct, then this function first builds it. */ upd_t* row_get_prebuilt_update_vector( /*===========================*/ /* out: prebuilt update vector */ row_prebuilt_t* prebuilt); /* in: prebuilt struct in MySQL handle */ /************************************************************************* Checks if a table is such that we automatically created a clustered index on it (on row id). */ ibool row_table_got_default_clust_index( /*==============================*/ dict_table_t* table); /************************************************************************* Calculates the key number used inside MySQL for an Innobase index. We have to take into account if we generated a default clustered index for the table */ ulint row_get_mysql_key_number_for_index( /*===============================*/ dict_index_t* index); /************************************************************************* Does an update or delete of a row for MySQL. */ int row_update_for_mysql( /*=================*/ /* out: error code or DB_SUCCESS */ byte* mysql_rec, /* in: the row to be updated, in the MySQL format */ row_prebuilt_t* prebuilt); /* in: prebuilt struct in MySQL handle */ /************************************************************************* Does a table creation operation for MySQL. */ int row_create_table_for_mysql( /*=======================*/ /* out: error code or DB_SUCCESS */ dict_table_t* table, /* in: table definition */ trx_t* trx); /* in: transaction handle */ /************************************************************************* Does an index creation operation for MySQL. TODO: currently failure to create an index results in dropping the whole table! This is no problem currently as all indexes must be created at the same time as the table. */ int row_create_index_for_mysql( /*=======================*/ /* out: error number or DB_SUCCESS */ dict_index_t* index, /* in: index defintion */ trx_t* trx); /* in: transaction handle */ /************************************************************************* Drops a table for MySQL. */ int row_drop_table_for_mysql( /*=====================*/ /* out: error code or DB_SUCCESS */ char* name, /* in: table name */ trx_t* trx, /* in: transaction handle */ ibool has_dict_mutex);/* in: TRUE if the caller already owns the dictionary system mutex */ /************************************************************************* Renames a table for MySQL. */ int row_rename_table_for_mysql( /*=======================*/ /* out: error code or DB_SUCCESS */ char* old_name, /* in: old table name */ char* new_name, /* in: new table name */ trx_t* trx); /* in: transaction handle */ /************************************************************************* Checks a table for corruption. */ ulint row_check_table_for_mysql( /*======================*/ /* out: DB_ERROR or DB_SUCCESS */ row_prebuilt_t* prebuilt); /* in: prebuilt struct in MySQL handle */ /* A struct describing a place for an individual column in the MySQL row format which is presented to the table handler in ha_innobase. This template struct is used to speed up row transformations between Innobase and MySQL. */ typedef struct mysql_row_templ_struct mysql_row_templ_t; struct mysql_row_templ_struct { ulint col_no; /* column number of the column */ ulint rec_field_no; /* field number of the column in an Innobase record in the current index; not defined if template_type is ROW_MYSQL_WHOLE_ROW */ ulint mysql_col_offset; /* offset of the column in the MySQL row format */ ulint mysql_col_len; /* length of the column in the MySQL row format */ ulint mysql_null_byte_offset; /* MySQL NULL bit byte offset in a MySQL record */ ulint mysql_null_bit_mask; /* bit mask to get the NULL bit, zero if column cannot be NULL */ ulint type; /* column type in Innobase mtype numbers DATA_CHAR... */ ulint is_unsigned; /* if a column type is an integer type and this field is != 0, then it is an unsigned integer type */ }; #define MYSQL_FETCH_CACHE_SIZE 8 /* After fetching this many rows, we start caching them in fetch_cache */ #define MYSQL_FETCH_CACHE_THRESHOLD 4 /* A struct for (sometimes lazily) prebuilt structures in an Innobase table handle used within MySQL; these are used to save CPU time. */ struct row_prebuilt_struct { dict_table_t* table; /* Innobase table handle */ trx_t* trx; /* current transaction handle */ ibool sql_stat_start; /* TRUE when we start processing of an SQL statement: we may have to set an intention lock on the table, create a consistent read view etc. */ ibool clust_index_was_generated; /* if the user did not define a primary key in MySQL, then Innobase automatically generated a clustered index where the ordering column is the row id: in this case this flag is set to TRUE */ dict_index_t* index; /* current index for a search, if any */ ulint template_type; /* ROW_MYSQL_WHOLE_ROW, ROW_MYSQL_REC_FIELDS, ROW_MYSQL_DUMMY_TEMPLATE, or ROW_MYSQL_NO_TEMPLATE */ ulint n_template; /* number of elements in the template */ ulint null_bitmap_len;/* number of bytes in the SQL NULL bitmap at the start of a row in the MySQL format */ ibool need_to_access_clustered; /* if we are fetching columns through a secondary index and at least one column is not in the secondary index, then this is set to TRUE */ ibool templ_contains_blob;/* TRUE if the template contains BLOB column(s) */ mysql_row_templ_t* mysql_template;/* template used to transform rows fast between MySQL and Innobase formats; memory for this template is not allocated from 'heap' */ mem_heap_t* heap; /* memory heap from which these auxiliary structures are allocated when needed */ ins_node_t* ins_node; /* Innobase SQL insert node used to perform inserts to the table */ byte* ins_upd_rec_buff;/* buffer for storing data converted to the Innobase format from the MySQL format */ ibool in_update_remember_pos; /* if an update is processed, then if this flag is set to TRUE, it means that the stored cursor position in SELECT is the right position also for the update: we can just restore the cursor and save CPU time */ upd_node_t* upd_node; /* Innobase SQL update node used to perform updates and deletes */ que_fork_t* ins_graph; /* Innobase SQL query graph used in inserts */ que_fork_t* upd_graph; /* Innobase SQL query graph used in updates or deletes */ btr_pcur_t* pcur; /* persistent cursor used in selects and updates */ btr_pcur_t* clust_pcur; /* persistent cursor used in some selects and updates */ que_fork_t* sel_graph; /* dummy query graph used in selects */ dtuple_t* search_tuple; /* prebuilt dtuple used in selects */ byte row_id[DATA_ROW_ID_LEN]; /* if the clustered index was generated, the row id of the last row fetched is stored here */ dtuple_t* clust_ref; /* prebuilt dtuple used in sel/upd/del */ ulint select_lock_type;/* LOCK_NONE, LOCK_S, or LOCK_X */ ulint mysql_row_len; /* length in bytes of a row in the MySQL format */ ulint n_rows_fetched; /* number of rows fetched after positioning the current cursor */ ulint fetch_direction;/* ROW_SEL_NEXT or ROW_SEL_PREV */ byte* fetch_cache[MYSQL_FETCH_CACHE_SIZE]; /* a cache for fetched rows if we fetch many rows from the same cursor: it saves CPU time to fetch them in a batch; we reserve mysql_row_len bytes for each such row */ ulint fetch_cache_first;/* position of the first not yet fetched row in fetch_cache */ ulint n_fetch_cached; /* number of not yet fetched rows in fetch_cache */ mem_heap_t* blob_heap; /* in SELECTS BLOB fields are copied to this heap */ mem_heap_t* old_vers_heap; /* memory heap where a previous version is built in consistent read */ }; #define ROW_MYSQL_WHOLE_ROW 0 #define ROW_MYSQL_REC_FIELDS 1 #define ROW_MYSQL_NO_TEMPLATE 2 #define ROW_MYSQL_DUMMY_TEMPLATE 3 /* dummy template used in row_scan_and_check_index */ #ifndef UNIV_NONINL #include "row0mysql.ic" #endif #endif