1 | /***************************************************************************** |
2 | |
3 | Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. |
4 | Copyright (c) 2017, 2018, MariaDB Corporation. |
5 | |
6 | This program is free software; you can redistribute it and/or modify it under |
7 | the terms of the GNU General Public License as published by the Free Software |
8 | Foundation; version 2 of the License. |
9 | |
10 | This program is distributed in the hope that it will be useful, but WITHOUT |
11 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
12 | FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. |
13 | |
14 | You should have received a copy of the GNU General Public License along with |
15 | this program; if not, write to the Free Software Foundation, Inc., |
16 | 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA |
17 | |
18 | *****************************************************************************/ |
19 | |
20 | /**************************************************//** |
21 | @file include/row0ins.h |
22 | Insert into a table |
23 | |
24 | Created 4/20/1996 Heikki Tuuri |
25 | *******************************************************/ |
26 | |
27 | #ifndef row0ins_h |
28 | #define row0ins_h |
29 | |
30 | #include "univ.i" |
31 | #include "data0data.h" |
32 | #include "que0types.h" |
33 | #include "dict0types.h" |
34 | #include "trx0types.h" |
35 | #include "row0types.h" |
36 | |
37 | /***************************************************************//** |
38 | Checks if foreign key constraint fails for an index entry. Sets shared locks |
39 | which lock either the success or the failure of the constraint. NOTE that |
40 | the caller must have a shared latch on dict_foreign_key_check_lock. |
41 | @return DB_SUCCESS, DB_LOCK_WAIT, DB_NO_REFERENCED_ROW, or |
42 | DB_ROW_IS_REFERENCED */ |
43 | dberr_t |
44 | row_ins_check_foreign_constraint( |
45 | /*=============================*/ |
46 | ibool check_ref,/*!< in: TRUE If we want to check that |
47 | the referenced table is ok, FALSE if we |
48 | want to check the foreign key table */ |
49 | dict_foreign_t* foreign,/*!< in: foreign constraint; NOTE that the |
50 | tables mentioned in it must be in the |
51 | dictionary cache if they exist at all */ |
52 | dict_table_t* table, /*!< in: if check_ref is TRUE, then the foreign |
53 | table, else the referenced table */ |
54 | dtuple_t* entry, /*!< in: index entry for index */ |
55 | que_thr_t* thr) /*!< in: query thread */ |
56 | MY_ATTRIBUTE((nonnull, warn_unused_result)); |
57 | /*********************************************************************//** |
58 | Creates an insert node struct. |
59 | @return own: insert node struct */ |
60 | ins_node_t* |
61 | ins_node_create( |
62 | /*============*/ |
63 | ulint ins_type, /*!< in: INS_VALUES, ... */ |
64 | dict_table_t* table, /*!< in: table where to insert */ |
65 | mem_heap_t* heap); /*!< in: mem heap where created */ |
66 | /*********************************************************************//** |
67 | Sets a new row to insert for an INS_DIRECT node. This function is only used |
68 | if we have constructed the row separately, which is a rare case; this |
69 | function is quite slow. */ |
70 | void |
71 | ins_node_set_new_row( |
72 | /*=================*/ |
73 | ins_node_t* node, /*!< in: insert node */ |
74 | dtuple_t* row); /*!< in: new row (or first row) for the node */ |
75 | /***************************************************************//** |
76 | Tries to insert an entry into a clustered index, ignoring foreign key |
77 | constraints. If a record with the same unique key is found, the other |
78 | record is necessarily marked deleted by a committed transaction, or a |
79 | unique key violation error occurs. The delete marked record is then |
80 | updated to an existing record, and we must write an undo log record on |
81 | the delete marked record. |
82 | @retval DB_SUCCESS on success |
83 | @retval DB_LOCK_WAIT on lock wait when !(flags & BTR_NO_LOCKING_FLAG) |
84 | @retval DB_FAIL if retry with BTR_MODIFY_TREE is needed |
85 | @return error code */ |
86 | dberr_t |
87 | row_ins_clust_index_entry_low( |
88 | /*==========================*/ |
89 | ulint flags, /*!< in: undo logging and locking flags */ |
90 | ulint mode, /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE, |
91 | depending on whether we wish optimistic or |
92 | pessimistic descent down the index tree */ |
93 | dict_index_t* index, /*!< in: clustered index */ |
94 | ulint n_uniq, /*!< in: 0 or index->n_uniq */ |
95 | dtuple_t* entry, /*!< in/out: index entry to insert */ |
96 | ulint n_ext, /*!< in: number of externally stored columns */ |
97 | que_thr_t* thr, /*!< in: query thread or NULL */ |
98 | bool dup_chk_only) |
99 | /*!< in: if true, just do duplicate check |
100 | and return. don't execute actual insert. */ |
101 | MY_ATTRIBUTE((warn_unused_result)); |
102 | |
103 | /***************************************************************//** |
104 | Tries to insert an entry into a secondary index. If a record with exactly the |
105 | same fields is found, the other record is necessarily marked deleted. |
106 | It is then unmarked. Otherwise, the entry is just inserted to the index. |
107 | @retval DB_SUCCESS on success |
108 | @retval DB_LOCK_WAIT on lock wait when !(flags & BTR_NO_LOCKING_FLAG) |
109 | @retval DB_FAIL if retry with BTR_MODIFY_TREE is needed |
110 | @return error code */ |
111 | dberr_t |
112 | row_ins_sec_index_entry_low( |
113 | /*========================*/ |
114 | ulint flags, /*!< in: undo logging and locking flags */ |
115 | ulint mode, /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE, |
116 | depending on whether we wish optimistic or |
117 | pessimistic descent down the index tree */ |
118 | dict_index_t* index, /*!< in: secondary index */ |
119 | mem_heap_t* offsets_heap, |
120 | /*!< in/out: memory heap that can be emptied */ |
121 | mem_heap_t* heap, /*!< in/out: memory heap */ |
122 | dtuple_t* entry, /*!< in/out: index entry to insert */ |
123 | trx_id_t trx_id, /*!< in: PAGE_MAX_TRX_ID during |
124 | row_log_table_apply(), or 0 */ |
125 | que_thr_t* thr, /*!< in: query thread */ |
126 | bool dup_chk_only) |
127 | /*!< in: if true, just do duplicate check |
128 | and return. don't execute actual insert. */ |
129 | MY_ATTRIBUTE((warn_unused_result)); |
130 | /** Sets the values of the dtuple fields in entry from the values of appropriate |
131 | columns in row. |
132 | @param[in] index index handler |
133 | @param[out] entry index entry to make |
134 | @param[in] row row */ |
135 | dberr_t |
136 | row_ins_index_entry_set_vals( |
137 | const dict_index_t* index, |
138 | dtuple_t* entry, |
139 | const dtuple_t* row); |
140 | |
141 | /***************************************************************//** |
142 | Inserts an entry into a clustered index. Tries first optimistic, |
143 | then pessimistic descent down the tree. If the entry matches enough |
144 | to a delete marked record, performs the insert by updating or delete |
145 | unmarking the delete marked record. |
146 | @return DB_SUCCESS, DB_LOCK_WAIT, DB_DUPLICATE_KEY, or some other error code */ |
147 | dberr_t |
148 | row_ins_clust_index_entry( |
149 | /*======================*/ |
150 | dict_index_t* index, /*!< in: clustered index */ |
151 | dtuple_t* entry, /*!< in/out: index entry to insert */ |
152 | que_thr_t* thr, /*!< in: query thread */ |
153 | ulint n_ext, /*!< in: number of externally stored columns */ |
154 | bool dup_chk_only) |
155 | /*!< in: if true, just do duplicate check |
156 | and return. don't execute actual insert. */ |
157 | MY_ATTRIBUTE((warn_unused_result)); |
158 | /***************************************************************//** |
159 | Inserts an entry into a secondary index. Tries first optimistic, |
160 | then pessimistic descent down the tree. If the entry matches enough |
161 | to a delete marked record, performs the insert by updating or delete |
162 | unmarking the delete marked record. |
163 | @return DB_SUCCESS, DB_LOCK_WAIT, DB_DUPLICATE_KEY, or some other error code */ |
164 | dberr_t |
165 | row_ins_sec_index_entry( |
166 | /*====================*/ |
167 | dict_index_t* index, /*!< in: secondary index */ |
168 | dtuple_t* entry, /*!< in/out: index entry to insert */ |
169 | que_thr_t* thr, /*!< in: query thread */ |
170 | bool dup_chk_only) |
171 | /*!< in: if true, just do duplicate check |
172 | and return. don't execute actual insert. */ |
173 | MY_ATTRIBUTE((warn_unused_result)); |
174 | /***********************************************************//** |
175 | Inserts a row to a table. This is a high-level function used in |
176 | SQL execution graphs. |
177 | @return query thread to run next or NULL */ |
178 | que_thr_t* |
179 | row_ins_step( |
180 | /*=========*/ |
181 | que_thr_t* thr); /*!< in: query thread */ |
182 | |
183 | /* Insert node structure */ |
184 | |
185 | struct ins_node_t{ |
186 | que_common_t common; /*!< node type: QUE_NODE_INSERT */ |
187 | ulint ins_type;/* INS_VALUES, INS_SEARCHED, or INS_DIRECT */ |
188 | dtuple_t* row; /*!< row to insert */ |
189 | dict_table_t* table; /*!< table where to insert */ |
190 | sel_node_t* select; /*!< select in searched insert */ |
191 | que_node_t* values_list;/* list of expressions to evaluate and |
192 | insert in an INS_VALUES insert */ |
193 | ulint state; /*!< node execution state */ |
194 | dict_index_t* index; /*!< NULL, or the next index where the index |
195 | entry should be inserted */ |
196 | dtuple_t* entry; /*!< NULL, or entry to insert in the index; |
197 | after a successful insert of the entry, |
198 | this should be reset to NULL */ |
199 | UT_LIST_BASE_NODE_T(dtuple_t) |
200 | entry_list;/* list of entries, one for each index */ |
201 | /** buffer for the system columns */ |
202 | byte sys_buf[DATA_ROW_ID_LEN |
203 | + DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN]; |
204 | trx_id_t trx_id; /*!< trx id or the last trx which executed the |
205 | node */ |
206 | byte vers_start_buf[8]; /* Buffers for System Versioning */ |
207 | byte vers_end_buf[8]; /* system fields. */ |
208 | mem_heap_t* entry_sys_heap; |
209 | /* memory heap used as auxiliary storage; |
210 | entry_list and sys fields are stored here; |
211 | if this is NULL, entry list should be created |
212 | and buffers for sys fields in row allocated */ |
213 | dict_index_t* duplicate; |
214 | /* This is the first index that reported |
215 | DB_DUPLICATE_KEY. Used in the case of REPLACE |
216 | or INSERT ... ON DUPLICATE UPDATE. */ |
217 | ulint magic_n; |
218 | }; |
219 | |
220 | #define INS_NODE_MAGIC_N 15849075 |
221 | |
222 | /* Insert node types */ |
223 | #define INS_SEARCHED 0 /* INSERT INTO ... SELECT ... */ |
224 | #define INS_VALUES 1 /* INSERT INTO ... VALUES ... */ |
225 | #define INS_DIRECT 2 /* this is for internal use in dict0crea: |
226 | insert the row directly */ |
227 | |
228 | /* Node execution states */ |
229 | #define INS_NODE_SET_IX_LOCK 1 /* we should set an IX lock on table */ |
230 | #define INS_NODE_ALLOC_ROW_ID 2 /* row id should be allocated */ |
231 | #define INS_NODE_INSERT_ENTRIES 3 /* index entries should be built and |
232 | inserted */ |
233 | #endif |
234 | |