| 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 | |