MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
handler_api.cc
1 /*****************************************************************************
2 
3 Copyright (c) 2013, Oracle and/or its affiliates. All Rights Reserved.
4 
5 This program is free software; you can redistribute it and/or modify it under
6 the terms of the GNU General Public License as published by the Free Software
7 Foundation; version 2 of the License.
8 
9 This program is distributed in the hope that it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12 
13 You should have received a copy of the GNU General Public License along with
14 this program; if not, write to the Free Software Foundation, Inc.,
15 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
16 
17 ****************************************************************************/
18 
19 /**************************************************/
25 #include "handler_api.h"
26 
27 #include <my_global.h>
28 #include <sql_priv.h>
29 #include <stdlib.h>
30 #include <ctype.h>
31 #include <mysql_version.h>
32 #include <mysql/plugin.h>
33 #include <my_dir.h>
34 #include "my_pthread.h"
35 #include "my_sys.h"
36 #include "m_string.h"
37 #include "sql_plugin.h"
38 #include "table.h"
39 #include "sql_class.h"
40 #include <sql_base.h>
41 #include "key.h"
42 #include "lock.h"
43 #include "transaction.h"
44 #include "sql_handler.h"
45 #include "handler.h"
46 
47 #include "log_event.h"
48 #include "innodb_config.h"
49 #include "binlog.h"
50 
53 extern int write_bin_log(THD *thd, bool clear_error,
54  char const *query, ulong query_length,
55  bool is_trans= false);
56 
58 extern void ha_close_connection(THD* thd);
59 
61 extern int binlog_log_row(TABLE* table,
62  const uchar *before_record,
63  const uchar *after_record,
64  Log_func* log_func);
65 
66 /**********************************************************************/
69 void*
71 /*===============*/
72  bool enable_binlog)
73 {
74  THD* thd;
75 
76  if (enable_binlog && !binlog_enabled()) {
77  fprintf(stderr, " InnoDB_Memcached: MySQL server"
78  " binlog not enabled\n");
79  return(NULL);
80  }
81 
82  my_thread_init();
83  thd = new THD;
84 
85  if (!thd) {
86  return(NULL);
87  }
88 
89  my_net_init(&thd->net,(st_vio*) 0);
90  thd->variables.pseudo_thread_id = thread_id++;
91  thd->thread_id = thd->variables.pseudo_thread_id;
92  thd->thread_stack = reinterpret_cast<char*>(&thd);
93  thd->store_globals();
94 
95  if (enable_binlog) {
96  thd->binlog_setup_trx_data();
97 
98  /* set binlog_format to "ROW" */
99  thd->set_current_stmt_binlog_format_row();
100  }
101 
102  return(thd);
103 }
104 
105 /**********************************************************************/
108 void
110 /*===============*/
111  void* my_thd,
112  void** original_thd)
113 {
114  THD* thd = static_cast<THD*>(my_thd);
115 
116  if (original_thd) {
117  *original_thd = my_pthread_getspecific(THD*, THR_THD);
118  assert(thd->mysys_var);
119  }
120 
121  my_pthread_setspecific_ptr(THR_THD, thd);
122  my_pthread_setspecific_ptr(THR_MALLOC, &thd->mem_root);
123  set_mysys_var(thd->mysys_var);
124 }
125 
126 /**********************************************************************/
129 void*
131 /*===============*/
132  void* my_thd,
133  const char* db_name,
134  const char* table_name,
135  int lock_type)
136 {
137  TABLE_LIST tables;
138  THD* thd = static_cast<THD*>(my_thd);
139  Open_table_context table_ctx(thd, 0);
140  thr_lock_type lock_mode;
141 
142  lock_mode = (lock_type <= HDL_READ)
143  ? TL_READ
144  : TL_WRITE;
145 
146  tables.init_one_table(db_name, strlen(db_name), table_name,
147  strlen(table_name), table_name, lock_mode);
148 
149  tables.mdl_request.init(MDL_key::TABLE, db_name, table_name,
150  (lock_mode > TL_READ)
151  ? MDL_SHARED_WRITE
152  : MDL_SHARED_READ, MDL_TRANSACTION);
153 
154  if (!open_table(thd, &tables, &table_ctx)) {
155  TABLE* table = tables.table;
156  table->use_all_columns();
157  return(table);
158  }
159 
160  return(NULL);
161 }
162 
163 /**********************************************************************/
165 void
167 /*===============*/
168  void* my_thd,
169  void* my_table,
170  int mode)
171 {
172  TABLE* table = static_cast<TABLE*>(my_table);
173  THD* thd = static_cast<THD*>(my_thd);
174  Log_func* log_func;
175 
176  if (thd->get_binlog_table_maps() == 0) {
177  /* Write the table map and BEGIN mark */
178  thd->binlog_write_table_map(
179  static_cast<TABLE*>(my_table), 1, 0);
180  }
181 
182  switch (mode) {
183  case HDL_UPDATE:
184  /* Updated record must be allocated and filled */
185  assert(table->record[1]);
186  log_func = Update_rows_log_event::binlog_row_logging_function;
187  binlog_log_row(table, table->record[1], table->record[0],
188  log_func);
189  break;
190  case HDL_INSERT:
191  log_func = Write_rows_log_event::binlog_row_logging_function;
192  binlog_log_row(table, 0, table->record[0], log_func);
193  break;
194  case HDL_DELETE:
195  log_func = Delete_rows_log_event::binlog_row_logging_function;
196  binlog_log_row(table, table->record[0], 0, log_func);
197  break;
198  default:
199  assert(0);
200  }
201 }
202 
203 /**********************************************************************/
205 void
207 /*==================*/
208  void* my_thd,
209  void* my_table)
210 {
211  THD* thd = static_cast<THD*>(my_thd);
212 
213  if (tc_log) {
214  tc_log->commit(thd, true);
215  }
216  trans_commit_stmt(thd);
217 }
218 
219 /**********************************************************************/
221 void
223 /*====================*/
224  void* my_thd,
225  void* my_table)
226 {
227  THD* thd = static_cast<THD*>(my_thd);
228 
229  /*
230  Memcached plugin doesn't use thd_mark_transaction_to_rollback()
231  on deadlocks. So no special handling for this flag is needed.
232  */
233  if (tc_log) {
234  tc_log->rollback(thd, true);
235  }
236  trans_rollback_stmt(thd);
237 }
238 
239 /**********************************************************************/
241 void
243 /*====================*/
244  void* my_thd,
245  char* table_name)
246 {
247  THD* thd = (THD*) my_thd;
248  char query_str[MAX_FULL_NAME_LEN + 16];
249  int len;
250 
251  memset(query_str, 0, sizeof(query_str));
252 
253  assert(strlen(table_name) < MAX_FULL_NAME_LEN);
254 
255  snprintf(query_str, MAX_FULL_NAME_LEN + 16, "%s %s",
256  "truncate table", table_name);
257 
258  len = strlen(query_str);
259 
260  write_bin_log(thd, 1, query_str, len);
261 }
262 
263 /**********************************************************************/
265 void
267 /*=============*/
268  void* my_table)
269 {
270  empty_record(static_cast<TABLE*>(my_table));
271 }
272 
273 /**********************************************************************/
275 void
277 /*==================*/
278  void* my_table,
279  int field_id,
280  const char* str,
281  int len)
282 {
283  Field* fld;
284  TABLE* table = static_cast<TABLE*>(my_table);
285 
286  fld = table->field[field_id];
287 
288  assert(len >= 0);
289 
290  if (len) {
291  fld->store(str, len, &my_charset_bin);
292  fld->set_notnull();
293  } else {
294  fld->set_null();
295  }
296 }
297 
298 /**********************************************************************/
300 void
302 /*==================*/
303  void* my_table,
304  int field_id,
305  int value,
306  bool unsigned_flag,
307  bool is_null)
308 {
309  Field* fld;
310  TABLE* table = static_cast<TABLE*>(my_table);
311 
312  fld = table->field[field_id];
313 
314  if (is_null) {
315  fld->set_null();
316  } else {
317  fld->set_notnull();
318  fld->store(value, unsigned_flag);
319  }
320 }
321 
322 /**********************************************************************/
324 void
326 /*=====================*/
327  void* my_table,
328  int field_id,
329  unsigned long long
330  value,
331  bool unsigned_flag,
332  bool is_null)
333 {
334  Field* fld;
335  TABLE* table = static_cast<TABLE*>(my_table);
336 
337  fld = table->field[field_id];
338 
339  if (is_null) {
340  fld->set_null();
341  } else {
342  fld->set_notnull();
343  fld->store(value, unsigned_flag);
344  }
345 }
346 
347 /**********************************************************************/
349 void
351 /*=================*/
352  void* my_table)
353 {
354  store_record(static_cast<TABLE*>(my_table), record[1]);
355 }
356 
357 /**********************************************************************/
359 void
361 /*==============*/
362  void* my_thd)
363 {
364  THD* thd = static_cast<THD*>(my_thd);
365 
366  /* destructor will not free it, because net.vio is 0. */
367  net_end(&thd->net);
368 
369  thd->release_resources();
370  delete (thd);
371 
372  /* Don't have a THD anymore */
373  my_pthread_setspecific_ptr(THR_THD, 0);
374 }
375 
376 /**********************************************************************/
379 int
381 /*=================*/
382  void* my_thd,
383  void* my_table,
384  int mode)
385 {
386  int result;
387  THD* thd = static_cast<THD*>(my_thd);
388  TABLE* table = static_cast<TABLE*>(my_table);
389  thr_lock_type lock_mode;
390 
391  lock_mode = (mode & HDL_READ) ? TL_READ : TL_WRITE;
392 
393  if (lock_mode == TL_WRITE) {
394  query_cache_invalidate3(thd, table, 1);
395  table->file->ha_release_auto_increment();
396  }
397 
398  result = trans_commit_stmt(thd);
399 
400  if (thd->lock) {
401  mysql_unlock_tables(thd, thd->lock);
402  }
403 
404  close_mysql_tables(thd);
405  thd->lock = 0;
406 
407  return(result);
408 }
409 
410 /**********************************************************************
411 Following APIs can perform DMLs through MySQL handler interface. They
412 are currently disabled and under HANDLER_API_MEMCACHED define
413 **********************************************************************/
414 
415 #ifdef HANDLER_API_MEMCACHED
416 /**********************************************************************/
419 uchar*
420 handler_select_rec(
421 /*===============*/
422  TABLE* my_table,
423  field_arg_t* srch_args,
424  int idx_to_use)
425 {
426  KEY* key_info = &my_table->key_info[0];
427  uchar* srch_buf = new uchar[key_info->key_length];
428  size_t total_key_len = 0;
429  key_part_map part_map;
430  int result;
431  handler* handle = my_table->file;
432 
433  assert(srch_args->num_arg <= key_info->key_parts);
434 
435  for (unsigned int i = 0; i < key_info->key_parts; i++) {
436  KEY_PART_INFO* key_part;
437 
438  key_part = &key_info->key_part[i];
439 
440  if (i < srch_args->num_arg) {
441  int srch_len = srch_args->len[i];
442 
443  assert(srch_len >= 0);
444 
445  if (srch_len != 0) {
446  key_part->field->set_null();
447  } else {
448  char* srch_value = srch_args->value[i];
449  key_part->field->set_notnull();
450  key_part->field->store(srch_value,
451  srch_len,
452  &my_charset_bin);
453  total_key_len += key_part->store_length;
454  }
455  } else {
456  key_part->field->set_null();
457  }
458  }
459 
460  assert(key_info->key_length >= total_key_len);
461 
462  key_copy(srch_buf, my_table->record[0], key_info, total_key_len);
463  my_table->read_set = &my_table->s->all_set;
464 
465  /* Max column supported is 4096 */
466  assert(srch_args->num_arg <= 4096);
467 
468  part_map = (1 << srch_args->num_arg) - 1;
469 
470  handle->ha_index_or_rnd_end();
471  handle->ha_index_init(idx_to_use, 1);
472 
473  result = handle->index_read_map(my_table->record[0], srch_buf,
474  part_map, HA_READ_KEY_EXACT);
475 
476  delete[] srch_buf;
477 
478  if (!result) {
479  return(my_table->record[0]);
480  }
481 
482  return(NULL);
483 }
484 
485 /**********************************************************************/
488 int
489 handler_insert_rec(
490 /*===============*/
491  TABLE* my_table,
492  field_arg_t* store_args)
493 {
494  uchar* insert_buf;
495  KEY* key_info = &(table->key_info[0]);
496  handler* handle = my_table->file;
497 
498  empty_record(my_table);
499 
500  assert(table->reginfo.lock_type > TL_READ
501  && table->reginfo.lock_type <= TL_WRITE_ONLY);
502 
503  insert_buf = my_table->record[0];
504  memset(insert_buf, 0, my_table->s->null_bytes);
505 
506  assert(store_args->num_arg == key_info->key_parts);
507 
508  for (unsigned int i = 0; i < key_info->key_parts; i++) {
509  Field* fld;
510 
511  fld = table->field[i];
512  if (store_args->len[i]) {
513  fld->store(store_args->value[i],
514  store_args->len[i], &my_charset_bin);
515  fld->set_notnull();
516  } else {
517  fld->set_null();
518  }
519  }
520 
521  return(handle->ha_write_row((uchar *)my_table->record[0]));
522 }
523 
524 /**********************************************************************/
527 int
528 handler_update_rec(
529 /*===============*/
530  TABLE* my_table,
531  field_arg_t* store_args)
532 {
533  uchar* buf = my_table->record[0];
534  handler* handle = my_table->file;
535  KEY* key_info = &my_table->key_info[0];
536 
537  store_record(my_table, record[1]);
538 
539  for (unsigned int i = 0; i < key_info->key_parts; i++) {
540  Field* fld;
541 
542  fld = my_table->field[i];
543  fld->store(store_args->value[i],
544  store_args->len[i], &my_charset_bin);
545  fld->set_notnull();
546  }
547 
548  return(handle->ha_update_row(my_table->record[1], buf));
549 }
550 
551 /**********************************************************************/
554 int
555 handler_delete_rec(
556 /*===============*/
557  TABLE* my_table)
558 {
559  return(my_table->file->ha_delete_row(my_table->record[0]));
560 }
561 
562 /**********************************************************************/
565 MYSQL_LOCK *
566 handler_lock_table(
567 /*===============*/
568  THD* my_thd,
569  TABLE* my_table,
570  thr_lock_type lock_mode)
571 {
572 
573  my_table->reginfo.lock_type = lock_mode;
574  my_thd->lock = mysql_lock_tables(my_thd, &my_table, 1, 0);
575 
576  return(my_thd->lock);
577 }
578 #endif /* HANDLER_API_MEMCACHED */