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