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 | |