1 /*****************************************************************************
2 
3 Copyright (c) 1996, 2021, Oracle and/or its affiliates.
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 #include <stack>
44 
45 #ifndef UNIV_HOTBACKUP
46 # include "btr0pcur.h"
47 # include "que0types.h"
48 # include "pars0types.h"
49 #endif /* !UNIV_HOTBACKUP */
50 
51 /*********************************************************************//**
52 Creates an update vector object.
53 @return own: update vector object */
54 UNIV_INLINE
55 upd_t*
56 upd_create(
57 /*=======*/
58 	ulint		n,	/*!< in: number of fields */
59 	mem_heap_t*	heap);	/*!< in: heap from which memory allocated */
60 /*********************************************************************//**
61 Returns the number of fields in the update vector == number of columns
62 to be updated by an update vector.
63 @return number of fields */
64 UNIV_INLINE
65 ulint
66 upd_get_n_fields(
67 /*=============*/
68 	const upd_t*	update);	/*!< in: update vector */
69 #ifdef UNIV_DEBUG
70 /*********************************************************************//**
71 Returns the nth field of an update vector.
72 @return update vector field */
73 UNIV_INLINE
74 upd_field_t*
75 upd_get_nth_field(
76 /*==============*/
77 	const upd_t*	update,	/*!< in: update vector */
78 	ulint		n);	/*!< in: field position in update vector */
79 #else
80 # define upd_get_nth_field(update, n) ((update)->fields + (n))
81 #endif
82 #ifndef UNIV_HOTBACKUP
83 /*********************************************************************//**
84 Sets an index field number to be updated by an update vector field. */
85 UNIV_INLINE
86 void
87 upd_field_set_field_no(
88 /*===================*/
89 	upd_field_t*	upd_field,	/*!< in: update vector field */
90 	ulint		field_no,	/*!< in: field number in a clustered
91 					index */
92 	dict_index_t*	index,		/*!< in: index */
93 	trx_t*		trx);		/*!< in: transaction */
94 
95 /** set field number to a update vector field, marks this field is updated
96 @param[in,out]	upd_field	update vector field
97 @param[in]	field_no	virtual column sequence num
98 @param[in]	index		index */
99 UNIV_INLINE
100 void
101 upd_field_set_v_field_no(
102 	upd_field_t*	upd_field,
103 	ulint		field_no,
104 	dict_index_t*	index);
105 /*********************************************************************//**
106 Returns a field of an update vector by field_no.
107 @return update vector field, or NULL */
108 UNIV_INLINE
109 const upd_field_t*
110 upd_get_field_by_field_no(
111 /*======================*/
112 	const upd_t*	update,	/*!< in: update vector */
113 	ulint		no,	/*!< in: field_no */
114 	bool		is_virtual) /*!< in: if it is a virtual column */
115 	MY_ATTRIBUTE((warn_unused_result));
116 /*********************************************************************//**
117 Writes into the redo log the values of trx id and roll ptr and enough info
118 to determine their positions within a clustered index record.
119 @return new pointer to mlog */
120 byte*
121 row_upd_write_sys_vals_to_log(
122 /*==========================*/
123 	dict_index_t*	index,	/*!< in: clustered index */
124 	trx_id_t	trx_id,	/*!< in: transaction id */
125 	roll_ptr_t	roll_ptr,/*!< in: roll ptr of the undo log record */
126 	byte*		log_ptr,/*!< pointer to a buffer of size > 20 opened
127 				in mlog */
128 	mtr_t*		mtr);	/*!< in: mtr */
129 /*********************************************************************//**
130 Updates the trx id and roll ptr field in a clustered index record when
131 a row is updated or marked deleted. */
132 UNIV_INLINE
133 void
134 row_upd_rec_sys_fields(
135 /*===================*/
136 	rec_t*		rec,	/*!< in/out: record */
137 	page_zip_des_t*	page_zip,/*!< in/out: compressed page whose
138 				uncompressed part will be updated, or NULL */
139 	dict_index_t*	index,	/*!< in: clustered index */
140 	const ulint*	offsets,/*!< in: rec_get_offsets(rec, index) */
141 	const trx_t*	trx,	/*!< in: transaction */
142 	roll_ptr_t	roll_ptr);/*!< in: roll ptr of the undo log record,
143 				  can be 0 during IMPORT */
144 /*********************************************************************//**
145 Sets the trx id or roll ptr field of a clustered index entry. */
146 void
147 row_upd_index_entry_sys_field(
148 /*==========================*/
149 	dtuple_t*	entry,	/*!< in/out: index entry, where the memory
150 				buffers for sys fields are already allocated:
151 				the function just copies the new values to
152 				them */
153 	dict_index_t*	index,	/*!< in: clustered index */
154 	ulint		type,	/*!< in: DATA_TRX_ID or DATA_ROLL_PTR */
155 	ib_uint64_t	val);	/*!< in: value to write */
156 /*********************************************************************//**
157 Creates an update node for a query graph.
158 @return own: update node */
159 upd_node_t*
160 upd_node_create(
161 /*============*/
162 	mem_heap_t*	heap);	/*!< in: mem heap where created */
163 /***********************************************************//**
164 Writes to the redo log the new values of the fields occurring in the index. */
165 void
166 row_upd_index_write_log(
167 /*====================*/
168 	const upd_t*	update,	/*!< in: update vector */
169 	byte*		log_ptr,/*!< in: pointer to mlog buffer: must
170 				contain at least MLOG_BUF_MARGIN bytes
171 				of free space; the buffer is closed
172 				within this function */
173 	mtr_t*		mtr);	/*!< in: mtr into whose log to write */
174 /***********************************************************//**
175 Returns TRUE if row update changes size of some field in index or if some
176 field to be updated is stored externally in rec or update.
177 @return TRUE if the update changes the size of some field in index or
178 the field is external in rec or update */
179 ibool
180 row_upd_changes_field_size_or_external(
181 /*===================================*/
182 	dict_index_t*	index,	/*!< in: index */
183 	const ulint*	offsets,/*!< in: rec_get_offsets(rec, index) */
184 	const upd_t*	update);/*!< in: update vector */
185 /***********************************************************//**
186 Returns true if row update contains disowned external fields.
187 @return true if the update contains disowned external fields. */
188 bool
189 row_upd_changes_disowned_external(
190 /*==============================*/
191 	const upd_t*	update)	/*!< in: update vector */
192 	MY_ATTRIBUTE((warn_unused_result));
193 #endif /* !UNIV_HOTBACKUP */
194 /***********************************************************//**
195 Replaces the new column values stored in the update vector to the
196 record given. No field size changes are allowed. This function is
197 usually invoked on a clustered index. The only use case for a
198 secondary index is row_ins_sec_index_entry_by_modify() or its
199 counterpart in ibuf_insert_to_index_page(). */
200 void
201 row_upd_rec_in_place(
202 /*=================*/
203 	rec_t*		rec,	/*!< in/out: record where replaced */
204 	dict_index_t*	index,	/*!< in: the index the record belongs to */
205 	const ulint*	offsets,/*!< in: array returned by rec_get_offsets() */
206 	const upd_t*	update,	/*!< in: update vector */
207 	page_zip_des_t*	page_zip);/*!< in: compressed page with enough space
208 				available, or NULL */
209 #ifndef UNIV_HOTBACKUP
210 /***************************************************************//**
211 Builds an update vector from those fields which in a secondary index entry
212 differ from a record that has the equal ordering fields. NOTE: we compare
213 the fields as binary strings!
214 @return own: update vector of differing fields */
215 upd_t*
216 row_upd_build_sec_rec_difference_binary(
217 /*====================================*/
218 	const rec_t*	rec,	/*!< in: secondary index record */
219 	dict_index_t*	index,	/*!< in: index */
220 	const ulint*	offsets,/*!< in: rec_get_offsets(rec, index) */
221 	const dtuple_t*	entry,	/*!< in: entry to insert */
222 	mem_heap_t*	heap)	/*!< in: memory heap from which allocated */
223 	MY_ATTRIBUTE((warn_unused_result));
224 /** Builds an update vector from those fields, excluding the roll ptr and
225 trx id fields, which in an index entry differ from a record that has
226 the equal ordering fields. NOTE: we compare the fields as binary strings!
227 @param[in]	index		clustered index
228 @param[in]	entry		clustered index entry to insert
229 @param[in]	rec		clustered index record
230 @param[in]	offsets		rec_get_offsets(rec,index), or NULL
231 @param[in]	no_sys		skip the system columns
232 				DB_TRX_ID and DB_ROLL_PTR
233 @param[in]	trx		transaction (for diagnostics),
234 				or NULL
235 @param[in]	heap		memory heap from which allocated
236 @param[in,out]	mysql_table	NULL, or mysql table object when
237 				user thread invokes dml
238 @param[out]	error		error number in case of failure
239 @return own: update vector of differing fields, excluding roll ptr and
240 trx id */
241 upd_t*
242 row_upd_build_difference_binary(
243 	dict_index_t*	index,
244 	const dtuple_t*	entry,
245 	const rec_t*	rec,
246 	const ulint*	offsets,
247 	bool		no_sys,
248 	trx_t*		trx,
249 	mem_heap_t*	heap,
250 	TABLE*		mysql_table,
251 	dberr_t*	error)
252 	MY_ATTRIBUTE((warn_unused_result));
253 /***********************************************************//**
254 Replaces the new column values stored in the update vector to the index entry
255 given. */
256 void
257 row_upd_index_replace_new_col_vals_index_pos(
258 /*=========================================*/
259 	dtuple_t*	entry,	/*!< in/out: index entry where replaced;
260 				the clustered index record must be
261 				covered by a lock or a page latch to
262 				prevent deletion (rollback or purge) */
263 	dict_index_t*	index,	/*!< in: index; NOTE that this may also be a
264 				non-clustered index */
265 	const upd_t*	update,	/*!< in: an update vector built for the index so
266 				that the field number in an upd_field is the
267 				index position */
268 	ibool		order_only,
269 				/*!< in: if TRUE, limit the replacement to
270 				ordering fields of index; note that this
271 				does not work for non-clustered indexes. */
272 	mem_heap_t*	heap);	/*!< in: memory heap for allocating and
273 				copying the new values */
274 /***********************************************************//**
275 Replaces the new column values stored in the update vector to the index entry
276 given. */
277 void
278 row_upd_index_replace_new_col_vals(
279 /*===============================*/
280 	dtuple_t*	entry,	/*!< in/out: index entry where replaced;
281 				the clustered index record must be
282 				covered by a lock or a page latch to
283 				prevent deletion (rollback or purge) */
284 	dict_index_t*	index,	/*!< in: index; NOTE that this may also be a
285 				non-clustered index */
286 	const upd_t*	update,	/*!< in: an update vector built for the
287 				CLUSTERED index so that the field number in
288 				an upd_field is the clustered index position */
289 	mem_heap_t*	heap);	/*!< in: memory heap for allocating and
290 				copying the new values */
291 /***********************************************************//**
292 Replaces the new column values stored in the update vector. */
293 void
294 row_upd_replace(
295 /*============*/
296 	dtuple_t*		row,	/*!< in/out: row where replaced,
297 					indexed by col_no;
298 					the clustered index record must be
299 					covered by a lock or a page latch to
300 					prevent deletion (rollback or purge) */
301 	row_ext_t**		ext,	/*!< out, own: NULL, or externally
302 					stored column prefixes */
303 	const dict_index_t*	index,	/*!< in: clustered index */
304 	const upd_t*		update,	/*!< in: an update vector built for the
305 					clustered index */
306 	mem_heap_t*		heap);	/*!< in: memory heap */
307 /** Replaces the virtual column values stored in a dtuple with that of
308 a update vector.
309 @param[in,out]	row	dtuple whose column to be updated
310 @param[in]	table	table
311 @param[in]	update	an update vector built for the clustered index
312 @param[in]	upd_new	update to new or old value
313 @param[in,out]	undo_row undo row (if needs to be updated)
314 @param[in]	ptr	remaining part in update undo log */
315 void
316 row_upd_replace_vcol(
317 	dtuple_t*		row,
318 	const dict_table_t*	table,
319 	const upd_t*		update,
320 	bool			upd_new,
321 	dtuple_t*		undo_row,
322 	const byte*		ptr);
323 
324 /***********************************************************//**
325 Checks if an update vector changes an ordering field of an index record.
326 
327 This function is fast if the update vector is short or the number of ordering
328 fields in the index is small. Otherwise, this can be quadratic.
329 NOTE: we compare the fields as binary strings!
330 @return TRUE if update vector changes an ordering field in the index record */
331 ibool
332 row_upd_changes_ord_field_binary_func(
333 /*==================================*/
334 	dict_index_t*	index,	/*!< in: index of the record */
335 	const upd_t*	update,	/*!< in: update vector for the row; NOTE: the
336 				field numbers in this MUST be clustered index
337 				positions! */
338 #ifdef UNIV_DEBUG
339 	const que_thr_t*thr,	/*!< in: query thread */
340 #endif /* UNIV_DEBUG */
341 	const dtuple_t*	row,	/*!< in: old value of row, or NULL if the
342 				row and the data values in update are not
343 				known when this function is called, e.g., at
344 				compile time */
345 	const row_ext_t*ext,	/*!< NULL, or prefixes of the externally
346 				stored columns in the old row */
347 	ulint		flag)	/*!< in: ROW_BUILD_NORMAL,
348 				ROW_BUILD_FOR_PURGE or ROW_BUILD_FOR_UNDO */
349 	MY_ATTRIBUTE((warn_unused_result));
350 #ifdef UNIV_DEBUG
351 # define row_upd_changes_ord_field_binary(index,update,thr,row,ext)	\
352 	row_upd_changes_ord_field_binary_func(index,update,thr,row,ext,0)
353 #else /* UNIV_DEBUG */
354 # define row_upd_changes_ord_field_binary(index,update,thr,row,ext)	\
355 	row_upd_changes_ord_field_binary_func(index,update,row,ext,0)
356 #endif /* UNIV_DEBUG */
357 /***********************************************************//**
358 Checks if an FTS indexed column is affected by an UPDATE.
359 @return offset within fts_t::indexes if FTS indexed column updated else
360 ULINT_UNDEFINED */
361 ulint
362 row_upd_changes_fts_column(
363 /*=======================*/
364 	dict_table_t*	table,		/*!< in: table */
365 	upd_field_t*	upd_field);	/*!< in: field to check */
366 /***********************************************************//**
367 Checks if an FTS Doc ID column is affected by an UPDATE.
368 @return whether Doc ID column is affected */
369 bool
370 row_upd_changes_doc_id(
371 /*===================*/
372 	dict_table_t*	table,		/*!< in: table */
373 	upd_field_t*	upd_field)	/*!< in: field to check */
374 	MY_ATTRIBUTE((warn_unused_result));
375 /***********************************************************//**
376 Checks if an update vector changes an ordering field of an index record.
377 This function is fast if the update vector is short or the number of ordering
378 fields in the index is small. Otherwise, this can be quadratic.
379 NOTE: we compare the fields as binary strings!
380 @return TRUE if update vector may change an ordering field in an index
381 record */
382 ibool
383 row_upd_changes_some_index_ord_field_binary(
384 /*========================================*/
385 	const dict_table_t*	table,	/*!< in: table */
386 	const upd_t*		update);/*!< in: update vector for the row */
387 /** Stores to the heap the row on which the node->pcur is positioned.
388 @param[in]	node		row update node
389 @param[in]	thd		mysql thread handle
390 @param[in,out]	mysql_table	NULL, or mysql table object when
391 				user thread invokes dml */
392 void
393 row_upd_store_row(
394 	upd_node_t*	node,
395 	THD*		thd,
396 	TABLE*		mysql_table);
397 /***********************************************************//**
398 Updates a row in a table. This is a high-level function used
399 in SQL execution graphs.
400 @return query thread to run next or NULL */
401 que_thr_t*
402 row_upd_step(
403 /*=========*/
404 	que_thr_t*	thr);	/*!< in: query thread */
405 #endif /* !UNIV_HOTBACKUP */
406 /*********************************************************************//**
407 Parses the log data of system field values.
408 @return log data end or NULL */
409 byte*
410 row_upd_parse_sys_vals(
411 /*===================*/
412 	const byte*	ptr,	/*!< in: buffer */
413 	const byte*	end_ptr,/*!< in: buffer end */
414 	ulint*		pos,	/*!< out: TRX_ID position in record */
415 	trx_id_t*	trx_id,	/*!< out: trx id */
416 	roll_ptr_t*	roll_ptr);/*!< out: roll ptr */
417 /*********************************************************************//**
418 Updates the trx id and roll ptr field in a clustered index record in database
419 recovery. */
420 void
421 row_upd_rec_sys_fields_in_recovery(
422 /*===============================*/
423 	rec_t*		rec,	/*!< in/out: record */
424 	page_zip_des_t*	page_zip,/*!< in/out: compressed page, or NULL */
425 	const ulint*	offsets,/*!< in: array returned by rec_get_offsets() */
426 	ulint		pos,	/*!< in: TRX_ID position in rec */
427 	trx_id_t	trx_id,	/*!< in: transaction id */
428 	roll_ptr_t	roll_ptr);/*!< in: roll ptr of the undo log record */
429 /*********************************************************************//**
430 Parses the log data written by row_upd_index_write_log.
431 @return log data end or NULL */
432 byte*
433 row_upd_index_parse(
434 /*================*/
435 	const byte*	ptr,	/*!< in: buffer */
436 	const byte*	end_ptr,/*!< in: buffer end */
437 	mem_heap_t*	heap,	/*!< in: memory heap where update vector is
438 				built */
439 	upd_t**		update_out);/*!< out: update vector */
440 
441 
442 /* Update vector field */
443 struct upd_field_t{
444 	unsigned	field_no:16;	/*!< field number in an index, usually
445 					the clustered index, but in updating
446 					a secondary index record in btr0cur.cc
447 					this is the position in the secondary
448 					index. If this field is a virtual
449 					column, then field_no represents
450 					the nth virtual	column in the table */
451 #ifndef UNIV_HOTBACKUP
452 	unsigned	orig_len:16;	/*!< original length of the locally
453 					stored part of an externally stored
454 					column, or 0 */
455 	que_node_t*	exp;		/*!< expression for calculating a new
456 					value: it refers to column values and
457 					constants in the symbol table of the
458 					query graph */
459 #endif /* !UNIV_HOTBACKUP */
460 	dfield_t	new_val;	/*!< new value for the column */
461 	dfield_t*	old_v_val;	/*!< old value for the virtual column */
462 };
463 
464 
465 /* check whether an update field is on virtual column */
466 #define upd_fld_is_virtual_col(upd_fld)			\
467 	(((upd_fld)->new_val.type.prtype & DATA_VIRTUAL) == DATA_VIRTUAL)
468 
469 /* set DATA_VIRTUAL bit on update field to show it is a virtual column */
470 #define upd_fld_set_virtual_col(upd_fld)			\
471 	((upd_fld)->new_val.type.prtype |= DATA_VIRTUAL)
472 
473 /* Update vector structure */
474 struct upd_t{
475 	mem_heap_t*	heap;		/*!< heap from which memory allocated */
476 	ulint		info_bits;	/*!< new value of info bits to record;
477 					default is 0 */
478 	dtuple_t*	old_vrow;	/*!< pointer to old row, used for
479 					virtual column update now */
480 	ulint		n_fields;	/*!< number of update fields */
481 	upd_field_t*	fields;		/*!< array of update fields */
482 
483 	/** Append an update field to the end of array
484 	@param[in]	field	an update field */
appendupd_t485 	void append(const upd_field_t& field)
486 	{
487 		fields[n_fields++] = field;
488 	}
489 
490 	/** Determine if the given field_no is modified.
491 	@return true if modified, false otherwise.  */
is_modifiedupd_t492 	bool is_modified(const ulint field_no) const
493 	{
494 		for (ulint i = 0; i < n_fields; ++i) {
495 			if (field_no == fields[i].field_no) {
496 				return(true);
497 			}
498 		}
499 		return(false);
500 	}
501 
502 #ifdef UNIV_DEBUG
validateupd_t503         bool validate() const
504         {
505                 for (ulint i = 0; i < n_fields; ++i) {
506                         dfield_t* field = &fields[i].new_val;
507                         if (dfield_is_ext(field)) {
508 				ut_ad(dfield_get_len(field)
509 				      >= BTR_EXTERN_FIELD_REF_SIZE);
510                         }
511                 }
512                 return(true);
513         }
514 #endif // UNIV_DEBUG
515 
516 };
517 
518 #ifndef UNIV_HOTBACKUP
519 /* Update node structure which also implements the delete operation
520 of a row */
521 
522 struct upd_node_t{
523 	que_common_t	common;	/*!< node type: QUE_NODE_UPDATE */
524 	ibool		is_delete;/* TRUE if delete, FALSE if update */
525 	ibool		searched_update;
526 				/* TRUE if searched update, FALSE if
527 				positioned */
528 	ibool		in_mysql_interface;
529 				/* TRUE if the update node was created
530 				for the MySQL interface */
531 	dict_foreign_t*	foreign;/* NULL or pointer to a foreign key
532 				constraint if this update node is used in
533 				doing an ON DELETE or ON UPDATE operation */
534         upd_node_t*     cascade_node;/* NULL or an update node template which
535                                 is used to implement ON DELETE/UPDATE CASCADE
536                                 or ... SET NULL for foreign keys */
537 	mem_heap_t*	cascade_heap;
538 				/*!< NULL or a mem heap where cascade
539 				node is created.*/
540 	sel_node_t*	select;	/*!< query graph subtree implementing a base
541 				table cursor: the rows returned will be
542 				updated */
543 	btr_pcur_t*	pcur;	/*!< persistent cursor placed on the clustered
544 				index record which should be updated or
545 				deleted; the cursor is stored in the graph
546 				of 'select' field above, except in the case
547 				of the MySQL interface */
548 	dict_table_t*	table;	/*!< table where updated */
549 	upd_t*		update;	/*!< update vector for the row */
550 	ulint		update_n_fields;
551 				/* when this struct is used to implement
552 				a cascade operation for foreign keys, we store
553 				here the size of the buffer allocated for use
554 				as the update vector */
555 	sym_node_list_t	columns;/* symbol table nodes for the columns
556 				to retrieve from the table */
557 	ibool		has_clust_rec_x_lock;
558 				/* TRUE if the select which retrieves the
559 				records to update already sets an x-lock on
560 				the clustered record; note that it must always
561 				set at least an s-lock */
562 	ulint		cmpl_info;/* information extracted during query
563 				compilation; speeds up execution:
564 				UPD_NODE_NO_ORD_CHANGE and
565 				UPD_NODE_NO_SIZE_CHANGE, ORed */
566 	/*----------------------*/
567 	/* Local storage for this graph node */
568 	ulint		state;	/*!< node execution state */
569 	dict_index_t*	index;	/*!< NULL, or the next index whose record should
570 				be updated */
571 	dtuple_t*	row;	/*!< NULL, or a copy (also fields copied to
572 				heap) of the row to update; this must be reset
573 				to NULL after a successful update */
574 	row_ext_t*	ext;	/*!< NULL, or prefixes of the externally
575 				stored columns in the old row */
576 	dtuple_t*	upd_row;/* NULL, or a copy of the updated row */
577 	row_ext_t*	upd_ext;/* NULL, or prefixes of the externally
578 				stored columns in upd_row */
579 	mem_heap_t*	heap;	/*!< memory heap used as auxiliary storage;
580 				this must be emptied after a successful
581 				update */
582 	/*----------------------*/
583 	sym_node_t*	table_sym;/* table node in symbol table */
584 	que_node_t*	col_assign_list;
585 				/* column assignment list */
586 	ulint		magic_n;
587 
588 };
589 
590 #define	UPD_NODE_MAGIC_N	1579975
591 
592 /* Node execution states */
593 #define UPD_NODE_SET_IX_LOCK	   1	/* execution came to the node from
594 					a node above and if the field
595 					has_clust_rec_x_lock is FALSE, we
596 					should set an intention x-lock on
597 					the table */
598 #define UPD_NODE_UPDATE_CLUSTERED  2	/* clustered index record should be
599 					updated */
600 #define UPD_NODE_INSERT_CLUSTERED  3	/* clustered index record should be
601 					inserted, old record is already delete
602 					marked */
603 #define UPD_NODE_UPDATE_ALL_SEC	   5	/* an ordering field of the clustered
604 					index record was changed, or this is
605 					a delete operation: should update
606 					all the secondary index records */
607 #define UPD_NODE_UPDATE_SOME_SEC   6	/* secondary index entries should be
608 					looked at and updated if an ordering
609 					field changed */
610 
611 /* Compilation info flags: these must fit within 3 bits; see trx0rec.h */
612 #define UPD_NODE_NO_ORD_CHANGE	1	/* no secondary index record will be
613 					changed in the update and no ordering
614 					field of the clustered index */
615 #define UPD_NODE_NO_SIZE_CHANGE	2	/* no record field size will be
616 					changed in the update */
617 
618 #endif /* !UNIV_HOTBACKUP */
619 
620 #ifndef UNIV_NONINL
621 #include "row0upd.ic"
622 #endif
623 
624 #endif
625