| 1 | /***************************************************************************** |
| 2 | |
| 3 | Copyright (c) 2000, 2017, Oracle and/or its affiliates. All Rights Reserved. |
| 4 | Copyright (c) 2017, 2018, MariaDB Corporation. |
| 5 | |
| 6 | This program is free software; you can redistribute it and/or modify it under |
| 7 | the terms of the GNU General Public License as published by the Free Software |
| 8 | Foundation; version 2 of the License. |
| 9 | |
| 10 | This program is distributed in the hope that it will be useful, but WITHOUT |
| 11 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
| 12 | FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. |
| 13 | |
| 14 | You should have received a copy of the GNU General Public License along with |
| 15 | this program; if not, write to the Free Software Foundation, Inc., |
| 16 | 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA |
| 17 | |
| 18 | *****************************************************************************/ |
| 19 | |
| 20 | /**************************************************//** |
| 21 | @file include/row0mysql.h |
| 22 | Interface between Innobase row operations and MySQL. |
| 23 | Contains also create table and other data dictionary operations. |
| 24 | |
| 25 | Created 9/17/2000 Heikki Tuuri |
| 26 | *******************************************************/ |
| 27 | |
| 28 | #ifndef row0mysql_h |
| 29 | #define row0mysql_h |
| 30 | |
| 31 | #include "ha_prototypes.h" |
| 32 | |
| 33 | #include "data0data.h" |
| 34 | #include "que0types.h" |
| 35 | #include "dict0types.h" |
| 36 | #include "trx0types.h" |
| 37 | #include "row0types.h" |
| 38 | #include "btr0pcur.h" |
| 39 | #include "trx0types.h" |
| 40 | #include "fil0crypt.h" |
| 41 | |
| 42 | // Forward declaration |
| 43 | struct SysIndexCallback; |
| 44 | |
| 45 | extern ibool row_rollback_on_timeout; |
| 46 | |
| 47 | struct row_prebuilt_t; |
| 48 | |
| 49 | /*******************************************************************//** |
| 50 | Frees the blob heap in prebuilt when no longer needed. */ |
| 51 | void |
| 52 | row_mysql_prebuilt_free_blob_heap( |
| 53 | /*==============================*/ |
| 54 | row_prebuilt_t* prebuilt); /*!< in: prebuilt struct of a |
| 55 | ha_innobase:: table handle */ |
| 56 | /*******************************************************************//** |
| 57 | Stores a >= 5.0.3 format true VARCHAR length to dest, in the MySQL row |
| 58 | format. |
| 59 | @return pointer to the data, we skip the 1 or 2 bytes at the start |
| 60 | that are used to store the len */ |
| 61 | byte* |
| 62 | row_mysql_store_true_var_len( |
| 63 | /*=========================*/ |
| 64 | byte* dest, /*!< in: where to store */ |
| 65 | ulint len, /*!< in: length, must fit in two bytes */ |
| 66 | ulint lenlen);/*!< in: storage length of len: either 1 or 2 bytes */ |
| 67 | /*******************************************************************//** |
| 68 | Reads a >= 5.0.3 format true VARCHAR length, in the MySQL row format, and |
| 69 | returns a pointer to the data. |
| 70 | @return pointer to the data, we skip the 1 or 2 bytes at the start |
| 71 | that are used to store the len */ |
| 72 | const byte* |
| 73 | row_mysql_read_true_varchar( |
| 74 | /*========================*/ |
| 75 | ulint* len, /*!< out: variable-length field length */ |
| 76 | const byte* field, /*!< in: field in the MySQL format */ |
| 77 | ulint lenlen);/*!< in: storage length of len: either 1 |
| 78 | or 2 bytes */ |
| 79 | /*******************************************************************//** |
| 80 | Stores a reference to a BLOB in the MySQL format. */ |
| 81 | void |
| 82 | row_mysql_store_blob_ref( |
| 83 | /*=====================*/ |
| 84 | byte* dest, /*!< in: where to store */ |
| 85 | ulint col_len,/*!< in: dest buffer size: determines into |
| 86 | how many bytes the BLOB length is stored, |
| 87 | the space for the length may vary from 1 |
| 88 | to 4 bytes */ |
| 89 | const void* data, /*!< in: BLOB data; if the value to store |
| 90 | is SQL NULL this should be NULL pointer */ |
| 91 | ulint len); /*!< in: BLOB length; if the value to store |
| 92 | is SQL NULL this should be 0; remember |
| 93 | also to set the NULL bit in the MySQL record |
| 94 | header! */ |
| 95 | /*******************************************************************//** |
| 96 | Reads a reference to a BLOB in the MySQL format. |
| 97 | @return pointer to BLOB data */ |
| 98 | const byte* |
| 99 | row_mysql_read_blob_ref( |
| 100 | /*====================*/ |
| 101 | ulint* len, /*!< out: BLOB length */ |
| 102 | const byte* ref, /*!< in: BLOB reference in the |
| 103 | MySQL format */ |
| 104 | ulint col_len); /*!< in: BLOB reference length |
| 105 | (not BLOB length) */ |
| 106 | /*******************************************************************//** |
| 107 | Converts InnoDB geometry data format to MySQL data format. */ |
| 108 | void |
| 109 | row_mysql_store_geometry( |
| 110 | /*=====================*/ |
| 111 | byte* dest, /*!< in/out: where to store */ |
| 112 | ulint dest_len, /*!< in: dest buffer size: determines into |
| 113 | how many bytes the geometry length is stored, |
| 114 | the space for the length may vary from 1 |
| 115 | to 4 bytes */ |
| 116 | const byte* src, /*!< in: geometry data; if the value to store |
| 117 | is SQL NULL this should be NULL pointer */ |
| 118 | ulint src_len); /*!< in: geometry length; if the value to store |
| 119 | is SQL NULL this should be 0; remember |
| 120 | also to set the NULL bit in the MySQL record |
| 121 | header! */ |
| 122 | /**************************************************************//** |
| 123 | Pad a column with spaces. */ |
| 124 | void |
| 125 | row_mysql_pad_col( |
| 126 | /*==============*/ |
| 127 | ulint mbminlen, /*!< in: minimum size of a character, |
| 128 | in bytes */ |
| 129 | byte* pad, /*!< out: padded buffer */ |
| 130 | ulint len); /*!< in: number of bytes to pad */ |
| 131 | |
| 132 | /**************************************************************//** |
| 133 | Stores a non-SQL-NULL field given in the MySQL format in the InnoDB format. |
| 134 | The counterpart of this function is row_sel_field_store_in_mysql_format() in |
| 135 | row0sel.cc. |
| 136 | @return up to which byte we used buf in the conversion */ |
| 137 | byte* |
| 138 | row_mysql_store_col_in_innobase_format( |
| 139 | /*===================================*/ |
| 140 | dfield_t* dfield, /*!< in/out: dfield where dtype |
| 141 | information must be already set when |
| 142 | this function is called! */ |
| 143 | byte* buf, /*!< in/out: buffer for a converted |
| 144 | integer value; this must be at least |
| 145 | col_len long then! NOTE that dfield |
| 146 | may also get a pointer to 'buf', |
| 147 | therefore do not discard this as long |
| 148 | as dfield is used! */ |
| 149 | ibool row_format_col, /*!< TRUE if the mysql_data is from |
| 150 | a MySQL row, FALSE if from a MySQL |
| 151 | key value; |
| 152 | in MySQL, a true VARCHAR storage |
| 153 | format differs in a row and in a |
| 154 | key value: in a key value the length |
| 155 | is always stored in 2 bytes! */ |
| 156 | const byte* mysql_data, /*!< in: MySQL column value, not |
| 157 | SQL NULL; NOTE that dfield may also |
| 158 | get a pointer to mysql_data, |
| 159 | therefore do not discard this as long |
| 160 | as dfield is used! */ |
| 161 | ulint col_len, /*!< in: MySQL column length; NOTE that |
| 162 | this is the storage length of the |
| 163 | column in the MySQL format row, not |
| 164 | necessarily the length of the actual |
| 165 | payload data; if the column is a true |
| 166 | VARCHAR then this is irrelevant */ |
| 167 | ulint comp); /*!< in: nonzero=compact format */ |
| 168 | /****************************************************************//** |
| 169 | Handles user errors and lock waits detected by the database engine. |
| 170 | @return true if it was a lock wait and we should continue running the |
| 171 | query thread */ |
| 172 | bool |
| 173 | row_mysql_handle_errors( |
| 174 | /*====================*/ |
| 175 | dberr_t* new_err,/*!< out: possible new error encountered in |
| 176 | rollback, or the old error which was |
| 177 | during the function entry */ |
| 178 | trx_t* trx, /*!< in: transaction */ |
| 179 | que_thr_t* thr, /*!< in: query thread, or NULL */ |
| 180 | trx_savept_t* savept) /*!< in: savepoint, or NULL */ |
| 181 | MY_ATTRIBUTE((nonnull(1,2))); |
| 182 | /********************************************************************//** |
| 183 | Create a prebuilt struct for a MySQL table handle. |
| 184 | @return own: a prebuilt struct */ |
| 185 | row_prebuilt_t* |
| 186 | row_create_prebuilt( |
| 187 | /*================*/ |
| 188 | dict_table_t* table, /*!< in: Innobase table handle */ |
| 189 | ulint mysql_row_len); /*!< in: length in bytes of a row in |
| 190 | the MySQL format */ |
| 191 | /********************************************************************//** |
| 192 | Free a prebuilt struct for a MySQL table handle. */ |
| 193 | void |
| 194 | row_prebuilt_free( |
| 195 | /*==============*/ |
| 196 | row_prebuilt_t* prebuilt, /*!< in, own: prebuilt struct */ |
| 197 | ibool dict_locked); /*!< in: TRUE=data dictionary locked */ |
| 198 | /*********************************************************************//** |
| 199 | Updates the transaction pointers in query graphs stored in the prebuilt |
| 200 | struct. */ |
| 201 | void |
| 202 | row_update_prebuilt_trx( |
| 203 | /*====================*/ |
| 204 | row_prebuilt_t* prebuilt, /*!< in/out: prebuilt struct |
| 205 | in MySQL handle */ |
| 206 | trx_t* trx); /*!< in: transaction handle */ |
| 207 | |
| 208 | /*********************************************************************//** |
| 209 | Sets an AUTO_INC type lock on the table mentioned in prebuilt. The |
| 210 | AUTO_INC lock gives exclusive access to the auto-inc counter of the |
| 211 | table. The lock is reserved only for the duration of an SQL statement. |
| 212 | It is not compatible with another AUTO_INC or exclusive lock on the |
| 213 | table. |
| 214 | @return error code or DB_SUCCESS */ |
| 215 | dberr_t |
| 216 | row_lock_table_autoinc_for_mysql( |
| 217 | /*=============================*/ |
| 218 | row_prebuilt_t* prebuilt) /*!< in: prebuilt struct in the MySQL |
| 219 | table handle */ |
| 220 | MY_ATTRIBUTE((nonnull, warn_unused_result)); |
| 221 | |
| 222 | /** Lock a table. |
| 223 | @param[in,out] prebuilt table handle |
| 224 | @return error code or DB_SUCCESS */ |
| 225 | dberr_t |
| 226 | row_lock_table(row_prebuilt_t* prebuilt); |
| 227 | |
| 228 | /** System Versioning: row_insert_for_mysql() modes */ |
| 229 | enum ins_mode_t { |
| 230 | /* plain row (without versioning) */ |
| 231 | ROW_INS_NORMAL = 0, |
| 232 | /* row_start = TRX_ID, row_end = MAX */ |
| 233 | ROW_INS_VERSIONED, |
| 234 | /* row_end = TRX_ID */ |
| 235 | ROW_INS_HISTORICAL |
| 236 | }; |
| 237 | |
| 238 | /** Does an insert for MySQL. |
| 239 | @param[in] mysql_rec row in the MySQL format |
| 240 | @param[in,out] prebuilt prebuilt struct in MySQL handle |
| 241 | @param[in] ins_mode what row type we're inserting |
| 242 | @return error code or DB_SUCCESS*/ |
| 243 | dberr_t |
| 244 | row_insert_for_mysql( |
| 245 | const byte* mysql_rec, |
| 246 | row_prebuilt_t* prebuilt, |
| 247 | ins_mode_t ins_mode) |
| 248 | MY_ATTRIBUTE((warn_unused_result)); |
| 249 | |
| 250 | /*********************************************************************//** |
| 251 | Builds a dummy query graph used in selects. */ |
| 252 | void |
| 253 | row_prebuild_sel_graph( |
| 254 | /*===================*/ |
| 255 | row_prebuilt_t* prebuilt); /*!< in: prebuilt struct in MySQL |
| 256 | handle */ |
| 257 | /*********************************************************************//** |
| 258 | Gets pointer to a prebuilt update vector used in updates. If the update |
| 259 | graph has not yet been built in the prebuilt struct, then this function |
| 260 | first builds it. |
| 261 | @return prebuilt update vector */ |
| 262 | upd_t* |
| 263 | row_get_prebuilt_update_vector( |
| 264 | /*===========================*/ |
| 265 | row_prebuilt_t* prebuilt); /*!< in: prebuilt struct in MySQL |
| 266 | handle */ |
| 267 | /** Does an update or delete of a row for MySQL. |
| 268 | @param[in,out] prebuilt prebuilt struct in MySQL handle |
| 269 | @return error code or DB_SUCCESS */ |
| 270 | dberr_t |
| 271 | row_update_for_mysql( |
| 272 | row_prebuilt_t* prebuilt) |
| 273 | MY_ATTRIBUTE((warn_unused_result)); |
| 274 | |
| 275 | /** This can only be used when srv_locks_unsafe_for_binlog is TRUE or this |
| 276 | session is using a READ COMMITTED or READ UNCOMMITTED isolation level. |
| 277 | Before calling this function row_search_for_mysql() must have |
| 278 | initialized prebuilt->new_rec_locks to store the information which new |
| 279 | record locks really were set. This function removes a newly set |
| 280 | clustered index record lock under prebuilt->pcur or |
| 281 | prebuilt->clust_pcur. Thus, this implements a 'mini-rollback' that |
| 282 | releases the latest clustered index record lock we set. |
| 283 | @param[in,out] prebuilt prebuilt struct in MySQL handle |
| 284 | @param[in] has_latches_on_recs TRUE if called so that we have the |
| 285 | latches on the records under pcur |
| 286 | and clust_pcur, and we do not need |
| 287 | to reposition the cursors. */ |
| 288 | void |
| 289 | row_unlock_for_mysql( |
| 290 | row_prebuilt_t* prebuilt, |
| 291 | ibool has_latches_on_recs); |
| 292 | |
| 293 | /*********************************************************************//** |
| 294 | Checks if a table name contains the string "/#sql" which denotes temporary |
| 295 | tables in MySQL. |
| 296 | @return true if temporary table */ |
| 297 | bool |
| 298 | row_is_mysql_tmp_table_name( |
| 299 | /*========================*/ |
| 300 | const char* name) MY_ATTRIBUTE((warn_unused_result)); |
| 301 | /*!< in: table name in the form |
| 302 | 'database/tablename' */ |
| 303 | |
| 304 | /*********************************************************************//** |
| 305 | Creates an query graph node of 'update' type to be used in the MySQL |
| 306 | interface. |
| 307 | @return own: update node */ |
| 308 | upd_node_t* |
| 309 | row_create_update_node_for_mysql( |
| 310 | /*=============================*/ |
| 311 | dict_table_t* table, /*!< in: table to update */ |
| 312 | mem_heap_t* heap); /*!< in: mem heap from which allocated */ |
| 313 | |
| 314 | /**********************************************************************//** |
| 315 | Does a cascaded delete or set null in a foreign key operation. |
| 316 | @return error code or DB_SUCCESS */ |
| 317 | dberr_t |
| 318 | row_update_cascade_for_mysql( |
| 319 | /*=========================*/ |
| 320 | que_thr_t* thr, /*!< in: query thread */ |
| 321 | upd_node_t* node, /*!< in: update node used in the cascade |
| 322 | or set null operation */ |
| 323 | dict_table_t* table) /*!< in: table where we do the operation */ |
| 324 | MY_ATTRIBUTE((nonnull, warn_unused_result)); |
| 325 | /*********************************************************************//** |
| 326 | Locks the data dictionary exclusively for performing a table create or other |
| 327 | data dictionary modification operation. */ |
| 328 | void |
| 329 | row_mysql_lock_data_dictionary_func( |
| 330 | /*================================*/ |
| 331 | trx_t* trx, /*!< in/out: transaction */ |
| 332 | const char* file, /*!< in: file name */ |
| 333 | unsigned line); /*!< in: line number */ |
| 334 | #define row_mysql_lock_data_dictionary(trx) \ |
| 335 | row_mysql_lock_data_dictionary_func(trx, __FILE__, __LINE__) |
| 336 | /*********************************************************************//** |
| 337 | Unlocks the data dictionary exclusive lock. */ |
| 338 | void |
| 339 | row_mysql_unlock_data_dictionary( |
| 340 | /*=============================*/ |
| 341 | trx_t* trx); /*!< in/out: transaction */ |
| 342 | /*********************************************************************//** |
| 343 | Locks the data dictionary in shared mode from modifications, for performing |
| 344 | foreign key check, rollback, or other operation invisible to MySQL. */ |
| 345 | void |
| 346 | row_mysql_freeze_data_dictionary_func( |
| 347 | /*==================================*/ |
| 348 | trx_t* trx, /*!< in/out: transaction */ |
| 349 | const char* file, /*!< in: file name */ |
| 350 | unsigned line); /*!< in: line number */ |
| 351 | #define row_mysql_freeze_data_dictionary(trx) \ |
| 352 | row_mysql_freeze_data_dictionary_func(trx, __FILE__, __LINE__) |
| 353 | /*********************************************************************//** |
| 354 | Unlocks the data dictionary shared lock. */ |
| 355 | void |
| 356 | row_mysql_unfreeze_data_dictionary( |
| 357 | /*===============================*/ |
| 358 | trx_t* trx); /*!< in/out: transaction */ |
| 359 | /*********************************************************************//** |
| 360 | Creates a table for MySQL. On failure the transaction will be rolled back |
| 361 | and the 'table' object will be freed. |
| 362 | @return error code or DB_SUCCESS */ |
| 363 | dberr_t |
| 364 | row_create_table_for_mysql( |
| 365 | /*=======================*/ |
| 366 | dict_table_t* table, /*!< in, own: table definition |
| 367 | (will be freed, or on DB_SUCCESS |
| 368 | added to the data dictionary cache) */ |
| 369 | trx_t* trx, /*!< in/out: transaction */ |
| 370 | fil_encryption_t mode, /*!< in: encryption mode */ |
| 371 | uint32_t key_id) /*!< in: encryption key_id */ |
| 372 | MY_ATTRIBUTE((warn_unused_result)); |
| 373 | |
| 374 | /*********************************************************************//** |
| 375 | Does an index creation operation for MySQL. TODO: currently failure |
| 376 | to create an index results in dropping the whole table! This is no problem |
| 377 | currently as all indexes must be created at the same time as the table. |
| 378 | @return error number or DB_SUCCESS */ |
| 379 | dberr_t |
| 380 | row_create_index_for_mysql( |
| 381 | /*=======================*/ |
| 382 | dict_index_t* index, /*!< in, own: index definition |
| 383 | (will be freed) */ |
| 384 | trx_t* trx, /*!< in: transaction handle */ |
| 385 | const ulint* field_lengths) /*!< in: if not NULL, must contain |
| 386 | dict_index_get_n_fields(index) |
| 387 | actual field lengths for the |
| 388 | index columns, which are |
| 389 | then checked for not being too |
| 390 | large. */ |
| 391 | MY_ATTRIBUTE((warn_unused_result)); |
| 392 | /*********************************************************************//** |
| 393 | Scans a table create SQL string and adds to the data dictionary |
| 394 | the foreign key constraints declared in the string. This function |
| 395 | should be called after the indexes for a table have been created. |
| 396 | Each foreign key constraint must be accompanied with indexes in |
| 397 | bot participating tables. The indexes are allowed to contain more |
| 398 | fields than mentioned in the constraint. |
| 399 | |
| 400 | @param[in] trx transaction |
| 401 | @param[in] sql_string table create statement where |
| 402 | foreign keys are declared like: |
| 403 | FOREIGN KEY (a, b) REFERENCES table2(c, d), |
| 404 | table2 can be written also with the database |
| 405 | name before it: test.table2; the default |
| 406 | database id the database of parameter name |
| 407 | @param[in] sql_length length of sql_string |
| 408 | @param[in] name table full name in normalized form |
| 409 | @param[in] reject_fks if TRUE, fail with error code |
| 410 | DB_CANNOT_ADD_CONSTRAINT if any |
| 411 | foreign keys are found. |
| 412 | @return error code or DB_SUCCESS */ |
| 413 | dberr_t |
| 414 | row_table_add_foreign_constraints( |
| 415 | trx_t* trx, |
| 416 | const char* sql_string, |
| 417 | size_t sql_length, |
| 418 | const char* name, |
| 419 | ibool reject_fks) |
| 420 | MY_ATTRIBUTE((warn_unused_result)); |
| 421 | |
| 422 | /*********************************************************************//** |
| 423 | The master thread in srv0srv.cc calls this regularly to drop tables which |
| 424 | we must drop in background after queries to them have ended. Such lazy |
| 425 | dropping of tables is needed in ALTER TABLE on Unix. |
| 426 | @return how many tables dropped + remaining tables in list */ |
| 427 | ulint |
| 428 | row_drop_tables_for_mysql_in_background(void); |
| 429 | /*=========================================*/ |
| 430 | /*********************************************************************//** |
| 431 | Get the background drop list length. NOTE: the caller must own the kernel |
| 432 | mutex! |
| 433 | @return how many tables in list */ |
| 434 | ulint |
| 435 | row_get_background_drop_list_len_low(void); |
| 436 | /*======================================*/ |
| 437 | |
| 438 | /** Drop garbage tables during recovery. */ |
| 439 | void |
| 440 | row_mysql_drop_garbage_tables(); |
| 441 | |
| 442 | /*********************************************************************//** |
| 443 | Sets an exclusive lock on a table. |
| 444 | @return error code or DB_SUCCESS */ |
| 445 | dberr_t |
| 446 | row_mysql_lock_table( |
| 447 | /*=================*/ |
| 448 | trx_t* trx, /*!< in/out: transaction */ |
| 449 | dict_table_t* table, /*!< in: table to lock */ |
| 450 | enum lock_mode mode, /*!< in: LOCK_X or LOCK_S */ |
| 451 | const char* op_info) /*!< in: string for trx->op_info */ |
| 452 | MY_ATTRIBUTE((nonnull, warn_unused_result)); |
| 453 | |
| 454 | /*********************************************************************//** |
| 455 | Truncates a table for MySQL. |
| 456 | @return error code or DB_SUCCESS */ |
| 457 | dberr_t |
| 458 | row_truncate_table_for_mysql( |
| 459 | /*=========================*/ |
| 460 | dict_table_t* table, /*!< in: table handle */ |
| 461 | trx_t* trx) /*!< in: transaction handle */ |
| 462 | MY_ATTRIBUTE((nonnull, warn_unused_result)); |
| 463 | /*********************************************************************//** |
| 464 | Drops a table for MySQL. If the data dictionary was not already locked |
| 465 | by the transaction, the transaction will be committed. Otherwise, the |
| 466 | data dictionary will remain locked. |
| 467 | @return error code or DB_SUCCESS */ |
| 468 | dberr_t |
| 469 | row_drop_table_for_mysql( |
| 470 | /*=====================*/ |
| 471 | const char* name, /*!< in: table name */ |
| 472 | trx_t* trx, /*!< in: dictionary transaction handle */ |
| 473 | bool drop_db,/*!< in: true=dropping whole database */ |
| 474 | ibool create_failed,/*!<in: TRUE=create table failed |
| 475 | because e.g. foreign key column |
| 476 | type mismatch. */ |
| 477 | bool nonatomic = true); |
| 478 | /*!< in: whether it is permitted |
| 479 | to release and reacquire dict_operation_lock */ |
| 480 | |
| 481 | /*********************************************************************//** |
| 482 | Discards the tablespace of a table which stored in an .ibd file. Discarding |
| 483 | means that this function deletes the .ibd file and assigns a new table id for |
| 484 | the table. Also the file_unreadable flag is set. |
| 485 | @return error code or DB_SUCCESS */ |
| 486 | dberr_t |
| 487 | row_discard_tablespace_for_mysql( |
| 488 | /*=============================*/ |
| 489 | const char* name, /*!< in: table name */ |
| 490 | trx_t* trx) /*!< in: transaction handle */ |
| 491 | MY_ATTRIBUTE((nonnull, warn_unused_result)); |
| 492 | /*****************************************************************//** |
| 493 | Imports a tablespace. The space id in the .ibd file must match the space id |
| 494 | of the table in the data dictionary. |
| 495 | @return error code or DB_SUCCESS */ |
| 496 | dberr_t |
| 497 | row_import_tablespace_for_mysql( |
| 498 | /*============================*/ |
| 499 | dict_table_t* table, /*!< in/out: table */ |
| 500 | row_prebuilt_t* prebuilt) /*!< in: prebuilt struct in MySQL */ |
| 501 | MY_ATTRIBUTE((nonnull, warn_unused_result)); |
| 502 | |
| 503 | /** Drop a database for MySQL. |
| 504 | @param[in] name database name which ends at '/' |
| 505 | @param[in] trx transaction handle |
| 506 | @param[out] found number of dropped tables/partitions |
| 507 | @return error code or DB_SUCCESS */ |
| 508 | dberr_t |
| 509 | row_drop_database_for_mysql( |
| 510 | const char* name, |
| 511 | trx_t* trx, |
| 512 | ulint* found); |
| 513 | |
| 514 | /*********************************************************************//** |
| 515 | Renames a table for MySQL. |
| 516 | @return error code or DB_SUCCESS */ |
| 517 | dberr_t |
| 518 | row_rename_table_for_mysql( |
| 519 | /*=======================*/ |
| 520 | const char* old_name, /*!< in: old table name */ |
| 521 | const char* new_name, /*!< in: new table name */ |
| 522 | trx_t* trx, /*!< in/out: transaction */ |
| 523 | bool commit) /*!< in: whether to commit trx */ |
| 524 | MY_ATTRIBUTE((nonnull, warn_unused_result)); |
| 525 | |
| 526 | /*********************************************************************//** |
| 527 | Scans an index for either COOUNT(*) or CHECK TABLE. |
| 528 | If CHECK TABLE; Checks that the index contains entries in an ascending order, |
| 529 | unique constraint is not broken, and calculates the number of index entries |
| 530 | in the read view of the current transaction. |
| 531 | @return DB_SUCCESS or other error */ |
| 532 | dberr_t |
| 533 | row_scan_index_for_mysql( |
| 534 | /*=====================*/ |
| 535 | row_prebuilt_t* prebuilt, /*!< in: prebuilt struct |
| 536 | in MySQL handle */ |
| 537 | const dict_index_t* index, /*!< in: index */ |
| 538 | ulint* n_rows) /*!< out: number of entries |
| 539 | seen in the consistent read */ |
| 540 | MY_ATTRIBUTE((warn_unused_result)); |
| 541 | /*********************************************************************//** |
| 542 | Initialize this module */ |
| 543 | void |
| 544 | row_mysql_init(void); |
| 545 | /*================*/ |
| 546 | |
| 547 | /*********************************************************************//** |
| 548 | Close this module */ |
| 549 | void |
| 550 | row_mysql_close(void); |
| 551 | /*=================*/ |
| 552 | |
| 553 | /* A struct describing a place for an individual column in the MySQL |
| 554 | row format which is presented to the table handler in ha_innobase. |
| 555 | This template struct is used to speed up row transformations between |
| 556 | Innobase and MySQL. */ |
| 557 | |
| 558 | struct mysql_row_templ_t { |
| 559 | ulint col_no; /*!< column number of the column */ |
| 560 | ulint rec_field_no; /*!< field number of the column in an |
| 561 | Innobase record in the current index; |
| 562 | not defined if template_type is |
| 563 | ROW_MYSQL_WHOLE_ROW */ |
| 564 | ibool rec_field_is_prefix; /* is this field in a prefix index? */ |
| 565 | ulint rec_prefix_field_no; /* record field, even if just a |
| 566 | prefix; same as rec_field_no when not a |
| 567 | prefix, otherwise rec_field_no is |
| 568 | ULINT_UNDEFINED but this is the true |
| 569 | field number*/ |
| 570 | ulint clust_rec_field_no; /*!< field number of the column in an |
| 571 | Innobase record in the clustered index; |
| 572 | not defined if template_type is |
| 573 | ROW_MYSQL_WHOLE_ROW */ |
| 574 | ulint icp_rec_field_no; /*!< field number of the column in an |
| 575 | Innobase record in the current index; |
| 576 | not defined unless |
| 577 | index condition pushdown is used */ |
| 578 | ulint mysql_col_offset; /*!< offset of the column in the MySQL |
| 579 | row format */ |
| 580 | ulint mysql_col_len; /*!< length of the column in the MySQL |
| 581 | row format */ |
| 582 | ulint mysql_null_byte_offset; /*!< MySQL NULL bit byte offset in a |
| 583 | MySQL record */ |
| 584 | ulint mysql_null_bit_mask; /*!< bit mask to get the NULL bit, |
| 585 | zero if column cannot be NULL */ |
| 586 | ulint type; /*!< column type in Innobase mtype |
| 587 | numbers DATA_CHAR... */ |
| 588 | ulint mysql_type; /*!< MySQL type code; this is always |
| 589 | < 256 */ |
| 590 | ulint mysql_length_bytes; /*!< if mysql_type |
| 591 | == DATA_MYSQL_TRUE_VARCHAR, this tells |
| 592 | whether we should use 1 or 2 bytes to |
| 593 | store the MySQL true VARCHAR data |
| 594 | length at the start of row in the MySQL |
| 595 | format (NOTE that the MySQL key value |
| 596 | format always uses 2 bytes for the data |
| 597 | len) */ |
| 598 | ulint charset; /*!< MySQL charset-collation code |
| 599 | of the column, or zero */ |
| 600 | ulint mbminlen; /*!< minimum length of a char, in bytes, |
| 601 | or zero if not a char type */ |
| 602 | ulint mbmaxlen; /*!< maximum length of a char, in bytes, |
| 603 | or zero if not a char type */ |
| 604 | ulint is_unsigned; /*!< if a column type is an integer |
| 605 | type and this field is != 0, then |
| 606 | it is an unsigned integer type */ |
| 607 | ulint is_virtual; /*!< if a column is a virtual column */ |
| 608 | }; |
| 609 | |
| 610 | #define MYSQL_FETCH_CACHE_SIZE 8 |
| 611 | /* After fetching this many rows, we start caching them in fetch_cache */ |
| 612 | #define MYSQL_FETCH_CACHE_THRESHOLD 4 |
| 613 | |
| 614 | #define ROW_PREBUILT_ALLOCATED 78540783 |
| 615 | #define ROW_PREBUILT_FREED 26423527 |
| 616 | |
| 617 | /** A struct for (sometimes lazily) prebuilt structures in an Innobase table |
| 618 | handle used within MySQL; these are used to save CPU time. */ |
| 619 | |
| 620 | struct row_prebuilt_t { |
| 621 | ulint magic_n; /*!< this magic number is set to |
| 622 | ROW_PREBUILT_ALLOCATED when created, |
| 623 | or ROW_PREBUILT_FREED when the |
| 624 | struct has been freed */ |
| 625 | dict_table_t* table; /*!< Innobase table handle */ |
| 626 | dict_index_t* index; /*!< current index for a search, if |
| 627 | any */ |
| 628 | trx_t* trx; /*!< current transaction handle */ |
| 629 | unsigned sql_stat_start:1;/*!< TRUE when we start processing of |
| 630 | an SQL statement: we may have to set |
| 631 | an intention lock on the table, |
| 632 | create a consistent read view etc. */ |
| 633 | unsigned clust_index_was_generated:1; |
| 634 | /*!< if the user did not define a |
| 635 | primary key in MySQL, then Innobase |
| 636 | automatically generated a clustered |
| 637 | index where the ordering column is |
| 638 | the row id: in this case this flag |
| 639 | is set to TRUE */ |
| 640 | unsigned index_usable:1; /*!< caches the value of |
| 641 | row_merge_is_index_usable(trx,index) */ |
| 642 | unsigned read_just_key:1;/*!< set to 1 when MySQL calls |
| 643 | ha_innobase::extra with the |
| 644 | argument HA_EXTRA_KEYREAD; it is enough |
| 645 | to read just columns defined in |
| 646 | the index (i.e., no read of the |
| 647 | clustered index record necessary) */ |
| 648 | unsigned used_in_HANDLER:1;/*!< TRUE if we have been using this |
| 649 | handle in a MySQL HANDLER low level |
| 650 | index cursor command: then we must |
| 651 | store the pcur position even in a |
| 652 | unique search from a clustered index, |
| 653 | because HANDLER allows NEXT and PREV |
| 654 | in such a situation */ |
| 655 | unsigned template_type:2;/*!< ROW_MYSQL_WHOLE_ROW, |
| 656 | ROW_MYSQL_REC_FIELDS, |
| 657 | ROW_MYSQL_DUMMY_TEMPLATE, or |
| 658 | ROW_MYSQL_NO_TEMPLATE */ |
| 659 | unsigned n_template:10; /*!< number of elements in the |
| 660 | template */ |
| 661 | unsigned null_bitmap_len:10;/*!< number of bytes in the SQL NULL |
| 662 | bitmap at the start of a row in the |
| 663 | MySQL format */ |
| 664 | unsigned need_to_access_clustered:1; /*!< if we are fetching |
| 665 | columns through a secondary index |
| 666 | and at least one column is not in |
| 667 | the secondary index, then this is |
| 668 | set to TRUE; note that sometimes this |
| 669 | is set but we later optimize out the |
| 670 | clustered index lookup */ |
| 671 | unsigned templ_contains_blob:1;/*!< TRUE if the template contains |
| 672 | a column with DATA_LARGE_MTYPE( |
| 673 | get_innobase_type_from_mysql_type()) |
| 674 | is TRUE; |
| 675 | not to be confused with InnoDB |
| 676 | externally stored columns |
| 677 | (VARCHAR can be off-page too) */ |
| 678 | unsigned versioned_write:1;/*!< whether this is |
| 679 | a versioned write */ |
| 680 | mysql_row_templ_t* mysql_template;/*!< template used to transform |
| 681 | rows fast between MySQL and Innobase |
| 682 | formats; memory for this template |
| 683 | is not allocated from 'heap' */ |
| 684 | mem_heap_t* heap; /*!< memory heap from which |
| 685 | these auxiliary structures are |
| 686 | allocated when needed */ |
| 687 | ins_node_t* ins_node; /*!< Innobase SQL insert node |
| 688 | used to perform inserts |
| 689 | to the table */ |
| 690 | byte* ins_upd_rec_buff;/*!< buffer for storing data converted |
| 691 | to the Innobase format from the MySQL |
| 692 | format */ |
| 693 | const byte* default_rec; /*!< the default values of all columns |
| 694 | (a "default row") in MySQL format */ |
| 695 | ulint ; |
| 696 | /*!< normally this is set to 0; if this |
| 697 | is set to ROW_RETRIEVE_PRIMARY_KEY, |
| 698 | then we should at least retrieve all |
| 699 | columns in the primary key; if this |
| 700 | is set to ROW_RETRIEVE_ALL_COLS, then |
| 701 | we must retrieve all columns in the |
| 702 | key (if read_just_key == 1), or all |
| 703 | columns in the table */ |
| 704 | upd_node_t* upd_node; /*!< Innobase SQL update node used |
| 705 | to perform updates and deletes */ |
| 706 | trx_id_t trx_id; /*!< The table->def_trx_id when |
| 707 | ins_graph was built */ |
| 708 | que_fork_t* ins_graph; /*!< Innobase SQL query graph used |
| 709 | in inserts. Will be rebuilt on |
| 710 | trx_id or n_indexes mismatch. */ |
| 711 | que_fork_t* upd_graph; /*!< Innobase SQL query graph used |
| 712 | in updates or deletes */ |
| 713 | btr_pcur_t* pcur; /*!< persistent cursor used in selects |
| 714 | and updates */ |
| 715 | btr_pcur_t* clust_pcur; /*!< persistent cursor used in |
| 716 | some selects and updates */ |
| 717 | que_fork_t* sel_graph; /*!< dummy query graph used in |
| 718 | selects */ |
| 719 | dtuple_t* search_tuple; /*!< prebuilt dtuple used in selects */ |
| 720 | byte row_id[DATA_ROW_ID_LEN]; |
| 721 | /*!< if the clustered index was |
| 722 | generated, the row id of the |
| 723 | last row fetched is stored |
| 724 | here */ |
| 725 | doc_id_t fts_doc_id; /* if the table has an FTS index on |
| 726 | it then we fetch the doc_id. |
| 727 | FTS-FIXME: Currently we fetch it always |
| 728 | but in the future we must only fetch |
| 729 | it when FTS columns are being |
| 730 | updated */ |
| 731 | dtuple_t* clust_ref; /*!< prebuilt dtuple used in |
| 732 | sel/upd/del */ |
| 733 | ulint select_lock_type;/*!< LOCK_NONE, LOCK_S, or LOCK_X */ |
| 734 | ulint stored_select_lock_type;/*!< this field is used to |
| 735 | remember the original select_lock_type |
| 736 | that was decided in ha_innodb.cc, |
| 737 | ::store_lock(), ::external_lock(), |
| 738 | etc. */ |
| 739 | ulint row_read_type; /*!< ROW_READ_WITH_LOCKS if row locks |
| 740 | should be the obtained for records |
| 741 | under an UPDATE or DELETE cursor. |
| 742 | If innodb_locks_unsafe_for_binlog |
| 743 | is TRUE, this can be set to |
| 744 | ROW_READ_TRY_SEMI_CONSISTENT, so that |
| 745 | if the row under an UPDATE or DELETE |
| 746 | cursor was locked by another |
| 747 | transaction, InnoDB will resort |
| 748 | to reading the last committed value |
| 749 | ('semi-consistent read'). Then, |
| 750 | this field will be set to |
| 751 | ROW_READ_DID_SEMI_CONSISTENT to |
| 752 | indicate that. If the row does not |
| 753 | match the WHERE condition, MySQL will |
| 754 | invoke handler::unlock_row() to |
| 755 | clear the flag back to |
| 756 | ROW_READ_TRY_SEMI_CONSISTENT and |
| 757 | to simply skip the row. If |
| 758 | the row matches, the next call to |
| 759 | row_search_for_mysql() will lock |
| 760 | the row. |
| 761 | This eliminates lock waits in some |
| 762 | cases; note that this breaks |
| 763 | serializability. */ |
| 764 | ulint new_rec_locks; /*!< normally 0; if |
| 765 | srv_locks_unsafe_for_binlog is |
| 766 | TRUE or session is using READ |
| 767 | COMMITTED or READ UNCOMMITTED |
| 768 | isolation level, set in |
| 769 | row_search_for_mysql() if we set a new |
| 770 | record lock on the secondary |
| 771 | or clustered index; this is |
| 772 | used in row_unlock_for_mysql() |
| 773 | when releasing the lock under |
| 774 | the cursor if we determine |
| 775 | after retrieving the row that |
| 776 | it does not need to be locked |
| 777 | ('mini-rollback') */ |
| 778 | ulint mysql_prefix_len;/*!< byte offset of the end of |
| 779 | the last requested column */ |
| 780 | ulint mysql_row_len; /*!< length in bytes of a row in the |
| 781 | MySQL format */ |
| 782 | ulint n_rows_fetched; /*!< number of rows fetched after |
| 783 | positioning the current cursor */ |
| 784 | ulint fetch_direction;/*!< ROW_SEL_NEXT or ROW_SEL_PREV */ |
| 785 | byte* fetch_cache[MYSQL_FETCH_CACHE_SIZE]; |
| 786 | /*!< a cache for fetched rows if we |
| 787 | fetch many rows from the same cursor: |
| 788 | it saves CPU time to fetch them in a |
| 789 | batch; we reserve mysql_row_len |
| 790 | bytes for each such row; these |
| 791 | pointers point 4 bytes past the |
| 792 | allocated mem buf start, because |
| 793 | there is a 4 byte magic number at the |
| 794 | start and at the end */ |
| 795 | bool keep_other_fields_on_keyread; /*!< when using fetch |
| 796 | cache with HA_EXTRA_KEYREAD, don't |
| 797 | overwrite other fields in mysql row |
| 798 | row buffer.*/ |
| 799 | ulint fetch_cache_first;/*!< position of the first not yet |
| 800 | fetched row in fetch_cache */ |
| 801 | ulint n_fetch_cached; /*!< number of not yet fetched rows |
| 802 | in fetch_cache */ |
| 803 | mem_heap_t* blob_heap; /*!< in SELECTS BLOB fields are copied |
| 804 | to this heap */ |
| 805 | mem_heap_t* old_vers_heap; /*!< memory heap where a previous |
| 806 | version is built in consistent read */ |
| 807 | bool in_fts_query; /*!< Whether we are in a FTS query */ |
| 808 | bool fts_doc_id_in_read_set; /*!< true if table has externally |
| 809 | defined FTS_DOC_ID coulmn. */ |
| 810 | /*----------------------*/ |
| 811 | ulonglong autoinc_last_value; |
| 812 | /*!< last value of AUTO-INC interval */ |
| 813 | ulonglong autoinc_increment;/*!< The increment step of the auto |
| 814 | increment column. Value must be |
| 815 | greater than or equal to 1. Required to |
| 816 | calculate the next value */ |
| 817 | ulonglong autoinc_offset; /*!< The offset passed to |
| 818 | get_auto_increment() by MySQL. Required |
| 819 | to calculate the next value */ |
| 820 | dberr_t autoinc_error; /*!< The actual error code encountered |
| 821 | while trying to init or read the |
| 822 | autoinc value from the table. We |
| 823 | store it here so that we can return |
| 824 | it to MySQL */ |
| 825 | /*----------------------*/ |
| 826 | void* idx_cond; /*!< In ICP, pointer to a ha_innobase, |
| 827 | passed to innobase_index_cond(). |
| 828 | NULL if index condition pushdown is |
| 829 | not used. */ |
| 830 | ulint idx_cond_n_cols;/*!< Number of fields in idx_cond_cols. |
| 831 | 0 if and only if idx_cond == NULL. */ |
| 832 | /*----------------------*/ |
| 833 | |
| 834 | /*----------------------*/ |
| 835 | rtr_info_t* rtr_info; /*!< R-tree Search Info */ |
| 836 | /*----------------------*/ |
| 837 | |
| 838 | ulint magic_n2; /*!< this should be the same as |
| 839 | magic_n */ |
| 840 | |
| 841 | byte* srch_key_val1; /*!< buffer used in converting |
| 842 | search key values from MySQL format |
| 843 | to InnoDB format.*/ |
| 844 | byte* srch_key_val2; /*!< buffer used in converting |
| 845 | search key values from MySQL format |
| 846 | to InnoDB format.*/ |
| 847 | uint srch_key_val_len; /*!< Size of search key */ |
| 848 | /** Disable prefetch. */ |
| 849 | bool m_no_prefetch; |
| 850 | |
| 851 | /** Return materialized key for secondary index scan */ |
| 852 | bool m_read_virtual_key; |
| 853 | |
| 854 | /** The MySQL table object */ |
| 855 | TABLE* m_mysql_table; |
| 856 | |
| 857 | /** Get template by dict_table_t::cols[] number */ |
| 858 | const mysql_row_templ_t* get_template_by_col(ulint col) const |
| 859 | { |
| 860 | ut_ad(col < n_template); |
| 861 | ut_ad(mysql_template); |
| 862 | for (ulint i = col; i < n_template; ++i) { |
| 863 | const mysql_row_templ_t* templ = &mysql_template[i]; |
| 864 | if (!templ->is_virtual && templ->col_no == col) { |
| 865 | return templ; |
| 866 | } |
| 867 | } |
| 868 | return NULL; |
| 869 | } |
| 870 | }; |
| 871 | |
| 872 | /** Callback for row_mysql_sys_index_iterate() */ |
| 873 | struct SysIndexCallback { |
| 874 | virtual ~SysIndexCallback() { } |
| 875 | |
| 876 | /** Callback method |
| 877 | @param mtr current mini transaction |
| 878 | @param pcur persistent cursor. */ |
| 879 | virtual void operator()(mtr_t* mtr, btr_pcur_t* pcur) throw() = 0; |
| 880 | }; |
| 881 | |
| 882 | /** Get the computed value by supplying the base column values. |
| 883 | @param[in,out] row the data row |
| 884 | @param[in] col virtual column |
| 885 | @param[in] index index on the virtual column |
| 886 | @param[in,out] local_heap heap memory for processing large data etc. |
| 887 | @param[in,out] heap memory heap that copies the actual index row |
| 888 | @param[in] ifield index field |
| 889 | @param[in] thd MySQL thread handle |
| 890 | @param[in,out] mysql_table mysql table object |
| 891 | @param[in] old_table during ALTER TABLE, this is the old table |
| 892 | or NULL. |
| 893 | @param[in] parent_update update vector for the parent row |
| 894 | @param[in] foreign foreign key information |
| 895 | @return the field filled with computed value */ |
| 896 | dfield_t* |
| 897 | innobase_get_computed_value( |
| 898 | const dtuple_t* row, |
| 899 | const dict_v_col_t* col, |
| 900 | const dict_index_t* index, |
| 901 | mem_heap_t** local_heap, |
| 902 | mem_heap_t* heap, |
| 903 | const dict_field_t* ifield, |
| 904 | THD* thd, |
| 905 | TABLE* mysql_table, |
| 906 | const dict_table_t* old_table, |
| 907 | upd_t* parent_update, |
| 908 | dict_foreign_t* foreign); |
| 909 | |
| 910 | /** Get the computed value by supplying the base column values. |
| 911 | @param[in,out] table the table whose virtual column template to be built */ |
| 912 | void |
| 913 | innobase_init_vc_templ( |
| 914 | dict_table_t* table); |
| 915 | |
| 916 | /** Change dbname and table name in table->vc_templ. |
| 917 | @param[in,out] table the table whose virtual column template |
| 918 | dbname and tbname to be renamed. */ |
| 919 | void |
| 920 | innobase_rename_vc_templ( |
| 921 | dict_table_t* table); |
| 922 | |
| 923 | #define ROW_PREBUILT_FETCH_MAGIC_N 465765687 |
| 924 | |
| 925 | #define ROW_MYSQL_WHOLE_ROW 0 |
| 926 | #define ROW_MYSQL_REC_FIELDS 1 |
| 927 | #define ROW_MYSQL_NO_TEMPLATE 2 |
| 928 | #define ROW_MYSQL_DUMMY_TEMPLATE 3 /* dummy template used in |
| 929 | row_scan_and_check_index */ |
| 930 | |
| 931 | /* Values for hint_need_to_fetch_extra_cols */ |
| 932 | #define ROW_RETRIEVE_PRIMARY_KEY 1 |
| 933 | #define ROW_RETRIEVE_ALL_COLS 2 |
| 934 | |
| 935 | /* Values for row_read_type */ |
| 936 | #define ROW_READ_WITH_LOCKS 0 |
| 937 | #define ROW_READ_TRY_SEMI_CONSISTENT 1 |
| 938 | #define ROW_READ_DID_SEMI_CONSISTENT 2 |
| 939 | |
| 940 | #ifdef UNIV_DEBUG |
| 941 | /** Wait for the background drop list to become empty. */ |
| 942 | void |
| 943 | row_wait_for_background_drop_list_empty(); |
| 944 | #endif /* UNIV_DEBUG */ |
| 945 | |
| 946 | #endif /* row0mysql.h */ |
| 947 | |