mariadb/storage/innobase/fts/fts0config.cc
Marko Mäkelä 5684aa220c MDEV-12488 Remove type mismatch in InnoDB printf-like calls
Alias the InnoDB ulint and lint data types to size_t and ssize_t,
which are the standard names for the machine-word-width data types.

Correspondingly, define ULINTPF as "%zu" and introduce ULINTPFx as "%zx".
In this way, better compiler warnings for type mismatch are possible.

Furthermore, use PRIu64 for that 64-bit format, and define
the feature macro __STDC_FORMAT_MACROS to enable it on Red Hat systems.

Fix some errors in error messages, and replace some error messages
with assertions.
Most notably, an IMPORT TABLESPACE error message in InnoDB was
displaying the number of columns instead of the mismatching flags.
2017-04-21 18:03:15 +03:00

438 lines
12 KiB
C++

/*****************************************************************************
Copyright (c) 2007, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*****************************************************************************/
/******************************************************************//**
@file fts/fts0config.cc
Full Text Search configuration table.
Created 2007/5/9 Sunny Bains
***********************************************************************/
#include "trx0roll.h"
#include "row0sel.h"
#include "fts0priv.h"
/******************************************************************//**
Callback function for fetching the config value.
@return always returns TRUE */
static
ibool
fts_config_fetch_value(
/*===================*/
void* row, /*!< in: sel_node_t* */
void* user_arg) /*!< in: pointer to
ib_vector_t */
{
sel_node_t* node = static_cast<sel_node_t*>(row);
fts_string_t* value = static_cast<fts_string_t*>(user_arg);
dfield_t* dfield = que_node_get_val(node->select_list);
dtype_t* type = dfield_get_type(dfield);
ulint len = dfield_get_len(dfield);
void* data = dfield_get_data(dfield);
ut_a(dtype_get_mtype(type) == DATA_VARCHAR);
if (len != UNIV_SQL_NULL) {
ulint max_len = ut_min(value->f_len - 1, len);
memcpy(value->f_str, data, max_len);
value->f_len = max_len;
value->f_str[value->f_len] = '\0';
}
return(TRUE);
}
/******************************************************************//**
Get value from the config table. The caller must ensure that enough
space is allocated for value to hold the column contents.
@return DB_SUCCESS or error code */
dberr_t
fts_config_get_value(
/*=================*/
trx_t* trx, /*!< transaction */
fts_table_t* fts_table, /*!< in: the indexed
FTS table */
const char* name, /*!< in: get config value for
this parameter name */
fts_string_t* value) /*!< out: value read from
config table */
{
pars_info_t* info;
que_t* graph;
dberr_t error;
ulint name_len = strlen(name);
char table_name[MAX_FULL_NAME_LEN];
info = pars_info_create();
*value->f_str = '\0';
ut_a(value->f_len > 0);
pars_info_bind_function(info, "my_func", fts_config_fetch_value,
value);
/* The len field of value must be set to the max bytes that
it can hold. On a successful read, the len field will be set
to the actual number of bytes copied to value. */
pars_info_bind_varchar_literal(info, "name", (byte*) name, name_len);
fts_table->suffix = "CONFIG";
fts_get_table_name(fts_table, table_name);
pars_info_bind_id(info, true, "table_name", table_name);
graph = fts_parse_sql(
fts_table,
info,
"DECLARE FUNCTION my_func;\n"
"DECLARE CURSOR c IS SELECT value FROM $table_name"
" WHERE key = :name;\n"
"BEGIN\n"
""
"OPEN c;\n"
"WHILE 1 = 1 LOOP\n"
" FETCH c INTO my_func();\n"
" IF c % NOTFOUND THEN\n"
" EXIT;\n"
" END IF;\n"
"END LOOP;\n"
"CLOSE c;");
trx->op_info = "getting FTS config value";
error = fts_eval_sql(trx, graph);
mutex_enter(&dict_sys->mutex);
que_graph_free(graph);
mutex_exit(&dict_sys->mutex);
return(error);
}
/*********************************************************************//**
Create the config table name for retrieving index specific value.
@return index config parameter name */
char*
fts_config_create_index_param_name(
/*===============================*/
const char* param, /*!< in: base name of param */
const dict_index_t* index) /*!< in: index for config */
{
ulint len;
char* name;
/* The format of the config name is: name_<index_id>. */
len = strlen(param);
/* Caller is responsible for deleting name. */
name = static_cast<char*>(ut_malloc_nokey(
len + FTS_AUX_MIN_TABLE_ID_LENGTH + 2));
::strcpy(name, param);
name[len] = '_';
fts_write_object_id(index->id, name + len + 1,
DICT_TF2_FLAG_IS_SET(index->table,
DICT_TF2_FTS_AUX_HEX_NAME));
return(name);
}
/******************************************************************//**
Get value specific to an FTS index from the config table. The caller
must ensure that enough space is allocated for value to hold the
column contents.
@return DB_SUCCESS or error code */
dberr_t
fts_config_get_index_value(
/*=======================*/
trx_t* trx, /*!< transaction */
dict_index_t* index, /*!< in: index */
const char* param, /*!< in: get config value for
this parameter name */
fts_string_t* value) /*!< out: value read from
config table */
{
char* name;
dberr_t error;
fts_table_t fts_table;
FTS_INIT_FTS_TABLE(&fts_table, "CONFIG", FTS_COMMON_TABLE,
index->table);
/* We are responsible for free'ing name. */
name = fts_config_create_index_param_name(param, index);
error = fts_config_get_value(trx, &fts_table, name, value);
ut_free(name);
return(error);
}
/******************************************************************//**
Set the value in the config table for name.
@return DB_SUCCESS or error code */
dberr_t
fts_config_set_value(
/*=================*/
trx_t* trx, /*!< transaction */
fts_table_t* fts_table, /*!< in: the indexed
FTS table */
const char* name, /*!< in: get config value for
this parameter name */
const fts_string_t*
value) /*!< in: value to update */
{
pars_info_t* info;
que_t* graph;
dberr_t error;
undo_no_t undo_no;
undo_no_t n_rows_updated;
ulint name_len = strlen(name);
char table_name[MAX_FULL_NAME_LEN];
info = pars_info_create();
pars_info_bind_varchar_literal(info, "name", (byte*) name, name_len);
pars_info_bind_varchar_literal(info, "value",
value->f_str, value->f_len);
fts_table->suffix = "CONFIG";
fts_get_table_name(fts_table, table_name);
pars_info_bind_id(info, true, "table_name", table_name);
graph = fts_parse_sql(
fts_table, info,
"BEGIN UPDATE $table_name SET value = :value"
" WHERE key = :name;");
trx->op_info = "setting FTS config value";
undo_no = trx->undo_no;
error = fts_eval_sql(trx, graph);
fts_que_graph_free_check_lock(fts_table, NULL, graph);
n_rows_updated = trx->undo_no - undo_no;
/* Check if we need to do an insert. */
if (n_rows_updated == 0) {
info = pars_info_create();
pars_info_bind_varchar_literal(
info, "name", (byte*) name, name_len);
pars_info_bind_varchar_literal(
info, "value", value->f_str, value->f_len);
fts_get_table_name(fts_table, table_name);
pars_info_bind_id(info, true, "table_name", table_name);
graph = fts_parse_sql(
fts_table, info,
"BEGIN\n"
"INSERT INTO $table_name VALUES(:name, :value);");
trx->op_info = "inserting FTS config value";
error = fts_eval_sql(trx, graph);
fts_que_graph_free_check_lock(fts_table, NULL, graph);
}
return(error);
}
/******************************************************************//**
Set the value specific to an FTS index in the config table.
@return DB_SUCCESS or error code */
dberr_t
fts_config_set_index_value(
/*=======================*/
trx_t* trx, /*!< transaction */
dict_index_t* index, /*!< in: index */
const char* param, /*!< in: get config value for
this parameter name */
fts_string_t* value) /*!< out: value read from
config table */
{
char* name;
dberr_t error;
fts_table_t fts_table;
FTS_INIT_FTS_TABLE(&fts_table, "CONFIG", FTS_COMMON_TABLE,
index->table);
/* We are responsible for free'ing name. */
name = fts_config_create_index_param_name(param, index);
error = fts_config_set_value(trx, &fts_table, name, value);
ut_free(name);
return(error);
}
#ifdef FTS_OPTIMIZE_DEBUG
/******************************************************************//**
Get an ulint value from the config table.
@return DB_SUCCESS if all OK else error code */
dberr_t
fts_config_get_index_ulint(
/*=======================*/
trx_t* trx, /*!< in: transaction */
dict_index_t* index, /*!< in: FTS index */
const char* name, /*!< in: param name */
ulint* int_value) /*!< out: value */
{
dberr_t error;
fts_string_t value;
/* We set the length of value to the max bytes it can hold. This
information is used by the callback that reads the value.*/
value.f_len = FTS_MAX_CONFIG_VALUE_LEN;
value.f_str = static_cast<byte*>(ut_malloc_nokey(value.f_len + 1));
error = fts_config_get_index_value(trx, index, name, &value);
if (UNIV_UNLIKELY(error != DB_SUCCESS)) {
ib::error() << "(" << ut_strerr(error) << ") reading `"
<< name << "'";
} else {
*int_value = strtoul((char*) value.f_str, NULL, 10);
}
ut_free(value.f_str);
return(error);
}
/******************************************************************//**
Set an ulint value in the config table.
@return DB_SUCCESS if all OK else error code */
dberr_t
fts_config_set_index_ulint(
/*=======================*/
trx_t* trx, /*!< in: transaction */
dict_index_t* index, /*!< in: FTS index */
const char* name, /*!< in: param name */
ulint int_value) /*!< in: value */
{
dberr_t error;
fts_string_t value;
/* We set the length of value to the max bytes it can hold. This
information is used by the callback that reads the value.*/
value.f_len = FTS_MAX_CONFIG_VALUE_LEN;
value.f_str = static_cast<byte*>(ut_malloc_nokey(value.f_len + 1));
// FIXME: Get rid of snprintf
ut_a(FTS_MAX_INT_LEN < FTS_MAX_CONFIG_VALUE_LEN);
value.f_len = ut_snprintf(
(char*) value.f_str, FTS_MAX_INT_LEN, ULINTPF, int_value);
error = fts_config_set_index_value(trx, index, name, &value);
if (UNIV_UNLIKELY(error != DB_SUCCESS)) {
ib::error() << "(" << ut_strerr(error) << ") writing `"
<< name << "'";
}
ut_free(value.f_str);
return(error);
}
#endif /* FTS_OPTIMIZE_DEBUG */
/******************************************************************//**
Get an ulint value from the config table.
@return DB_SUCCESS if all OK else error code */
dberr_t
fts_config_get_ulint(
/*=================*/
trx_t* trx, /*!< in: transaction */
fts_table_t* fts_table, /*!< in: the indexed
FTS table */
const char* name, /*!< in: param name */
ulint* int_value) /*!< out: value */
{
dberr_t error;
fts_string_t value;
/* We set the length of value to the max bytes it can hold. This
information is used by the callback that reads the value.*/
value.f_len = FTS_MAX_CONFIG_VALUE_LEN;
value.f_str = static_cast<byte*>(ut_malloc_nokey(value.f_len + 1));
error = fts_config_get_value(trx, fts_table, name, &value);
if (UNIV_UNLIKELY(error != DB_SUCCESS)) {
ib::error() << "(" << ut_strerr(error) << ") reading `"
<< name << "'";
} else {
*int_value = strtoul((char*) value.f_str, NULL, 10);
}
ut_free(value.f_str);
return(error);
}
/******************************************************************//**
Set an ulint value in the config table.
@return DB_SUCCESS if all OK else error code */
dberr_t
fts_config_set_ulint(
/*=================*/
trx_t* trx, /*!< in: transaction */
fts_table_t* fts_table, /*!< in: the indexed
FTS table */
const char* name, /*!< in: param name */
ulint int_value) /*!< in: value */
{
dberr_t error;
fts_string_t value;
/* We set the length of value to the max bytes it can hold. This
information is used by the callback that reads the value.*/
value.f_len = FTS_MAX_CONFIG_VALUE_LEN;
value.f_str = static_cast<byte*>(ut_malloc_nokey(value.f_len + 1));
ut_a(FTS_MAX_INT_LEN < FTS_MAX_CONFIG_VALUE_LEN);
value.f_len = my_snprintf(
(char*) value.f_str, FTS_MAX_INT_LEN, ULINTPF, int_value);
error = fts_config_set_value(trx, fts_table, name, &value);
if (UNIV_UNLIKELY(error != DB_SUCCESS)) {
ib::error() << "(" << ut_strerr(error) << ") writing `"
<< name << "'";
}
ut_free(value.f_str);
return(error);
}