MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
fts0config.cc
Go to the documentation of this file.
1 /*****************************************************************************
2 
3 Copyright (c) 2007, 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 /******************************************************************/
26 #include "trx0roll.h"
27 #include "row0sel.h"
28 
29 #include "fts0priv.h"
30 
31 #ifndef UNIV_NONINL
32 #include "fts0types.ic"
33 #include "fts0vlc.ic"
34 #endif
35 
36 /******************************************************************/
39 static
40 ibool
41 fts_config_fetch_value(
42 /*===================*/
43  void* row,
44  void* user_arg)
46 {
47  sel_node_t* node = static_cast<sel_node_t*>(row);
48  fts_string_t* value = static_cast<fts_string_t*>(user_arg);
49 
50  dfield_t* dfield = que_node_get_val(node->select_list);
51  dtype_t* type = dfield_get_type(dfield);
52  ulint len = dfield_get_len(dfield);
53  void* data = dfield_get_data(dfield);
54 
55  ut_a(dtype_get_mtype(type) == DATA_VARCHAR);
56 
57  if (len != UNIV_SQL_NULL) {
58  ulint max_len = ut_min(value->f_len - 1, len);
59 
60  memcpy(value->f_str, data, max_len);
61  value->f_len = max_len;
62  value->f_str[value->f_len] = '\0';
63  }
64 
65  return(TRUE);
66 }
67 
68 /******************************************************************/
72 UNIV_INTERN
73 dberr_t
75 /*=================*/
76  trx_t* trx,
79  const char* name,
81  fts_string_t* value)
83 {
84  pars_info_t* info;
85  que_t* graph;
86  dberr_t error;
87  ulint name_len = strlen(name);
88 
89  info = pars_info_create();
90 
91  *value->f_str = '\0';
92  ut_a(value->f_len > 0);
93 
94  pars_info_bind_function(info, "my_func", fts_config_fetch_value,
95  value);
96 
97  /* The len field of value must be set to the max bytes that
98  it can hold. On a successful read, the len field will be set
99  to the actual number of bytes copied to value. */
100  pars_info_bind_varchar_literal(info, "name", (byte*) name, name_len);
101 
102  fts_table->suffix = "CONFIG";
103 
104  graph = fts_parse_sql(
105  fts_table,
106  info,
107  "DECLARE FUNCTION my_func;\n"
108  "DECLARE CURSOR c IS SELECT value FROM %s"
109  " WHERE key = :name;\n"
110  "BEGIN\n"
111  ""
112  "OPEN c;\n"
113  "WHILE 1 = 1 LOOP\n"
114  " FETCH c INTO my_func();\n"
115  " IF c % NOTFOUND THEN\n"
116  " EXIT;\n"
117  " END IF;\n"
118  "END LOOP;\n"
119  "CLOSE c;");
120 
121  trx->op_info = "getting FTS config value";
122 
123  error = fts_eval_sql(trx, graph);
124 
125  mutex_enter(&dict_sys->mutex);
126  que_graph_free(graph);
127  mutex_exit(&dict_sys->mutex);
128 
129  return(error);
130 }
131 
132 /*********************************************************************/
135 UNIV_INTERN
136 char*
138 /*===============================*/
139  const char* param,
140  const dict_index_t* index)
141 {
142  ulint len;
143  char* name;
144 
145  /* The format of the config name is: name_<index_id>. */
146  len = strlen(param);
147 
148  /* Caller is responsible for deleting name. */
149  name = static_cast<char*>(ut_malloc(
150  len + FTS_AUX_MIN_TABLE_ID_LENGTH + 2));
151  strcpy(name, param);
152  name[len] = '_';
153 
154  fts_write_object_id(index->id, name + len + 1);
155 
156  return(name);
157 }
158 
159 /******************************************************************/
164 UNIV_INTERN
165 dberr_t
167 /*=======================*/
168  trx_t* trx,
170  const char* param,
172  fts_string_t* value)
174 {
175  char* name;
176  dberr_t error;
178 
179  FTS_INIT_FTS_TABLE(&fts_table, "CONFIG", FTS_COMMON_TABLE,
180  index->table);
181 
182  /* We are responsible for free'ing name. */
183  name = fts_config_create_index_param_name(param, index);
184 
185  error = fts_config_get_value(trx, &fts_table, name, value);
186 
187  ut_free(name);
188 
189  return(error);
190 }
191 
192 /******************************************************************/
195 UNIV_INTERN
196 dberr_t
198 /*=================*/
199  trx_t* trx,
202  const char* name,
204  const fts_string_t*
205  value)
206 {
207  pars_info_t* info;
208  que_t* graph;
209  dberr_t error;
210  undo_no_t undo_no;
211  undo_no_t n_rows_updated;
212  ulint name_len = strlen(name);
213 
214  info = pars_info_create();
215 
216  pars_info_bind_varchar_literal(info, "name", (byte*) name, name_len);
217  pars_info_bind_varchar_literal(info, "value",
218  value->f_str, value->f_len);
219 
220  fts_table->suffix = "CONFIG";
221 
222  graph = fts_parse_sql(
223  fts_table, info,
224  "BEGIN UPDATE \"%s\" SET value = :value WHERE key = :name;");
225 
226  trx->op_info = "setting FTS config value";
227 
228  undo_no = trx->undo_no;
229 
230  error = fts_eval_sql(trx, graph);
231 
232  fts_que_graph_free_check_lock(fts_table, NULL, graph);
233 
234  n_rows_updated = trx->undo_no - undo_no;
235 
236  /* Check if we need to do an insert. */
237  if (n_rows_updated == 0) {
238  info = pars_info_create();
239 
241  info, "name", (byte*) name, name_len);
242 
244  info, "value", value->f_str, value->f_len);
245 
246  graph = fts_parse_sql(
247  fts_table, info,
248  "BEGIN\n"
249  "INSERT INTO \"%s\" VALUES(:name, :value);");
250 
251  trx->op_info = "inserting FTS config value";
252 
253  error = fts_eval_sql(trx, graph);
254 
255  fts_que_graph_free_check_lock(fts_table, NULL, graph);
256  }
257 
258  return(error);
259 }
260 
261 /******************************************************************/
264 UNIV_INTERN
265 dberr_t
267 /*=======================*/
268  trx_t* trx,
270  const char* param,
272  fts_string_t* value)
274 {
275  char* name;
276  dberr_t error;
278 
279  FTS_INIT_FTS_TABLE(&fts_table, "CONFIG", FTS_COMMON_TABLE,
280  index->table);
281 
282  /* We are responsible for free'ing name. */
283  name = fts_config_create_index_param_name(param, index);
284 
285  error = fts_config_set_value(trx, &fts_table, name, value);
286 
287  ut_free(name);
288 
289  return(error);
290 }
291 
292 /******************************************************************/
295 UNIV_INTERN
296 dberr_t
298 /*=======================*/
299  trx_t* trx,
301  const char* name,
302  ulint* int_value)
303 {
304  dberr_t error;
305  fts_string_t value;
306 
307  /* We set the length of value to the max bytes it can hold. This
308  information is used by the callback that reads the value.*/
310  value.f_str = static_cast<byte*>(ut_malloc(value.f_len + 1));
311 
312  error = fts_config_get_index_value(trx, index, name, &value);
313 
314  if (UNIV_UNLIKELY(error != DB_SUCCESS)) {
315  ut_print_timestamp(stderr);
316 
317  fprintf(stderr, " InnoDB: Error: (%s) reading `%s'\n",
318  ut_strerr(error), name);
319  } else {
320  *int_value = strtoul((char*) value.f_str, NULL, 10);
321  }
322 
323  ut_free(value.f_str);
324 
325  return(error);
326 }
327 
328 /******************************************************************/
331 UNIV_INTERN
332 dberr_t
334 /*=======================*/
335  trx_t* trx,
337  const char* name,
338  ulint int_value)
339 {
340  dberr_t error;
341  fts_string_t value;
342 
343  /* We set the length of value to the max bytes it can hold. This
344  information is used by the callback that reads the value.*/
346  value.f_str = static_cast<byte*>(ut_malloc(value.f_len + 1));
347 
348  // FIXME: Get rid of snprintf
350 
351  value.f_len = ut_snprintf(
352  (char*) value.f_str, FTS_MAX_INT_LEN, "%lu", int_value);
353 
354  error = fts_config_set_index_value(trx, index, name, &value);
355 
356  if (UNIV_UNLIKELY(error != DB_SUCCESS)) {
357  ut_print_timestamp(stderr);
358 
359  fprintf(stderr, " InnoDB: Error: (%s) writing `%s'\n",
360  ut_strerr(error), name);
361  }
362 
363  ut_free(value.f_str);
364 
365  return(error);
366 }
367 
368 /******************************************************************/
371 UNIV_INTERN
372 dberr_t
374 /*=================*/
375  trx_t* trx,
378  const char* name,
379  ulint* int_value)
380 {
381  dberr_t error;
382  fts_string_t value;
383 
384  /* We set the length of value to the max bytes it can hold. This
385  information is used by the callback that reads the value.*/
387  value.f_str = static_cast<byte*>(ut_malloc(value.f_len + 1));
388 
389  error = fts_config_get_value(trx, fts_table, name, &value);
390 
391  if (UNIV_UNLIKELY(error != DB_SUCCESS)) {
392  ut_print_timestamp(stderr);
393 
394  fprintf(stderr, " InnoDB: Error: (%s) reading `%s'\n",
395  ut_strerr(error), name);
396  } else {
397  *int_value = strtoul((char*) value.f_str, NULL, 10);
398  }
399 
400  ut_free(value.f_str);
401 
402  return(error);
403 }
404 
405 /******************************************************************/
408 UNIV_INTERN
409 dberr_t
411 /*=================*/
412  trx_t* trx,
415  const char* name,
416  ulint int_value)
417 {
418  dberr_t error;
419  fts_string_t value;
420 
421  /* We set the length of value to the max bytes it can hold. This
422  information is used by the callback that reads the value.*/
424  value.f_str = static_cast<byte*>(ut_malloc(value.f_len + 1));
425 
426  // FIXME: Get rid of snprintf
428 
429  value.f_len = snprintf(
430  (char*) value.f_str, FTS_MAX_INT_LEN, "%lu", int_value);
431 
432  error = fts_config_set_value(trx, fts_table, name, &value);
433 
434  if (UNIV_UNLIKELY(error != DB_SUCCESS)) {
435  ut_print_timestamp(stderr);
436 
437  fprintf(stderr, " InnoDB: Error: (%s) writing `%s'\n",
438  ut_strerr(error), name);
439  }
440 
441  ut_free(value.f_str);
442 
443  return(error);
444 }
445 
446 /******************************************************************/
449 UNIV_INTERN
450 dberr_t
452 /*=======================*/
453  trx_t* trx,
456  const char* name,
458  ulint delta)
460 {
461  dberr_t error;
462  fts_string_t value;
463  que_t* graph = NULL;
464  ulint name_len = strlen(name);
465  pars_info_t* info = pars_info_create();
466 
467  /* We set the length of value to the max bytes it can hold. This
468  information is used by the callback that reads the value.*/
470  value.f_str = static_cast<byte*>(ut_malloc(value.f_len + 1));
471 
472  *value.f_str = '\0';
473 
474  pars_info_bind_varchar_literal(info, "name", (byte*) name, name_len);
475 
477  info, "my_func", fts_config_fetch_value, &value);
478 
479  fts_table->suffix = "CONFIG";
480 
481  graph = fts_parse_sql(
482  fts_table, info,
483  "DECLARE FUNCTION my_func;\n"
484  "DECLARE CURSOR c IS SELECT value FROM %s"
485  " WHERE key = :name FOR UPDATE;\n"
486  "BEGIN\n"
487  ""
488  "OPEN c;\n"
489  "WHILE 1 = 1 LOOP\n"
490  " FETCH c INTO my_func();\n"
491  " IF c % NOTFOUND THEN\n"
492  " EXIT;\n"
493  " END IF;\n"
494  "END LOOP;\n"
495  "CLOSE c;");
496 
497  trx->op_info = "read FTS config value";
498 
499  error = fts_eval_sql(trx, graph);
500 
501  fts_que_graph_free_check_lock(fts_table, NULL, graph);
502 
503  if (UNIV_UNLIKELY(error == DB_SUCCESS)) {
504  ulint int_value;
505 
506  int_value = strtoul((char*) value.f_str, NULL, 10);
507 
508  int_value += delta;
509 
511 
512  // FIXME: Get rid of snprintf
513  value.f_len = snprintf(
514  (char*) value.f_str, FTS_MAX_INT_LEN, "%lu", int_value);
515 
516  fts_config_set_value(trx, fts_table, name, &value);
517  }
518 
519  if (UNIV_UNLIKELY(error != DB_SUCCESS)) {
520 
521  ut_print_timestamp(stderr);
522 
523  fprintf(stderr, " InnoDB: Error: (%s) "
524  "while incrementing %s.\n", ut_strerr(error), name);
525  }
526 
527  ut_free(value.f_str);
528 
529  return(error);
530 }
531 
532 /******************************************************************/
535 UNIV_INTERN
536 dberr_t
538 /*=============================*/
539  trx_t* trx,
541  const char* param,
543  ulint delta)
545 {
546  char* name;
547  dberr_t error;
549 
550  FTS_INIT_FTS_TABLE(&fts_table, "CONFIG", FTS_COMMON_TABLE,
551  index->table);
552 
553  /* We are responsible for free'ing name. */
554  name = fts_config_create_index_param_name(param, index);
555 
556  error = fts_config_increment_value(trx, &fts_table, name, delta);
557 
558  ut_free(name);
559 
560  return(error);
561 }
562