1 /* Copyright (c) 2015, 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_RESULTSET_INCLUDE
24 #define SQL_RESULTSET_INCLUDE
25 
26 #include <mysql/plugin.h>
27 #include <stddef.h>
28 #include <string>
29 #include <vector>
30 
31 #include "my_inttypes.h"
32 
33 struct Field_type {
34   std::string db_name;
35   std::string table_name;
36   std::string org_table_name;
37   std::string col_name;
38   std::string org_col_name;
39   unsigned long length;
40   unsigned int charsetnr;
41   unsigned int flags;
42   unsigned int decimals;
43   enum_field_types type;
44 };
45 
46 struct Field_value {
47   Field_value();
48   Field_value(const Field_value &other);
49   Field_value(const longlong &num, bool unsign = false);
50   Field_value(const decimal_t &decimal);
51   Field_value(const double num);
52   Field_value(const MYSQL_TIME &time);
53   Field_value(const char *str, size_t length);
54   Field_value &operator=(const Field_value &other);
55   ~Field_value();
56   union {
57     longlong v_long;
58     double v_double;
59     decimal_t v_decimal;
60     MYSQL_TIME v_time;
61     char *v_string;
62   } value;
63   size_t v_string_length;
64   bool is_unsigned;
65   bool has_ptr;
66 
67  private:
68   void copy_string(const char *str, size_t length);
69 };
70 
71 class Sql_resultset {
72  public:
Sql_resultset()73   Sql_resultset()
74       : current_row(0),
75         num_cols(0),
76         num_rows(0),
77         num_metarow(0),
78         m_resultcs(nullptr),
79         m_server_status(0),
80         m_warn_count(0),
81         m_affected_rows(0),
82         m_last_insert_id(0),
83         m_sql_errno(0),
84         m_killed(false) {}
85 
~Sql_resultset()86   ~Sql_resultset() { clear(); }
87 
88   /* new row started for resultset */
89   void new_row();
90 
91   /*
92     add new field to existing row
93 
94     @param val Field_value to be stored in resulset
95   */
96   void new_field(Field_value *val);
97 
98   /* truncate and free resultset rows and field values */
99   void clear();
100 
101   /* move row index to next row */
102   bool next();
103 
104   /*
105     move row index to particular row
106 
107     @param row  row position to set
108   */
absolute(int row)109   void absolute(int row) { current_row = row; }
110 
111   /* move row index to first row */
first()112   void first() { current_row = 0; }
113 
114   /* move row index to last row */
last()115   void last() { current_row = num_rows > 0 ? num_rows - 1 : 0; }
116 
117   /* increment number of rows in resulset */
increment_rows()118   void increment_rows() { ++num_rows; }
119 
120   /** Set Methods **/
121 
122   /*
123     set number of rows in resulset
124 
125     @param rows  number of rows in resultset
126   */
set_rows(uint rows)127   void set_rows(uint rows) { num_rows = rows; }
128 
129   /*
130     set number of cols in resulset
131 
132     @param rows  number of cols in resultset
133   */
set_cols(uint cols)134   void set_cols(uint cols) { num_cols = cols; }
135 
136   /**
137     set resultset charset info
138 
139     @param result_cs   charset of resulset
140   */
set_charset(const CHARSET_INFO * result_cs)141   void set_charset(const CHARSET_INFO *result_cs) { m_resultcs = result_cs; }
142 
143   /**
144     set server status. check mysql_com for more details
145 
146     @param server_status   server status
147   */
set_server_status(uint server_status)148   void set_server_status(uint server_status) {
149     m_server_status = server_status;
150   }
151 
152   /**
153     set count of warning issued during command execution
154 
155     @param warn_count  number of warning
156   */
set_warn_count(uint warn_count)157   void set_warn_count(uint warn_count) { m_warn_count = warn_count; }
158 
159   /**
160     set rows affected due to last command execution
161 
162     @param affected_rows  number of rows affected due to last operation
163   */
set_affected_rows(ulonglong affected_rows)164   void set_affected_rows(ulonglong affected_rows) {
165     m_affected_rows = affected_rows;
166   }
167 
168   /**
169     set value of the AUTOINCREMENT column for the last INSERT
170 
171     @param last_insert_id   last inserted value in AUTOINCREMENT column
172   */
set_last_insert_id(ulonglong last_insert_id)173   void set_last_insert_id(ulonglong last_insert_id) {
174     m_last_insert_id = last_insert_id;
175   }
176 
177   /**
178     set client message
179 
180     @param msg  client message
181   */
set_message(std::string msg)182   void set_message(std::string msg) { m_message = msg; }
183 
184   /**
185     set sql error number saved during error in
186     last command execution
187 
188     @param sql_errno  sql error number
189   */
set_sql_errno(uint sql_errno)190   void set_sql_errno(uint sql_errno) { m_sql_errno = sql_errno; }
191 
192   /**
193     set sql error message saved during error in
194     last command execution
195 
196     @param msg  sql error message
197   */
set_err_msg(std::string msg)198   void set_err_msg(std::string msg) { m_err_msg = msg; }
199 
200   /**
201     set sql error state saved during error in
202     last command execution
203 
204     @param state  sql error state
205   */
set_sqlstate(std::string state)206   void set_sqlstate(std::string state) { m_sqlstate = state; }
207 
208   /* Session was shutdown while command was running */
set_killed()209   void set_killed() { m_killed = true; /* purecov: inspected */ }
210 
211   /** Get Methods **/
212 
213   /*
214     get number of rows in resulset
215 
216     @return number of rows in resultset
217   */
get_rows()218   uint get_rows() { return num_rows; }
219 
220   /*
221     get number of cols in resulset
222 
223     @return number of cols in resultset
224   */
get_cols()225   uint get_cols() { return num_cols; }
226 
227   /**
228     get resultset charset info
229 
230     @return charset info
231   */
get_charset()232   const CHARSET_INFO *get_charset() { return m_resultcs; }
233 
234   /**
235     get server status. check mysql_com for more details
236 
237     @return server status
238   */
get_server_status()239   uint get_server_status() { return m_server_status; }
240 
241   /**
242     get count of warning issued during command execution
243 
244     @return warn_count
245   */
get_warn_count()246   uint get_warn_count() { return m_warn_count; }
247 
248   /**
249     return rows affected dure to last command execution
250 
251     @return affected_row
252   */
get_affected_rows()253   ulonglong get_affected_rows() { return m_affected_rows; }
254 
255   /**
256     get value of the AUTOINCREMENT column for the last INSERT
257 
258     @return the sql error number
259   */
get_last_insert_id()260   ulonglong get_last_insert_id() { return m_last_insert_id; }
261 
262   /**
263     get client message
264 
265     @return message
266   */
get_message()267   std::string get_message() { return m_message; }
268 
269   /** Getting error info **/
270   /**
271     get sql error number saved during error in last command execution
272 
273     @return the sql error number
274       @retval 0      OK
275       @retval !=0    SQL Error Number
276   */
sql_errno()277   uint sql_errno() { return m_sql_errno; }
278 
279   /**
280     get sql error message saved during error in last command execution
281 
282     @return the sql error message
283   */
err_msg()284   std::string err_msg() { return m_err_msg; /* purecov: inspected */ }
285 
286   /**
287     get sql error state saved during error in last command execution
288 
289     @return the sql error state
290   */
sqlstate()291   std::string sqlstate() { return m_sqlstate; }
292 
293   /* get long field type column */
getLong(uint columnIndex)294   longlong getLong(uint columnIndex) {
295     return result_value[current_row][columnIndex]->value.v_long;
296   }
297 
298   /* get decimal field type column */
getDecimal(uint columnIndex)299   decimal_t getDecimal(uint columnIndex) {
300     return result_value[current_row][columnIndex]->value.v_decimal;
301   }
302 
303   /* get double field type column */
getDouble(uint columnIndex)304   double getDouble(uint columnIndex) {
305     return result_value[current_row][columnIndex]->value.v_double;
306   }
307 
308   /* get time field type column */
getTime(uint columnIndex)309   MYSQL_TIME getTime(uint columnIndex) {
310     return result_value[current_row][columnIndex]->value.v_time;
311   }
312 
313   /* get string field type column */
getString(uint columnIndex)314   char *getString(uint columnIndex) {
315     if (result_value[current_row][columnIndex] != nullptr)
316       return result_value[current_row][columnIndex]->value.v_string;
317     return const_cast<char *>("");
318   }
319 
320   /* resultset metadata functions */
321 
322   /* set metadata info */
set_metadata(Field_type ftype)323   void set_metadata(Field_type ftype) {
324     result_meta.push_back(ftype);
325     ++num_metarow;
326   }
327 
328   /* get database */
329   std::string get_database(uint rowIndex = 0) {
330     return result_meta[rowIndex].db_name;
331   }
332 
333   /* get table alias */
334   std::string get_table(uint rowIndex = 0) {
335     return result_meta[rowIndex].table_name;
336   }
337 
338   /* get original table */
339   std::string get_org_table(uint rowIndex = 0) {
340     return result_meta[rowIndex].org_table_name;
341   }
342 
343   /* get column name alias */
344   std::string get_column_name(uint rowIndex = 0) {
345     return result_meta[rowIndex].col_name;
346   }
347 
348   /* get original column name */
349   std::string get_org_column_name(uint rowIndex = 0) {
350     return result_meta[rowIndex].org_col_name;
351   }
352 
353   /* get field width */
354   unsigned long get_length(uint rowIndex = 0) {
355     return result_meta[rowIndex].length;
356   }
357 
358   /* get field charsetnr */
359   unsigned int get_charsetnr(uint rowIndex = 0) {
360     return result_meta[rowIndex].charsetnr;
361   }
362 
363   /*
364     get field flag.
365     Check
366       https://dev.mysql.com/doc/refman/5.7/en/c-api-data-structures.html
367     for all flags
368   */
369   unsigned int get_flags(uint rowIndex = 0) {
370     return result_meta[rowIndex].flags;
371   }
372 
373   /* get the number of decimals for numeric fields */
374   unsigned int get_decimals(uint rowIndex = 0) {
375     return result_meta[rowIndex].decimals;
376   }
377 
378   /* get field type. Check enum enum_field_types for whole list */
379   enum_field_types get_field_type(uint rowIndex = 0) {
380     return result_meta[rowIndex].type;
381   }
382 
383   /*
384     get status whether session was shutdown while command was running
385 
386     @return session shutdown status
387       @retval true   session was stopped
388       @retval false  session was not stopped
389   */
get_killed_status()390   bool get_killed_status() { return m_killed; }
391 
392  private:
393   /* resultset store */
394   std::vector<std::vector<Field_value *>> result_value;
395   /* metadata store */
396   std::vector<Field_type> result_meta;
397 
398   int current_row;  /* current row position */
399   uint num_cols;    /* number of columns in resultset/metadata */
400   uint num_rows;    /* number of rows in resultset */
401   uint num_metarow; /* number of rows in metadata */
402 
403   const CHARSET_INFO *m_resultcs; /* result charset */
404 
405   uint m_server_status; /* server status */
406   uint m_warn_count;    /* warning count */
407 
408   /* rows affected mostly useful for command like update */
409   ulonglong m_affected_rows;
410   ulonglong m_last_insert_id; /* last auto-increment column value */
411   std::string m_message;      /* client message */
412 
413   uint m_sql_errno;       /* sql error number */
414   std::string m_err_msg;  /* sql error message */
415   std::string m_sqlstate; /* sql error state */
416 
417   bool m_killed; /* session killed status */
418 };
419 
420 #endif  // SQL_RESULTSET_INCLUDE
421