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