Commit e00bf403 authored by marko@hundin.mysql.fi's avatar marko@hundin.mysql.fi

InnoDB cleanup: fixing buffer overflows and quoting of quotes

parent ebc7b6ba
......@@ -37,67 +37,6 @@ static
dtuple_t*
dict_create_sys_tables_tuple(
/*=========================*/
/* out: the tuple which should be inserted */
dict_table_t* table, /* in: table */
mem_heap_t* heap); /* in: memory heap from which the memory for
the built tuple is allocated */
/*********************************************************************
Based on a table object, this function builds the entry to be inserted
in the SYS_COLUMNS system table. */
static
dtuple_t*
dict_create_sys_columns_tuple(
/*==========================*/
/* out: the tuple which should be inserted */
dict_table_t* table, /* in: table */
ulint i, /* in: column number */
mem_heap_t* heap); /* in: memory heap from which the memory for
the built tuple is allocated */
/*********************************************************************
Based on an index object, this function builds the entry to be inserted
in the SYS_INDEXES system table. */
static
dtuple_t*
dict_create_sys_indexes_tuple(
/*==========================*/
/* out: the tuple which should be inserted */
dict_index_t* index, /* in: index */
mem_heap_t* heap, /* in: memory heap from which the memory for
the built tuple is allocated */
trx_t* trx); /* in: transaction handle */
/*********************************************************************
Based on an index object, this function builds the entry to be inserted
in the SYS_FIELDS system table. */
static
dtuple_t*
dict_create_sys_fields_tuple(
/*=========================*/
/* out: the tuple which should be inserted */
dict_index_t* index, /* in: index */
ulint i, /* in: field number */
mem_heap_t* heap); /* in: memory heap from which the memory for
the built tuple is allocated */
/*********************************************************************
Creates the tuple with which the index entry is searched for
writing the index tree root page number, if such a tree is created. */
static
dtuple_t*
dict_create_search_tuple(
/*=====================*/
/* out: the tuple for search */
dtuple_t* tuple, /* in: the tuple inserted in the SYS_INDEXES
table */
mem_heap_t* heap); /* in: memory heap from which the memory for
the built tuple is allocated */
/*********************************************************************
Based on a table object, this function builds the entry to be inserted
in the SYS_TABLES system table. */
static
dtuple_t*
dict_create_sys_tables_tuple(
/*=========================*/
/* out: the tuple which should be inserted */
dict_table_t* table, /* in: table */
mem_heap_t* heap) /* in: memory heap from which the memory for
the built tuple is allocated */
......@@ -331,9 +270,8 @@ dict_create_sys_indexes_tuple(
/*==========================*/
/* out: the tuple which should be inserted */
dict_index_t* index, /* in: index */
mem_heap_t* heap, /* in: memory heap from which the memory for
mem_heap_t* heap) /* in: memory heap from which the memory for
the built tuple is allocated */
trx_t* trx) /* in: transaction handle */
{
dict_table_t* sys_indexes;
dict_table_t* table;
......@@ -341,7 +279,6 @@ dict_create_sys_indexes_tuple(
dfield_t* dfield;
byte* ptr;
UT_NOT_USED(trx);
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex)));
#endif /* UNIV_SYNC_DEBUG */
......@@ -387,7 +324,9 @@ dict_create_sys_indexes_tuple(
dfield_set_data(dfield, ptr, 4);
/* 7: SPACE --------------------------*/
ut_a(DICT_SYS_INDEXES_SPACE_NO_FIELD == 7);
#if DICT_SYS_INDEXES_SPACE_NO_FIELD != 7
#error "DICT_SYS_INDEXES_SPACE_NO_FIELD != 7"
#endif
dfield = dtuple_get_nth_field(entry, 5);
......@@ -397,7 +336,9 @@ dict_create_sys_indexes_tuple(
dfield_set_data(dfield, ptr, 4);
/* 8: PAGE_NO --------------------------*/
ut_a(DICT_SYS_INDEXES_PAGE_NO_FIELD == 8);
#if DICT_SYS_INDEXES_PAGE_NO_FIELD != 8
#error "DICT_SYS_INDEXES_PAGE_NO_FIELD != 8"
#endif
dfield = dtuple_get_nth_field(entry, 6);
......@@ -565,8 +506,7 @@ dict_build_index_def_step(
index->page_no = FIL_NULL;
row = dict_create_sys_indexes_tuple(index, node->heap,
thr_get_trx(thr));
row = dict_create_sys_indexes_tuple(index, node->heap);
node->ind_row = row;
ins_node_set_new_row(node->ind_def, row);
......@@ -602,7 +542,6 @@ ulint
dict_create_index_tree_step(
/*========================*/
/* out: DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
que_thr_t* thr, /* in: query thread */
ind_node_t* node) /* in: index create node */
{
dict_index_t* index;
......@@ -615,7 +554,6 @@ dict_create_index_tree_step(
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex)));
#endif /* UNIV_SYNC_DEBUG */
UT_NOT_USED(thr);
index = node->index;
table = node->table;
......@@ -963,7 +901,7 @@ dict_create_index_step(
if (node->state == INDEX_CREATE_INDEX_TREE) {
err = dict_create_index_tree_step(thr, node);
err = dict_create_index_tree_step(node);
if (err != DB_SUCCESS) {
......@@ -1166,11 +1104,22 @@ dict_create_add_foreigns_to_dictionary(
que_t* graph;
ulint number = start_id + 1;
ulint len;
ulint namelen;
ulint error;
char* ebuf = dict_foreign_err_buf;
ulint i;
char buf[10000];
char* sql;
char* sqlend;
/* This procedure builds an InnoDB stored procedure which will insert
the necessary rows into SYS_FOREIGN and SYS_FOREIGN_COLS. */
static const char str1[] = "PROCEDURE ADD_FOREIGN_DEFS_PROC () IS\n"
"BEGIN\n"
"INSERT INTO SYS_FOREIGN VALUES(";
static const char str2[] = ");\n";
static const char str3[] =
"INSERT INTO SYS_FOREIGN_COLS VALUES(";
static const char str4[] =
"COMMIT WORK;\n"
"END;\n";
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex)));
......@@ -1190,58 +1139,75 @@ loop:
return(DB_SUCCESS);
}
/* Build an InnoDB stored procedure which will insert the necessary
rows to SYS_FOREIGN and SYS_FOREIGN_COLS */
len = 0;
len += sprintf(buf,
"PROCEDURE ADD_FOREIGN_DEFS_PROC () IS\n"
"BEGIN\n");
namelen = strlen(table->name);
ut_a(namelen < MAX_TABLE_NAME_LEN);
if (foreign->id == NULL) {
/* Generate a new constraint id */
foreign->id = mem_heap_alloc(foreign->heap, namelen + 20);
ulint namelen = strlen(table->name);
char* id = mem_heap_alloc(foreign->heap, namelen + 20);
/* no overflow if number < 1e13 */
sprintf(foreign->id, "%s_ibfk_%lu", table->name, number);
number++;
sprintf(id, "%s_ibfk_%lu", table->name, number++);
foreign->id = id;
}
ut_a(strlen(foreign->id) < MAX_IDENTIFIER_LEN);
ut_a(len < (sizeof buf)
- 46 - 2 * MAX_TABLE_NAME_LEN - MAX_IDENTIFIER_LEN - 20);
len = (sizeof str1) + (sizeof str2) + (sizeof str4) - 3
+ 9/* ' and , chars */ + 10/* 32-bit integer */
+ ut_strlenq(foreign->id, '\'') * (foreign->n_fields + 1)
+ ut_strlenq(table->name, '\'')
+ ut_strlenq(foreign->referenced_table_name, '\'');
for (i = 0; i < foreign->n_fields; i++) {
len += 9/* ' and , chars */ + 10/* 32-bit integer */
+ (sizeof str3) + (sizeof str2) - 2
+ ut_strlenq(foreign->foreign_col_names[i], '\'')
+ ut_strlenq(foreign->referenced_col_names[i], '\'');
}
len += sprintf(buf + len,
"INSERT INTO SYS_FOREIGN VALUES('%s', '%s', '%s', %lu);\n",
foreign->id,
table->name,
foreign->referenced_table_name,
foreign->n_fields
+ (foreign->type << 24));
sql = sqlend = mem_alloc(len + 1);
/* INSERT INTO SYS_FOREIGN VALUES(...); */
memcpy(sqlend, str1, (sizeof str1) - 1);
sqlend += (sizeof str1) - 1;
*sqlend++ = '\'';
sqlend = ut_strcpyq(sqlend, '\'', foreign->id);
*sqlend++ = '\'', *sqlend++ = ',', *sqlend++ = '\'';
sqlend = ut_strcpyq(sqlend, '\'', table->name);
*sqlend++ = '\'', *sqlend++ = ',', *sqlend++ = '\'';
sqlend = ut_strcpyq(sqlend, '\'', foreign->referenced_table_name);
*sqlend++ = '\'', *sqlend++ = ',';
sqlend += sprintf(sqlend, "%010lu",
foreign->n_fields + (foreign->type << 24));
memcpy(sqlend, str2, (sizeof str2) - 1);
sqlend += (sizeof str2) - 1;
for (i = 0; i < foreign->n_fields; i++) {
ut_a(len < (sizeof buf)
- 51 - 2 * MAX_COLUMN_NAME_LEN
- MAX_IDENTIFIER_LEN - 20);
len += sprintf(buf + len,
"INSERT INTO SYS_FOREIGN_COLS VALUES('%s', %lu, '%s', '%s');\n",
foreign->id,
i,
foreign->foreign_col_names[i],
foreign->referenced_col_names[i]);
/* INSERT INTO SYS_FOREIGN_COLS VALUES(...); */
memcpy(sqlend, str3, (sizeof str3) - 1);
sqlend += (sizeof str3) - 1;
*sqlend++ = '\'';
sqlend = ut_strcpyq(sqlend, '\'', foreign->id);
*sqlend++ = '\''; *sqlend++ = ',';
sqlend += sprintf(sqlend, "%010lu", i);
*sqlend++ = ','; *sqlend++ = '\'';
sqlend = ut_strcpyq(sqlend, '\'',
foreign->foreign_col_names[i]);
*sqlend++ = '\''; *sqlend++ = ','; *sqlend++ = '\'';
sqlend = ut_strcpyq(sqlend, '\'',
foreign->referenced_col_names[i]);
*sqlend++ = '\'';
memcpy(sqlend, str2, (sizeof str2) - 1);
sqlend += (sizeof str2) - 1;
}
ut_a(len < (sizeof buf) - 19);
len += sprintf(buf + len,"COMMIT WORK;\nEND;\n");
memcpy(sqlend, str4, sizeof str4);
sqlend += sizeof str4;
graph = pars_sql(buf);
ut_a(sqlend == sql + len + 1);
graph = pars_sql(sql);
ut_a(graph);
mem_free(sql);
graph->trx = trx;
trx->graph = NULL;
......
......@@ -49,7 +49,10 @@ rw_lock_t dict_operation_lock; /* table create, drop, etc. reserve
hash table fixed size in bytes */
#define DICT_POOL_PER_VARYING 4 /* buffer pool max size per data
dictionary varying size in bytes */
/* Identifies generated InnoDB foreign key names */
static char dict_ibfk[] = "_ibfk_";
/**************************************************************************
Adds a column to the data dictionary hash table. */
static
......@@ -129,16 +132,7 @@ dict_index_build_internal_non_clust(
dict_index_t* index); /* in: user representation of a non-clustered
index */
/**************************************************************************
In an index tree, finds the index corresponding to a record in the tree. */
UNIV_INLINE
dict_index_t*
dict_tree_find_index_low(
/*=====================*/
/* out: index */
dict_tree_t* tree, /* in: index tree */
rec_t* rec); /* in: record for which to find correct index */
/**************************************************************************
Removes a foreign constraint struct from the dictionet cache. */
Removes a foreign constraint struct from the dictionary cache. */
static
void
dict_foreign_remove_from_cache(
......@@ -187,26 +181,18 @@ static
ibool
dict_tables_have_same_db(
/*=====================*/
/* out: TRUE if same db name */
char* name1, /* in: table name in the form dbname '/' tablename */
char* name2) /* in: table name in the form dbname '/' tablename */
/* out: TRUE if same db name */
const char* name1, /* in: table name in the form
dbname '/' tablename */
const char* name2) /* in: table name in the form
dbname '/' tablename */
{
ulint i;
for (i = 0; i < 100000; i++) {
if (name1[i] == '/' && name2[i] == '/') {
for (; *name1 == *name2; name1++, name2++) {
if (*name1 == '/') {
return(TRUE);
}
if (name1[i] != name2[i]) {
return(FALSE);
}
ut_a(*name1); /* the names must contain '/' */
}
ut_error;
return(FALSE);
}
......@@ -219,18 +205,11 @@ dict_remove_db_name(
/* out: table name */
char* name) /* in: table name in the form dbname '/' tablename */
{
ulint i;
for (i = 0; i < 100000 ; i++) {
if (name[i] == '/') {
return(name + i + 1);
}
}
ut_error;
return(NULL);
char* s;
s = strchr(name, '/');
ut_a(s);
if (s) s++;
return(s);
}
/************************************************************************
......@@ -239,21 +218,14 @@ Get the database name length in a table name. */
ulint
dict_get_db_name_len(
/*=================*/
/* out: database name length */
char* name) /* in: table name in the form dbname '/' tablename */
/* out: database name length */
const char* name) /* in: table name in the form
dbname '/' tablename */
{
ulint i;
for (i = 0; i < 100000 ; i++) {
if (name[i] == '/') {
return(i);
}
}
ut_error;
return(0);
const char* s;
s = strchr(name, '/');
ut_a(s);
return(s - name);
}
/************************************************************************
......@@ -889,7 +861,6 @@ dict_table_rename_in_cache(
dict_index_t* index;
ulint fold;
ulint old_size;
char* name_buf;
char* old_name;
ulint i;
......@@ -923,16 +894,9 @@ dict_table_rename_in_cache(
/* Remove table from the hash tables of tables */
HASH_DELETE(dict_table_t, name_hash, dict_sys->table_hash,
ut_fold_string(table->name), table);
old_name = mem_heap_alloc(table->heap, ut_strlen(table->name) + 1);
ut_strcpy(old_name, table->name);
name_buf = mem_heap_alloc(table->heap, ut_strlen(new_name) + 1);
ut_memcpy(name_buf, new_name, ut_strlen(new_name) + 1);
old_name = mem_heap_strdup(table->heap, table->name);
table->name = mem_heap_strdup(table->heap, new_name);
table->name = name_buf;
/* Add table to hash table of tables */
HASH_INSERT(dict_table_t, name_hash, dict_sys->table_hash, fold,
table);
......@@ -1000,30 +964,27 @@ dict_table_rename_in_cache(
ut_strlen(table->name) + 1);
}
sprintf(foreign->foreign_table_name, "%s", table->name);
strcpy(foreign->foreign_table_name, table->name);
if (strchr(foreign->id, '/')) {
ulint db_len;
char old_id[2000];
char* old_id;
/* This is a >= 4.0.18 format id */
ut_a(ut_strlen(foreign->id) < 1999);
ut_strcpy(old_id, foreign->id);
old_id = mem_strdup(foreign->id);
if (ut_strlen(foreign->id) > ut_strlen(old_name)
+ ut_strlen("_ibfk_")
+ ((sizeof dict_ibfk) - 1)
&& 0 == ut_memcmp(foreign->id, old_name,
ut_strlen(old_name))
&& 0 == ut_memcmp(
foreign->id + ut_strlen(old_name),
(char*)"_ibfk_", ut_strlen("_ibfk_"))) {
dict_ibfk, (sizeof dict_ibfk) - 1)) {
/* This is a generated >= 4.0.18 format id */
if (ut_strlen(table->name)
> ut_strlen(old_name)) {
if (ut_strlen(table->name) > ut_strlen(old_name)) {
foreign->id = mem_heap_alloc(
foreign->heap,
ut_strlen(table->name)
......@@ -1032,7 +993,8 @@ dict_table_rename_in_cache(
/* Replace the prefix 'databasename/tablename'
with the new names */
sprintf(foreign->id, "%s%s", table->name,
strcpy(foreign->id, table->name);
strcat(foreign->id,
old_id + ut_strlen(old_name));
} else {
/* This is a >= 4.0.18 format id where the user
......@@ -1052,9 +1014,11 @@ dict_table_rename_in_cache(
ut_memcpy(foreign->id, table->name, db_len);
sprintf(foreign->id + db_len, "%s",
strcpy(foreign->id + db_len,
dict_remove_db_name(old_id));
}
mem_free(old_id);
}
foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
......@@ -1073,7 +1037,7 @@ dict_table_rename_in_cache(
ut_strlen(table->name) + 1);
}
sprintf(foreign->referenced_table_name, "%s", table->name);
strcpy(foreign->referenced_table_name, table->name);
foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
}
......@@ -1971,7 +1935,7 @@ dict_foreign_find_index(
/*====================*/
/* out: matching index, NULL if not found */
dict_table_t* table, /* in: table */
char** columns,/* in: array of column names */
const char** columns,/* in: array of column names */
ulint n_cols, /* in: number of columns */
dict_index_t* types_idx)/* in: NULL or an index to whose types the
column types must match */
......@@ -1996,11 +1960,8 @@ dict_foreign_find_index(
break;
}
if (ut_strlen(columns[i]) !=
ut_strlen(col_name)
|| 0 != ut_cmp_in_lower_case(columns[i],
col_name,
ut_strlen(col_name))) {
if (0 != ut_cmp_in_lower_case(columns[i],
col_name)) {
break;
}
......@@ -2072,9 +2033,9 @@ dict_foreign_add_to_cache(
if (for_in_cache->referenced_table == NULL && ref_table) {
index = dict_foreign_find_index(ref_table,
for_in_cache->referenced_col_names,
for_in_cache->n_fields,
for_in_cache->foreign_index);
(const char**) for_in_cache->referenced_col_names,
for_in_cache->n_fields,
for_in_cache->foreign_index);
if (index == NULL) {
mutex_enter(&dict_foreign_err_mutex);
......@@ -2113,9 +2074,9 @@ dict_foreign_add_to_cache(
if (for_in_cache->foreign_table == NULL && for_table) {
index = dict_foreign_find_index(for_table,
for_in_cache->foreign_col_names,
for_in_cache->n_fields,
for_in_cache->referenced_index);
(const char**) for_in_cache->foreign_col_names,
for_in_cache->n_fields,
for_in_cache->referenced_index);
if (index == NULL) {
mutex_enter(&dict_foreign_err_mutex);
......@@ -2165,12 +2126,12 @@ Scans from pointer onwards. Stops if is at the start of a copy of
'string' where characters are compared without case sensitivity. Stops
also at '\0'. */
static
char*
const char*
dict_scan_to(
/*=========*/
/* out: scanned up to this */
char* ptr, /* in: scan from */
const char *string) /* in: look for this */
const char* ptr, /* in: scan from */
const char* string) /* in: look for this */
{
ibool success;
ulint i;
......@@ -2202,18 +2163,18 @@ loop:
/*************************************************************************
Accepts a specified string. Comparisons are case-insensitive. */
char*
const char*
dict_accept(
/*========*/
/* out: if string was accepted, the pointer
is moved after that, else ptr is returned */
char* ptr, /* in: scan from this */
const char* string,/* in: accept only this string as the next
non-whitespace string */
ibool* success)/* out: TRUE if accepted */
/* out: if string was accepted, the pointer
is moved after that, else ptr is returned */
const char* ptr, /* in: scan from this */
const char* string, /* in: accept only this string as the next
non-whitespace string */
ibool* success)/* out: TRUE if accepted */
{
char* old_ptr = ptr;
char* old_ptr2;
const char* old_ptr = ptr;
const char* old_ptr2;
*success = FALSE;
......@@ -2238,21 +2199,27 @@ dict_accept(
Scans an id. For the lexical definition of an 'id', see the code below.
Strips backquotes or double quotes from around the id. */
static
char*
const char*
dict_scan_id(
/*=========*/
/* out: scanned to */
char* ptr, /* in: scanned to */
char** start, /* out: start of the id; NULL if no id was
const char* ptr, /* in: scanned to */
mem_heap_t* heap, /* in: heap where to allocate the id
(NULL=id will not be allocated, but it
will point to string near ptr) */
const char** id, /* out,own: the id; NULL if no id was
scannable */
ulint* len, /* out: length of the id */
ibool accept_also_dot)/* in: TRUE if also a dot can appear in a
ibool accept_also_dot)
/* in: TRUE if also a dot can appear in a
non-quoted id; in a quoted id it can appear
always */
{
char quote = '\0';
char quote = '\0';
ulint len = 0;
const char* s;
char* d;
*start = NULL;
*id = NULL;
while (isspace(*ptr)) {
ptr++;
......@@ -2266,12 +2233,23 @@ dict_scan_id(
if (*ptr == '`' || *ptr == '"') {
quote = *ptr++;
}
*start = ptr;
s = ptr;
if (quote) {
while (*ptr != quote && *ptr != '\0') {
for (;;) {
if (!*ptr) {
/* Syntax error */
return(ptr);
}
if (*ptr == quote) {
ptr++;
if (*ptr != quote) {
break;
}
}
ptr++;
len++;
}
} else {
while (!isspace(*ptr) && *ptr != '(' && *ptr != ')'
......@@ -2280,17 +2258,25 @@ dict_scan_id(
ptr++;
}
len = ptr - s;
}
*len = (ulint) (ptr - *start);
if (quote) {
if (*ptr == quote) {
ptr++;
} else {
/* Syntax error */
*start = NULL;
if (quote && heap) {
*id = d = mem_heap_alloc(heap, len + 1);
while (len--) {
if ((*d++ = *s++) == quote) {
s++;
}
}
*d++ = 0;
ut_a(*s == quote);
ut_a(s + 1 == ptr);
} else if (heap) {
*id = mem_heap_strdupl(heap, s, len);
} else {
/* no heap given: id will point to source string */
*id = (char*) s;
}
return(ptr);
......@@ -2299,26 +2285,26 @@ dict_scan_id(
/*************************************************************************
Tries to scan a column name. */
static
char*
const char*
dict_scan_col(
/*==========*/
/* out: scanned to */
char* ptr, /* in: scanned to */
const char* ptr, /* in: scanned to */
ibool* success,/* out: TRUE if success */
dict_table_t* table, /* in: table in which the column is */
dict_col_t** column, /* out: pointer to column if success */
char** column_name,/* out: pointer to column->name if
success */
ulint* column_name_len)/* out: column name length */
mem_heap_t* heap, /* in: heap where to allocate the name */
const char** name) /* out,own: the column name; NULL if no name
was scannable */
{
dict_col_t* col;
ulint i;
*success = FALSE;
ptr = dict_scan_id(ptr, column_name, column_name_len, TRUE);
ptr = dict_scan_id(ptr, heap, name, TRUE);
if (column_name == NULL) {
if (*name == NULL) {
return(ptr); /* Syntax error */
}
......@@ -2331,15 +2317,12 @@ dict_scan_col(
col = dict_table_get_nth_col(table, i);
if (ut_strlen(col->name) == *column_name_len
&& 0 == ut_cmp_in_lower_case(col->name,
*column_name,
*column_name_len)) {
if (0 == ut_cmp_in_lower_case(col->name, *name)) {
/* Found */
*success = TRUE;
*column = col;
*column_name = col->name;
strcpy((char*) *name, col->name);
break;
}
......@@ -2352,33 +2335,31 @@ dict_scan_col(
/*************************************************************************
Scans the referenced table name from an SQL string. */
static
char*
const char*
dict_scan_table_name(
/*=================*/
/* out: scanned to */
char* ptr, /* in: scanned to */
const char* ptr, /* in: scanned to */
dict_table_t** table, /* out: table object or NULL */
char* name, /* in: foreign key table name */
const char* name, /* in: foreign key table name */
ibool* success,/* out: TRUE if ok name found */
char* second_table_name)/* in/out: buffer where to store
the referenced table name; must be at least
2500 bytes */
mem_heap_t* heap, /* in: heap where to allocate the id */
const char** ref_name)/* out,own: the referenced table name;
NULL if no name was scannable */
{
char* database_name = NULL;
ulint database_name_len = 999999999; /* init to a dummy value to
suppress a compiler warning */
char* table_name = NULL;
ulint table_name_len;
char* scanned_id;
ulint scanned_id_len;
ulint i;
const char* database_name = NULL;
ulint database_name_len = 0;
const char* table_name = NULL;
ulint table_name_len;
const char* scan_name;
char* ref;
*success = FALSE;
*table = NULL;
ptr = dict_scan_id(ptr, &scanned_id, &scanned_id_len, FALSE);
ptr = dict_scan_id(ptr, heap, &scan_name, FALSE);
if (scanned_id == NULL) {
if (scan_name == NULL) {
return(ptr); /* Syntax error */
}
......@@ -2388,10 +2369,10 @@ dict_scan_table_name(
ptr++;
database_name = scanned_id;
database_name_len = scanned_id_len;
database_name = scan_name;
database_name_len = strlen(database_name);
ptr = dict_scan_id(ptr, &table_name, &table_name_len, FALSE);
ptr = dict_scan_id(ptr, heap, &table_name, FALSE);
if (table_name == NULL) {
......@@ -2405,65 +2386,57 @@ dict_scan_table_name(
... REFERENCES `databasename.tablename` ...
starting from 4.0.18 it is
... REFERENCES `databasename`.`tablename` ... */
for (i = 0; i < scanned_id_len; i++) {
if (scanned_id[i] == '.') {
database_name = scanned_id;
database_name_len = i;
scanned_id = scanned_id + i + 1;
scanned_id_len -= i + 1;
const char* s;
for (s = scan_name; *s; s++) {
if (*s == '.') {
database_name = scan_name;
database_name_len = s - scan_name;
scan_name = ++s;
break;/* to do: multiple dots? */
}
}
table_name = scanned_id;
table_name_len = scanned_id_len;
table_name = scan_name;
}
if (database_name == NULL) {
/* Use the database name of the foreign key table */
database_name = name;
database_name_len = dict_get_db_name_len(name);
}
if (table_name_len + database_name_len > 2000) {
table_name_len = strlen(table_name);
ref = mem_heap_alloc(heap, database_name_len + table_name_len + 2);
return(ptr); /* Too long name */
}
#ifdef __WIN__
ut_cpy_in_lower_case(second_table_name, database_name,
database_name_len);
ut_cpy_in_lower_case(ref, database_name, database_name_len);
#else
if (srv_lower_case_table_names) {
ut_cpy_in_lower_case(second_table_name, database_name,
database_name_len);
ut_cpy_in_lower_case(ref, database_name, database_name_len);
} else {
ut_memcpy(second_table_name, database_name,
database_name_len);
memcpy(ref, database_name, database_name_len);
}
#endif
second_table_name[database_name_len] = '/';
(ref)[database_name_len] = '/';
#ifdef __WIN__
ut_cpy_in_lower_case(second_table_name + database_name_len + 1,
table_name, table_name_len);
ut_cpy_in_lower_case(ref + database_name_len + 1,
table_name, table_name_len + 1);
#else
if (srv_lower_case_table_names) {
ut_cpy_in_lower_case(second_table_name + database_name_len + 1,
table_name, table_name_len);
ut_cpy_in_lower_case(ref + database_name_len + 1,
table_name, table_name_len + 1);
} else {
ut_memcpy(second_table_name + database_name_len + 1,
table_name, table_name_len);
strcpy(ref + database_name_len + 1, table_name);
}
#endif
second_table_name[database_name_len + 1 + table_name_len] = '\0';
*success = TRUE;
*table = dict_table_get_low(second_table_name);
*ref_name = ref;
*table = dict_table_get_low(ref);
return(ptr);
}
......@@ -2471,20 +2444,19 @@ dict_scan_table_name(
/*************************************************************************
Skips one id. The id is allowed to contain also '.'. */
static
char*
const char*
dict_skip_word(
/*===========*/
/* out: scanned to */
char* ptr, /* in: scanned to */
ibool* success)/* out: TRUE if success, FALSE if just spaces left in
string or a syntax error */
/* out: scanned to */
const char* ptr, /* in: scanned to */
ibool* success)/* out: TRUE if success, FALSE if just spaces
left in string or a syntax error */
{
char* start;
ulint len;
const char* start;
*success = FALSE;
ptr = dict_scan_id(ptr, &start, &len, TRUE);
ptr = dict_scan_id(ptr, NULL, &start, TRUE);
if (start) {
*success = TRUE;
......@@ -2528,10 +2500,10 @@ scan_more:
}
if (*sptr == '#'
|| (strlen(sptr) >= 3 && 0 == memcmp("-- ", sptr, 3))) {
|| (0 == memcmp("-- ", sptr, 3))) {
for (;;) {
/* In Unix a newline is 0x0D while in Windows
it is 0x0A followed by 0x0D */
/* In Unix a newline is 0x0A while in Windows
it is 0x0D followed by 0x0A */
if (*sptr == (char)0x0A
|| *sptr == (char)0x0D
......@@ -2544,10 +2516,9 @@ scan_more:
}
}
if (strlen(sptr) >= 2 && *sptr == '/' && *(sptr + 1) == '*') {
if (*sptr == '/' && *(sptr + 1) == '*') {
for (;;) {
if (strlen(sptr) >= 2
&& *sptr == '*' && *(sptr + 1) == '/') {
if (*sptr == '*' && *(sptr + 1) == '/') {
sptr += 2;
......@@ -2586,27 +2557,28 @@ dict_table_get_highest_foreign_id(
char* endp;
ulint biggest_id = 0;
ulint id;
ulint len;
ut_a(table);
len = ut_strlen(table->name);
foreign = UT_LIST_GET_FIRST(table->foreign_list);
while (foreign) {
if (ut_strlen(foreign->id) > ut_strlen("_ibfk_")
+ ut_strlen(table->name)
&& 0 == ut_memcmp(foreign->id, table->name,
ut_strlen(table->name))
&& 0 == ut_memcmp(foreign->id + ut_strlen(table->name),
(char*)"_ibfk_", ut_strlen("_ibfk_"))) {
if (ut_strlen(foreign->id) > ((sizeof dict_ibfk) - 1) + len
&& 0 == ut_memcmp(foreign->id, table->name, len)
&& 0 == ut_memcmp(foreign->id + len,
dict_ibfk, (sizeof dict_ibfk) - 1)) {
/* It is of the >= 4.0.18 format */
id = strtoul(foreign->id + ut_strlen(table->name)
+ ut_strlen("_ibfk_"),
id = strtoul(foreign->id + len + ((sizeof dict_ibfk) - 1),
&endp, 10);
ut_a(id != biggest_id);
if (*endp == '\0') {
ut_a(id != biggest_id);
if (id > biggest_id) {
biggest_id = id;
if (id > biggest_id) {
biggest_id = id;
}
}
}
......@@ -2622,10 +2594,11 @@ static
void
dict_foreign_report_syntax_err(
/*===========================*/
char* name, /* in: table name */
char* start_of_latest_foreign,/* in: start of the foreign key clause
const char* name, /* in: table name */
const char* start_of_latest_foreign,
/* in: start of the foreign key clause
in the SQL string */
char* ptr) /* in: place of the syntax error */
const char* ptr) /* in: place of the syntax error */
{
char* buf = dict_foreign_err_buf;
......@@ -2652,14 +2625,16 @@ ulint
dict_create_foreign_constraints_low(
/*================================*/
/* out: error code or DB_SUCCESS */
trx_t* trx, /* in: transaction */
char* sql_string, /* in: table create or ALTER TABLE
statement where foreign keys are declared like:
trx_t* trx, /* in: transaction */
mem_heap_t* heap, /* in: memory heap */
const char* sql_string,
/* in: CREATE TABLE or ALTER TABLE statement
where foreign keys are declared like:
FOREIGN KEY (a, b) REFERENCES table2(c, d),
table2 can be written also with the database
name before it: test.table2; the default
database is the database of parameter name */
char* name) /* in: table full name in the normalized form
const char* name) /* in: table full name in the normalized form
database_name/table_name */
{
dict_table_t* table;
......@@ -2668,31 +2643,28 @@ dict_create_foreign_constraints_low(
ulint highest_id_so_far = 0;
dict_index_t* index;
dict_foreign_t* foreign;
char* ptr = sql_string;
char* start_of_latest_foreign = sql_string;
const char* ptr = sql_string;
const char* start_of_latest_foreign = sql_string;
char* buf = dict_foreign_err_buf;
char* constraint_name; /* this is NOT a null-
terminated string */
ulint constraint_name_len;
const char* constraint_name;
ibool success;
ulint error;
char* ptr1;
char* ptr2;
const char* ptr1;
const char* ptr2;
ulint i;
ulint j;
ibool is_on_delete;
ulint n_on_deletes;
ulint n_on_updates;
dict_col_t* columns[500];
char* column_names[500];
ulint column_name_lens[500];
char referenced_table_name[2500];
const char* column_names[500];
const char* referenced_table_name;
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex)));
#endif /* UNIV_SYNC_DEBUG */
table = dict_table_get_low(name);
table = dict_table_get_low((char*) name);
if (table == NULL) {
mutex_enter(&dict_foreign_err_mutex);
......@@ -2700,7 +2672,7 @@ dict_create_foreign_constraints_low(
sprintf(buf + strlen(buf),
" Error in foreign key constraint of table %.500s.\n"
"Cannot find the table from the internal data dictionary of InnoDB.\n"
"Create table statement:\n%.2000\n", name, sql_string);
"Create table statement:\n%.2000s\n", name, sql_string);
ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN);
mutex_exit(&dict_foreign_err_mutex);
......@@ -2729,7 +2701,7 @@ dict_create_foreign_constraints_low(
buffer */
ptr = dict_scan_table_name(ptr, &table_to_alter, name,
&success, referenced_table_name);
&success, heap, &referenced_table_name);
if (!success) {
fprintf(stderr,
"InnoDB: Error: could not find the table being ALTERED in:\n%s\n", sql_string);
......@@ -2757,8 +2729,8 @@ dict_create_foreign_constraints_low(
loop:
/* Scan either to "CONSTRAINT" or "FOREIGN", whichever is closer */
ptr1 = dict_scan_to(ptr, (char *) "CONSTRAINT");
ptr2 = dict_scan_to(ptr, (char *) "FOREIGN");
ptr1 = dict_scan_to(ptr, "CONSTRAINT");
ptr2 = dict_scan_to(ptr, "FOREIGN");
constraint_name = NULL;
......@@ -2768,7 +2740,7 @@ loop:
the id of the constraint to system tables. */
ptr = ptr1;
ptr = dict_accept(ptr, (char *) "CONSTRAINT", &success);
ptr = dict_accept(ptr, "CONSTRAINT", &success);
ut_a(success);
......@@ -2782,8 +2754,7 @@ loop:
/* read constraint name unless got "CONSTRAINT FOREIGN" */
if (ptr != ptr2) {
ptr = dict_scan_id(ptr, &constraint_name,
&constraint_name_len, FALSE);
ptr = dict_scan_id(ptr, heap, &constraint_name, FALSE);
}
} else {
ptr = ptr2;
......@@ -2801,19 +2772,19 @@ loop:
start_of_latest_foreign = ptr;
ptr = dict_accept(ptr, (char *) "FOREIGN", &success);
ptr = dict_accept(ptr, "FOREIGN", &success);
if (!isspace(*ptr)) {
goto loop;
}
ptr = dict_accept(ptr, (char *) "KEY", &success);
ptr = dict_accept(ptr, "KEY", &success);
if (!success) {
goto loop;
}
ptr = dict_accept(ptr, (char *) "(", &success);
ptr = dict_accept(ptr, "(", &success);
if (!success) {
/* MySQL allows also an index id before the '('; we
......@@ -2827,7 +2798,7 @@ loop:
return(DB_CANNOT_ADD_CONSTRAINT);
}
ptr = dict_accept(ptr, (char *) "(", &success);
ptr = dict_accept(ptr, "(", &success);
if (!success) {
/* We do not flag a syntax error here because in an
......@@ -2841,8 +2812,9 @@ loop:
/* Scan the columns in the first list */
col_loop1:
ut_a(i < (sizeof column_names) / sizeof *column_names);
ptr = dict_scan_col(ptr, &success, table, columns + i,
column_names + i, column_name_lens + i);
heap, column_names + i);
if (!success) {
mutex_enter(&dict_foreign_err_mutex);
ut_sprintf_timestamp(buf);
......@@ -2858,13 +2830,13 @@ col_loop1:
i++;
ptr = dict_accept(ptr, (char *) ",", &success);
ptr = dict_accept(ptr, ",", &success);
if (success) {
goto col_loop1;
}
ptr = dict_accept(ptr, (char *) ")", &success);
ptr = dict_accept(ptr, ")", &success);
if (!success) {
dict_foreign_report_syntax_err(name, start_of_latest_foreign,
......@@ -2914,15 +2886,11 @@ col_loop1:
db_len = dict_get_db_name_len(table->name);
foreign->id = mem_heap_alloc(foreign->heap,
db_len + 1 + constraint_name_len + 1);
ut_memcpy(foreign->id, table->name, db_len);
db_len + strlen(constraint_name) + 2);
ut_memcpy(foreign->id, table->name, db_len);
foreign->id[db_len] = '/';
ut_memcpy(foreign->id + db_len + 1, constraint_name,
constraint_name_len);
foreign->id[db_len + 1 + constraint_name_len] = '\0';
strcpy(foreign->id + db_len + 1, constraint_name);
}
foreign->foreign_table = table;
......@@ -2932,14 +2900,12 @@ col_loop1:
foreign->foreign_col_names = mem_heap_alloc(foreign->heap,
i * sizeof(void*));
for (i = 0; i < foreign->n_fields; i++) {
foreign->foreign_col_names[i] = mem_heap_alloc(foreign->heap,
1 + ut_strlen(columns[i]->name));
ut_memcpy(foreign->foreign_col_names[i], columns[i]->name,
1 + ut_strlen(columns[i]->name));
foreign->foreign_col_names[i] =
mem_heap_strdup(foreign->heap, columns[i]->name);
}
ptr = dict_scan_table_name(ptr, &referenced_table, name,
&success, referenced_table_name);
&success, heap, &referenced_table_name);
/* Note that referenced_table can be NULL if the user has suppressed
checking of foreign key constraints! */
......@@ -2973,7 +2939,7 @@ col_loop1:
col_loop2:
ptr = dict_scan_col(ptr, &success, referenced_table, columns + i,
column_names + i, column_name_lens + i);
heap, column_names + i);
i++;
if (!success) {
......@@ -3179,21 +3145,14 @@ try_find_index:
foreign->referenced_index = index;
foreign->referenced_table = referenced_table;
foreign->referenced_table_name = mem_heap_alloc(foreign->heap,
1 + ut_strlen(referenced_table_name));
ut_memcpy(foreign->referenced_table_name, referenced_table_name,
1 + ut_strlen(referenced_table_name));
foreign->referenced_table_name = mem_heap_strdup(foreign->heap,
referenced_table_name);
foreign->referenced_col_names = mem_heap_alloc(foreign->heap,
i * sizeof(void*));
for (i = 0; i < foreign->n_fields; i++) {
foreign->referenced_col_names[i]
= mem_heap_alloc(foreign->heap,
1 + column_name_lens[i]);
ut_memcpy(foreign->referenced_col_names[i], column_names[i],
column_name_lens[i]);
(foreign->referenced_col_names[i])[column_name_lens[i]] = '\0';
= mem_heap_strdup(foreign->heap, column_names[i]);
}
/* We found an ok constraint definition: add to the lists */
......@@ -3230,15 +3189,18 @@ dict_create_foreign_constraints(
char* name) /* in: table full name in the normalized form
database_name/table_name */
{
char* str;
ulint err;
char* str;
ulint err;
mem_heap_t* heap;
str = dict_strip_comments(sql_string);
heap = mem_heap_create(10000);
err = dict_create_foreign_constraints_low(trx, str, name);
err = dict_create_foreign_constraints_low(trx, heap, str, name);
mem_heap_free(heap);
mem_free(str);
mem_free(str);
return(err);
}
......@@ -3258,17 +3220,15 @@ dict_foreign_parse_drop_constraints(
dict_table_t* table, /* in: table */
ulint* n, /* out: number of constraints
to drop */
char*** constraints_to_drop) /* out: id's of the
const char*** constraints_to_drop) /* out: id's of the
constraints to drop */
{
dict_foreign_t* foreign;
ibool success;
char* str;
char* ptr;
dict_foreign_t* foreign;
ibool success;
char* str;
const char* ptr;
char* buf = dict_foreign_err_buf;
char* start;
char* id;
ulint len;
const char* id;
*n = 0;
......@@ -3281,47 +3241,43 @@ dict_foreign_parse_drop_constraints(
ut_ad(mutex_own(&(dict_sys->mutex)));
#endif /* UNIV_SYNC_DEBUG */
loop:
ptr = dict_scan_to(ptr, (char *) "DROP");
ptr = dict_scan_to(ptr, "DROP");
if (*ptr == '\0') {
ut_a(*n < 1000);
mem_free(str);
return(DB_SUCCESS);
}
ptr = dict_accept(ptr, (char *) "DROP", &success);
ptr = dict_accept(ptr, "DROP", &success);
if (!isspace(*ptr)) {
goto loop;
}
ptr = dict_accept(ptr, (char *) "FOREIGN", &success);
ptr = dict_accept(ptr, "FOREIGN", &success);
if (!success) {
goto loop;
}
ptr = dict_accept(ptr, (char *) "KEY", &success);
ptr = dict_accept(ptr, "KEY", &success);
if (!success) {
goto syntax_error;
}
ptr = dict_scan_id(ptr, &start, &len, TRUE);
ptr = dict_scan_id(ptr, heap, &id, TRUE);
if (start == NULL) {
if (id == NULL) {
goto syntax_error;
}
id = mem_heap_alloc(heap, len + 1);
ut_memcpy(id, start, len);
id[len] = '\0';
ut_a(*n < 1000);
(*constraints_to_drop)[*n] = id;
(*n)++;
......@@ -3330,9 +3286,9 @@ loop:
foreign = UT_LIST_GET_FIRST(table->foreign_list);
while (foreign != NULL) {
if (0 == ut_strcmp(foreign->id, id)
if (0 == strcmp(foreign->id, id)
|| (strchr(foreign->id, '/')
&& 0 == ut_strcmp(id,
&& 0 == strcmp(id,
dict_remove_db_name(foreign->id)))) {
/* Found */
break;
......
......@@ -39,7 +39,6 @@ dict_get_first_table_name_in_db(
rec_t* rec;
byte* field;
ulint len;
char* table_name;
mtr_t mtr;
#ifdef UNIV_SYNC_DEBUG
......@@ -91,9 +90,7 @@ loop:
/* We found one */
table_name = mem_alloc(len + 1);
ut_memcpy(table_name, field, len);
table_name[len] = '\0';
char* table_name = mem_strdupl(field, len);
btr_pcur_close(&pcur);
mtr_commit(&mtr);
......@@ -122,7 +119,6 @@ dict_print(void)
rec_t* rec;
byte* field;
ulint len;
char table_name[10000];
mtr_t mtr;
mutex_enter(&(dict_sys->mutex));
......@@ -156,14 +152,14 @@ loop:
/* We found one */
ut_memcpy(table_name, field, len);
table_name[len] = '\0';
char* table_name = mem_strdupl(field, len);
btr_pcur_store_position(&pcur, &mtr);
mtr_commit(&mtr);
table = dict_table_get_low(table_name);
mem_free(table_name);
if (table == NULL) {
fprintf(stderr, "InnoDB: Failed to load table %s\n",
......@@ -205,7 +201,6 @@ dict_load_columns(
byte* field;
ulint len;
byte* buf;
char* name_buf;
char* name;
ulint mtype;
ulint prtype;
......@@ -256,12 +251,7 @@ dict_load_columns(
dict_table_get_first_index(sys_columns), 4))->name));
field = rec_get_nth_field(rec, 4, &len);
name_buf = mem_heap_alloc(heap, len + 1);
ut_memcpy(name_buf, field, len);
name_buf[len] = '\0';
name = name_buf;
name = mem_heap_strdupl(heap, field, len);
field = rec_get_nth_field(rec, 5, &len);
mtype = mach_read_from_4(field);
......@@ -304,7 +294,6 @@ dict_load_fields(
btr_pcur_t pcur;
dtuple_t* tuple;
dfield_t* dfield;
char* col_name;
ulint pos_and_prefix_len;
ulint prefix_len;
rec_t* rec;
......@@ -383,11 +372,8 @@ dict_load_fields(
field = rec_get_nth_field(rec, 4, &len);
col_name = mem_heap_alloc(heap, len + 1);
ut_memcpy(col_name, field, len);
col_name[len] = '\0';
dict_mem_index_add_field(index, col_name, 0, prefix_len);
dict_mem_index_add_field(index,
mem_heap_strdupl(heap, field, len), 0, prefix_len);
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
}
......@@ -492,10 +478,7 @@ dict_load_indexes(
dict_table_get_first_index(sys_indexes), 4))->name));
field = rec_get_nth_field(rec, 4, &name_len);
name_buf = mem_heap_alloc(heap, name_len + 1);
ut_memcpy(name_buf, field, name_len);
name_buf[name_len] = '\0';
name_buf = mem_heap_strdupl(heap, field, name_len);
field = rec_get_nth_field(rec, 5, &len);
n_fields = mach_read_from_4(field);
......@@ -544,7 +527,7 @@ dict_load_indexes(
if (is_sys_table
&& ((type & DICT_CLUSTERED)
|| ((table == dict_sys->sys_tables)
&& (name_len == ut_strlen("ID_IND"))
&& (name_len == (sizeof "ID_IND") - 1)
&& (0 == ut_memcmp(name_buf, (char*)"ID_IND",
name_len))))) {
......@@ -593,7 +576,6 @@ dict_load_table(
rec_t* rec;
byte* field;
ulint len;
char* buf;
ulint space;
ulint n_cols;
ulint err;
......@@ -674,15 +656,13 @@ dict_load_table(
if (table->type == DICT_TABLE_CLUSTER_MEMBER) {
ut_error;
#if 0 /* clustered tables have not been implemented yet */
field = rec_get_nth_field(rec, 6, &len);
table->mix_id = mach_read_from_8(field);
field = rec_get_nth_field(rec, 8, &len);
buf = mem_heap_alloc(heap, len);
ut_memcpy(buf, field, len);
table->cluster_name = buf;
table->cluster_name = mem_heap_strdupl(heap, field, len);
#endif
}
if ((table->type == DICT_TABLE_CLUSTER)
......@@ -751,7 +731,6 @@ dict_load_table_on_id(
byte* field;
ulint len;
dict_table_t* table;
char* name;
mtr_t mtr;
#ifdef UNIV_SYNC_DEBUG
......@@ -814,13 +793,8 @@ dict_load_table_on_id(
/* Now we get the table name from the record */
field = rec_get_nth_field(rec, 1, &len);
name = mem_heap_alloc(heap, len + 1);
ut_memcpy(name, field, len);
name[len] = '\0';
/* Load the table definition to memory */
table = dict_load_table(name);
table = dict_load_table(mem_heap_strdupl(heap, field, len));
btr_pcur_close(&pcur);
mtr_commit(&mtr);
......@@ -867,7 +841,6 @@ dict_load_foreign_cols(
btr_pcur_t pcur;
dtuple_t* tuple;
dfield_t* dfield;
char* col_name;
rec_t* rec;
byte* field;
ulint len;
......@@ -912,21 +885,13 @@ dict_load_foreign_cols(
ut_a(i == mach_read_from_4(field));
field = rec_get_nth_field(rec, 4, &len);
col_name = mem_heap_alloc(foreign->heap, len + 1);
ut_memcpy(col_name, field, len);
col_name[len] = '\0';
foreign->foreign_col_names[i] = col_name;
foreign->foreign_col_names[i] =
mem_heap_strdupl(foreign->heap, field, len);
field = rec_get_nth_field(rec, 5, &len);
foreign->referenced_col_names[i] =
mem_heap_strdupl(foreign->heap, field, len);
col_name = mem_heap_alloc(foreign->heap, len + 1);
ut_memcpy(col_name, field, len);
col_name[len] = '\0';
foreign->referenced_col_names[i] = col_name;
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
}
......@@ -1023,23 +988,15 @@ dict_load_foreign(
foreign->type = foreign->n_fields >> 24;
foreign->n_fields = foreign->n_fields & 0xFFFFFF;
foreign->id = mem_heap_alloc(foreign->heap, ut_strlen(id) + 1);
ut_memcpy(foreign->id, id, ut_strlen(id) + 1);
foreign->id = mem_heap_strdup(foreign->heap, id);
field = rec_get_nth_field(rec, 3, &len);
foreign->foreign_table_name = mem_heap_alloc(foreign->heap, 1 + len);
ut_memcpy(foreign->foreign_table_name, field, len);
foreign->foreign_table_name[len] = '\0';
foreign->foreign_table_name =
mem_heap_strdupl(foreign->heap, field, len);
field = rec_get_nth_field(rec, 4, &len);
foreign->referenced_table_name = mem_heap_alloc(foreign->heap,
1 + len);
ut_memcpy(foreign->referenced_table_name, field, len);
foreign->referenced_table_name[len] = '\0';
foreign->referenced_table_name =
mem_heap_strdupl(foreign->heap, field, len);
btr_pcur_close(&pcur);
mtr_commit(&mtr);
......@@ -1153,10 +1110,7 @@ loop:
/* Now we get a foreign key constraint id */
field = rec_get_nth_field(rec, 1, &len);
id = mem_heap_alloc(heap, len + 1);
ut_memcpy(id, field, len);
id[len] = '\0';
id = mem_heap_strdupl(heap, field, len);
btr_pcur_store_position(&pcur, &mtr);
......
......@@ -49,9 +49,7 @@ dict_mem_table_create(
table->heap = heap;
str = mem_heap_alloc(heap, 1 + ut_strlen(name));
ut_strcpy(str, name);
str = mem_heap_strdup(heap, name);
table->type = DICT_TABLE_ORDINARY;
table->name = str;
......@@ -146,7 +144,6 @@ dict_mem_table_add_col(
ulint len, /* in: length */
ulint prec) /* in: precision */
{
char* str;
dict_col_t* col;
dtype_t* type;
......@@ -154,15 +151,11 @@ dict_mem_table_add_col(
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
table->n_def++;
col = dict_table_get_nth_col(table, table->n_def - 1);
str = mem_heap_alloc(table->heap, 1 + ut_strlen(name));
ut_strcpy(str, name);
col = dict_table_get_nth_col(table, table->n_def - 1);
col->ind = table->n_def - 1;
col->name = str;
col->name = mem_heap_strdup(table->heap, name);
col->table = table;
col->ord_part = 0;
......@@ -188,7 +181,6 @@ dict_mem_index_create(
ulint type, /* in: DICT_UNIQUE, DICT_CLUSTERED, ... ORed */
ulint n_fields) /* in: number of fields */
{
char* str;
dict_index_t* index;
mem_heap_t* heap;
......@@ -199,13 +191,9 @@ dict_mem_index_create(
index->heap = heap;
str = mem_heap_alloc(heap, 1 + ut_strlen(index_name));
ut_strcpy(str, index_name);
index->type = type;
index->space = space;
index->name = str;
index->name = mem_heap_strdup(heap, index_name);
index->table_name = table_name;
index->table = NULL;
index->n_def = 0;
......
......@@ -667,7 +667,6 @@ eval_predefined(
{
que_node_t* arg1;
lint int_val;
byte* str1;
byte* data;
int func;
......@@ -681,21 +680,63 @@ eval_predefined(
} else if (func == PARS_TO_CHAR_TOKEN) {
/* Convert number to character string as a
signed decimal integer. */
ulint uint_val;
int int_len;
int_val = eval_node_get_int_val(arg1);
data = eval_node_ensure_val_buf(func_node, 11);
sprintf((char*)data, "%10li", int_val);
/* Determine the length of the string. */
if (int_val == 0) {
int_len = 1; /* the number 0 occupies 1 byte */
} else {
int_len = 0;
if (int_val < 0) {
uint_val = ((ulint) -int_val - 1) + 1;
int_len++; /* reserve space for minus sign */
} else {
uint_val = (ulint) int_val;
}
for (; uint_val > 0; int_len++) {
uint_val /= 10;
}
}
/* allocate the string */
data = eval_node_ensure_val_buf(func_node, int_len + 1);
dfield_set_len(que_node_get_val(func_node), 10);
/* add terminating NUL character */
data[int_len] = 0;
/* convert the number */
if (int_val == 0) {
data[0] = '0';
} else {
int tmp;
if (int_val < 0) {
data[0] = '-'; /* preceding minus sign */
uint_val = ((ulint) -int_val - 1) + 1;
} else {
uint_val = (ulint) int_val;
}
for (tmp = int_len; uint_val > 0; uint_val /= 10) {
data[--tmp] = '0' + (uint_val % 10);
}
}
dfield_set_len((dfield_t*) que_node_get_val(func_node),
int_len);
return;
} else if (func == PARS_TO_NUMBER_TOKEN) {
str1 = dfield_get_data(que_node_get_val(arg1));
int_val = atoi((char*)str1);
int_val = atoi((char*)
dfield_get_data(que_node_get_val(arg1)));
} else if (func == PARS_SYSDATE_TOKEN) {
int_val = (lint)ut_time();
......
......@@ -288,7 +288,6 @@ fil_node_create(
{
fil_node_t* node;
fil_space_t* space;
char* name2;
fil_system_t* system = fil_system;
ut_a(system);
......@@ -299,11 +298,7 @@ fil_node_create(
node = mem_alloc(sizeof(fil_node_t));
name2 = mem_alloc(ut_strlen(name) + 1);
ut_strcpy(name2, name);
node->name = name2;
node->name = mem_strdup(name);
node->open = FALSE;
node->size = size;
node->magic_n = FIL_NODE_MAGIC_N;
......@@ -626,7 +621,6 @@ fil_space_create(
ulint purpose)/* in: FIL_TABLESPACE, or FIL_LOG if log */
{
fil_space_t* space;
char* name2;
fil_system_t* system = fil_system;
ut_a(system);
......@@ -642,11 +636,7 @@ fil_space_create(
space = mem_alloc(sizeof(fil_space_t));
name2 = mem_alloc(ut_strlen(name) + 1);
ut_strcpy(name2, name);
space->name = name2;
space->name = mem_strdup(name);
space->id = id;
space->purpose = purpose;
space->size = 0;
......
......@@ -102,9 +102,10 @@ pages, as long as it obeys the access order rules. */
#define IBUF_POOL_SIZE_PER_MAX_SIZE 2
/* The insert buffer control structure */
ibuf_t* ibuf = NULL;
ibuf_t* ibuf = NULL;
ulint ibuf_rnd = 986058871;
static
ulint ibuf_rnd = 986058871;
ulint ibuf_flush_count = 0;
......@@ -113,9 +114,9 @@ ulint ibuf_flush_count = 0;
#define IBUF_COUNT_N_PAGES 10000
/* Buffered entry counts for file pages, used in debugging */
ulint* ibuf_counts[IBUF_COUNT_N_SPACES];
static ulint* ibuf_counts[IBUF_COUNT_N_SPACES];
ibool ibuf_counts_inited = FALSE;
static ibool ibuf_counts_inited = FALSE;
/* The start address for an insert buffer bitmap page bitmap */
#define IBUF_BITMAP PAGE_DATA
......@@ -129,15 +130,18 @@ ibool ibuf_counts_inited = FALSE;
/* Number of bits describing a single page */
#define IBUF_BITS_PER_PAGE 4
#if IBUF_BITS_PER_PAGE % 2
# error "IBUF_BITS_PER_PAGE must be an even number!"
#endif
/* The mutex used to block pessimistic inserts to ibuf trees */
mutex_t ibuf_pessimistic_insert_mutex;
static mutex_t ibuf_pessimistic_insert_mutex;
/* The mutex protecting the insert buffer structs */
mutex_t ibuf_mutex;
static mutex_t ibuf_mutex;
/* The mutex protecting the insert buffer bitmaps */
mutex_t ibuf_bitmap_mutex;
static mutex_t ibuf_bitmap_mutex;
/* The area in pages from which contract looks for page numbers for merge */
#define IBUF_MERGE_AREA 8
......@@ -2506,16 +2510,13 @@ ibuf_merge_or_delete_for_page(
dtuple_t* entry;
dtuple_t* search_tuple;
rec_t* ibuf_rec;
ibool closed;
buf_block_t* block;
page_t* bitmap_page;
ibuf_data_t* ibuf_data;
ibool success;
ulint n_inserts;
#ifdef UNIV_IBUF_DEBUG
ulint volume;
ulint old_bits;
ulint new_bits;
dulint max_trx_id;
#endif
ibool corruption_noticed = FALSE;
mtr_t mtr;
char err_buf[500];
......@@ -2605,12 +2606,14 @@ ibuf_merge_or_delete_for_page(
}
n_inserts = 0;
#ifdef UNIV_IBUF_DEBUG
volume = 0;
#endif
loop:
mtr_start(&mtr);
if (page) {
success = buf_page_get_known_nowait(RW_X_LATCH, page,
ibool success = buf_page_get_known_nowait(RW_X_LATCH, page,
BUF_KEEP_OLD,
IB__FILE__, __LINE__,
&mtr);
......@@ -2667,7 +2670,7 @@ loop:
keep the latch to the ibuf_rec page until the
insertion is finished! */
max_trx_id = page_get_max_trx_id(
dulint max_trx_id = page_get_max_trx_id(
buf_frame_align(ibuf_rec));
page_update_max_trx_id(page, max_trx_id);
......@@ -2686,9 +2689,8 @@ loop:
n_inserts++;
/* Delete the record from ibuf */
closed = ibuf_delete_rec(space, page_no, &pcur, search_tuple,
&mtr);
if (closed) {
if (ibuf_delete_rec(space, page_no, &pcur, search_tuple,
&mtr)) {
/* Deletion was pessimistic and mtr was committed:
we start from the beginning again */
......@@ -2717,10 +2719,9 @@ reset_bit:
ibuf_bitmap_page_set_bits(bitmap_page, page_no,
IBUF_BITMAP_BUFFERED, FALSE, &mtr);
if (page) {
old_bits = ibuf_bitmap_page_get_bits(bitmap_page, page_no,
IBUF_BITMAP_FREE, &mtr);
new_bits = ibuf_index_page_calc_free(page);
ulint old_bits = ibuf_bitmap_page_get_bits(bitmap_page,
page_no, IBUF_BITMAP_FREE, &mtr);
ulint new_bits = ibuf_index_page_calc_free(page);
#ifdef UNIV_IBUF_DEBUG
/* printf("Old bits %lu new bits %lu max size %lu\n", old_bits,
new_bits,
......
......@@ -294,6 +294,7 @@ dtuple_check_typed_no_assert(
/*=========================*/
/* out: TRUE if ok */
dtuple_t* tuple); /* in: tuple */
#ifdef UNIV_DEBUG
/**************************************************************
Validates the consistency of a tuple which must be complete, i.e,
all fields must have been set. */
......@@ -303,6 +304,7 @@ dtuple_validate(
/*============*/
/* out: TRUE if ok */
dtuple_t* tuple); /* in: tuple */
#endif /* UNIV_DEBUG */
/*****************************************************************
Pretty prints a dfield value according to its data type. */
......
......@@ -299,7 +299,7 @@ dtuple_get_data_size(
ut_ad(tuple);
ut_ad(dtuple_check_typed(tuple));
ut_ad(tuple->magic_n = DATA_TUPLE_MAGIC_N);
ut_ad(tuple->magic_n == DATA_TUPLE_MAGIC_N);
n_fields = tuple->n_fields;
......@@ -355,7 +355,7 @@ dtuple_fold(
ulint fold;
ut_ad(tuple);
ut_ad(tuple->magic_n = DATA_TUPLE_MAGIC_N);
ut_ad(tuple->magic_n == DATA_TUPLE_MAGIC_N);
ut_ad(dtuple_check_typed(tuple));
fold = ut_fold_dulint(tree_id);
......
......@@ -32,20 +32,21 @@ Get the database name length in a table name. */
ulint
dict_get_db_name_len(
/*=================*/
/* out: database name length */
char* name); /* in: table name in the form dbname '/' tablename */
/* out: database name length */
const char* name); /* in: table name in the form
dbname '/' tablename */
/*************************************************************************
Accepts a specified string. Comparisons are case-insensitive. */
char*
const char*
dict_accept(
/*========*/
/* out: if string was accepted, the pointer
is moved after that, else ptr is returned */
char* ptr, /* in: scan from this */
const char* string,/* in: accept only this string as the next
non-whitespace string */
ibool* success);/* out: TRUE if accepted */
/* out: if string was accepted, the pointer
is moved after that, else ptr is returned */
const char* ptr, /* in: scan from this */
const char* string, /* in: accept only this string as the next
non-whitespace string */
ibool* success);/* out: TRUE if accepted */
/************************************************************************
Decrements the count of open MySQL handles to a table. */
......@@ -216,7 +217,7 @@ dict_foreign_parse_drop_constraints(
dict_table_t* table, /* in: table */
ulint* n, /* out: number of constraints
to drop */
char*** constraints_to_drop); /* out: id's of the
const char*** constraints_to_drop); /* out: id's of the
constraints to drop */
/**************************************************************************
Returns a table object and memoryfixes it. NOTE! This is a high-level
......@@ -321,7 +322,7 @@ dict_table_print_by_name(
/*=====================*/
char* name);
/**************************************************************************
Sprintfs to a string info on foreign keys of a table. */
Outputs info on foreign keys of a table. */
void
dict_print_info_on_foreign_keys(
......
......@@ -526,12 +526,12 @@ extern lock_sys_t* lock_sys;
#define LOCK_X 5 /* exclusive */
#define LOCK_AUTO_INC 6 /* locks the auto-inc counter of a table
in an exclusive mode */
#define LOCK_MODE_MASK 0xF /* mask used to extract mode from the
#define LOCK_MODE_MASK 0xFUL /* mask used to extract mode from the
type_mode field in a lock */
/* Lock types */
#define LOCK_TABLE 16 /* these type values should be so high that */
#define LOCK_REC 32 /* they can be ORed to the lock mode */
#define LOCK_TYPE_MASK 0xF0 /* mask used to extract lock type from the
#define LOCK_TYPE_MASK 0xF0UL /* mask used to extract lock type from the
type_mode field in a lock */
/* Waiting lock flag */
#define LOCK_WAIT 256 /* this wait bit should be so high that
......
......@@ -366,7 +366,6 @@ Writes a buffer to a log file group. */
void
log_group_write_buf(
/*================*/
ulint type, /* in: LOG_FLUSH or LOG_RECOVER */
log_group_t* group, /* in: log group */
byte* buf, /* in: buffer */
ulint len, /* in: buffer len; must be divisible
......@@ -551,7 +550,7 @@ extern log_t* log_sys;
highest bit is set to 1 if this is the
first log block in a log flush write
segment */
#define LOG_BLOCK_FLUSH_BIT_MASK 0x80000000
#define LOG_BLOCK_FLUSH_BIT_MASK 0x80000000UL
/* mask used to get the highest bit in
the preceding field */
#define LOG_BLOCK_HDR_DATA_LEN 4 /* number of bytes of log written to
......
......@@ -271,6 +271,59 @@ mem_realloc(
ulint n, /* in: desired number of bytes */
char* file_name,/* in: file name where called */
ulint line); /* in: line where called */
/**************************************************************************
Duplicates a NUL-terminated string. */
UNIV_INLINE
char*
mem_strdup(
/*=======*/
/* out, own: a copy of the string,
must be deallocated with mem_free */
const char* str); /* in: string to be copied */
/**************************************************************************
Makes a NUL-terminated copy of a nonterminated string. */
UNIV_INLINE
char*
mem_strdupl(
/*========*/
/* out, own: a copy of the string,
must be deallocated with mem_free */
const char* str, /* in: string to be copied */
ulint len); /* in: length of str, in bytes */
/**************************************************************************
Makes a NUL-terminated quoted copy of a NUL-terminated string. */
UNIV_INLINE
char*
mem_strdupq(
/*========*/
/* out, own: a quoted copy of the string,
must be deallocated with mem_free */
const char* str, /* in: string to be copied */
char q); /* in: quote character */
/**************************************************************************
Duplicates a NUL-terminated string, allocated from a memory heap. */
UNIV_INLINE
char*
mem_heap_strdup(
/*============*/
/* out, own: a copy of the string */
mem_heap_t* heap, /* in: memory heap where string is allocated */
const char* str); /* in: string to be copied */
/**************************************************************************
Makes a NUL-terminated copy of a nonterminated string,
allocated from a memory heap. */
UNIV_INLINE
char*
mem_heap_strdupl(
/*=============*/
/* out, own: a copy of the string */
mem_heap_t* heap, /* in: memory heap where string is allocated */
const char* str, /* in: string to be copied */
ulint len); /* in: length of str, in bytes */
#ifdef MEM_PERIODIC_CHECK
/**********************************************************************
Goes through the list of all allocated mem blocks, checks their magic
......
......@@ -579,3 +579,99 @@ mem_realloc(
return(mem_alloc_func(n, file_name, line));
}
/**************************************************************************
Duplicates a NUL-terminated string. */
UNIV_INLINE
char*
mem_strdup(
/*=======*/
/* out, own: a copy of the string,
must be deallocated with mem_free */
const char* str) /* in: string to be copied */
{
ulint len = strlen(str) + 1;
return(memcpy(mem_alloc(len), str, len));
}
/**************************************************************************
Makes a NUL-terminated copy of a nonterminated string. */
UNIV_INLINE
char*
mem_strdupl(
/*========*/
/* out, own: a copy of the string,
must be deallocated with mem_free */
const char* str, /* in: string to be copied */
ulint len) /* in: length of str, in bytes */
{
char* s = mem_alloc(len + 1);
s[len] = 0;
return(memcpy(s, str, len));
}
/**************************************************************************
Makes a NUL-terminated quoted copy of a NUL-terminated string. */
UNIV_INLINE
char*
mem_strdupq(
/*========*/
/* out, own: a quoted copy of the string,
must be deallocated with mem_free */
const char* str, /* in: string to be copied */
char q) /* in: quote character */
{
char* dst;
char* d;
const char* s = str;
int len = strlen(str) + 3;
/* calculate the number of quote characters in the string */
while((s = strchr(s, q)) != NULL) {
s++;
len++;
}
/* allocate the quoted string, and copy it */
d = dst = mem_alloc(len);
*d++ = q;
s = str;
while(*s) {
if ((*d++ = *s++) == q) {
*d++ = q;
}
}
*d++ = q;
*d++ = '\0';
ut_ad(len == d - dst);
return(dst);
}
/**************************************************************************
Duplicates a NUL-terminated string, allocated from a memory heap. */
UNIV_INLINE
char*
mem_heap_strdup(
/*============*/
/* out, own: a copy of the string */
mem_heap_t* heap, /* in: memory heap where string is allocated */
const char* str) /* in: string to be copied */
{
ulint len = strlen(str) + 1;
return(memcpy(mem_heap_alloc(heap, len), str, len));
}
/**************************************************************************
Makes a NUL-terminated copy of a nonterminated string,
allocated from a memory heap. */
UNIV_INLINE
char*
mem_heap_strdupl(
/*=============*/
/* out, own: a copy of the string */
mem_heap_t* heap, /* in: memory heap where string is allocated */
const char* str, /* in: string to be copied */
ulint len) /* in: length of str, in bytes */
{
char* s = mem_heap_alloc(heap, len + 1);
s[len] = 0;
return(memcpy(s, str, len));
}
......@@ -26,8 +26,7 @@ ulint
row_undo_ins(
/*=========*/
/* out: DB_SUCCESS */
undo_node_t* node, /* in: row undo node */
que_thr_t* thr); /* in: query thread */
undo_node_t* node); /* in: row undo node */
#ifndef UNIV_NONINL
......
......@@ -41,8 +41,7 @@ row_undo_search_clust_to_pcur(
/* out: TRUE if found; NOTE the node->pcur
must be closed by the caller, regardless of
the return value */
undo_node_t* node, /* in: row undo node */
que_thr_t* thr); /* in: query thread */
undo_node_t* node); /* in: row undo node */
/***************************************************************
Undoes a row operation in a table. This is a high-level function used
in SQL execution graphs. */
......
......@@ -235,21 +235,19 @@ Copies a string to a memory location, setting characters to lower case. */
void
ut_cpy_in_lower_case(
/*=================*/
char* dest, /* in: destination */
char* source, /* in: source */
ulint len); /* in: string length */
char* dest, /* in: destination */
const char* source, /* in: source */
ulint len); /* in: string length */
/****************************************************************
Compares two strings when converted to lower case. */
int
ut_cmp_in_lower_case(
/*=================*/
/* out: -1, 0, 1 if str1 < str2, str1 == str2,
str1 > str2, respectively */
char* str1, /* in: string1 */
char* str2, /* in: string2 */
ulint len); /* in: length of both strings */
/* out: -1, 0, 1 if str1 < str2, str1 == str2,
str1 > str2, respectively */
const char* str1, /* in: string1 */
const char* str2); /* in: string2 */
#ifndef UNIV_NONINL
#include "ut0byte.ic"
......
......@@ -75,6 +75,39 @@ UNIV_INLINE
int
ut_strcmp(void* str1, void* str2);
/**************************************************************************
Determine the length of a string when it is quoted with ut_strcpyq(). */
UNIV_INLINE
ulint
ut_strlenq(
/*=======*/
/* out: length of the string when quoted */
const char* str, /* in: null-terminated string */
char q); /* in: the quote character */
/**************************************************************************
Make a quoted copy of a string. */
char*
ut_strcpyq(
/*=======*/
/* out: pointer to end of dest */
char* dest, /* in: output buffer */
char q, /* in: the quote character */
const char* src); /* in: null-terminated string */
/**************************************************************************
Make a quoted copy of a fixed-length string. */
char*
ut_memcpyq(
/*=======*/
/* out: pointer to end of dest */
char* dest, /* in: output buffer */
char q, /* in: the quote character */
const char* src, /* in: string to be quoted */
ulint len); /* in: length of src */
/**************************************************************************
Catenates two strings into newly allocated memory. The memory must be freed
using mem_free. */
......
......@@ -48,3 +48,23 @@ ut_strcmp(void* str1, void* str2)
return(strcmp((char*)str1, (char*)str2));
}
/**************************************************************************
Determine the length of a string when it is quoted with ut_strcpyq(). */
UNIV_INLINE
ulint
ut_strlenq(
/*=======*/
/* out: length of the string when quoted */
const char* str, /* in: null-terminated string */
char q) /* in: the quote character */
{
ulint len;
for (len = 0; *str; len++, str++) {
if (*str == q) {
len++;
}
}
return(len);
}
......@@ -28,7 +28,9 @@ ut_sprintf(
/*=======*/
char* buf, /* in/out: buffer where to print */
const char* format, /* in: format of prints */
...); /* in: arguments to be printed */
...) /* in: arguments to be printed */
__attribute__((__format__ (__printf__, 2, 3)));
/************************************************************
Gets the high 32 bits in a ulint. That is makes a shift >> 32,
but since there seem to be compiler bugs in both gcc and Visual C++,
......
......@@ -4592,7 +4592,6 @@ lock_clust_rec_modify_check_and_lock(
dict_index_t* index, /* in: clustered index */
que_thr_t* thr) /* in: query thread */
{
trx_t* trx;
ulint err;
if (flags & BTR_NO_LOCKING_FLAG) {
......@@ -4602,8 +4601,6 @@ lock_clust_rec_modify_check_and_lock(
ut_ad(index->type & DICT_CLUSTERED);
trx = thr_get_trx(thr);
lock_mutex_enter_kernel();
ut_ad(lock_table_has(thr_get_trx(thr), index->table, LOCK_IX));
......
......@@ -1015,7 +1015,7 @@ log_io_complete(
return;
}
if ((ulint)group & 0x1) {
if ((ulint)group & 0x1UL) {
/* It was a checkpoint write */
group = (log_group_t*)((ulint)group - 1);
......@@ -1070,7 +1070,6 @@ static
void
log_group_file_header_flush(
/*========================*/
ulint type, /* in: LOG_FLUSH or LOG_RECOVER */
log_group_t* group, /* in: log group */
ulint nth_file, /* in: header to the nth file in the
log file space */
......@@ -1079,9 +1078,6 @@ log_group_file_header_flush(
{
byte* buf;
ulint dest_offset;
UT_NOT_USED(type);
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(log_sys->mutex)));
#endif /* UNIV_SYNC_DEBUG */
......@@ -1136,7 +1132,6 @@ Writes a buffer to a log file group. */
void
log_group_write_buf(
/*================*/
ulint type, /* in: LOG_FLUSH or LOG_RECOVER */
log_group_t* group, /* in: log group */
byte* buf, /* in: buffer */
ulint len, /* in: buffer len; must be divisible
......@@ -1177,7 +1172,7 @@ loop:
&& write_header) {
/* We start to write a new log file instance in the group */
log_group_file_header_flush(type, group,
log_group_file_header_flush(group,
next_offset / group->file_size, start_lsn);
}
......@@ -1396,7 +1391,7 @@ loop:
/* Do the write to the log files */
while (group) {
log_group_write_buf(LOG_FLUSH, group,
log_group_write_buf(group,
log_sys->buf + area_start,
area_end - area_start,
ut_dulint_align_down(log_sys->written_to_all_lsn,
......@@ -2137,11 +2132,11 @@ void
log_archived_file_name_gen(
/*=======================*/
char* buf, /* in: buffer where to write */
ulint id, /* in: group id */
ulint id __attribute__((unused)),
/* in: group id;
currently we only archive the first group */
ulint file_no)/* in: file number */
{
UT_NOT_USED(id); /* Currently we only archive the first group */
sprintf(buf, "%sib_arch_log_%010lu", srv_arch_dir, file_no);
}
......
......@@ -274,8 +274,7 @@ recv_truncate_group(
len = ut_dulint_minus(end_lsn, start_lsn);
log_group_write_buf(LOG_RECOVER, group, log_sys->buf, len,
start_lsn, 0);
log_group_write_buf(group, log_sys->buf, len, start_lsn, 0);
if (ut_dulint_cmp(end_lsn, finish_lsn) >= 0) {
return;
......@@ -330,8 +329,7 @@ recv_copy_group(
len = ut_dulint_minus(end_lsn, start_lsn);
log_group_write_buf(LOG_RECOVER, group, log_sys->buf, len,
start_lsn, 0);
log_group_write_buf(group, log_sys->buf, len, start_lsn, 0);
if (ut_dulint_cmp(end_lsn, recovered_lsn) >= 0) {
......@@ -523,7 +521,7 @@ recv_find_max_checkpoint(
"InnoDB: the problem may be that during an earlier attempt you managed\n"
"InnoDB: to create the InnoDB data files, but log file creation failed.\n"
"InnoDB: If that is the case, please refer to section 3.1 of\n"
"InnoDB: http://www.innodb.com/ibman.html\n");
"InnoDB: http://www.innodb.com/ibman.php\n");
return(DB_ERROR);
}
......
......@@ -196,12 +196,7 @@ mem_heap_create_block(
mem_block_set_start(block, MEM_BLOCK_HEADER_SIZE);
block->free_block = NULL;
if (init_block != NULL) {
block->init_block = TRUE;
} else {
block->init_block = FALSE;
}
block->init_block = (init_block != NULL);
ut_ad((ulint)MEM_BLOCK_HEADER_SIZE < len);
......
......@@ -95,6 +95,7 @@ mlog_parse_initial_log_record(
}
*type = (byte)((ulint)*ptr & ~MLOG_SINGLE_REC_FLAG);
ut_ad(*type <= MLOG_BIGGEST_TYPE);
ptr++;
......@@ -171,13 +172,13 @@ mlog_parse_nbytes(
}
if (type == MLOG_1BYTE) {
if (val > 0xFF) {
if (val > 0xFFUL) {
recv_sys->found_corrupt_log = TRUE;
return(NULL);
}
} else if (type == MLOG_2BYTES) {
if (val > 0xFFFF) {
if (val > 0xFFFFUL) {
recv_sys->found_corrupt_log = TRUE;
return(NULL);
......@@ -234,7 +235,7 @@ mlog_write_ulint(
mach_write_to_4(ptr, val);
}
log_ptr = mlog_open(mtr, 30);
log_ptr = mlog_open(mtr, 11 + 2 + 5);
/* If no logging is requested, we may return now */
if (log_ptr == NULL) {
......@@ -276,7 +277,7 @@ mlog_write_dulint(
mach_write_to_8(ptr, val);
log_ptr = mlog_open(mtr, 30);
log_ptr = mlog_open(mtr, 11 + 2 + 9);
/* If no logging is requested, we may return now */
if (log_ptr == NULL) {
......
......@@ -479,6 +479,7 @@ page_cur_insert_rec_write_log(
ulint i;
ut_a(rec_size < UNIV_PAGE_SIZE);
ut_ad(rec_size == rec_get_size(insert_rec));
log_ptr = mlog_open(mtr, 30 + MLOG_BUF_MARGIN);
......@@ -630,8 +631,8 @@ page_cur_parse_insert_rec(
return(NULL);
}
extra_info_yes = end_seg_len & 0x1;
end_seg_len = end_seg_len / 2;
extra_info_yes = end_seg_len & 0x1UL;
end_seg_len >>= 1;
if (end_seg_len >= UNIV_PAGE_SIZE) {
recv_sys->found_corrupt_log = TRUE;
......@@ -694,7 +695,7 @@ page_cur_parse_insert_rec(
mismatch_index = rec_get_size(cursor_rec) - end_seg_len;
}
if (mismatch_index + end_seg_len < 1024) {
if (mismatch_index + end_seg_len < sizeof buf1) {
buf = buf1;
} else {
buf = mem_alloc(mismatch_index + end_seg_len);
......@@ -726,7 +727,7 @@ page_cur_parse_insert_rec(
page_cur_rec_insert(&cursor, buf + origin_offset, mtr);
if (mismatch_index + end_seg_len >= 1024) {
if (buf != buf1) {
mem_free(buf);
}
......
......@@ -1604,7 +1604,7 @@ page_validate(
page_cur_set_before_first(page, &cur);
for (;;) {
rec = (&cur)->rec;
rec = cur.rec;
if (!page_rec_validate(rec)) {
goto func_exit;
......@@ -1793,16 +1793,13 @@ page_find_rec_with_heap_no(
ulint heap_no)/* in: heap number */
{
page_cur_t cur;
rec_t* rec;
page_cur_set_before_first(page, &cur);
for (;;) {
rec = (&cur)->rec;
if (rec_get_heap_no(rec) == heap_no) {
if (rec_get_heap_no(cur.rec) == heap_no) {
return(rec);
return(cur.rec);
}
if (page_cur_is_after_last(&cur)) {
......
......@@ -532,8 +532,8 @@ opt_search_plan_for_table(
ulint best_goodness;
ulint best_last_op = 0; /* remove warning */
ulint mix_id_pos;
que_node_t* index_plan[128];
que_node_t* best_index_plan[128];
que_node_t* index_plan[256];
que_node_t* best_index_plan[256];
plan = sel_node_get_nth_plan(sel_node, i);
......
......@@ -1745,8 +1745,6 @@ pars_sql(
sym_node_t* sym_node;
mem_heap_t* heap;
que_t* graph;
ulint len;
char* buf;
ut_ad(str);
......@@ -1758,12 +1756,8 @@ pars_sql(
#endif /* UNIV_SYNC_DEBUG */
pars_sym_tab_global = sym_tab_create(heap);
len = ut_strlen(str);
buf = mem_heap_alloc(heap, len + 1);
ut_memcpy(buf, str, len + 1);
pars_sym_tab_global->sql_string = buf;
pars_sym_tab_global->string_len = len;
pars_sym_tab_global->sql_string = mem_heap_strdup(heap, str);
pars_sym_tab_global->string_len = strlen(str);
pars_sym_tab_global->next_char_pos = 0;
yyparse();
......
......@@ -568,8 +568,7 @@ static
void
row_ins_foreign_report_add_err(
/*===========================*/
que_thr_t* thr, /* in: query thread whose run_node
is an insert node */
trx_t* trx, /* in: transaction */
dict_foreign_t* foreign, /* in: foreign key constraint */
rec_t* rec, /* in: a record in the parent table:
it does not match entry because we
......@@ -582,7 +581,7 @@ row_ins_foreign_report_add_err(
mutex_enter(&dict_foreign_err_mutex);
ut_sprintf_timestamp(buf);
sprintf(buf + strlen(buf), " Transaction:\n");
trx_print(buf + strlen(buf), thr_get_trx(thr));
trx_print(buf + strlen(buf), trx);
sprintf(buf + strlen(buf),
"Foreign key constraint fails for table %.500s:\n",
foreign->foreign_table_name);
......@@ -661,15 +660,10 @@ row_ins_foreign_check_on_constraint(
the MySQL query cache for table */
ut_a(ut_strlen(table->name) < 998);
ut_memcpy(table_name_buf, table->name, ut_strlen(table->name) + 1);
ptr = table_name_buf;
while (*ptr != '/') {
ptr++;
}
strcpy(table_name_buf, table->name);
ptr = strchr(table_name_buf, '/');
ut_a(ptr);
*ptr = '\0';
/* We call a function in ha_innodb.cc */
......@@ -1200,11 +1194,6 @@ run_again:
break;
}
/* printf(
"FOREIGN: Found matching record from %s %s\n",
check_index->table_name, check_index->name);
rec_print(rec);
*/
if (check_ref) {
err = DB_SUCCESS;
......@@ -1244,7 +1233,7 @@ run_again:
if (check_ref) {
err = DB_NO_REFERENCED_ROW;
row_ins_foreign_report_add_err(
thr, foreign, rec, entry);
thr_get_trx(thr), foreign, rec, entry);
} else {
err = DB_SUCCESS;
}
......@@ -1260,7 +1249,7 @@ next_rec:
if (check_ref) {
rec = btr_pcur_get_rec(&pcur);
row_ins_foreign_report_add_err(
thr, foreign, rec, entry);
thr_get_trx(thr), foreign, rec, entry);
err = DB_NO_REFERENCED_ROW;
} else {
err = DB_SUCCESS;
......@@ -2167,15 +2156,8 @@ row_ins_step(
error_handling:
trx->error_state = err;
if (err == DB_SUCCESS) {
/* Ok: do nothing */
} else if (err == DB_LOCK_WAIT) {
return(NULL);
} else {
/* SQL error detected */
if (err != DB_SUCCESS) {
/* err == DB_LOCK_WAIT or SQL error detected */
return(NULL);
}
......
......@@ -44,6 +44,51 @@ struct row_mysql_drop_struct{
UT_LIST_BASE_NODE_T(row_mysql_drop_t) row_mysql_drop_list;
ibool row_mysql_drop_list_inited = FALSE;
/* Magic table names for invoking various monitor threads */
static const char S_innodb_monitor[] = "innodb_monitor";
static const char S_innodb_lock_monitor[] = "innodb_lock_monitor";
static const char S_innodb_tablespace_monitor[] = "innodb_tablespace_monitor";
static const char S_innodb_table_monitor[] = "innodb_table_monitor";
static const char S_innodb_mem_validate[] = "innodb_mem_validate";
/* Name suffix for recovered orphaned temporary tables */
static const char S_recover_innodb_tmp_table[] = "_recover_innodb_tmp_table";
/***********************************************************************
Determine if the given name ends in the suffix reserved for recovered
orphaned temporary tables. */
static
ibool
row_mysql_is_recovered_tmp_table(
/*=============================*/
/* out: TRUE if table name ends in
the reserved suffix */
const char* name)
{
ulint namelen = strlen(name) + 1;
return(namelen >= sizeof S_recover_innodb_tmp_table
&& !memcmp(name + namelen -
sizeof S_recover_innodb_tmp_table,
S_recover_innodb_tmp_table,
sizeof S_recover_innodb_tmp_table));
}
/***********************************************************************
Determine if the given name is a name reserved for MySQL system tables. */
static
ibool
row_mysql_is_system_table(
/*======================*/
/* out: TRUE if name is a MySQL
system table name */
const char* name)
{
if (memcmp(name, "mysql/", 6)) {
return(FALSE);
}
return(0 == strcmp(name + 6, "host")
|| 0 == strcmp(name + 6, "user")
|| 0 == strcmp(name + 6, "db"));
}
/***********************************************************************
Reads a MySQL format variable-length field (like VARCHAR) length and
returns pointer to the field data. */
......@@ -900,11 +945,7 @@ row_update_for_mysql(
upd_node_t* node;
dict_table_t* table = prebuilt->table;
trx_t* trx = prebuilt->trx;
/* mem_heap_t* heap;
dtuple_t* search_tuple;
dtuple_t* row_tuple;
mtr_t mtr; */
ut_ad(prebuilt && trx);
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
UT_NOT_USED(mysql_rec);
......@@ -1147,34 +1188,30 @@ row_mysql_recover_tmp_table(
dict_table_t* table, /* in: table definition */
trx_t* trx) /* in: transaction handle */
{
char* ptr;
char old_name[1000];
ut_memcpy(old_name, table->name, ut_strlen(table->name) + 1);
const char* ptr = strstr(table->name, "/rsql");
ptr = old_name;
for (;;) {
if (ptr >= old_name + ut_strlen(table->name) - 6) {
trx_commit_for_mysql(trx);
return(DB_ERROR);
}
if (0 == ut_memcmp(ptr, (char*)"/rsql", 5)) {
ptr++;
*ptr = '#';
break;
}
ptr++;
if (!ptr) {
/* table name does not begin with "/rsql" */
trx_commit_for_mysql(trx);
return(DB_ERROR);
}
else {
int status;
int namelen = strlen(table->name);
char* old_name = mem_strdupl(table->name, namelen);
/* replace "rsql" with "#sql" */
old_name[ptr - table->name + 1] = '#';
/* remove "_recover_innodb_tmp_table" suffix */
ut_ad(namelen > (int) sizeof S_recover_innodb_tmp_table);
ut_ad(!strcmp(old_name + namelen + 1 -
sizeof S_recover_innodb_tmp_table,
S_recover_innodb_tmp_table));
old_name[namelen + 1 - sizeof S_recover_innodb_tmp_table] = 0;
status = row_rename_table_for_mysql(old_name,
table->name, trx);
mem_free(old_name);
return(status);
}
old_name[ut_strlen(table->name)
- ut_strlen("_recover_innodb_tmp_table")] = '\0';
return(row_rename_table_for_mysql(old_name, table->name, trx));
}
/*************************************************************************
......@@ -1248,10 +1285,10 @@ row_mysql_unlock_data_dictionary(
}
/*************************************************************************
Does a table creation operation for MySQL. If the name of the created
table ends to characters INNODB_MONITOR, then this also starts
printing of monitor output by the master thread. */
Does a table creation operation for MySQL. If the name of the table
to be created is equal with one of the predefined magic table names,
then this also starts printing the corresponding monitor output by
the master thread. */
int
row_create_table_for_mysql(
/*=======================*/
......@@ -1263,7 +1300,6 @@ row_create_table_for_mysql(
mem_heap_t* heap;
que_thr_t* thr;
ulint namelen;
ulint keywordlen;
ulint err;
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
......@@ -1288,10 +1324,8 @@ row_create_table_for_mysql(
trx->op_info = (char *) "creating table";
if (0 == ut_strcmp(table->name, (char*)"mysql/host")
|| 0 == ut_strcmp(table->name, (char*)"mysql/user")
|| 0 == ut_strcmp(table->name, (char*)"mysql/db")) {
if (row_mysql_is_system_table(table->name)) {
fprintf(stderr,
"InnoDB: Error: trying to create a MySQL system table %s of type InnoDB.\n"
"InnoDB: MySQL system tables must be of the MyISAM type!\n",
......@@ -1304,13 +1338,7 @@ row_create_table_for_mysql(
trx_start_if_not_started(trx);
namelen = ut_strlen(table->name);
keywordlen = ut_strlen("_recover_innodb_tmp_table");
if (namelen >= keywordlen
&& 0 == ut_memcmp(table->name + namelen - keywordlen,
(char*)"_recover_innodb_tmp_table", keywordlen)) {
if (row_mysql_is_recovered_tmp_table(table->name)) {
/* MySQL prevents accessing of tables whose name begins
with #sql, that is temporary tables. If mysqld crashes in
......@@ -1322,15 +1350,13 @@ row_create_table_for_mysql(
return(row_mysql_recover_tmp_table(table, trx));
}
namelen = ut_strlen(table->name);
keywordlen = ut_strlen((char *) "innodb_monitor");
namelen = strlen(table->name) + 1;
if (namelen >= keywordlen
&& 0 == ut_memcmp(table->name + namelen - keywordlen,
(char *) "innodb_monitor", keywordlen)) {
if (namelen == sizeof S_innodb_monitor
&& !memcmp(table->name, S_innodb_monitor,
sizeof S_innodb_monitor)) {
/* Table name ends to characters innodb_monitor:
/* Table equals "innodb_monitor":
start monitor prints */
srv_print_innodb_monitor = TRUE;
......@@ -1339,47 +1365,28 @@ row_create_table_for_mysql(
of InnoDB monitor prints */
os_event_set(srv_lock_timeout_thread_event);
}
keywordlen = ut_strlen((char *) "innodb_lock_monitor");
if (namelen >= keywordlen
&& 0 == ut_memcmp(table->name + namelen - keywordlen,
(char *) "innodb_lock_monitor", keywordlen)) {
} else if (namelen == sizeof S_innodb_lock_monitor
&& !memcmp(table->name, S_innodb_lock_monitor,
sizeof S_innodb_lock_monitor)) {
srv_print_innodb_monitor = TRUE;
srv_print_innodb_lock_monitor = TRUE;
os_event_set(srv_lock_timeout_thread_event);
}
keywordlen = ut_strlen((char *) "innodb_tablespace_monitor");
if (namelen >= keywordlen
&& 0 == ut_memcmp(table->name + namelen - keywordlen,
(char *) "innodb_tablespace_monitor",
keywordlen)) {
} else if (namelen == sizeof S_innodb_tablespace_monitor
&& !memcmp(table->name, S_innodb_tablespace_monitor,
sizeof S_innodb_tablespace_monitor)) {
srv_print_innodb_tablespace_monitor = TRUE;
os_event_set(srv_lock_timeout_thread_event);
}
keywordlen = ut_strlen((char *) "innodb_table_monitor");
if (namelen >= keywordlen
&& 0 == ut_memcmp(table->name + namelen - keywordlen,
(char *) "innodb_table_monitor",
keywordlen)) {
} else if (namelen == sizeof S_innodb_table_monitor
&& !memcmp(table->name, S_innodb_table_monitor,
sizeof S_innodb_table_monitor)) {
srv_print_innodb_table_monitor = TRUE;
os_event_set(srv_lock_timeout_thread_event);
}
keywordlen = ut_strlen("innodb_mem_validate");
if (namelen >= keywordlen
&& 0 == ut_memcmp(table->name + namelen - keywordlen,
(char*)"innodb_mem_validate", keywordlen)) {
} else if (namelen == sizeof S_innodb_mem_validate
&& !memcmp(table->name, S_innodb_mem_validate,
sizeof S_innodb_mem_validate)) {
/* We define here a debugging feature intended for
developers */
......@@ -1468,8 +1475,6 @@ row_create_index_for_mysql(
ind_node_t* node;
mem_heap_t* heap;
que_thr_t* thr;
ulint namelen;
ulint keywordlen;
ulint err;
ulint i, j;
......@@ -1482,7 +1487,7 @@ row_create_index_for_mysql(
trx->op_info = (char *) "creating index";
/* Check that the same column does not appear twice in the index.
Starting from 4.0.14 InnoDB should be able to cope with that, but
Starting from 4.0.14, InnoDB should be able to cope with that, but
safer not to allow them. */
for (i = 0; i < dict_index_get_n_fields(index); i++) {
......@@ -1508,14 +1513,7 @@ row_create_index_for_mysql(
trx_start_if_not_started(trx);
namelen = ut_strlen(index->table_name);
keywordlen = ut_strlen("_recover_innodb_tmp_table");
if (namelen >= keywordlen
&& 0 == ut_memcmp(
index->table_name + namelen - keywordlen,
(char*)"_recover_innodb_tmp_table", keywordlen)) {
if (row_mysql_is_recovered_tmp_table(index->table_name)) {
return(DB_SUCCESS);
}
......@@ -1576,8 +1574,6 @@ row_table_add_foreign_constraints(
char* name) /* in: table full name in the normalized form
database_name/table_name */
{
ulint namelen;
ulint keywordlen;
ulint err;
#ifdef UNIV_SYNC_DEBUG
......@@ -1590,14 +1586,7 @@ row_table_add_foreign_constraints(
trx_start_if_not_started(trx);
namelen = ut_strlen(name);
keywordlen = ut_strlen("_recover_innodb_tmp_table");
if (namelen >= keywordlen
&& 0 == ut_memcmp(
name + namelen - keywordlen,
(char*)"_recover_innodb_tmp_table", keywordlen)) {
if (row_mysql_is_recovered_tmp_table(name)) {
return(DB_SUCCESS);
}
......@@ -1781,9 +1770,7 @@ row_add_table_to_background_drop_list(
drop = mem_alloc(sizeof(row_mysql_drop_t));
drop->table_name = mem_alloc(1 + ut_strlen(table->name));
ut_memcpy(drop->table_name, table->name, 1 + ut_strlen(table->name));
drop->table_name = mem_strdup(table->name);
mutex_enter(&kernel_mutex);
......@@ -1817,83 +1804,15 @@ row_drop_table_for_mysql(
que_thr_t* thr;
que_t* graph;
ulint err;
char* str1;
char* str2;
ulint len;
ulint namelen;
ulint keywordlen;
ibool locked_dictionary = FALSE;
char buf[10000];
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
ut_a(name != NULL);
if (srv_created_new_raw) {
fprintf(stderr,
"InnoDB: A new raw disk partition was initialized or\n"
"InnoDB: innodb_force_recovery is on: we do not allow\n"
"InnoDB: database modifications by the user. Shut down\n"
"InnoDB: mysqld and edit my.cnf so that newraw is replaced\n"
"InnoDB: with raw, and innodb_force_... is removed.\n");
return(DB_ERROR);
}
trx->op_info = (char *) "dropping table";
trx_start_if_not_started(trx);
namelen = ut_strlen(name);
keywordlen = ut_strlen((char *) "innodb_monitor");
if (namelen >= keywordlen
&& 0 == ut_memcmp(name + namelen - keywordlen,
(char *) "innodb_monitor", keywordlen)) {
/* Table name ends to characters innodb_monitor:
stop monitor prints */
srv_print_innodb_monitor = FALSE;
srv_print_innodb_lock_monitor = FALSE;
}
keywordlen = ut_strlen((char *) "innodb_lock_monitor");
if (namelen >= keywordlen
&& 0 == ut_memcmp(name + namelen - keywordlen,
(char *) "innodb_lock_monitor",
keywordlen)) {
srv_print_innodb_monitor = FALSE;
srv_print_innodb_lock_monitor = FALSE;
}
keywordlen = ut_strlen((char *) "innodb_tablespace_monitor");
if (namelen >= keywordlen
&& 0 == ut_memcmp(name + namelen - keywordlen,
(char *) "innodb_tablespace_monitor",
keywordlen)) {
srv_print_innodb_tablespace_monitor = FALSE;
}
keywordlen = ut_strlen((char *) "innodb_table_monitor");
if (namelen >= keywordlen
&& 0 == ut_memcmp(name + namelen - keywordlen,
(char *) "innodb_table_monitor",
keywordlen)) {
srv_print_innodb_table_monitor = FALSE;
}
char* quoted_name;
char* sql;
/* We use the private SQL parser of Innobase to generate the
query graphs needed in deleting the dictionary data from system
tables in Innobase. Deleting a row from SYS_INDEXES table also
frees the file segments of the B-tree associated with the index. */
str1 = (char *)
static const char str1[] =
"PROCEDURE DROP_TABLE_PROC () IS\n"
"table_name CHAR;\n"
"sys_foreign_id CHAR;\n"
......@@ -1902,10 +1821,9 @@ row_drop_table_for_mysql(
"foreign_id CHAR;\n"
"found INT;\n"
"BEGIN\n"
"table_name := '";
str2 = (char *)
"';\n"
"table_name := ";
static const char str2[] =
";\n"
"SELECT ID INTO table_id\n"
"FROM SYS_TABLES\n"
"WHERE NAME = table_name;\n"
......@@ -1955,14 +1873,60 @@ row_drop_table_for_mysql(
"COMMIT WORK;\n"
"END;\n";
len = ut_strlen(str1);
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
ut_a(name != NULL);
if (srv_created_new_raw) {
fputs(
"InnoDB: A new raw disk partition was initialized or\n"
"InnoDB: innodb_force_recovery is on: we do not allow\n"
"InnoDB: database modifications by the user. Shut down\n"
"InnoDB: mysqld and edit my.cnf so that newraw is replaced\n"
"InnoDB: with raw, and innodb_force_... is removed.\n",
stderr);
return(DB_ERROR);
}
trx->op_info = (char *) "dropping table";
trx_start_if_not_started(trx);
namelen = strlen(name) + 1;
ut_memcpy(buf, str1, len);
ut_memcpy(buf + len, name, ut_strlen(name));
if (namelen == sizeof S_innodb_monitor
&& !memcmp(name, S_innodb_monitor,
sizeof S_innodb_monitor)) {
/* Table name equals "innodb_monitor":
stop monitor prints */
srv_print_innodb_monitor = FALSE;
srv_print_innodb_lock_monitor = FALSE;
} else if (namelen == sizeof S_innodb_lock_monitor
&& !memcmp(name, S_innodb_lock_monitor,
sizeof S_innodb_lock_monitor)) {
len += ut_strlen(name);
srv_print_innodb_monitor = FALSE;
srv_print_innodb_lock_monitor = FALSE;
} else if (namelen == sizeof S_innodb_tablespace_monitor
&& !memcmp(name, S_innodb_tablespace_monitor,
sizeof S_innodb_tablespace_monitor)) {
srv_print_innodb_tablespace_monitor = FALSE;
} else if (namelen == sizeof S_innodb_table_monitor
&& !memcmp(name, S_innodb_table_monitor,
sizeof S_innodb_table_monitor)) {
srv_print_innodb_table_monitor = FALSE;
}
ut_memcpy(buf + len, str2, ut_strlen(str2) + 1);
quoted_name = mem_strdupq(name, '\'');
namelen = strlen(quoted_name);
sql = mem_alloc((sizeof str1) + (sizeof str2) - 2 + 1 + namelen);
memcpy(sql, str1, (sizeof str1) - 1);
memcpy(sql + (sizeof str1) - 1, quoted_name, namelen);
memcpy(sql + (sizeof str1) - 1 + namelen, str2, sizeof str2);
/* Serialize data dictionary operations with dictionary mutex:
no deadlocks can occur then in these operations */
......@@ -1981,9 +1945,10 @@ row_drop_table_for_mysql(
ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */
graph = pars_sql(buf);
graph = pars_sql(sql);
ut_a(graph);
mem_free(sql);
graph->trx = trx;
trx->graph = NULL;
......@@ -2144,9 +2109,10 @@ loop:
row_mysql_lock_data_dictionary(trx);
while ((table_name = dict_get_first_table_name_in_db(name))) {
ut_a(memcmp(table_name, name, strlen(name)) == 0);
ut_a(strcmp(table_name, name) == 0);
table = dict_table_get_low(table_name);
fprintf(stderr, "drop %p:%s\n", table, table_name);
ut_a(table);
......@@ -2197,19 +2163,11 @@ static
ibool
row_is_mysql_tmp_table_name(
/*========================*/
/* out: TRUE if temporary table */
char* name) /* in: table name in the form 'database/tablename' */
/* out: TRUE if temporary table */
const char* name) /* in: table name in the form
'database/tablename' */
{
ulint i;
for (i = 0; i + 5 <= ut_strlen(name); i++) {
if (ut_memcmp(name + i, (char*)"/#sql", 5) == 0) {
return(TRUE);
}
}
return(FALSE);
return(strstr(name, "/#sql") != NULL);
}
/*************************************************************************
......@@ -2227,39 +2185,112 @@ row_rename_table_for_mysql(
que_thr_t* thr;
que_t* graph = NULL;
ulint err;
char* str1;
char* str2;
char* str3;
/* We use the private SQL parser of Innobase to generate the
query graphs needed in deleting the dictionary data from system
tables in Innobase. Deleting a row from SYS_INDEXES table also
frees the file segments of the B-tree associated with the index. */
static const char str1[] =
"PROCEDURE RENAME_TABLE_PROC () IS\n"
"new_table_name CHAR;\n"
"old_table_name CHAR;\n"
"gen_constr_prefix CHAR;\n"
"new_db_name CHAR;\n"
"foreign_id CHAR;\n"
"new_foreign_id CHAR;\n"
"old_db_name_len INT;\n"
"old_t_name_len INT;\n"
"new_db_name_len INT;\n"
"id_len INT;\n"
"found INT;\n"
"BEGIN\n"
"new_table_name := '";
static const char str2[] =
"';\nold_table_name := '";
static const char str3[] =
"';\n"
"UPDATE SYS_TABLES SET NAME = new_table_name\n"
"WHERE NAME = old_table_name;\n";
static const char str4a1[] = /* drop some constraints of tmp tables */
"DELETE FROM SYS_FOREIGN_COLS WHERE ID = '";
static const char str4a2[] = "';\n"
"DELETE FROM SYS_FOREIGN WHERE ID = '";
static const char str4a3[] = "';\n";
static const char str4b[] = /* rename all constraints */
"found := 1;\n"
"old_db_name_len := INSTR(old_table_name, '/') - 1;\n"
"new_db_name_len := INSTR(new_table_name, '/') - 1;\n"
"new_db_name := SUBSTR(new_table_name, 0, new_db_name_len);\n"
"old_t_name_len := LENGTH(old_table_name);\n"
"gen_constr_prefix := CONCAT(old_table_name, '_ibfk_');\n"
"WHILE found = 1 LOOP\n"
" SELECT ID INTO foreign_id\n"
" FROM SYS_FOREIGN\n"
" WHERE FOR_NAME = old_table_name;\n"
" IF (SQL % NOTFOUND) THEN\n"
" found := 0;\n"
" ELSE\n"
" UPDATE SYS_FOREIGN\n"
" SET FOR_NAME = new_table_name\n"
" WHERE ID = foreign_id;\n"
" id_len := LENGTH(foreign_id);\n"
" IF (INSTR(foreign_id, '/') > 0) THEN\n"
" IF (INSTR(foreign_id,\n"
" gen_constr_prefix) > 0)\n"
" THEN\n"
" new_foreign_id :=\n"
" CONCAT(new_table_name,\n"
" SUBSTR(foreign_id, old_t_name_len,\n"
" id_len - old_t_name_len));\n"
" ELSE\n"
" new_foreign_id :=\n"
" CONCAT(new_db_name,\n"
" SUBSTR(foreign_id,\n"
" old_db_name_len,\n"
" id_len - old_db_name_len));\n"
" END IF;\n"
" UPDATE SYS_FOREIGN\n"
" SET ID = new_foreign_id\n"
" WHERE ID = foreign_id;\n"
" UPDATE SYS_FOREIGN_COLS\n"
" SET ID = new_foreign_id\n"
" WHERE ID = foreign_id;\n"
" END IF;\n"
" END IF;\n"
"END LOOP;\n"
"UPDATE SYS_FOREIGN SET REF_NAME = new_table_name\n"
"WHERE REF_NAME = old_table_name;\n";
static const char str5[] =
"END;\n";
mem_heap_t* heap = NULL;
char** constraints_to_drop = NULL;
const char** constraints_to_drop = NULL;
ulint n_constraints_to_drop = 0;
ibool recovering_temp_table = FALSE;
ulint namelen;
ulint keywordlen;
ulint len;
ulint i;
char* db_name;
char buf[10000];
/* length of database name; 0 if not renaming to a temporary table */
ulint db_name_len;
char* sql;
char* sqlend;
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
ut_a(old_name != NULL);
ut_a(new_name != NULL);
if (srv_created_new_raw || srv_force_recovery) {
fprintf(stderr,
fputs(
"InnoDB: A new raw disk partition was initialized or\n"
"InnoDB: innodb_force_recovery is on: we do not allow\n"
"InnoDB: database modifications by the user. Shut down\n"
"InnoDB: mysqld and edit my.cnf so that newraw is replaced\n"
"InnoDB: with raw, and innodb_force_... is removed.\n");
"InnoDB: with raw, and innodb_force_... is removed.\n",
stderr);
trx_commit_for_mysql(trx);
return(DB_ERROR);
}
if (0 == ut_strcmp(new_name, (char*)"mysql/host")
|| 0 == ut_strcmp(new_name, (char*)"mysql/user")
|| 0 == ut_strcmp(new_name, (char*)"mysql/db")) {
if (row_mysql_is_system_table(new_name)) {
fprintf(stderr,
"InnoDB: Error: trying to create a MySQL system table %s of type InnoDB.\n"
......@@ -2273,21 +2304,15 @@ row_rename_table_for_mysql(
trx->op_info = (char *) "renaming table";
trx_start_if_not_started(trx);
namelen = ut_strlen(new_name);
keywordlen = ut_strlen("_recover_innodb_tmp_table");
if (namelen >= keywordlen
&& 0 == ut_memcmp(new_name + namelen - keywordlen,
(char*)"_recover_innodb_tmp_table", keywordlen)) {
if (row_mysql_is_recovered_tmp_table(new_name)) {
recovering_temp_table = TRUE;
}
}
/* Serialize data dictionary operations with dictionary mutex:
no deadlocks can occur then in these operations */
if (!recovering_temp_table) {
if (!recovering_temp_table) {
row_mysql_lock_data_dictionary(trx);
}
......@@ -2299,26 +2324,12 @@ row_rename_table_for_mysql(
goto funct_exit;
}
str1 = (char *)
"PROCEDURE RENAME_TABLE_PROC () IS\n"
"new_table_name CHAR;\n"
"old_table_name CHAR;\n"
"gen_constr_prefix CHAR;\n"
"new_db_name CHAR;\n"
"foreign_id CHAR;\n"
"new_foreign_id CHAR;\n"
"old_db_name_len INT;\n"
"old_t_name_len INT;\n"
"new_db_name_len INT;\n"
"id_len INT;\n"
"found INT;\n"
"BEGIN\n"
"new_table_name :='";
str2 = (char *)
"';\nold_table_name := '";
/* calculate the length of the SQL string */
len = (sizeof str1) + (sizeof str2) + (sizeof str3) + (sizeof str5) - 4
+ ut_strlenq(new_name, '\'') + ut_strlenq(old_name, '\'');
if (row_is_mysql_tmp_table_name(new_name)) {
db_name_len = dict_get_db_name_len(old_name) + 1;
/* MySQL is doing an ALTER TABLE command and it renames the
original table to a temporary table name. We want to preserve
......@@ -2336,31 +2347,57 @@ row_rename_table_for_mysql(
goto funct_exit;
}
str3 = mem_heap_alloc(heap,
1000 + 1000 * n_constraints_to_drop);
*str3 = '\0';
sprintf(str3,
"';\n"
"UPDATE SYS_TABLES SET NAME = new_table_name\n"
"WHERE NAME = old_table_name;\n");
db_name = mem_heap_alloc(heap, 1 + dict_get_db_name_len(
old_name));
ut_memcpy(db_name, old_name, dict_get_db_name_len(old_name));
db_name[dict_get_db_name_len(old_name)] = '\0';
/* reserve space for all database names */
len += 2 * n_constraints_to_drop
* (ut_strlenq(old_name, '\'')
- ut_strlenq(old_name + db_name_len, '\''));
for (i = 0; i < n_constraints_to_drop; i++) {
ulint addlen
= 2 * ut_strlenq(constraints_to_drop[i], '\'')
+ ((sizeof str4a1) + (sizeof str4a2)
+ (sizeof str4a3) - 3);
if (!strchr(constraints_to_drop[i], '/')) {
addlen *= 2;
}
len += addlen;
}
} else {
db_name_len = 0;
len += (sizeof str4b) - 1;
}
sql = sqlend = mem_alloc(len + 1);
memcpy(sql, str1, (sizeof str1) - 1);
sqlend += (sizeof str1) - 1;
sqlend = ut_strcpyq(sqlend, '\'', new_name);
memcpy(sqlend, str2, (sizeof str2) - 1);
sqlend += (sizeof str2) - 1;
sqlend = ut_strcpyq(sqlend, '\'', old_name);
memcpy(sqlend, str3, (sizeof str3) - 1);
sqlend += (sizeof str3) - 1;
if (db_name_len) {
/* Internally, old format < 4.0.18 constraints have as the
constraint id <number>_<number>, while new format constraints
have <databasename>/<constraintname>. */
for (i = 0; i < n_constraints_to_drop; i++) {
sprintf(str3 + strlen(str3),
"DELETE FROM SYS_FOREIGN_COLS WHERE ID = '%s/%s';\n"
"DELETE FROM SYS_FOREIGN WHERE ID = '%s/%s';\n",
db_name, constraints_to_drop[i],
db_name, constraints_to_drop[i]);
memcpy(sqlend, str4a1, (sizeof str4a1) - 1);
sqlend += (sizeof str4a1) - 1;
sqlend = ut_memcpyq(sqlend, '\'',
old_name, db_name_len);
sqlend = ut_strcpyq(sqlend, '\'',
constraints_to_drop[i]);
memcpy(sqlend, str4a2, (sizeof str4a2) - 1);
sqlend += (sizeof str4a2) - 1;
sqlend = ut_memcpyq(sqlend, '\'',
old_name, db_name_len);
sqlend = ut_strcpyq(sqlend, '\'',
constraints_to_drop[i]);
memcpy(sqlend, str4a3, (sizeof str4a3) - 1);
sqlend += (sizeof str4a3) - 1;
if (!strchr(constraints_to_drop[i], '/')) {
/* If this happens to be an old format
......@@ -2368,90 +2405,33 @@ row_rename_table_for_mysql(
format constraints contain '/', it does no
harm to run these DELETEs anyway. */
sprintf(str3 + strlen(str3),
"DELETE FROM SYS_FOREIGN_COLS WHERE ID = '%s';\n"
"DELETE FROM SYS_FOREIGN WHERE ID = '%s';\n",
constraints_to_drop[i],
constraints_to_drop[i]);
memcpy(sqlend, str4a1, (sizeof str4a1) - 1);
sqlend += (sizeof str4a1) - 1;
sqlend = ut_strcpyq(sqlend, '\'',
constraints_to_drop[i]);
memcpy(sqlend, str4a2, (sizeof str4a2) - 1);
sqlend += (sizeof str4a2) - 1;
sqlend = ut_strcpyq(sqlend, '\'',
constraints_to_drop[i]);
memcpy(sqlend, str4a3, (sizeof str4a3) - 1);
sqlend += (sizeof str4a3) - 1;
}
}
}
else {
memcpy(sqlend, str4b, (sizeof str4b) - 1);
sqlend += (sizeof str4b) - 1;
}
sprintf(str3 + strlen(str3),
"END;\n");
memcpy(sqlend, str5, sizeof str5);
sqlend += sizeof str5;
ut_a(strlen(str3) < 1000 + 1000 * n_constraints_to_drop);
} else {
str3 = (char*)
"';\n"
"UPDATE SYS_TABLES SET NAME = new_table_name\n"
"WHERE NAME = old_table_name;\n"
"found := 1;\n"
"old_db_name_len := INSTR(old_table_name, '/') - 1;\n"
"new_db_name_len := INSTR(new_table_name, '/') - 1;\n"
"new_db_name := SUBSTR(new_table_name, 0, new_db_name_len);\n"
"old_t_name_len := LENGTH(old_table_name);\n"
"gen_constr_prefix := CONCAT(old_table_name, '_ibfk_');\n"
"WHILE found = 1 LOOP\n"
" SELECT ID INTO foreign_id\n"
" FROM SYS_FOREIGN\n"
" WHERE FOR_NAME = old_table_name;\n"
" IF (SQL % NOTFOUND) THEN\n"
" found := 0;\n"
" ELSE\n"
" UPDATE SYS_FOREIGN\n"
" SET FOR_NAME = new_table_name\n"
" WHERE ID = foreign_id;\n"
" id_len := LENGTH(foreign_id);\n"
" IF (INSTR(foreign_id, '/') > 0) THEN\n"
" IF (INSTR(foreign_id,\n"
" gen_constr_prefix) > 0)\n"
" THEN\n"
" new_foreign_id :=\n"
" CONCAT(new_table_name,\n"
" SUBSTR(foreign_id, old_t_name_len,\n"
" id_len - old_t_name_len));\n"
" ELSE\n"
" new_foreign_id :=\n"
" CONCAT(new_db_name,\n"
" SUBSTR(foreign_id,\n"
" old_db_name_len,\n"
" id_len - old_db_name_len));\n"
" END IF;\n"
" UPDATE SYS_FOREIGN\n"
" SET ID = new_foreign_id\n"
" WHERE ID = foreign_id;\n"
" UPDATE SYS_FOREIGN_COLS\n"
" SET ID = new_foreign_id\n"
" WHERE ID = foreign_id;\n"
" END IF;\n"
" END IF;\n"
"END LOOP;\n"
"UPDATE SYS_FOREIGN SET REF_NAME = new_table_name\n"
"WHERE REF_NAME = old_table_name;\n"
"END;\n";
}
len = ut_strlen(str1);
ut_memcpy(buf, str1, len);
ut_memcpy(buf + len, new_name, ut_strlen(new_name));
len += ut_strlen(new_name);
ut_memcpy(buf + len, str2, ut_strlen(str2));
len += ut_strlen(str2);
ut_memcpy(buf + len, old_name, ut_strlen(old_name));
len += ut_strlen(old_name);
ut_memcpy(buf + len, str3, ut_strlen(str3) + 1);
graph = pars_sql(buf);
ut_a(sqlend == sql + len + 1);
graph = pars_sql(sql);
ut_a(graph);
mem_free(sql);
graph->trx = trx;
trx->graph = NULL;
......@@ -2609,7 +2589,7 @@ loop:
template */
rec = buf + mach_read_from_4(buf);
if (prev_entry != NULL) {
matched_fields = 0;
matched_bytes = 0;
......
......@@ -91,7 +91,6 @@ row_purge_remove_clust_if_poss_low(
/* out: TRUE if success, or if not found, or
if modified after the delete marking */
purge_node_t* node, /* in: row purge node */
que_thr_t* thr, /* in: query thread */
ulint mode) /* in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE */
{
dict_index_t* index;
......@@ -101,8 +100,6 @@ row_purge_remove_clust_if_poss_low(
ulint err;
mtr_t mtr;
UT_NOT_USED(thr);
index = dict_table_get_first_index(node->table);
pcur = &(node->pcur);
......@@ -156,23 +153,20 @@ static
void
row_purge_remove_clust_if_poss(
/*===========================*/
purge_node_t* node, /* in: row purge node */
que_thr_t* thr) /* in: query thread */
purge_node_t* node) /* in: row purge node */
{
ibool success;
ulint n_tries = 0;
/* printf("Purge: Removing clustered record\n"); */
success = row_purge_remove_clust_if_poss_low(node, thr,
BTR_MODIFY_LEAF);
success = row_purge_remove_clust_if_poss_low(node, BTR_MODIFY_LEAF);
if (success) {
return;
}
retry:
success = row_purge_remove_clust_if_poss_low(node, thr,
BTR_MODIFY_TREE);
success = row_purge_remove_clust_if_poss_low(node, BTR_MODIFY_TREE);
/* The delete operation may fail if we have little
file space left: TODO: easiest to crash the database
and restart with more file space */
......@@ -196,7 +190,6 @@ row_purge_remove_sec_if_poss_low(
/*=============================*/
/* out: TRUE if success or if not found */
purge_node_t* node, /* in: row purge node */
que_thr_t* thr, /* in: query thread */
dict_index_t* index, /* in: index */
dtuple_t* entry, /* in: index entry */
ulint mode) /* in: latch mode BTR_MODIFY_LEAF or
......@@ -211,8 +204,6 @@ row_purge_remove_sec_if_poss_low(
mtr_t mtr;
mtr_t* mtr_vers;
UT_NOT_USED(thr);
log_free_check();
mtr_start(&mtr);
......@@ -284,7 +275,6 @@ void
row_purge_remove_sec_if_poss(
/*=========================*/
purge_node_t* node, /* in: row purge node */
que_thr_t* thr, /* in: query thread */
dict_index_t* index, /* in: index */
dtuple_t* entry) /* in: index entry */
{
......@@ -293,14 +283,14 @@ row_purge_remove_sec_if_poss(
/* printf("Purge: Removing secondary record\n"); */
success = row_purge_remove_sec_if_poss_low(node, thr, index, entry,
success = row_purge_remove_sec_if_poss_low(node, index, entry,
BTR_MODIFY_LEAF);
if (success) {
return;
}
retry:
success = row_purge_remove_sec_if_poss_low(node, thr, index, entry,
success = row_purge_remove_sec_if_poss_low(node, index, entry,
BTR_MODIFY_TREE);
/* The delete operation may fail if we have little
file space left: TODO: easiest to crash the database
......@@ -324,14 +314,13 @@ static
void
row_purge_del_mark(
/*===============*/
purge_node_t* node, /* in: row purge node */
que_thr_t* thr) /* in: query thread */
purge_node_t* node) /* in: row purge node */
{
mem_heap_t* heap;
dtuple_t* entry;
dict_index_t* index;
ut_ad(node && thr);
ut_ad(node);
heap = mem_heap_create(1024);
......@@ -341,14 +330,14 @@ row_purge_del_mark(
/* Build the index entry */
entry = row_build_index_entry(node->row, index, heap);
row_purge_remove_sec_if_poss(node, thr, index, entry);
row_purge_remove_sec_if_poss(node, index, entry);
node->index = dict_table_get_next_index(node->index);
}
mem_heap_free(heap);
row_purge_remove_clust_if_poss(node, thr);
row_purge_remove_clust_if_poss(node);
}
/***************************************************************
......@@ -358,8 +347,7 @@ static
void
row_purge_upd_exist_or_extern(
/*==========================*/
purge_node_t* node, /* in: row purge node */
que_thr_t* thr) /* in: query thread */
purge_node_t* node) /* in: row purge node */
{
mem_heap_t* heap;
dtuple_t* entry;
......@@ -375,7 +363,7 @@ row_purge_upd_exist_or_extern(
ulint i;
mtr_t mtr;
ut_ad(node && thr);
ut_ad(node);
if (node->rec_type == TRX_UNDO_UPD_DEL_REC) {
......@@ -392,7 +380,7 @@ row_purge_upd_exist_or_extern(
/* Build the older version of the index entry */
entry = row_build_index_entry(node->row, index, heap);
row_purge_remove_sec_if_poss(node, thr, index, entry);
row_purge_remove_sec_if_poss(node, index, entry);
}
node->index = dict_table_get_next_index(node->index);
......@@ -519,7 +507,7 @@ row_purge_parse_undo_rec(
mutex_enter(&(dict_sys->mutex));
node->table = dict_table_get_on_id_low(table_id, thr_get_trx(thr));
node->table = dict_table_get_on_id_low(table_id, trx);
mutex_exit(&(dict_sys->mutex));
......@@ -609,12 +597,12 @@ row_purge(
dict_table_get_first_index(node->table));
if (node->rec_type == TRX_UNDO_DEL_MARK_REC) {
row_purge_del_mark(node, thr);
row_purge_del_mark(node);
} else if (updated_extern
|| node->rec_type == TRX_UNDO_UPD_EXIST_REC) {
row_purge_upd_exist_or_extern(node, thr);
row_purge_upd_exist_or_extern(node);
}
if (node->found_clust) {
......
......@@ -568,7 +568,7 @@ row_get_clust_rec(
found = row_search_on_row_ref(&pcur, mode, table, ref, mtr);
clust_rec = btr_pcur_get_rec(&pcur);
clust_rec = found ? btr_pcur_get_rec(&pcur) : NULL;
mem_heap_free(heap);
......@@ -576,11 +576,6 @@ row_get_clust_rec(
*clust_index = dict_table_get_first_index(table);
if (!found) {
return(NULL);
}
return(clust_rec);
}
......
......@@ -37,8 +37,7 @@ ulint
row_undo_ins_remove_clust_rec(
/*==========================*/
/* out: DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
undo_node_t* node, /* in: undo node */
que_thr_t* thr) /* in: query thread */
undo_node_t* node) /* in: undo node */
{
btr_cur_t* btr_cur;
ibool success;
......@@ -46,8 +45,6 @@ row_undo_ins_remove_clust_rec(
ulint n_tries = 0;
mtr_t mtr;
UT_NOT_USED(thr);
mtr_start(&mtr);
success = btr_pcur_restore_position(BTR_MODIFY_LEAF, &(node->pcur),
......@@ -126,8 +123,7 @@ row_undo_ins_remove_sec_low(
depending on whether we wish optimistic or
pessimistic descent down the index tree */
dict_index_t* index, /* in: index */
dtuple_t* entry, /* in: index entry to remove */
que_thr_t* thr) /* in: query thread */
dtuple_t* entry) /* in: index entry to remove */
{
btr_pcur_t pcur;
btr_cur_t* btr_cur;
......@@ -136,8 +132,6 @@ row_undo_ins_remove_sec_low(
ulint err;
mtr_t mtr;
UT_NOT_USED(thr);
log_free_check();
mtr_start(&mtr);
......@@ -148,15 +142,6 @@ row_undo_ins_remove_sec_low(
if (!found) {
/* Not found */
/* FIXME: remove printfs in the final version */
/* printf(
"--UNDO INS: Record not found from page %lu index %s\n",
buf_frame_get_page_no(btr_cur_get_rec(btr_cur)),
index->name); */
/* ibuf_print(); */
btr_pcur_close(&pcur);
mtr_commit(&mtr);
......@@ -192,15 +177,14 @@ row_undo_ins_remove_sec(
/*====================*/
/* out: DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
dict_index_t* index, /* in: index */
dtuple_t* entry, /* in: index entry to insert */
que_thr_t* thr) /* in: query thread */
dtuple_t* entry) /* in: index entry to insert */
{
ulint err;
ulint n_tries = 0;
/* Try first optimistic descent to the B-tree */
err = row_undo_ins_remove_sec_low(BTR_MODIFY_LEAF, index, entry, thr);
err = row_undo_ins_remove_sec_low(BTR_MODIFY_LEAF, index, entry);
if (err == DB_SUCCESS) {
......@@ -209,7 +193,7 @@ row_undo_ins_remove_sec(
/* Try then pessimistic descent to the B-tree */
retry:
err = row_undo_ins_remove_sec_low(BTR_MODIFY_TREE, index, entry, thr);
err = row_undo_ins_remove_sec_low(BTR_MODIFY_TREE, index, entry);
/* The delete operation may fail if we have little
file space left: TODO: easiest to crash the database
......@@ -233,8 +217,7 @@ static
void
row_undo_ins_parse_undo_rec(
/*========================*/
undo_node_t* node, /* in: row undo node */
que_thr_t* thr __attribute__((unused))) /* in: query thread */
undo_node_t* node) /* in: row undo node */
{
dict_index_t* clust_index;
byte* ptr;
......@@ -244,7 +227,7 @@ row_undo_ins_parse_undo_rec(
ulint dummy;
ibool dummy_extern;
ut_ad(node && thr);
ut_ad(node);
ptr = trx_undo_rec_get_pars(node->undo_rec, &type, &dummy,
&dummy_extern, &undo_no, &table_id);
......@@ -273,22 +256,21 @@ ulint
row_undo_ins(
/*=========*/
/* out: DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
undo_node_t* node, /* in: row undo node */
que_thr_t* thr) /* in: query thread */
undo_node_t* node) /* in: row undo node */
{
dtuple_t* entry;
ibool found;
ulint err;
ut_ad(node && thr);
ut_ad(node);
ut_ad(node->state == UNDO_NODE_INSERT);
row_undo_ins_parse_undo_rec(node, thr);
row_undo_ins_parse_undo_rec(node);
if (node->table == NULL) {
found = FALSE;
} else {
found = row_undo_search_clust_to_pcur(node, thr);
found = row_undo_search_clust_to_pcur(node);
}
if (!found) {
......@@ -303,7 +285,7 @@ row_undo_ins(
while (node->index != NULL) {
entry = row_build_index_entry(node->row, node->index,
node->heap);
err = row_undo_ins_remove_sec(node->index, entry, thr);
err = row_undo_ins_remove_sec(node->index, entry);
if (err != DB_SUCCESS) {
......@@ -313,7 +295,7 @@ row_undo_ins(
node->index = dict_table_get_next_index(node->index);
}
err = row_undo_ins_remove_clust_rec(node, thr);
err = row_undo_ins_remove_clust_rec(node);
return(err);
}
......@@ -95,14 +95,11 @@ row_undo_mod_clust_low(
ulint mode) /* in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE */
{
big_rec_t* dummy_big_rec;
dict_index_t* index;
btr_pcur_t* pcur;
btr_cur_t* btr_cur;
ulint err;
ibool success;
index = dict_table_get_first_index(node->table);
pcur = &(node->pcur);
btr_cur = btr_pcur_get_btr_cur(pcur);
......@@ -317,13 +314,6 @@ row_undo_mod_del_mark_or_remove_sec_low(
if (!found) {
/* Not found */
/* FIXME: remove printfs in the final version */
/* printf(
"--UNDO MOD: Record not found from page %lu index %s\n",
buf_frame_get_page_no(btr_cur_get_rec(btr_cur)),
index->name); */
btr_pcur_close(&pcur);
mtr_commit(&mtr);
......@@ -421,7 +411,6 @@ row_undo_mod_del_unmark_sec_and_undo_update(
DB_OUT_OF_FILE_SPACE */
ulint mode, /* in: search mode: BTR_MODIFY_LEAF or
BTR_MODIFY_TREE */
undo_node_t* node, /* in: row undo node */
que_thr_t* thr, /* in: query thread */
dict_index_t* index, /* in: index */
dtuple_t* entry) /* in: index entry */
......@@ -430,15 +419,12 @@ row_undo_mod_del_unmark_sec_and_undo_update(
btr_pcur_t pcur;
btr_cur_t* btr_cur;
upd_t* update;
rec_t* rec;
ulint err = DB_SUCCESS;
ibool found;
big_rec_t* dummy_big_rec;
mtr_t mtr;
char err_buf[1000];
UT_NOT_USED(node);
log_free_check();
mtr_start(&mtr);
......@@ -463,15 +449,13 @@ row_undo_mod_del_unmark_sec_and_undo_update(
} else {
btr_cur = btr_pcur_get_btr_cur(&pcur);
rec = btr_cur_get_rec(btr_cur);
err = btr_cur_del_mark_set_sec_rec(BTR_NO_LOCKING_FLAG,
btr_cur, FALSE, thr, &mtr);
ut_a(err == DB_SUCCESS);
heap = mem_heap_create(100);
update = row_upd_build_sec_rec_difference_binary(index, entry,
rec, heap);
btr_cur_get_rec(btr_cur), heap);
if (upd_get_n_fields(update) == 0) {
/* Do nothing */
......@@ -566,11 +550,11 @@ row_undo_mod_del_mark_sec(
err = row_undo_mod_del_unmark_sec_and_undo_update(
BTR_MODIFY_LEAF,
node, thr, index, entry);
thr, index, entry);
if (err == DB_FAIL) {
err = row_undo_mod_del_unmark_sec_and_undo_update(
BTR_MODIFY_TREE,
node, thr, index, entry);
thr, index, entry);
}
if (err != DB_SUCCESS) {
......@@ -649,12 +633,12 @@ row_undo_mod_upd_exist_sec(
node->update, NULL);
err = row_undo_mod_del_unmark_sec_and_undo_update(
BTR_MODIFY_LEAF,
node, thr, index, entry);
thr, index, entry);
if (err == DB_FAIL) {
err =
row_undo_mod_del_unmark_sec_and_undo_update(
BTR_MODIFY_TREE,
node, thr, index, entry);
thr, index, entry);
}
if (err != DB_SUCCESS) {
......@@ -745,7 +729,7 @@ row_undo_mod(
if (node->table == NULL) {
found = FALSE;
} else {
found = row_undo_search_clust_to_pcur(node, thr);
found = row_undo_search_clust_to_pcur(node);
}
if (!found) {
......
......@@ -144,8 +144,7 @@ row_undo_search_clust_to_pcur(
/* out: TRUE if found; NOTE the node->pcur
must be closed by the caller, regardless of
the return value */
undo_node_t* node, /* in: row undo node */
que_thr_t* thr) /* in: query thread */
undo_node_t* node) /* in: row undo node */
{
dict_index_t* clust_index;
ibool found;
......@@ -153,8 +152,6 @@ row_undo_search_clust_to_pcur(
ibool ret;
rec_t* rec;
UT_NOT_USED(thr);
mtr_start(&mtr);
clust_index = dict_table_get_first_index(node->table);
......@@ -269,7 +266,7 @@ row_undo(
if (node->state == UNDO_NODE_INSERT) {
err = row_undo_ins(node, thr);
err = row_undo_ins(node);
node->state = UNDO_NODE_FETCH_NEXT;
} else {
......
......@@ -1576,7 +1576,8 @@ ulint
srv_lock_timeout_and_monitor_thread(
/*================================*/
/* out: a dummy parameter */
void* arg) /* in: a dummy parameter required by
void* arg __attribute__((unused)))
/* in: a dummy parameter required by
os_thread_create */
{
srv_slot_t* slot;
......@@ -1593,7 +1594,6 @@ srv_lock_timeout_and_monitor_thread(
printf("Lock timeout thread starts, id %lu\n",
os_thread_pf(os_thread_get_curr_id()));
#endif
UT_NOT_USED(arg);
srv_last_monitor_time = time(NULL);
last_table_monitor_time = time(NULL);
last_monitor_time = time(NULL);
......@@ -1738,7 +1738,7 @@ exit_func:
os_thread_exit(NULL);
#ifndef __WIN__
return(NULL);
return(NULL);
#else
return(0);
#endif
......@@ -1756,12 +1756,12 @@ ulint
srv_error_monitor_thread(
/*=====================*/
/* out: a dummy parameter */
void* arg) /* in: a dummy parameter required by
void* arg __attribute__((unused)))
/* in: a dummy parameter required by
os_thread_create */
{
ulint cnt = 0;
UT_NOT_USED(arg);
#ifdef UNIV_DEBUG_THREAD_CREATION
printf("Error monitor thread starts, id %lu\n",
os_thread_pf(os_thread_get_curr_id()));
......@@ -1801,7 +1801,7 @@ loop:
os_thread_exit(NULL);
#ifndef __WIN__
return(NULL);
return(NULL);
#else
return(0);
#endif
......@@ -1857,7 +1857,8 @@ ulint
srv_master_thread(
/*==============*/
/* out: a dummy parameter */
void* arg) /* in: a dummy parameter required by
void* arg __attribute__((unused)))
/* in: a dummy parameter required by
os_thread_create */
{
os_event_t event;
......@@ -1876,8 +1877,6 @@ srv_master_thread(
ibool skip_sleep = FALSE;
ulint i;
UT_NOT_USED(arg);
#ifdef UNIV_DEBUG_THREAD_CREATION
printf("Master thread starts, id %lu\n",
os_thread_pf(os_thread_get_curr_id()));
......
......@@ -159,17 +159,13 @@ srv_parse_data_file_paths_and_sizes(
str++;
}
if (strlen(str) >= ut_strlen(":autoextend")
&& 0 == ut_memcmp(str, (char*)":autoextend",
ut_strlen(":autoextend"))) {
if (0 == memcmp(str, ":autoextend", (sizeof ":autoextend") - 1)) {
str += ut_strlen(":autoextend");
str += (sizeof ":autoextend") - 1;
if (strlen(str) >= ut_strlen(":max:")
&& 0 == ut_memcmp(str, (char*)":max:",
ut_strlen(":max:"))) {
if (0 == memcmp(str, ":max:", (sizeof ":max:") - 1)) {
str += ut_strlen(":max:");
str += (sizeof ":max:") - 1;
size = strtoul(str, &endp, 10);
......@@ -198,10 +194,7 @@ srv_parse_data_file_paths_and_sizes(
str += 3;
}
if (strlen(str) >= 3
&& *str == 'r'
&& *(str + 1) == 'a'
&& *(str + 2) == 'w') {
if (*str == 'r' && *(str + 1) == 'a' && *(str + 2) == 'w') {
str += 3;
}
......@@ -263,19 +256,15 @@ srv_parse_data_file_paths_and_sizes(
(*data_file_names)[i] = path;
(*data_file_sizes)[i] = size;
if (strlen(str) >= ut_strlen(":autoextend")
&& 0 == ut_memcmp(str, (char*)":autoextend",
ut_strlen(":autoextend"))) {
if (0 == memcmp(str, ":autoextend", (sizeof ":autoextend") - 1)) {
*is_auto_extending = TRUE;
str += ut_strlen(":autoextend");
str += (sizeof ":autoextend") - 1;
if (strlen(str) >= ut_strlen(":max:")
&& 0 == ut_memcmp(str, (char*)":max:",
ut_strlen(":max:"))) {
if (0 == memcmp(str, ":max:", (sizeof ":max:") - 1)) {
str += ut_strlen(":max:");
str += (sizeof ":max:") - 1;
size = strtoul(str, &endp, 10);
......@@ -309,10 +298,7 @@ srv_parse_data_file_paths_and_sizes(
(*data_file_is_raw_partition)[i] = SRV_NEW_RAW;
}
if (strlen(str) >= 3
&& *str == 'r'
&& *(str + 1) == 'a'
&& *(str + 2) == 'w') {
if (*str == 'r' && *(str + 1) == 'a' && *(str + 2) == 'w') {
str += 3;
if ((*data_file_is_raw_partition)[i] == 0) {
......@@ -454,12 +440,10 @@ srv_normalize_path_for_win(
char* str __attribute__((unused))) /* in/out: null-terminated character string */
{
#ifdef __WIN__
ulint i;
for (; *str; str++) {
for (i = 0; i < ut_strlen(str); i++) {
if (str[i] == '/') {
str[i] = '\\';
if (*str == '/') {
*str = '\\';
}
}
#endif
......@@ -528,8 +512,6 @@ ulint
open_or_create_log_file(
/*====================*/
/* out: DB_SUCCESS or error code */
ibool create_new_db, /* in: TRUE if we should create a
new database */
ibool* log_file_created, /* out: TRUE if new log file
created */
ibool log_file_has_been_opened,/* in: TRUE if a log file has been
......@@ -544,8 +526,6 @@ open_or_create_log_file(
ulint size_high;
char name[10000];
UT_NOT_USED(create_new_db);
*log_file_created = FALSE;
srv_normalize_path_for_win(srv_log_group_home_dirs[k]);
......@@ -1149,8 +1129,7 @@ NetWare. */
for (i = 0; i < srv_n_log_files; i++) {
err = open_or_create_log_file(create_new_db,
&log_file_created,
err = open_or_create_log_file(&log_file_created,
log_opened, k, i);
if (err != DB_SUCCESS) {
......
......@@ -301,8 +301,7 @@ trx_savepoint_for_mysql(
savep = mem_alloc(sizeof(trx_named_savept_t));
savep->name = mem_alloc(1 + ut_strlen(savepoint_name));
ut_memcpy(savep->name, savepoint_name, 1 + ut_strlen(savepoint_name));
savep->name = mem_strdup(savepoint_name);
savep->savept = trx_savept_take(trx);
......
......@@ -576,8 +576,7 @@ trx_sys_update_mysql_binlog_offset(
MLOG_4BYTES, mtr);
}
if (0 != ut_memcmp(sys_header + field + TRX_SYS_MYSQL_LOG_NAME,
file_name, 1 + ut_strlen(file_name))) {
if (0 != strcmp(sys_header + field + TRX_SYS_MYSQL_LOG_NAME, file_name)) {
mlog_write_string((byte*) (sys_header + field
+ TRX_SYS_MYSQL_LOG_NAME),
......
......@@ -36,9 +36,9 @@ Copies a string to a memory location, setting characters to lower case. */
void
ut_cpy_in_lower_case(
/*=================*/
char* dest, /* in: destination */
char* source,/* in: source */
ulint len) /* in: string length */
char* dest, /* in: destination */
const char* source, /* in: source */
ulint len) /* in: string length */
{
ulint i;
......@@ -53,23 +53,27 @@ Compares two strings when converted to lower case. */
int
ut_cmp_in_lower_case(
/*=================*/
/* out: -1, 0, 1 if str1 < str2, str1 == str2,
str1 > str2, respectively */
char* str1, /* in: string1 */
char* str2, /* in: string2 */
ulint len) /* in: length of both strings */
/* out: -1, 0, 1 if str1 < str2, str1 == str2,
str1 > str2, respectively */
const char* str1, /* in: string1 */
const char* str2) /* in: string2 */
{
ulint i;
for (i = 0; i < len; i++) {
if (tolower(str1[i]) < tolower(str2[i])) {
return(-1);
}
if (tolower(str1[i]) > tolower(str2[i])) {
return(1);
}
}
for (;;) {
int c1, c2;
if (!*str1) {
return(*str2 ? -1 : 0);
} else if (!*str2) {
return 1;
}
c1 = tolower(*str1++);
c2 = tolower(*str2++);
if (c1 < c2) {
return(-1);
}
if (c1 > c2) {
return(1);
}
}
return(0);
return(0);
}
......@@ -106,7 +106,7 @@ ut_malloc_low(
/* Make an intentional seg fault so that we get a stack
trace */
printf("%lu\n", *ut_mem_null_ptr);
if (*ut_mem_null_ptr) ut_mem_null_ptr = 0;
}
if (set_to_zero) {
......@@ -194,6 +194,49 @@ ut_free_all_mem(void)
}
}
/**************************************************************************
Make a quoted copy of a string. */
char*
ut_strcpyq(
/*=======*/
/* out: pointer to end of dest */
char* dest, /* in: output buffer */
char q, /* in: the quote character */
const char* src) /* in: null-terminated string */
{
while (*src) {
if ((*dest++ = *src++) == q) {
*dest++ = q;
}
}
return(dest);
}
/**************************************************************************
Make a quoted copy of a fixed-length string. */
char*
ut_memcpyq(
/*=======*/
/* out: pointer to end of dest */
char* dest, /* in: output buffer */
char q, /* in: the quote character */
const char* src, /* in: string to be quoted */
ulint len) /* in: length of src */
{
const char* srcend = src + len;
while (src < srcend) {
if ((*dest++ = *src++) == q) {
*dest++ = q;
}
}
return(dest);
}
/**************************************************************************
Catenates two strings into newly allocated memory. The memory must be freed
using mem_free. */
......@@ -215,9 +258,7 @@ ut_str_catenate(
str = mem_alloc(len1 + len2 + 1);
ut_memcpy(str, str1, len1);
ut_memcpy(str + len1, str2, len2);
str[len1 + len2] = '\0';
ut_memcpy(str + len1, str2, len2 + 1);
return(str);
}
......@@ -3298,12 +3298,9 @@ create_index(
field = form->field[j];
if (strlen(field->field_name)
== strlen(key_part->field->field_name)
&& 0 == ut_cmp_in_lower_case(
if (0 == ut_cmp_in_lower_case(
(char*)field->field_name,
(char*)key_part->field->field_name,
strlen(field->field_name))) {
(char*)key_part->field->field_name)) {
/* Found the corresponding column */
break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment