1 /*****************************************************************************
2 
3 Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
4 
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License, version 2.0,
7 as published by the Free Software Foundation.
8 
9 This program is also distributed with certain software (including
10 but not limited to OpenSSL) that is licensed under separate terms,
11 as designated in a particular file or component or in included license
12 documentation.  The authors of MySQL hereby grant you an additional
13 permission to link the program and your derivative works with the
14 separately licensed software that they have included with MySQL.
15 
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 GNU General Public License, version 2.0, for more details.
20 
21 You should have received a copy of the GNU General Public License along with
22 this program; if not, write to the Free Software Foundation, Inc.,
23 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
24 
25 *****************************************************************************/
26 
27 /**************************************************//**
28 @file include/row0upd.h
29 Update of a row
30 
31 Created 12/27/1996 Heikki Tuuri
32 *******************************************************/
33 
34 #ifndef row0upd_h
35 #define row0upd_h
36 
37 #include "univ.i"
38 #include "data0data.h"
39 #include "row0types.h"
40 #include "btr0types.h"
41 #include "dict0types.h"
42 #include "trx0types.h"
43 
44 #ifndef UNIV_HOTBACKUP
45 # include "btr0pcur.h"
46 # include "que0types.h"
47 # include "pars0types.h"
48 #endif /* !UNIV_HOTBACKUP */
49 
50 /*********************************************************************//**
51 Creates an update vector object.
52 @return	own: update vector object */
53 UNIV_INLINE
54 upd_t*
55 upd_create(
56 /*=======*/
57 	ulint		n,	/*!< in: number of fields */
58 	mem_heap_t*	heap);	/*!< in: heap from which memory allocated */
59 /*********************************************************************//**
60 Returns the number of fields in the update vector == number of columns
61 to be updated by an update vector.
62 @return	number of fields */
63 UNIV_INLINE
64 ulint
65 upd_get_n_fields(
66 /*=============*/
67 	const upd_t*	update);	/*!< in: update vector */
68 #ifdef UNIV_DEBUG
69 /*********************************************************************//**
70 Returns the nth field of an update vector.
71 @return	update vector field */
72 UNIV_INLINE
73 upd_field_t*
74 upd_get_nth_field(
75 /*==============*/
76 	const upd_t*	update,	/*!< in: update vector */
77 	ulint		n);	/*!< in: field position in update vector */
78 #else
79 # define upd_get_nth_field(update, n) ((update)->fields + (n))
80 #endif
81 #ifndef UNIV_HOTBACKUP
82 /*********************************************************************//**
83 Sets an index field number to be updated by an update vector field. */
84 UNIV_INLINE
85 void
86 upd_field_set_field_no(
87 /*===================*/
88 	upd_field_t*	upd_field,	/*!< in: update vector field */
89 	ulint		field_no,	/*!< in: field number in a clustered
90 					index */
91 	dict_index_t*	index,		/*!< in: index */
92 	trx_t*		trx);		/*!< in: transaction */
93 /*********************************************************************//**
94 Returns a field of an update vector by field_no.
95 @return	update vector field, or NULL */
96 UNIV_INLINE
97 const upd_field_t*
98 upd_get_field_by_field_no(
99 /*======================*/
100 	const upd_t*	update,	/*!< in: update vector */
101 	ulint		no)	/*!< in: field_no */
102 	MY_ATTRIBUTE((nonnull, pure));
103 /*********************************************************************//**
104 Writes into the redo log the values of trx id and roll ptr and enough info
105 to determine their positions within a clustered index record.
106 @return	new pointer to mlog */
107 UNIV_INTERN
108 byte*
109 row_upd_write_sys_vals_to_log(
110 /*==========================*/
111 	dict_index_t*	index,	/*!< in: clustered index */
112 	trx_id_t	trx_id,	/*!< in: transaction id */
113 	roll_ptr_t	roll_ptr,/*!< in: roll ptr of the undo log record */
114 	byte*		log_ptr,/*!< pointer to a buffer of size > 20 opened
115 				in mlog */
116 	mtr_t*		mtr);	/*!< in: mtr */
117 /*********************************************************************//**
118 Updates the trx id and roll ptr field in a clustered index record when
119 a row is updated or marked deleted. */
120 UNIV_INLINE
121 void
122 row_upd_rec_sys_fields(
123 /*===================*/
124 	rec_t*		rec,	/*!< in/out: record */
125 	page_zip_des_t*	page_zip,/*!< in/out: compressed page whose
126 				uncompressed part will be updated, or NULL */
127 	dict_index_t*	index,	/*!< in: clustered index */
128 	const ulint*	offsets,/*!< in: rec_get_offsets(rec, index) */
129 	const trx_t*	trx,	/*!< in: transaction */
130 	roll_ptr_t	roll_ptr);/*!< in: roll ptr of the undo log record,
131 				  can be 0 during IMPORT */
132 /*********************************************************************//**
133 Sets the trx id or roll ptr field of a clustered index entry. */
134 UNIV_INTERN
135 void
136 row_upd_index_entry_sys_field(
137 /*==========================*/
138 	dtuple_t*	entry,	/*!< in/out: index entry, where the memory
139 				buffers for sys fields are already allocated:
140 				the function just copies the new values to
141 				them */
142 	dict_index_t*	index,	/*!< in: clustered index */
143 	ulint		type,	/*!< in: DATA_TRX_ID or DATA_ROLL_PTR */
144 	ib_uint64_t	val);	/*!< in: value to write */
145 /*********************************************************************//**
146 Creates an update node for a query graph.
147 @return	own: update node */
148 UNIV_INTERN
149 upd_node_t*
150 upd_node_create(
151 /*============*/
152 	mem_heap_t*	heap);	/*!< in: mem heap where created */
153 /***********************************************************//**
154 Writes to the redo log the new values of the fields occurring in the index. */
155 UNIV_INTERN
156 void
157 row_upd_index_write_log(
158 /*====================*/
159 	const upd_t*	update,	/*!< in: update vector */
160 	byte*		log_ptr,/*!< in: pointer to mlog buffer: must
161 				contain at least MLOG_BUF_MARGIN bytes
162 				of free space; the buffer is closed
163 				within this function */
164 	mtr_t*		mtr);	/*!< in: mtr into whose log to write */
165 /***********************************************************//**
166 Returns TRUE if row update changes size of some field in index or if some
167 field to be updated is stored externally in rec or update.
168 @return TRUE if the update changes the size of some field in index or
169 the field is external in rec or update */
170 UNIV_INTERN
171 ibool
172 row_upd_changes_field_size_or_external(
173 /*===================================*/
174 	dict_index_t*	index,	/*!< in: index */
175 	const ulint*	offsets,/*!< in: rec_get_offsets(rec, index) */
176 	const upd_t*	update);/*!< in: update vector */
177 /***********************************************************//**
178 Returns true if row update contains disowned external fields.
179 @return true if the update contains disowned external fields. */
180 UNIV_INTERN
181 bool
182 row_upd_changes_disowned_external(
183 /*==============================*/
184 	const upd_t*	update)	/*!< in: update vector */
185 	MY_ATTRIBUTE((nonnull, warn_unused_result));
186 #endif /* !UNIV_HOTBACKUP */
187 /***********************************************************//**
188 Replaces the new column values stored in the update vector to the
189 record given. No field size changes are allowed. This function is
190 usually invoked on a clustered index. The only use case for a
191 secondary index is row_ins_sec_index_entry_by_modify() or its
192 counterpart in ibuf_insert_to_index_page(). */
193 UNIV_INTERN
194 void
195 row_upd_rec_in_place(
196 /*=================*/
197 	rec_t*		rec,	/*!< in/out: record where replaced */
198 	dict_index_t*	index,	/*!< in: the index the record belongs to */
199 	const ulint*	offsets,/*!< in: array returned by rec_get_offsets() */
200 	const upd_t*	update,	/*!< in: update vector */
201 	page_zip_des_t*	page_zip);/*!< in: compressed page with enough space
202 				available, or NULL */
203 #ifndef UNIV_HOTBACKUP
204 /***************************************************************//**
205 Builds an update vector from those fields which in a secondary index entry
206 differ from a record that has the equal ordering fields. NOTE: we compare
207 the fields as binary strings!
208 @return	own: update vector of differing fields */
209 UNIV_INTERN
210 upd_t*
211 row_upd_build_sec_rec_difference_binary(
212 /*====================================*/
213 	const rec_t*	rec,	/*!< in: secondary index record */
214 	dict_index_t*	index,	/*!< in: index */
215 	const ulint*	offsets,/*!< in: rec_get_offsets(rec, index) */
216 	const dtuple_t*	entry,	/*!< in: entry to insert */
217 	mem_heap_t*	heap)	/*!< in: memory heap from which allocated */
218 	MY_ATTRIBUTE((warn_unused_result, nonnull));
219 /***************************************************************//**
220 Builds an update vector from those fields, excluding the roll ptr and
221 trx id fields, which in an index entry differ from a record that has
222 the equal ordering fields. NOTE: we compare the fields as binary strings!
223 @return own: update vector of differing fields, excluding roll ptr and
224 trx id */
225 UNIV_INTERN
226 const upd_t*
227 row_upd_build_difference_binary(
228 /*============================*/
229 	dict_index_t*	index,	/*!< in: clustered index */
230 	const dtuple_t*	entry,	/*!< in: entry to insert */
231 	const rec_t*	rec,	/*!< in: clustered index record */
232 	const ulint*	offsets,/*!< in: rec_get_offsets(rec,index), or NULL */
233 	bool		no_sys,	/*!< in: skip the system columns
234 				DB_TRX_ID and DB_ROLL_PTR */
235 	trx_t*		trx,	/*!< in: transaction (for diagnostics),
236 				or NULL */
237 	mem_heap_t*	heap)	/*!< in: memory heap from which allocated */
238 	MY_ATTRIBUTE((nonnull(1,2,3,7), warn_unused_result));
239 /***********************************************************//**
240 Replaces the new column values stored in the update vector to the index entry
241 given. */
242 UNIV_INTERN
243 void
244 row_upd_index_replace_new_col_vals_index_pos(
245 /*=========================================*/
246 	dtuple_t*	entry,	/*!< in/out: index entry where replaced;
247 				the clustered index record must be
248 				covered by a lock or a page latch to
249 				prevent deletion (rollback or purge) */
250 	dict_index_t*	index,	/*!< in: index; NOTE that this may also be a
251 				non-clustered index */
252 	const upd_t*	update,	/*!< in: an update vector built for the index so
253 				that the field number in an upd_field is the
254 				index position */
255 	ibool		order_only,
256 				/*!< in: if TRUE, limit the replacement to
257 				ordering fields of index; note that this
258 				does not work for non-clustered indexes. */
259 	mem_heap_t*	heap)	/*!< in: memory heap for allocating and
260 				copying the new values */
261 	MY_ATTRIBUTE((nonnull));
262 /***********************************************************//**
263 Replaces the new column values stored in the update vector to the index entry
264 given. */
265 UNIV_INTERN
266 void
267 row_upd_index_replace_new_col_vals(
268 /*===============================*/
269 	dtuple_t*	entry,	/*!< in/out: index entry where replaced;
270 				the clustered index record must be
271 				covered by a lock or a page latch to
272 				prevent deletion (rollback or purge) */
273 	dict_index_t*	index,	/*!< in: index; NOTE that this may also be a
274 				non-clustered index */
275 	const upd_t*	update,	/*!< in: an update vector built for the
276 				CLUSTERED index so that the field number in
277 				an upd_field is the clustered index position */
278 	mem_heap_t*	heap)	/*!< in: memory heap for allocating and
279 				copying the new values */
280 	MY_ATTRIBUTE((nonnull));
281 /***********************************************************//**
282 Replaces the new column values stored in the update vector. */
283 UNIV_INTERN
284 void
285 row_upd_replace(
286 /*============*/
287 	dtuple_t*		row,	/*!< in/out: row where replaced,
288 					indexed by col_no;
289 					the clustered index record must be
290 					covered by a lock or a page latch to
291 					prevent deletion (rollback or purge) */
292 	row_ext_t**		ext,	/*!< out, own: NULL, or externally
293 					stored column prefixes */
294 	const dict_index_t*	index,	/*!< in: clustered index */
295 	const upd_t*		update,	/*!< in: an update vector built for the
296 					clustered index */
297 	mem_heap_t*		heap);	/*!< in: memory heap */
298 /***********************************************************//**
299 Checks if an update vector changes an ordering field of an index record.
300 
301 This function is fast if the update vector is short or the number of ordering
302 fields in the index is small. Otherwise, this can be quadratic.
303 NOTE: we compare the fields as binary strings!
304 @return TRUE if update vector changes an ordering field in the index record */
305 UNIV_INTERN
306 ibool
307 row_upd_changes_ord_field_binary_func(
308 /*==================================*/
309 	dict_index_t*	index,	/*!< in: index of the record */
310 	const upd_t*	update,	/*!< in: update vector for the row; NOTE: the
311 				field numbers in this MUST be clustered index
312 				positions! */
313 #ifdef UNIV_DEBUG
314 	const que_thr_t*thr,	/*!< in: query thread */
315 #endif /* UNIV_DEBUG */
316 	const dtuple_t*	row,	/*!< in: old value of row, or NULL if the
317 				row and the data values in update are not
318 				known when this function is called, e.g., at
319 				compile time */
320 	const row_ext_t*ext)	/*!< NULL, or prefixes of the externally
321 				stored columns in the old row */
322 	MY_ATTRIBUTE((nonnull(1,2), warn_unused_result));
323 #ifdef UNIV_DEBUG
324 # define row_upd_changes_ord_field_binary(index,update,thr,row,ext)	\
325 	row_upd_changes_ord_field_binary_func(index,update,thr,row,ext)
326 #else /* UNIV_DEBUG */
327 # define row_upd_changes_ord_field_binary(index,update,thr,row,ext)	\
328 	row_upd_changes_ord_field_binary_func(index,update,row,ext)
329 #endif /* UNIV_DEBUG */
330 /***********************************************************//**
331 Checks if an FTS indexed column is affected by an UPDATE.
332 @return offset within fts_t::indexes if FTS indexed column updated else
333 ULINT_UNDEFINED */
334 UNIV_INTERN
335 ulint
336 row_upd_changes_fts_column(
337 /*=======================*/
338 	dict_table_t*	table,		/*!< in: table */
339 	upd_field_t*	upd_field);	/*!< in: field to check */
340 /***********************************************************//**
341 Checks if an FTS Doc ID column is affected by an UPDATE.
342 @return whether Doc ID column is affected */
343 UNIV_INTERN
344 bool
345 row_upd_changes_doc_id(
346 /*===================*/
347 	dict_table_t*	table,		/*!< in: table */
348 	upd_field_t*	upd_field)	/*!< in: field to check */
349 	MY_ATTRIBUTE((nonnull, warn_unused_result));
350 /***********************************************************//**
351 Checks if an update vector changes an ordering field of an index record.
352 This function is fast if the update vector is short or the number of ordering
353 fields in the index is small. Otherwise, this can be quadratic.
354 NOTE: we compare the fields as binary strings!
355 @return TRUE if update vector may change an ordering field in an index
356 record */
357 UNIV_INTERN
358 ibool
359 row_upd_changes_some_index_ord_field_binary(
360 /*========================================*/
361 	const dict_table_t*	table,	/*!< in: table */
362 	const upd_t*		update);/*!< in: update vector for the row */
363 /***********************************************************//**
364 Updates a row in a table. This is a high-level function used
365 in SQL execution graphs.
366 @return	query thread to run next or NULL */
367 UNIV_INTERN
368 que_thr_t*
369 row_upd_step(
370 /*=========*/
371 	que_thr_t*	thr);	/*!< in: query thread */
372 #endif /* !UNIV_HOTBACKUP */
373 /*********************************************************************//**
374 Parses the log data of system field values.
375 @return	log data end or NULL */
376 UNIV_INTERN
377 byte*
378 row_upd_parse_sys_vals(
379 /*===================*/
380 	byte*		ptr,	/*!< in: buffer */
381 	byte*		end_ptr,/*!< in: buffer end */
382 	ulint*		pos,	/*!< out: TRX_ID position in record */
383 	trx_id_t*	trx_id,	/*!< out: trx id */
384 	roll_ptr_t*	roll_ptr);/*!< out: roll ptr */
385 /*********************************************************************//**
386 Updates the trx id and roll ptr field in a clustered index record in database
387 recovery. */
388 UNIV_INTERN
389 void
390 row_upd_rec_sys_fields_in_recovery(
391 /*===============================*/
392 	rec_t*		rec,	/*!< in/out: record */
393 	page_zip_des_t*	page_zip,/*!< in/out: compressed page, or NULL */
394 	const ulint*	offsets,/*!< in: array returned by rec_get_offsets() */
395 	ulint		pos,	/*!< in: TRX_ID position in rec */
396 	trx_id_t	trx_id,	/*!< in: transaction id */
397 	roll_ptr_t	roll_ptr);/*!< in: roll ptr of the undo log record */
398 /*********************************************************************//**
399 Parses the log data written by row_upd_index_write_log.
400 @return	log data end or NULL */
401 UNIV_INTERN
402 byte*
403 row_upd_index_parse(
404 /*================*/
405 	byte*		ptr,	/*!< in: buffer */
406 	byte*		end_ptr,/*!< in: buffer end */
407 	mem_heap_t*	heap,	/*!< in: memory heap where update vector is
408 				built */
409 	upd_t**		update_out);/*!< out: update vector */
410 
411 
412 /* Update vector field */
413 struct upd_field_t{
414 	unsigned	field_no:16;	/*!< field number in an index, usually
415 					the clustered index, but in updating
416 					a secondary index record in btr0cur.cc
417 					this is the position in the secondary
418 					index */
419 #ifndef UNIV_HOTBACKUP
420 	unsigned	orig_len:16;	/*!< original length of the locally
421 					stored part of an externally stored
422 					column, or 0 */
423 	que_node_t*	exp;		/*!< expression for calculating a new
424 					value: it refers to column values and
425 					constants in the symbol table of the
426 					query graph */
427 #endif /* !UNIV_HOTBACKUP */
428 	dfield_t	new_val;	/*!< new value for the column */
429 };
430 
431 /* Update vector structure */
432 struct upd_t{
433 	ulint		info_bits;	/*!< new value of info bits to record;
434 					default is 0 */
435 	ulint		n_fields;	/*!< number of update fields */
436 	upd_field_t*	fields;		/*!< array of update fields */
437 };
438 
439 #ifndef UNIV_HOTBACKUP
440 /* Update node structure which also implements the delete operation
441 of a row */
442 
443 struct upd_node_t{
444 	que_common_t	common;	/*!< node type: QUE_NODE_UPDATE */
445 	ibool		is_delete;/* TRUE if delete, FALSE if update */
446 	ibool		searched_update;
447 				/* TRUE if searched update, FALSE if
448 				positioned */
449 	ibool		in_mysql_interface;
450 				/* TRUE if the update node was created
451 				for the MySQL interface */
452 	dict_foreign_t*	foreign;/* NULL or pointer to a foreign key
453 				constraint if this update node is used in
454 				doing an ON DELETE or ON UPDATE operation */
455 	upd_node_t*	cascade_node;/* NULL or an update node template which
456 				is used to implement ON DELETE/UPDATE CASCADE
457 				or ... SET NULL for foreign keys */
458 	mem_heap_t*	cascade_heap;/* NULL or a mem heap where the cascade
459 				node is created */
460 	sel_node_t*	select;	/*!< query graph subtree implementing a base
461 				table cursor: the rows returned will be
462 				updated */
463 	btr_pcur_t*	pcur;	/*!< persistent cursor placed on the clustered
464 				index record which should be updated or
465 				deleted; the cursor is stored in the graph
466 				of 'select' field above, except in the case
467 				of the MySQL interface */
468 	dict_table_t*	table;	/*!< table where updated */
469 	upd_t*		update;	/*!< update vector for the row */
470 	ulint		update_n_fields;
471 				/* when this struct is used to implement
472 				a cascade operation for foreign keys, we store
473 				here the size of the buffer allocated for use
474 				as the update vector */
475 	sym_node_list_t	columns;/* symbol table nodes for the columns
476 				to retrieve from the table */
477 	ibool		has_clust_rec_x_lock;
478 				/* TRUE if the select which retrieves the
479 				records to update already sets an x-lock on
480 				the clustered record; note that it must always
481 				set at least an s-lock */
482 	ulint		cmpl_info;/* information extracted during query
483 				compilation; speeds up execution:
484 				UPD_NODE_NO_ORD_CHANGE and
485 				UPD_NODE_NO_SIZE_CHANGE, ORed */
486 	/*----------------------*/
487 	/* Local storage for this graph node */
488 	ulint		state;	/*!< node execution state */
489 	dict_index_t*	index;	/*!< NULL, or the next index whose record should
490 				be updated */
491 	dtuple_t*	row;	/*!< NULL, or a copy (also fields copied to
492 				heap) of the row to update; this must be reset
493 				to NULL after a successful update */
494 	row_ext_t*	ext;	/*!< NULL, or prefixes of the externally
495 				stored columns in the old row */
496 	dtuple_t*	upd_row;/* NULL, or a copy of the updated row */
497 	row_ext_t*	upd_ext;/* NULL, or prefixes of the externally
498 				stored columns in upd_row */
499 	mem_heap_t*	heap;	/*!< memory heap used as auxiliary storage;
500 				this must be emptied after a successful
501 				update */
502 	/*----------------------*/
503 	sym_node_t*	table_sym;/* table node in symbol table */
504 	que_node_t*	col_assign_list;
505 				/* column assignment list */
506 	ulint		magic_n;
507 };
508 
509 #define	UPD_NODE_MAGIC_N	1579975
510 
511 /* Node execution states */
512 #define UPD_NODE_SET_IX_LOCK	   1	/* execution came to the node from
513 					a node above and if the field
514 					has_clust_rec_x_lock is FALSE, we
515 					should set an intention x-lock on
516 					the table */
517 #define UPD_NODE_UPDATE_CLUSTERED  2	/* clustered index record should be
518 					updated */
519 #define UPD_NODE_INSERT_CLUSTERED  3	/* clustered index record should be
520 					inserted, old record is already delete
521 					marked */
522 #define UPD_NODE_INSERT_BLOB	   4	/* clustered index record should be
523 					inserted, old record is already
524 					delete-marked; non-updated BLOBs
525 					should be inherited by the new record
526 					and disowned by the old record */
527 #define UPD_NODE_UPDATE_ALL_SEC	   5	/* an ordering field of the clustered
528 					index record was changed, or this is
529 					a delete operation: should update
530 					all the secondary index records */
531 #define UPD_NODE_UPDATE_SOME_SEC   6	/* secondary index entries should be
532 					looked at and updated if an ordering
533 					field changed */
534 
535 /* Compilation info flags: these must fit within 3 bits; see trx0rec.h */
536 #define UPD_NODE_NO_ORD_CHANGE	1	/* no secondary index record will be
537 					changed in the update and no ordering
538 					field of the clustered index */
539 #define UPD_NODE_NO_SIZE_CHANGE	2	/* no record field size will be
540 					changed in the update */
541 
542 #endif /* !UNIV_HOTBACKUP */
543 
544 #ifndef UNIV_NONINL
545 #include "row0upd.ic"
546 #endif
547 
548 #endif
549