mirror of
https://github.com/MariaDB/server.git
synced 2025-01-22 14:54:20 +01:00
5684aa220c
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.
438 lines
12 KiB
C++
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);
|
|
}
|