1 /* 2 * Copyright (c) 2015, 2021, Oracle and/or its affiliates. 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License, version 2.0, 6 * as published by the Free Software Foundation. 7 * 8 * This program is also distributed with certain software (including 9 * but not limited to OpenSSL) that is licensed under separate terms, 10 * as designated in a particular file or component or in included license 11 * documentation. The authors of MySQL hereby grant you an additional 12 * permission to link the program and your derivative works with the 13 * separately licensed software that they have included with MySQL. 14 * 15 * This program is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License, version 2.0, for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with this program; if not, write to the Free Software 22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 23 * 02110-1301 USA 24 */ 25 26 #ifndef _XPL_COMMAND_DELEGATE_H_ 27 #define _XPL_COMMAND_DELEGATE_H_ 28 29 #include "ngs/protocol_encoder.h" 30 31 #include "m_ctype.h" 32 #include "decimal.h" 33 #include "mysql/service_command.h" 34 35 namespace xpl 36 { 37 class Command_delegate 38 { 39 public: 40 struct Field_type 41 { 42 enum_field_types type; 43 unsigned int flags; 44 }; 45 typedef std::vector<Field_type> Field_types; 46 Command_delegate()47 Command_delegate() 48 { 49 reset(); 50 } ~Command_delegate()51 virtual ~Command_delegate() {} 52 get_error()53 ngs::Error_code get_error() const 54 { 55 if (m_sql_errno == 0) 56 return ngs::Error_code(); 57 else 58 return ngs::Error_code(m_sql_errno, m_err_msg, m_sqlstate); 59 } 60 server_status()61 inline uint server_status() const { return m_server_status; } statement_warn_count()62 inline uint statement_warn_count() const { return m_statement_warn_count; } affected_rows()63 inline ulonglong affected_rows() const { return m_affected_rows; } last_insert_id()64 inline ulonglong last_insert_id() const { return m_last_insert_id; } message()65 inline const std::string &message() const { return m_message; } get_field_types()66 inline const Field_types &get_field_types() const { return m_field_types; } 67 killed()68 bool killed() const { return m_killed; } got_eof()69 bool got_eof() const { return m_got_eof; } 70 reset()71 virtual void reset() 72 { 73 m_server_status = 0; 74 m_statement_warn_count = 0; 75 m_affected_rows = 0; 76 m_last_insert_id = 0; 77 m_sql_errno = 0; 78 m_killed = false; 79 m_streaming_metadata = false; 80 m_field_types.clear(); 81 m_got_eof = false; 82 m_message = ""; 83 } 84 callbacks()85 const st_command_service_cbs *callbacks() const 86 { 87 static st_command_service_cbs cbs = { 88 &Command_delegate::call_start_result_metadata, 89 &Command_delegate::call_field_metadata, 90 &Command_delegate::call_end_result_metadata, 91 &Command_delegate::call_start_row, 92 &Command_delegate::call_end_row, 93 &Command_delegate::call_abort_row, 94 &Command_delegate::call_get_client_capabilities, 95 &Command_delegate::call_get_null, 96 &Command_delegate::call_get_integer, 97 &Command_delegate::call_get_longlong, 98 &Command_delegate::call_get_decimal, 99 &Command_delegate::call_get_double, 100 &Command_delegate::call_get_date, 101 &Command_delegate::call_get_time, 102 &Command_delegate::call_get_datetime, 103 &Command_delegate::call_get_string, 104 &Command_delegate::call_handle_ok, 105 &Command_delegate::call_handle_error, 106 &Command_delegate::call_shutdown 107 }; 108 return &cbs; 109 } 110 111 virtual enum cs_text_or_binary representation() const = 0; 112 113 protected: 114 uint m_server_status; 115 uint m_statement_warn_count; 116 ulonglong m_affected_rows; 117 ulonglong m_last_insert_id; 118 std::string m_message; 119 Field_types m_field_types; 120 121 uint m_sql_errno; 122 std::string m_err_msg; 123 std::string m_sqlstate; 124 125 st_command_service_cbs m_callbacks; 126 127 bool m_killed; 128 bool m_streaming_metadata; 129 bool m_got_eof; 130 131 public: 132 /*** Getting metadata ***/ 133 /* 134 Indicates beginning of metadata for the result set 135 136 @param num_cols Number of fields being sent 137 @param flags Flags to alter the metadata sending 138 @param resultcs Charset of the result set 139 140 @returns 141 true an error occured, server will abort the command 142 false ok 143 */ start_result_metadata(uint num_cols,uint flags,const CHARSET_INFO * resultcs)144 virtual int start_result_metadata(uint num_cols, uint flags, 145 const CHARSET_INFO *resultcs) 146 { 147 m_field_types.clear(); 148 return false; 149 } 150 151 /* 152 Field metadata is provided via this callback 153 154 @param field Field's metadata (see field.h) 155 @param charset Field's charset 156 157 @returns 158 true an error occured, server will abort the command 159 false ok 160 */ field_metadata(struct st_send_field * field,const CHARSET_INFO * charset)161 virtual int field_metadata(struct st_send_field *field, 162 const CHARSET_INFO *charset) 163 { 164 Field_type type = { field->type, field->flags }; 165 m_field_types.push_back(type); 166 167 return false; 168 } 169 170 /* 171 Indicates end of metadata for the result set 172 173 @returns 174 true an error occured, server will abort the command 175 false ok 176 */ end_result_metadata(uint server_status,uint warn_count)177 virtual int end_result_metadata(uint server_status, 178 uint warn_count) 179 { 180 return false; 181 } 182 183 /* 184 Indicates the beginning of a new row in the result set/metadata 185 186 @returns 187 true an error occured, server will abort the command 188 false ok 189 */ start_row()190 virtual int start_row() 191 { 192 return false; 193 } 194 195 /* 196 Indicates the end of the current row in the result set/metadata 197 198 @returns 199 true an error occured, server will abort the command 200 false ok 201 */ end_row()202 virtual int end_row() 203 { 204 return false; 205 } 206 207 /* 208 An error occured during execution 209 210 @details This callback indicates that an error occureded during command 211 execution and the partial row should be dropped. Server will raise error 212 and return. 213 214 @returns 215 true an error occured, server will abort the command 216 false ok 217 */ abort_row()218 virtual void abort_row() 219 { 220 } 221 222 /* 223 Return client's capabilities (see mysql_com.h, CLIENT_*) 224 225 @return Bitmap of client's capabilities 226 */ get_client_capabilities()227 virtual ulong get_client_capabilities() 228 { 229 return 0; 230 } 231 232 /****** Getting data ******/ 233 /* 234 Receive NULL value from server 235 236 @returns 237 true an error occured, server will abort the command 238 false ok 239 */ get_null()240 virtual int get_null() 241 { 242 return false; 243 } 244 245 /* 246 Get TINY/SHORT/LONG value from server 247 248 @param value Value received 249 250 @note In order to know which type exactly was received, the plugin must 251 track the metadata that was sent just prior to the result set. 252 253 @returns 254 true an error occured, server will abort the command 255 false ok 256 */ get_integer(longlong value)257 virtual int get_integer(longlong value) 258 { 259 return false; 260 } 261 262 /* 263 Get LONGLONG value from server 264 265 @param value Value received 266 @param unsigned_flag TRUE <=> value is unsigned 267 268 @returns 269 true an error occured, server will abort the command 270 false ok 271 */ get_longlong(longlong value,uint unsigned_flag)272 virtual int get_longlong(longlong value, uint unsigned_flag) 273 { 274 return false; 275 } 276 277 /* 278 Receive DECIMAL value from server 279 280 @param value Value received 281 282 @returns 283 true an error occured, server will abort the command 284 false ok 285 */ get_decimal(const decimal_t * value)286 virtual int get_decimal(const decimal_t * value) 287 { 288 return false; 289 } 290 291 /* 292 Get FLOAT/DOUBLE from server 293 294 @param value Value received 295 @param decimals Number of decimals 296 297 @note In order to know which type exactly was received, the plugin must 298 track the metadata that was sent just prior to the result set. 299 300 @returns 301 true an error occured, server will abort the command 302 false ok 303 */ get_double(double value,uint32 decimals)304 virtual int get_double(double value, uint32 decimals) 305 { 306 return false; 307 } 308 309 /* 310 Get DATE value from server 311 312 @param value Value received 313 314 @returns 315 true an error occured during storing, server will abort the command 316 false ok 317 */ get_date(const MYSQL_TIME * value)318 virtual int get_date(const MYSQL_TIME * value) 319 { 320 return false; 321 } 322 323 /* 324 Get TIME value from server 325 326 @param value Value received 327 @param decimals Number of decimals 328 329 @returns 330 true an error occured during storing, server will abort the command 331 false ok 332 */ get_time(const MYSQL_TIME * value,uint decimals)333 virtual int get_time(const MYSQL_TIME * value, uint decimals) 334 { 335 return false; 336 } 337 338 /* 339 Get DATETIME value from server 340 341 @param value Value received 342 @param decimals Number of decimals 343 344 @returns 345 true an error occured during storing, server will abort the command 346 false ok 347 */ get_datetime(const MYSQL_TIME * value,uint decimals)348 virtual int get_datetime(const MYSQL_TIME * value, uint decimals) 349 { 350 return false; 351 } 352 353 /* 354 Get STRING value from server 355 356 @param value Value received 357 @param length Value's length 358 @param valuecs Value's charset 359 360 @returns 361 true an error occured, server will abort the command 362 false ok 363 */ get_string(const char * const value,size_t length,const CHARSET_INFO * const valuecs)364 virtual int get_string(const char * const value, size_t length, 365 const CHARSET_INFO * const valuecs) 366 { 367 return false; 368 } 369 370 /****** Getting execution status ******/ 371 /* 372 Command ended with success 373 374 @param server_status Status of server (see mysql_com.h, 375 SERVER_STATUS_*) 376 @param statement_warn_count Number of warnings thrown during execution 377 @param affected_rows Number of rows affected by the command 378 @param last_insert_id Last insert id being assigned during execution 379 @param message A message from server 380 */ handle_ok(uint server_status,uint statement_warn_count,ulonglong affected_rows,ulonglong last_insert_id,const char * const message)381 virtual void handle_ok(uint server_status, uint statement_warn_count, 382 ulonglong affected_rows, ulonglong last_insert_id, 383 const char * const message) 384 { 385 m_server_status = server_status; 386 m_statement_warn_count = statement_warn_count; 387 m_affected_rows = affected_rows; 388 m_last_insert_id = last_insert_id; 389 m_message = message ? message : ""; 390 } 391 392 /* 393 Command ended with ERROR 394 395 @param sql_errno Error code 396 @param err_msg Error message 397 @param sqlstate SQL state correspongin to the error code 398 */ handle_error(uint sql_errno,const char * const err_msg,const char * const sqlstate)399 virtual void handle_error(uint sql_errno, const char * const err_msg, 400 const char * const sqlstate) 401 { 402 m_sql_errno = sql_errno; 403 m_err_msg = err_msg ? err_msg : ""; 404 m_sqlstate = sqlstate ? sqlstate : ""; 405 } 406 407 /* 408 Session was shutdown while command was running 409 410 */ shutdown(int flag)411 virtual void shutdown(int flag) 412 { 413 m_killed = true; 414 } 415 416 private: 417 Command_delegate(const Command_delegate &); 418 Command_delegate &operator=(const Command_delegate &); 419 call_start_result_metadata(void * ctx,uint num_cols,uint flags,const CHARSET_INFO * resultcs)420 static int call_start_result_metadata(void *ctx, uint num_cols, uint flags, 421 const CHARSET_INFO *resultcs) 422 { 423 Command_delegate *self = static_cast<Command_delegate*>(ctx); 424 self->m_streaming_metadata = true; 425 return self->start_result_metadata(num_cols, flags, resultcs); 426 } 427 call_field_metadata(void * ctx,struct st_send_field * field,const CHARSET_INFO * charset)428 static int call_field_metadata(void *ctx, struct st_send_field *field, 429 const CHARSET_INFO *charset) 430 { 431 return static_cast<Command_delegate*>(ctx)->field_metadata(field, charset); 432 } 433 call_end_result_metadata(void * ctx,uint server_status,uint warn_count)434 static int call_end_result_metadata(void *ctx, uint server_status, 435 uint warn_count) 436 { 437 Command_delegate *self = static_cast<Command_delegate*>(ctx); 438 int tmp = self->end_result_metadata(server_status, warn_count); 439 self->m_streaming_metadata = false; 440 return tmp; 441 } 442 call_start_row(void * ctx)443 static int call_start_row(void *ctx) 444 { 445 Command_delegate *self = static_cast<Command_delegate*>(ctx); 446 if (self->m_streaming_metadata) 447 return false; 448 return self->start_row(); 449 } 450 call_end_row(void * ctx)451 static int call_end_row(void *ctx) 452 { 453 Command_delegate *self = static_cast<Command_delegate*>(ctx); 454 if (self->m_streaming_metadata) 455 return false; 456 return self->end_row(); 457 } 458 call_abort_row(void * ctx)459 static void call_abort_row(void *ctx) 460 { 461 static_cast<Command_delegate*>(ctx)->abort_row(); 462 } 463 call_get_client_capabilities(void * ctx)464 static ulong call_get_client_capabilities(void *ctx) 465 { 466 return static_cast<Command_delegate*>(ctx)->get_client_capabilities(); 467 } 468 call_get_null(void * ctx)469 static int call_get_null(void * ctx) 470 { 471 return static_cast<Command_delegate*>(ctx)->get_null(); 472 } 473 call_get_integer(void * ctx,longlong value)474 static int call_get_integer(void * ctx, longlong value) 475 { 476 return static_cast<Command_delegate*>(ctx)->get_integer(value); 477 } 478 call_get_longlong(void * ctx,longlong value,uint unsigned_flag)479 static int call_get_longlong(void * ctx, longlong value, uint unsigned_flag) 480 { 481 return static_cast<Command_delegate*>(ctx)->get_longlong(value, unsigned_flag); 482 } 483 call_get_decimal(void * ctx,const decimal_t * value)484 static int call_get_decimal(void * ctx, const decimal_t * value) 485 { 486 return static_cast<Command_delegate*>(ctx)->get_decimal(value); 487 } 488 call_get_double(void * ctx,double value,uint32 decimals)489 static int call_get_double(void * ctx, double value, uint32 decimals) 490 { 491 return static_cast<Command_delegate*>(ctx)->get_double(value, decimals); 492 } 493 call_get_date(void * ctx,const MYSQL_TIME * value)494 static int call_get_date(void * ctx, const MYSQL_TIME * value) 495 { 496 return static_cast<Command_delegate*>(ctx)->get_date(value); 497 } 498 call_get_time(void * ctx,const MYSQL_TIME * value,uint decimals)499 static int call_get_time(void * ctx, const MYSQL_TIME * value, uint decimals) 500 { 501 return static_cast<Command_delegate*>(ctx)->get_time(value, decimals); 502 } 503 call_get_datetime(void * ctx,const MYSQL_TIME * value,uint decimals)504 static int call_get_datetime(void * ctx, const MYSQL_TIME * value, uint decimals) 505 { 506 return static_cast<Command_delegate*>(ctx)->get_datetime(value, decimals); 507 } 508 call_get_string(void * ctx,const char * const value,size_t length,const CHARSET_INFO * const valuecs)509 static int call_get_string(void * ctx, 510 const char * const value, size_t length, 511 const CHARSET_INFO * const valuecs) 512 { 513 return static_cast<Command_delegate*>(ctx)->get_string(value, length, valuecs); 514 } 515 call_handle_ok(void * ctx,uint server_status,uint statement_warn_count,ulonglong affected_rows,ulonglong last_insert_id,const char * const message)516 static void call_handle_ok(void * ctx, 517 uint server_status, uint statement_warn_count, 518 ulonglong affected_rows, ulonglong last_insert_id, 519 const char * const message) 520 { 521 static_cast<Command_delegate*>(ctx)->m_got_eof = (message == NULL); 522 523 static_cast<Command_delegate*>(ctx)->handle_ok(server_status, statement_warn_count, 524 affected_rows, last_insert_id, 525 message); 526 } 527 call_handle_error(void * ctx,uint sql_errno,const char * const err_msg,const char * const sqlstate)528 static void call_handle_error(void * ctx, uint sql_errno, const char * const err_msg, 529 const char * const sqlstate) 530 { 531 static_cast<Command_delegate*>(ctx)->handle_error(sql_errno, err_msg, sqlstate); 532 } 533 call_shutdown(void * ctx,int flag)534 static void call_shutdown(void *ctx, int flag) 535 { 536 static_cast<Command_delegate*>(ctx)->shutdown(flag); 537 } 538 }; 539 } // namespace xpl 540 541 #endif // _XPL_COMMAND_DELEGATE_H_ 542