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