-
Notifications
You must be signed in to change notification settings - Fork 4k
/
Copy pathsql_update.h
191 lines (159 loc) · 7.14 KB
/
sql_update.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
/* Copyright (c) 2006, 2024, Oracle and/or its affiliates.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License, version 2.0,
as published by the Free Software Foundation.
This program is designed to work with certain software (including
but not limited to OpenSSL) that is licensed under separate terms,
as designated in a particular file or component or in included license
documentation. The authors of MySQL hereby grant you an additional
permission to link the program and your derivative works with the
separately licensed software that they have either included with
the program or referenced in the documentation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License, version 2.0, for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
#ifndef SQL_UPDATE_INCLUDED
#define SQL_UPDATE_INCLUDED
#include <sys/types.h>
#include "mem_root_deque.h"
#include "my_alloc.h"
#include "my_sqlcommand.h"
#include "my_table_map.h"
#include "sql/query_result.h" // Query_result_interceptor
#include "sql/sql_cmd_dml.h" // Sql_cmd_dml
#include "sql/sql_list.h"
#include "sql/thr_malloc.h"
class COPY_INFO;
class Copy_field;
class Item;
class JOIN;
class Query_block;
class Query_expression;
class RowIterator;
class Select_lex_visitor;
class THD;
class Temp_table_param;
struct TABLE;
class Table_ref;
bool records_are_comparable(const TABLE *table);
bool compare_records(const TABLE *table);
bool should_switch_to_multi_table_if_subqueries(const THD *thd,
const Query_block *select,
const Table_ref *table_list);
class Query_result_update final : public Query_result_interceptor {
/// Number of tables being updated
uint update_table_count{0};
/// Pointer to list of updated tables, linked via 'next_local'
Table_ref *update_tables{nullptr};
/// Array of references to temporary tables used to store cached updates
TABLE **tmp_tables{nullptr};
/// Array of parameter structs for creation of temporary tables
Temp_table_param *tmp_table_param{nullptr};
/// The first table in the join operation
TABLE *main_table{nullptr};
/**
In a multi-table update, this is equal to the first table in the join
operation (#main_table) if that table can be updated on the fly while
scanning it. It is `nullptr` otherwise.
@see safe_update_on_fly
*/
TABLE *table_to_update{nullptr};
/// List of pointers to fields to update, in order from statement
const mem_root_deque<Item *> *fields;
/// List of pointers to values to update with, in order from statement
const mem_root_deque<Item *> *values;
/// The fields list decomposed into separate lists per table
mem_root_deque<Item *> **fields_for_table;
/// The values list decomposed into separate lists per table
mem_root_deque<Item *> **values_for_table;
/**
List of tables referenced in the CHECK OPTION condition of
the updated view excluding the updated table.
*/
List<TABLE> unupdated_check_opt_tables;
/// ???
Copy_field *copy_field{nullptr};
/**
Array of update operations, arranged per _updated_ table. For each
_updated_ table in the multiple table update statement, a COPY_INFO
pointer is present at the table's position in this array.
The array is allocated and populated during Query_result_update::prepare().
The position that each table is assigned is also given here and is stored
in the member TABLE::pos_in_table_list::shared. However, this is a publicly
available field, so nothing can be trusted about its integrity.
This member is NULL when the Query_result_update is created.
@see Query_result_update::prepare
*/
COPY_INFO **update_operations{nullptr};
public:
Query_result_update(mem_root_deque<Item *> *field_list,
mem_root_deque<Item *> *value_list)
: Query_result_interceptor(), fields(field_list), values(value_list) {}
bool need_explain_interceptor() const override { return true; }
bool prepare(THD *thd, const mem_root_deque<Item *> &list,
Query_expression *u) override;
bool optimize();
bool start_execution(THD *thd) override;
bool send_data(THD *thd, const mem_root_deque<Item *> &items) override;
bool do_updates(THD *thd);
bool send_eof(THD *thd) override;
void cleanup() override;
unique_ptr_destroy_only<RowIterator> create_iterator(
THD *thd, MEM_ROOT *mem_root,
unique_ptr_destroy_only<RowIterator> source);
};
class Sql_cmd_update final : public Sql_cmd_dml {
public:
Sql_cmd_update(bool multitable_arg, mem_root_deque<Item *> *update_values)
: multitable(multitable_arg),
original_fields(*THR_MALLOC),
update_value_list(update_values) {}
enum_sql_command sql_command_code() const override {
return multitable ? SQLCOM_UPDATE_MULTI : SQLCOM_UPDATE;
}
bool is_single_table_plan() const override { return !multitable; }
protected:
bool precheck(THD *thd) override;
bool check_privileges(THD *thd) override;
bool prepare_inner(THD *thd) override;
bool execute_inner(THD *thd) override;
private:
bool update_single_table(THD *thd);
bool multitable;
/// Bitmap of all tables which are to be updated
table_map tables_for_update{0};
bool accept(THD *thd, Select_lex_visitor *visitor) override;
/// Convert list of fields to update to base table fields
bool make_base_table_fields(THD *thd, mem_root_deque<Item *> *items);
public:
/// The original list of fields to update, used for privilege checking
mem_root_deque<Item *> original_fields;
/// The values used to update fields
mem_root_deque<Item *> *update_value_list;
};
/// Find out which of the target tables can be updated immediately while
/// scanning. This is used by the old optimizer *after* the plan has been
/// created. The hypergraph optimizer does not use this function, as it makes
/// the decision about immediate update *during* planning, not after planning.
///
/// @param join The top-level JOIN object of the UPDATE statement.
/// @param single_target True if the UPDATE statement has exactly
/// one target table.
/// @return Map of tables to update while scanning.
table_map GetImmediateUpdateTable(const JOIN *join, bool single_target);
/// Makes the TABLE and handler objects ready for being used in an UPDATE
/// statement. Called at the beginning of each execution.
///
/// @param join The top-level JOIN object of the UPDATE operation.
/// @return true on error.
bool FinalizeOptimizationForUpdate(JOIN *join);
/// Creates an UpdateRowsIterator which updates the rows returned by the given
/// "source" iterator.
unique_ptr_destroy_only<RowIterator> CreateUpdateRowsIterator(
THD *thd, MEM_ROOT *mem_root, JOIN *join,
unique_ptr_destroy_only<RowIterator> source);
#endif /* SQL_UPDATE_INCLUDED */