1
/******************************************************
6
Created 12/27/1996 Heikki Tuuri
7
*******************************************************/
13
#include "data0data.h"
14
#include "btr0types.h"
16
#include "dict0types.h"
17
#include "trx0types.h"
18
#include "que0types.h"
19
#include "row0types.h"
20
#include "pars0types.h"
22
/*************************************************************************
23
Creates an update vector object. */
28
/* out, own: update vector object */
29
ulint n, /* in: number of fields */
30
mem_heap_t* heap); /* in: heap from which memory allocated */
31
/*************************************************************************
32
Returns the number of fields in the update vector == number of columns
33
to be updated by an update vector. */
38
/* out: number of fields */
39
const upd_t* update); /* in: update vector */
41
/*************************************************************************
42
Returns the nth field of an update vector. */
47
/* out: update vector field */
48
const upd_t* update, /* in: update vector */
49
ulint n); /* in: field position in update vector */
51
# define upd_get_nth_field(update, n) ((update)->fields + (n))
53
/*************************************************************************
54
Sets an index field number to be updated by an update vector field. */
57
upd_field_set_field_no(
58
/*===================*/
59
upd_field_t* upd_field, /* in: update vector field */
60
ulint field_no, /* in: field number in a clustered
62
dict_index_t* index, /* in: index */
63
trx_t* trx); /* in: transaction */
64
/*************************************************************************
65
Returns a field of an update vector by field_no. */
68
upd_get_field_by_field_no(
69
/*======================*/
70
/* out: update vector field, or NULL */
71
const upd_t* update, /* in: update vector */
72
ulint no) /* in: field_no */
73
__attribute__((nonnull, pure));
74
/*************************************************************************
75
Writes into the redo log the values of trx id and roll ptr and enough info
76
to determine their positions within a clustered index record. */
79
row_upd_write_sys_vals_to_log(
80
/*==========================*/
81
/* out: new pointer to mlog */
82
dict_index_t* index, /* in: clustered index */
83
trx_t* trx, /* in: transaction */
84
dulint roll_ptr,/* in: roll ptr of the undo log record */
85
byte* log_ptr,/* pointer to a buffer of size > 20 opened
87
mtr_t* mtr); /* in: mtr */
88
/*************************************************************************
89
Updates the trx id and roll ptr field in a clustered index record when
90
a row is updated or marked deleted. */
93
row_upd_rec_sys_fields(
94
/*===================*/
95
rec_t* rec, /* in/out: record */
96
page_zip_des_t* page_zip,/* in/out: compressed page whose
97
uncompressed part will be updated, or NULL */
98
dict_index_t* index, /* in: clustered index */
99
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
100
trx_t* trx, /* in: transaction */
101
dulint roll_ptr);/* in: roll ptr of the undo log record */
102
/*************************************************************************
103
Sets the trx id or roll ptr field of a clustered index entry. */
106
row_upd_index_entry_sys_field(
107
/*==========================*/
108
const dtuple_t* entry, /* in: index entry, where the memory buffers
109
for sys fields are already allocated:
110
the function just copies the new values to
112
dict_index_t* index, /* in: clustered index */
113
ulint type, /* in: DATA_TRX_ID or DATA_ROLL_PTR */
114
dulint val); /* in: value to write */
115
/*************************************************************************
116
Creates an update node for a query graph. */
121
/* out, own: update node */
122
mem_heap_t* heap); /* in: mem heap where created */
123
/***************************************************************
124
Writes to the redo log the new values of the fields occurring in the index. */
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. */
140
row_upd_changes_field_size_or_external(
141
/*===================================*/
142
/* out: TRUE if the update changes the size of
143
some field in index or the field is external
145
dict_index_t* index, /* in: index */
146
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
147
const upd_t* update);/* in: update vector */
148
/***************************************************************
149
Replaces the new column values stored in the update vector to the record
150
given. No field size changes are allowed. */
153
row_upd_rec_in_place(
154
/*=================*/
155
rec_t* rec, /* in/out: record where replaced */
156
dict_index_t* index, /* in: the index the record belongs to */
157
const ulint* offsets,/* in: array returned by rec_get_offsets() */
158
const upd_t* update, /* in: update vector */
159
page_zip_des_t* page_zip);/* in: compressed page with enough space
160
available, or NULL */
161
/*******************************************************************
162
Builds an update vector from those fields which in a secondary index entry
163
differ from a record that has the equal ordering fields. NOTE: we compare
164
the fields as binary strings! */
167
row_upd_build_sec_rec_difference_binary(
168
/*====================================*/
169
/* out, own: update vector of differing
171
dict_index_t* index, /* in: index */
172
const dtuple_t* entry, /* in: entry to insert */
173
const rec_t* rec, /* in: secondary index record */
174
trx_t* trx, /* in: transaction */
175
mem_heap_t* heap); /* in: memory heap from which allocated */
176
/*******************************************************************
177
Builds an update vector from those fields, excluding the roll ptr and
178
trx id fields, which in an index entry differ from a record that has
179
the equal ordering fields. NOTE: we compare the fields as binary strings! */
182
row_upd_build_difference_binary(
183
/*============================*/
184
/* out, own: update vector of differing
185
fields, excluding roll ptr and trx id */
186
dict_index_t* index, /* in: clustered index */
187
const dtuple_t* entry, /* in: entry to insert */
188
const rec_t* rec, /* in: clustered index record */
189
trx_t* trx, /* in: transaction */
190
mem_heap_t* heap); /* in: memory heap from which allocated */
191
/***************************************************************
192
Replaces the new column values stored in the update vector to the index entry
196
row_upd_index_replace_new_col_vals_index_pos(
197
/*=========================================*/
198
dtuple_t* entry, /* in/out: index entry where replaced;
199
the clustered index record must be
200
covered by a lock or a page latch to
201
prevent deletion (rollback or purge) */
202
dict_index_t* index, /* in: index; NOTE that this may also be a
203
non-clustered index */
204
const upd_t* update, /* in: an update vector built for the index so
205
that the field number in an upd_field is the
208
/* in: if TRUE, limit the replacement to
209
ordering fields of index; note that this
210
does not work for non-clustered indexes. */
211
mem_heap_t* heap) /* in: memory heap for allocating and
212
copying the new values */
213
__attribute__((nonnull));
214
/***************************************************************
215
Replaces the new column values stored in the update vector to the index entry
219
row_upd_index_replace_new_col_vals(
220
/*===============================*/
221
dtuple_t* entry, /* in/out: index entry where replaced;
222
the clustered index record must be
223
covered by a lock or a page latch to
224
prevent deletion (rollback or purge) */
225
dict_index_t* index, /* in: index; NOTE that this may also be a
226
non-clustered index */
227
const upd_t* update, /* in: an update vector built for the
228
CLUSTERED index so that the field number in
229
an upd_field is the clustered index position */
230
mem_heap_t* heap) /* in: memory heap for allocating and
231
copying the new values */
232
__attribute__((nonnull));
233
/***************************************************************
234
Replaces the new column values stored in the update vector. */
239
dtuple_t* row, /* in/out: row where replaced,
241
the clustered index record must be
242
covered by a lock or a page latch to
243
prevent deletion (rollback or purge) */
244
row_ext_t** ext, /* out, own: NULL, or externally
245
stored column prefixes */
246
const dict_index_t* index, /* in: clustered index */
247
const upd_t* update, /* in: an update vector built for the
249
mem_heap_t* heap); /* in: memory heap */
250
/***************************************************************
251
Checks if an update vector changes an ordering field of an index record.
252
This function is fast if the update vector is short or the number of ordering
253
fields in the index is small. Otherwise, this can be quadratic.
254
NOTE: we compare the fields as binary strings! */
257
row_upd_changes_ord_field_binary(
258
/*=============================*/
259
/* out: TRUE if update vector changes
260
an ordering field in the index record;
261
NOTE: the fields are compared as binary
263
const dtuple_t* row, /* in: old value of row, or NULL if the
264
row and the data values in update are not
265
known when this function is called, e.g., at
267
dict_index_t* index, /* in: index of the record */
268
const upd_t* update);/* in: update vector for the row; NOTE: the
269
field numbers in this MUST be clustered index
271
/***************************************************************
272
Checks if an update vector changes an ordering field of an index record.
273
This function is fast if the update vector is short or the number of ordering
274
fields in the index is small. Otherwise, this can be quadratic.
275
NOTE: we compare the fields as binary strings! */
278
row_upd_changes_some_index_ord_field_binary(
279
/*========================================*/
280
/* out: TRUE if update vector
281
may change an ordering field
282
in an index record */
283
const dict_table_t* table, /* in: table */
284
const upd_t* update);/* in: update vector for the row */
285
/***************************************************************
286
Updates a row in a table. This is a high-level function used
287
in SQL execution graphs. */
292
/* out: query thread to run next or NULL */
293
que_thr_t* thr); /* in: query thread */
294
/*************************************************************************
295
Performs an in-place update for the current clustered index record in
299
row_upd_in_place_in_select(
300
/*=======================*/
301
sel_node_t* sel_node, /* in: select node */
302
que_thr_t* thr, /* in: query thread */
303
mtr_t* mtr); /* in: mtr */
304
/*************************************************************************
305
Parses the log data of system field values. */
308
row_upd_parse_sys_vals(
309
/*===================*/
310
/* out: log data end or NULL */
311
byte* ptr, /* in: buffer */
312
byte* end_ptr,/* in: buffer end */
313
ulint* pos, /* out: TRX_ID position in record */
314
dulint* trx_id, /* out: trx id */
315
dulint* roll_ptr);/* out: roll ptr */
316
/*************************************************************************
317
Updates the trx id and roll ptr field in a clustered index record in database
321
row_upd_rec_sys_fields_in_recovery(
322
/*===============================*/
323
rec_t* rec, /* in/out: record */
324
page_zip_des_t* page_zip,/* in/out: compressed page, or NULL */
325
const ulint* offsets,/* in: array returned by rec_get_offsets() */
326
ulint pos, /* in: TRX_ID position in rec */
327
dulint trx_id, /* in: transaction id */
328
dulint roll_ptr);/* in: roll ptr of the undo log record */
329
/*************************************************************************
330
Parses the log data written by row_upd_index_write_log. */
335
/* out: log data end or NULL */
336
byte* ptr, /* in: buffer */
337
byte* end_ptr,/* in: buffer end */
338
mem_heap_t* heap, /* in: memory heap where update vector is
340
upd_t** update_out);/* out: update vector */
343
/* Update vector field */
344
struct upd_field_struct{
345
unsigned field_no:16; /* field number in an index, usually
346
the clustered index, but in updating
347
a secondary index record in btr0cur.c
348
this is the position in the secondary
350
unsigned orig_len:16; /* original length of the locally
351
stored part of an externally stored
353
que_node_t* exp; /* expression for calculating a new
354
value: it refers to column values and
355
constants in the symbol table of the
357
dfield_t new_val; /* new value for the column */
360
/* Update vector structure */
362
ulint info_bits; /* new value of info bits to record;
364
ulint n_fields; /* number of update fields */
365
upd_field_t* fields; /* array of update fields */
368
/* Update node structure which also implements the delete operation
371
struct upd_node_struct{
372
que_common_t common; /* node type: QUE_NODE_UPDATE */
373
ibool is_delete;/* TRUE if delete, FALSE if update */
374
ibool searched_update;
375
/* TRUE if searched update, FALSE if
377
ibool select_will_do_update;
378
/* TRUE if a searched update where ordering
379
fields will not be updated, and the size of
380
the fields will not change: in this case the
381
select node will take care of the update */
382
ibool in_mysql_interface;
383
/* TRUE if the update node was created
384
for the MySQL interface */
385
dict_foreign_t* foreign;/* NULL or pointer to a foreign key
386
constraint if this update node is used in
387
doing an ON DELETE or ON UPDATE operation */
388
upd_node_t* cascade_node;/* NULL or an update node template which
389
is used to implement ON DELETE/UPDATE CASCADE
390
or ... SET NULL for foreign keys */
391
mem_heap_t* cascade_heap;/* NULL or a mem heap where the cascade
393
sel_node_t* select; /* query graph subtree implementing a base
394
table cursor: the rows returned will be
396
btr_pcur_t* pcur; /* persistent cursor placed on the clustered
397
index record which should be updated or
398
deleted; the cursor is stored in the graph
399
of 'select' field above, except in the case
400
of the MySQL interface */
401
dict_table_t* table; /* table where updated */
402
upd_t* update; /* update vector for the row */
403
ulint update_n_fields;
404
/* when this struct is used to implement
405
a cascade operation for foreign keys, we store
406
here the size of the buffer allocated for use
407
as the update vector */
408
sym_node_list_t columns;/* symbol table nodes for the columns
409
to retrieve from the table */
410
ibool has_clust_rec_x_lock;
411
/* TRUE if the select which retrieves the
412
records to update already sets an x-lock on
413
the clustered record; note that it must always
414
set at least an s-lock */
415
ulint cmpl_info;/* information extracted during query
416
compilation; speeds up execution:
417
UPD_NODE_NO_ORD_CHANGE and
418
UPD_NODE_NO_SIZE_CHANGE, ORed */
419
/*----------------------*/
420
/* Local storage for this graph node */
421
ulint state; /* node execution state */
422
dict_index_t* index; /* NULL, or the next index whose record should
424
dtuple_t* row; /* NULL, or a copy (also fields copied to
425
heap) of the row to update; this must be reset
426
to NULL after a successful update */
427
row_ext_t* ext; /* NULL, or prefixes of the externally
428
stored columns in the old row */
429
dtuple_t* upd_row;/* NULL, or a copy of the updated row */
430
row_ext_t* upd_ext;/* NULL, or prefixes of the externally
431
stored columns in upd_row */
432
mem_heap_t* heap; /* memory heap used as auxiliary storage;
433
this must be emptied after a successful
435
/*----------------------*/
436
sym_node_t* table_sym;/* table node in symbol table */
437
que_node_t* col_assign_list;
438
/* column assignment list */
442
#define UPD_NODE_MAGIC_N 1579975
444
/* Node execution states */
445
#define UPD_NODE_SET_IX_LOCK 1 /* execution came to the node from
446
a node above and if the field
447
has_clust_rec_x_lock is FALSE, we
448
should set an intention x-lock on
450
#define UPD_NODE_UPDATE_CLUSTERED 2 /* clustered index record should be
452
#define UPD_NODE_INSERT_CLUSTERED 3 /* clustered index record should be
453
inserted, old record is already delete
455
#define UPD_NODE_UPDATE_ALL_SEC 4 /* an ordering field of the clustered
456
index record was changed, or this is
457
a delete operation: should update
458
all the secondary index records */
459
#define UPD_NODE_UPDATE_SOME_SEC 5 /* secondary index entries should be
460
looked at and updated if an ordering
463
/* Compilation info flags: these must fit within 3 bits; see trx0rec.h */
464
#define UPD_NODE_NO_ORD_CHANGE 1 /* no secondary index record will be
465
changed in the update and no ordering
466
field of the clustered index */
467
#define UPD_NODE_NO_SIZE_CHANGE 2 /* no record field size will be
468
changed in the update */
471
#include "row0upd.ic"