File: query_result.h

package info (click to toggle)
mysql-8.0 8.0.43-3
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 1,273,924 kB
  • sloc: cpp: 4,684,605; ansic: 412,450; pascal: 108,398; java: 83,641; perl: 30,221; cs: 27,067; sql: 26,594; sh: 24,181; python: 21,816; yacc: 17,169; php: 11,522; xml: 7,388; javascript: 7,076; makefile: 2,194; lex: 1,075; awk: 670; asm: 520; objc: 183; ruby: 97; lisp: 86
file content (307 lines) | stat: -rw-r--r-- 10,148 bytes parent folder | download
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
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
/* Copyright (c) 2015, 2025, 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 QUERY_RESULT_INCLUDED
#define QUERY_RESULT_INCLUDED

#include <assert.h>
#include <sys/types.h>

#include "my_base.h"

#include "my_inttypes.h"
#include "my_io.h"
#include "my_sys.h"
#include "mysql/components/services/bits/my_io_bits.h"  // File
#include "mysqld_error.h"                               // ER_*
#include "sql/sql_list.h"

class Item;
class Item_subselect;
class PT_select_var;
class Query_expression;
class Query_term_set_op;
class Server_side_cursor;
class THD;
struct CHARSET_INFO;
template <class Element_type>
class mem_root_deque;

/*
  This is used to get result from a query
*/

class Query_result {
 protected:
  Query_expression *unit;

 public:
  /**
    Number of records estimated in this result.
    Valid only for materialized derived tables/views.
  */
  ha_rows estimated_rowcount;
  /**
    Cost to execute the subquery which produces this result.
    Valid only for materialized derived tables/views.
  */
  double estimated_cost;

  Query_result() : unit(nullptr), estimated_rowcount(0), estimated_cost(0) {}
  virtual ~Query_result() = default;

  virtual bool needs_file_privilege() const { return false; }

  /**
    Change wrapped Query_result.

    Replace the wrapped query result object with new_result and call
    prepare() on new_result.

    This base class implementation doesn't wrap other Query_results.

    @retval false Success
    @retval true  Error
  */
  virtual bool change_query_result(THD *, Query_result *) { return false; }
  /// @return true if an interceptor object is needed for EXPLAIN
  virtual bool need_explain_interceptor() const { return false; }

  /**
    Perform preparation specific to the query expression or DML statement.

    @returns false if success, true if error
  */
  virtual bool prepare(THD *, const mem_root_deque<Item *> &,
                       Query_expression *u) {
    unit = u;
    return false;
  }

  /**
    Prepare for execution of the query expression or DML statement.

    Generally, this will have an implementation only for outer-most
    Query_block objects, such as data change statements (for preparation
    of the target table(s)) or dump statements (for preparation of target file).

    @returns false if success, true if error
  */
  virtual bool start_execution(THD *) { return false; }

  /// Create table, only needed to support CREATE TABLE ... SELECT
  virtual bool create_table_for_query_block(THD *) { return false; }
  /*
    Because of peculiarities of prepared statements protocol
    we need to know number of columns in the result set (if
    there is a result set) apart from sending columns metadata.
  */
  virtual uint field_count(const mem_root_deque<Item *> &fields) const;
  virtual bool send_result_set_metadata(THD *thd,
                                        const mem_root_deque<Item *> &list,
                                        uint flags) = 0;
  virtual bool send_data(THD *thd, const mem_root_deque<Item *> &items) = 0;
  virtual bool send_eof(THD *thd) = 0;
  /**
    Check if this query result set supports cursors

    @returns false if success, true if error
  */
  virtual bool check_supports_cursor() const {
    my_error(ER_SP_BAD_CURSOR_QUERY, MYF(0));
    return true;
  }
  virtual void abort_result_set(THD *) {}
  /**
    Cleanup after one execution of the unit, to be ready for a next execution
    inside the same statement.
    @returns true if error
  */
  virtual bool reset() {
    assert(false);
    return false;
  }
  /**
    Cleanup after this execution. Completes the execution and resets object
    before next execution of a prepared statement/stored procedure.
  */
  virtual void cleanup() { /* do nothing */
  }

  /**
    Checks if this Query_result intercepts and transforms the result set.

    @return true if it is an interceptor, false otherwise
  */
  virtual bool is_interceptor() const { return false; }

  /// Only overridden (and non-empty) for Query_result_union, q.v.
  virtual void set_limit(ha_rows) {}

  /// @returns server side cursor, if associated with query result
  virtual Server_side_cursor *cursor() const {
    assert(false);
    return nullptr;
  }
};

/*
  Base class for Query_result descendants which intercept and
  transform result set rows. As the rows are not sent to the client,
  sending of result set metadata should be suppressed as well.
*/

