1 /* Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
2 
3    This program is free software; you can redistribute it and/or modify
4    it under the terms of the GNU General Public License, version 2.0,
5    as published by the Free Software Foundation.
6 
7    This program is also distributed with certain software (including
8    but not limited to OpenSSL) that is licensed under separate terms,
9    as designated in a particular file or component or in included license
10    documentation.  The authors of MySQL hereby grant you an additional
11    permission to link the program and your derivative works with the
12    separately licensed software that they have included with MySQL.
13 
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License, version 2.0, for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
22 
23 #ifndef SQL_UPDATE_INCLUDED
24 #define SQL_UPDATE_INCLUDED
25 
26 #include <stddef.h>
27 #include <sys/types.h>
28 
29 #include "my_base.h"
30 #include "my_sqlcommand.h"
31 #include "sql/query_result.h"  // Query_result_interceptor
32 #include "sql/sql_cmd_dml.h"   // Sql_cmd_dml
33 #include "sql/sql_list.h"
34 
35 class COPY_INFO;
36 class Copy_field;
37 class Item;
38 class SELECT_LEX_UNIT;
39 class Select_lex_visitor;
40 class THD;
41 class Temp_table_param;
42 struct TABLE;
43 struct TABLE_LIST;
44 
45 bool records_are_comparable(const TABLE *table);
46 bool compare_records(const TABLE *table);
47 bool should_switch_to_multi_table_if_subqueries(const THD *thd,
48                                                 const SELECT_LEX *select,
49                                                 const TABLE_LIST *table_list);
50 
51 class Query_result_update final : public Query_result_interceptor {
52   /// Number of tables being updated
53   uint update_table_count;
54   /// Pointer to list of updated tables, linked via 'next_local'
55   TABLE_LIST *update_tables;
56   /// Array of references to temporary tables used to store cached updates
57   TABLE **tmp_tables;
58   /// Array of parameter structs for creation of temporary tables
59   Temp_table_param *tmp_table_param;
60   /// The first table in the join operation
61   TABLE *main_table;
62   /**
63     In a multi-table update, this is equal to the first table in the join
64     operation (#main_table) if that table can be updated on the fly while
65     scanning it. It is `nullptr` otherwise.
66 
67     @see safe_update_on_fly
68   */
69   TABLE *table_to_update;
70   /// Number of rows found that matches join and WHERE conditions
71   ha_rows found_rows;
72   /// Number of rows actually updated, in all affected tables
73   ha_rows updated_rows;
74   /// List of pointers to fields to update, in order from statement
75   List<Item> *fields;
76   /// List of pointers to values to update with, in order from statement
77   List<Item> *values;
78   /// The fields list decomposed into separate lists per table
79   List<Item> **fields_for_table;
80   /// The values list decomposed into separate lists per table
81   List<Item> **values_for_table;
82   /**
83    List of tables referenced in the CHECK OPTION condition of
84    the updated view excluding the updated table.
85   */
86   List<TABLE> unupdated_check_opt_tables;
87   /// ???
88   Copy_field *copy_field;
89   /// Length of the copy_field array.
90   size_t max_fields{0};
91   /// True if the full update operation is complete
92   bool update_completed;
93   /// True if all tables to be updated are transactional.
94   bool trans_safe;
95   /// True if the update operation has made a change in a transactional table
96   bool transactional_tables;
97   /**
98      error handling (rollback and binlogging) can happen in send_eof()
99      so that afterward send_error() needs to find out that.
100   */
101   bool error_handled;
102 
103   /**
104      Array of update operations, arranged per _updated_ table. For each
105      _updated_ table in the multiple table update statement, a COPY_INFO
106      pointer is present at the table's position in this array.
107 
108      The array is allocated and populated during Query_result_update::prepare().
109      The position that each table is assigned is also given here and is stored
110      in the member TABLE::pos_in_table_list::shared. However, this is a publicly
111      available field, so nothing can be trusted about its integrity.
112 
113      This member is NULL when the Query_result_update is created.
114 
115      @see Query_result_update::prepare
116   */
117   COPY_INFO **update_operations;
118 
119  public:
Query_result_update(List<Item> * field_list,List<Item> * value_list)120   Query_result_update(List<Item> *field_list, List<Item> *value_list)
121       : Query_result_interceptor(),
122         update_table_count(0),
123         update_tables(nullptr),
124         tmp_tables(nullptr),
125         main_table(nullptr),
126         table_to_update(nullptr),
127         found_rows(0),
128         updated_rows(0),
129         fields(field_list),
130         values(value_list),
131         copy_field(nullptr),
132         update_completed(false),
133         trans_safe(true),
134         transactional_tables(false),
135         error_handled(false),
136         update_operations(nullptr) {}
need_explain_interceptor()137   bool need_explain_interceptor() const override { return true; }
138   bool prepare(THD *thd, List<Item> &list, SELECT_LEX_UNIT *u) override;
139   bool optimize() override;
start_execution(THD *)140   bool start_execution(THD *) override {
141     update_completed = false;
142     return false;
143   }
144   bool send_data(THD *thd, List<Item> &items) override;
145   void send_error(THD *thd, uint errcode, const char *err) override;
146   bool do_updates(THD *thd);
147   bool send_eof(THD *thd) override;
148   void abort_result_set(THD *thd) override;
149   void cleanup(THD *thd) override;
150 
151   bool immediate_update(TABLE_LIST *t) const override;
152 };
153 
154 class Sql_cmd_update final : public Sql_cmd_dml {
155  public:
Sql_cmd_update(bool multitable_arg,List<Item> * update_values)156   Sql_cmd_update(bool multitable_arg, List<Item> *update_values)
157       : multitable(multitable_arg), update_value_list(update_values) {}
158 
sql_command_code()159   enum_sql_command sql_command_code() const override {
160     return multitable ? SQLCOM_UPDATE_MULTI : SQLCOM_UPDATE;
161   }
162 
is_single_table_plan()163   bool is_single_table_plan() const override { return !multitable; }
164 
165  protected:
166   bool precheck(THD *thd) override;
167 
168   bool prepare_inner(THD *thd) override;
169 
170   bool execute_inner(THD *thd) override;
171 
172  private:
173   bool update_single_table(THD *thd);
174 
175   bool multitable;
176 
177   bool accept(THD *thd, Select_lex_visitor *visitor) override;
178 
179  public:
180   List<Item> *update_value_list;
181 };
182 
183 #endif /* SQL_UPDATE_INCLUDED */
184