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