class Query_result_interceptor : public Query_result {
 public:
  Query_result_interceptor() : Query_result() {}
  uint field_count(const mem_root_deque<Item *> &) const override { return 0; }
  bool send_result_set_metadata(THD *, const mem_root_deque<Item *> &,
                                uint) override {
    return false;
  }
  bool is_interceptor() const final { return true; }
};

class Query_result_send : public Query_result {
  /**
    True if we have sent result set metadata to the client.
    In this case the client always expects us to end the result
    set with an eof or error packet
  */
  bool is_result_set_started;

 public:
  Query_result_send() : Query_result(), is_result_set_started(false) {}
  bool send_result_set_metadata(THD *thd, const mem_root_deque<Item *> &list,
                                uint flags) override;
  bool send_data(THD *thd, const mem_root_deque<Item *> &items) override;
  bool send_eof(THD *thd) override;
  bool check_supports_cursor() const override { return false; }
  void abort_result_set(THD *thd) override;
  void cleanup() override { is_result_set_started = false; }
};

class sql_exchange;

class Query_result_to_file : public Query_result_interceptor {
 protected:
  sql_exchange *exchange;
  File file;
  IO_CACHE cache;
  ha_rows row_count;
  char path[FN_REFLEN];

 public:
  explicit Query_result_to_file(sql_exchange *ex)
      : Query_result_interceptor(), exchange(ex), file(-1), row_count(0L) {
    path[0] = 0;
  }
  ~Query_result_to_file() override { assert(file < 0); }

  bool needs_file_privilege() const override { return true; }
  bool check_supports_cursor() const override;
  bool send_eof(THD *thd) override;
  void cleanup() override;
};

#define ESCAPE_CHARS "ntrb0ZN"  // keep synchronous with READ_INFO::unescape

/*
 List of all possible characters of a numeric value text representation.
*/
#define NUMERIC_CHARS ".0123456789e+-"

class Query_result_export final : public Query_result_to_file {
  size_t field_term_length;
  int field_sep_char, escape_char, line_sep_char;
  int field_term_char;  // first char of FIELDS TERMINATED BY or MAX_INT
  /*
    The is_ambiguous_field_sep field is true if a value of the field_sep_char
    field is one of the 'n', 't', 'r' etc characters
    (see the READ_INFO::unescape method and the ESCAPE_CHARS constant value).
  */
  bool is_ambiguous_field_sep;
  /*
     The is_ambiguous_field_term is true if field_sep_char contains the first
     char of the FIELDS TERMINATED BY (ENCLOSED BY is empty), and items can
     contain this character.
  */
  bool is_ambiguous_field_term;
  /*
    The is_unsafe_field_sep field is true if a value of the field_sep_char
    field is one of the '0'..'9', '+', '-', '.' and 'e' characters
    (see the NUMERIC_CHARS constant value).
  */
  bool is_unsafe_field_sep;
  bool fixed_row_size;
  const CHARSET_INFO *write_cs;  // output charset
 public:
  explicit Query_result_export(sql_exchange *ex) : Query_result_to_file(ex) {}
  bool prepare(THD *thd, const mem_root_deque<Item *> &list,
               Query_expression *u) override;
  bool start_execution(THD *thd) override;
  bool send_data(THD *thd, const mem_root_deque<Item *> &items) override;
  void cleanup() override;
};

class Query_result_dump : public Query_result_to_file {
 public:
  explicit Query_result_dump(sql_exchange *ex) : Query_result_to_file(ex) {}
  bool prepare(THD *thd, const mem_root_deque<Item *> &list,
               Query_expression *u) override;
  bool start_execution(THD *thd) override;
  bool send_data(THD *thd, const mem_root_deque<Item *> &items) override;
};

class Query_dumpvar final : public Query_result_interceptor {
  ha_rows row_count;

 public:
  List<PT_select_var> var_list;
  Query_dumpvar() : Query_result_interceptor(), row_count(0) {
    var_list.clear();
  }
  bool prepare(THD *thd, const mem_root_deque<Item *> &list,
               Query_expression *u) override;
  bool send_data(THD *thd, const mem_root_deque<Item *> &items) override;
  bool send_eof(THD *thd) override;
  bool check_supports_cursor() const override;
  void cleanup() override { row_count = 0; }
};

/**
  Base class for result from a subquery.
*/

class Query_result_subquery : public Query_result_interceptor {
 protected:
  Item_subselect *item;

 public:
  explicit Query_result_subquery(Item_subselect *item_arg)
      : Query_result_interceptor(), item(item_arg) {}
  bool send_data(THD *thd, const mem_root_deque<Item *> &items) override = 0;
  bool send_eof(THD *) override { return false; }
};

#endif  // QUERY_RESULT_INCLUDED