Below is the list of changes that have just been committed into a local
5.1 repository of evgen. When evgen does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
ChangeSet@stripped, 2006-08-29 18:58:50+04:00, evgen@stripped +57 -0
Merge moonbone.local:/work/tmp_merge-5.0-mysql
into moonbone.local:/work/tmp_merge-5.1-opt-mysql
MERGE: 1.1810.1697.129
BUILD/check-cpu@stripped, 2006-08-29 17:35:46+04:00, evgen@stripped +0 -0
Auto merged
MERGE: 1.13.1.1
client/mysqltest.c@stripped, 2006-08-29 18:58:47+04:00, evgen@stripped +0 -0
Manual merge
MERGE: 1.155.9.50
include/config-netware.h@stripped, 2006-08-29 17:35:46+04:00, evgen@stripped +0 -0
Auto merged
MERGE: 1.14.2.1
mysql-test/r/func_time.result@stripped, 2006-08-29 17:35:46+04:00, evgen@stripped +0
-0
Auto merged
MERGE: 1.47.1.19
mysql-test/r/group_by.result@stripped, 2006-08-29 17:35:47+04:00, evgen@stripped +0 -0
Auto merged
MERGE: 1.69.1.1
mysql-test/r/innodb_mysql.result@stripped, 2006-08-29 18:58:47+04:00, evgen@stripped +0
-0
Manual merge
MERGE: 1.3.4.3
mysql-test/r/join_outer.result@stripped, 2006-08-29 17:35:47+04:00, evgen@stripped +0
-0
Auto merged
MERGE: 1.44.1.7
mysql-test/r/ndb_condition_pushdown.result@stripped, 2006-08-29 17:35:47+04:00,
evgen@stripped +0 -0
Auto merged
MERGE: 1.15.1.6
mysql-test/r/range.result@stripped, 2006-08-29 17:35:47+04:00, evgen@stripped +0 -0
Auto merged
MERGE: 1.44.1.4
mysql-test/r/select.result@stripped, 2006-08-29 17:35:47+04:00, evgen@stripped +0 -0
Auto merged
MERGE: 1.121.1.17
mysql-test/r/subselect.result@stripped, 2006-08-29 17:35:47+04:00, evgen@stripped +0
-0
Auto merged
MERGE: 1.134.1.20
mysql-test/r/type_datetime.result@stripped, 2006-08-29 17:35:47+04:00, evgen@stripped
+0 -0
Auto merged
MERGE: 1.30.1.2
mysql-test/r/user_var.result@stripped, 2006-08-29 17:35:47+04:00, evgen@stripped +0 -0
Auto merged
MERGE: 1.37.1.3
mysql-test/r/view.result@stripped, 2006-08-29 17:35:47+04:00, evgen@stripped +0 -0
Auto merged
MERGE: 1.138.1.33
mysql-test/t/func_time.test@stripped, 2006-08-29 17:35:47+04:00, evgen@stripped +0 -0
Auto merged
MERGE: 1.41.1.13
mysql-test/t/innodb_mysql.test@stripped, 2006-08-29 18:58:47+04:00, evgen@stripped +0
-0
Manual merge
MERGE: 1.3.4.3
mysql-test/t/join_outer.test@stripped, 2006-08-29 18:58:47+04:00, evgen@stripped +6 -0
Manual merge
MERGE: 1.37.1.1
mysql-test/t/range.test@stripped, 2006-08-29 17:35:47+04:00, evgen@stripped +0 -0
Auto merged
MERGE: 1.37.1.4
mysql-test/t/select.test@stripped, 2006-08-29 17:35:47+04:00, evgen@stripped +0 -0
Auto merged
MERGE: 1.102.1.10
mysql-test/t/type_datetime.test@stripped, 2006-08-29 17:35:47+04:00, evgen@stripped +0
-0
Auto merged
MERGE: 1.18.1.1
mysql-test/t/view.test@stripped, 2006-08-29 17:35:47+04:00, evgen@stripped +0 -0
Auto merged
MERGE: 1.126.1.32
sql/ha_innodb.cc@stripped, 2006-08-29 17:35:47+04:00, evgen@stripped +0 -0
Auto merged
MERGE: 1.202.1.96
sql/item.cc@stripped, 2006-08-29 17:35:47+04:00, evgen@stripped +0 -0
Auto merged
MERGE: 1.113.1.119
sql/item.h@stripped, 2006-08-29 17:35:47+04:00, evgen@stripped +0 -0
Auto merged
MERGE: 1.183.1.23
sql/item_cmpfunc.cc@stripped, 2006-08-29 18:58:47+04:00, evgen@stripped +1 -1
Manual merge
MERGE: 1.187.1.29
sql/item_func.cc@stripped, 2006-08-29 17:35:48+04:00, evgen@stripped +0 -0
Auto merged
MERGE: 1.270.1.29
sql/item_func.h@stripped, 2006-08-29 17:35:48+04:00, evgen@stripped +0 -0
Auto merged
MERGE: 1.136.2.11
sql/item_subselect.cc@stripped, 2006-08-29 17:35:48+04:00, evgen@stripped +0 -0
Auto merged
MERGE: 1.113.1.19
sql/item_timefunc.cc@stripped, 2006-08-29 17:35:48+04:00, evgen@stripped +0 -0
Auto merged
MERGE: 1.100.1.24
sql/mysql_priv.h@stripped, 2006-08-29 18:58:47+04:00, evgen@stripped +1 -1
Manual merge
MERGE: 1.290.1.116
sql/opt_range.cc@stripped, 2006-08-29 18:58:47+04:00, evgen@stripped +2 -2
Manual merge
MERGE: 1.159.1.63
sql/opt_range.h@stripped, 2006-08-29 17:35:48+04:00, evgen@stripped +0 -0
Auto merged
MERGE: 1.57.1.3
sql/set_var.cc@stripped, 2006-08-29 17:35:48+04:00, evgen@stripped +0 -0
Auto merged
MERGE: 1.125.5.20
sql/sql_acl.cc@stripped, 2006-08-29 17:35:48+04:00, evgen@stripped +0 -0
Auto merged
MERGE: 1.128.1.76
sql/sql_base.cc@stripped, 2006-08-29 18:58:47+04:00, evgen@stripped +5 -8
Manual merge
MERGE: 1.235.1.114
sql/sql_class.cc@stripped, 2006-08-29 17:35:48+04:00, evgen@stripped +0 -0
Auto merged
MERGE: 1.223.1.23
sql/sql_delete.cc@stripped, 2006-08-29 17:35:48+04:00, evgen@stripped +0 -0
Auto merged
MERGE: 1.144.1.34
sql/sql_insert.cc@stripped, 2006-08-29 17:35:48+04:00, evgen@stripped +0 -0
Auto merged
MERGE: 1.146.1.53
sql/sql_load.cc@stripped, 2006-08-29 17:35:48+04:00, evgen@stripped +0 -0
Auto merged
MERGE: 1.78.1.19
sql/sql_parse.cc@stripped, 2006-08-29 17:35:49+04:00, evgen@stripped +0 -0
Auto merged
MERGE: 1.426.1.138
sql/sql_select.cc@stripped, 2006-08-29 17:35:49+04:00, evgen@stripped +0 -0
Auto merged
MERGE: 1.312.1.135
sql/sql_update.cc@stripped, 2006-08-29 17:35:49+04:00, evgen@stripped +0 -0
Auto merged
MERGE: 1.154.2.42
storage/innobase/btr/btr0btr.c@stripped, 2006-08-29 17:35:49+04:00, evgen@stripped +0
-0
Auto merged
MERGE: 1.38.3.2
storage/innobase/btr/btr0btr.c@stripped, 2006-08-29 17:35:46+04:00, evgen@stripped
+0 -0
Merge rename: innobase/btr/btr0btr.c -> storage/innobase/btr/btr0btr.c
storage/innobase/buf/buf0buf.c@stripped, 2006-08-29 17:35:49+04:00, evgen@stripped +0
-0
Auto merged
MERGE: 1.45.6.2
storage/innobase/buf/buf0buf.c@stripped, 2006-08-29 17:35:46+04:00, evgen@stripped
+0 -0
Merge rename: innobase/buf/buf0buf.c -> storage/innobase/buf/buf0buf.c
storage/innobase/dict/dict0dict.c@stripped, 2006-08-29 17:35:49+04:00, evgen@stripped
+0 -0
Auto merged
MERGE: 1.65.11.2
storage/innobase/dict/dict0dict.c@stripped, 2006-08-29 17:35:46+04:00,
evgen@stripped +0 -0
Merge rename: innobase/dict/dict0dict.c -> storage/innobase/dict/dict0dict.c
storage/innobase/fil/fil0fil.c@stripped, 2006-08-29 17:35:49+04:00, evgen@stripped +0
-0
Auto merged
MERGE: 1.54.11.2
storage/innobase/fil/fil0fil.c@stripped, 2006-08-29 17:35:46+04:00,
evgen@stripped +0 -0
Merge rename: innobase/fil/fil0fil.c -> storage/innobase/fil/fil0fil.c
storage/innobase/fsp/fsp0fsp.c@stripped, 2006-08-29 17:35:49+04:00, evgen@stripped +0
-0
Auto merged
MERGE: 1.25.2.2
storage/innobase/fsp/fsp0fsp.c@stripped, 2006-08-29 17:35:46+04:00, evgen@stripped
+0 -0
Merge rename: innobase/fsp/fsp0fsp.c -> storage/innobase/fsp/fsp0fsp.c
storage/innobase/include/btr0cur.ic@stripped, 2006-08-29 18:58:47+04:00, evgen@stripped
+0 -0
Manual merge
MERGE: 1.2.2.2
storage/innobase/include/btr0cur.ic@stripped, 2006-08-29 17:35:46+04:00,
evgen@stripped +0 -0
Merge rename: innobase/include/btr0cur.ic -> storage/innobase/include/btr0cur.ic
storage/innobase/include/buf0buf.ic@stripped, 2006-08-29 17:35:49+04:00,
evgen@stripped +0 -0
Auto merged
MERGE: 1.17.2.2
storage/innobase/include/buf0buf.ic@stripped, 2006-08-29 17:35:46+04:00,
evgen@stripped +0 -0
Merge rename: innobase/include/buf0buf.ic -> storage/innobase/include/buf0buf.ic
storage/innobase/log/log0log.c@stripped, 2006-08-29 17:35:49+04:00, evgen@stripped +0
-0
Auto merged
MERGE: 1.41.4.2
storage/innobase/log/log0log.c@stripped, 2006-08-29 17:35:46+04:00, evgen@stripped
+0 -0
Merge rename: innobase/log/log0log.c -> storage/innobase/log/log0log.c
storage/innobase/log/log0recv.c@stripped, 2006-08-29 17:35:49+04:00, evgen@stripped +0
-0
Auto merged
MERGE: 1.46.5.2
storage/innobase/log/log0recv.c@stripped, 2006-08-29 17:35:46+04:00,
evgen@stripped +0 -0
Merge rename: innobase/log/log0recv.c -> storage/innobase/log/log0recv.c
storage/innobase/os/os0file.c@stripped, 2006-08-29 17:35:50+04:00, evgen@stripped +0
-0
Auto merged
MERGE: 1.103.10.2
storage/innobase/os/os0file.c@stripped, 2006-08-29 17:35:46+04:00,
evgen@stripped +0 -0
Merge rename: innobase/os/os0file.c -> storage/innobase/os/os0file.c
storage/innobase/row/row0mysql.c@stripped, 2006-08-29 18:58:47+04:00, evgen@stripped
+1 -2
Manual merge
MERGE: 1.103.15.2
storage/innobase/row/row0mysql.c@stripped, 2006-08-29 17:35:46+04:00,
evgen@stripped +0 -0
Merge rename: innobase/row/row0mysql.c -> storage/innobase/row/row0mysql.c
storage/innobase/row/row0sel.c@stripped, 2006-08-29 17:35:50+04:00, evgen@stripped +0
-0
Auto merged
MERGE: 1.92.8.2
storage/innobase/row/row0sel.c@stripped, 2006-08-29 17:35:46+04:00, evgen@stripped
+0 -0
Merge rename: innobase/row/row0sel.c -> storage/innobase/row/row0sel.c
storage/innobase/srv/srv0start.c@stripped, 2006-08-29 17:35:50+04:00, evgen@stripped
+0 -0
Auto merged
MERGE: 1.80.10.2
storage/innobase/srv/srv0start.c@stripped, 2006-08-29 17:35:46+04:00,
evgen@stripped +0 -0
Merge rename: innobase/srv/srv0start.c -> storage/innobase/srv/srv0start.c
storage/innobase/ut/ut0dbg.c@stripped, 2006-08-29 17:35:50+04:00, evgen@stripped +0 -0
Auto merged
MERGE: 1.7.2.2
storage/innobase/ut/ut0dbg.c@stripped, 2006-08-29 17:35:46+04:00, evgen@stripped +0
-0
Merge rename: innobase/ut/ut0dbg.c -> storage/innobase/ut/ut0dbg.c
tests/mysql_client_test.c@stripped, 2006-08-29 17:35:50+04:00, evgen@stripped +0 -0
Auto merged
MERGE: 1.167.1.37
# This is a BitKeeper patch. What follows are the unified diffs for the
# set of deltas contained in the patch. The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User: evgen
# Host: moonbone.local
# Root: /work/tmp_merge-5.1-opt-mysql/RESYNC
--- 1.205/sql/item.cc 2006-08-29 18:58:58 +04:00
+++ 1.206/sql/item.cc 2006-08-29 18:58:58 +04:00
@@ -302,6 +302,7 @@
maybe_null=null_value=with_sum_func=unsigned_flag=0;
decimals= 0; max_length= 0;
with_subselect= 0;
+ cmp_context= (Item_result)-1;
/* Put item in free list so that we can free all items at end */
THD *thd= current_thd;
@@ -340,7 +341,8 @@
unsigned_flag(item->unsigned_flag),
with_sum_func(item->with_sum_func),
fixed(item->fixed),
- collation(item->collation)
+ collation(item->collation),
+ cmp_context(item->cmp_context)
{
next= thd->free_list; // Put in free list
thd->free_list= this;
@@ -3828,7 +3830,19 @@
Item *item= 0;
if (item_equal)
item= item_equal->get_const();
- if (!item)
+ /*
+ Disable const propagation for items used in different comparison contexts.
+ This must be done because, for example, Item_hex_string->val_int() is not
+ the same as (Item_hex_string->val_str() in BINARY column)->val_int().
+ We cannot simply disable the replacement in a particular context (
+ e.g. <bin_col> = <int_col> AND <bin_col> = <hex_string>)
since
+ Items don't know the context they are in and there are functions like
+ IF (<hex_string>, 'yes', 'no').
+ The same problem occurs when comparing a DATE/TIME field with a
+ DATE/TIME represented as an int and as a string.
+ */
+ if (!item ||
+ (cmp_context != (Item_result)-1 && item->cmp_context != cmp_context))
item= this;
return item;
}
--- 1.207/sql/item.h 2006-08-29 18:58:58 +04:00
+++ 1.208/sql/item.h 2006-08-29 18:58:58 +04:00
@@ -495,7 +495,7 @@
my_bool with_subselect; /* If this item is a subselect or some
of its arguments is or contains a
subselect */
-
+ Item_result cmp_context; /* Comparison context */
// alloc & destruct is done as start of select using sql_alloc
Item();
/*
--- 1.213/sql/item_cmpfunc.cc 2006-08-29 18:58:58 +04:00
+++ 1.214/sql/item_cmpfunc.cc 2006-08-29 18:58:58 +04:00
@@ -125,31 +125,39 @@
uchar null_byte;
Field *field= NULL;
- /* Search for date/time fields/functions */
- for (i= 0; i < nitems; i++)
+ /*
+ Do not convert items while creating a or showing a view in order
+ to store/display the original query in these cases.
+ */
+ if (thd->lex->sql_command != SQLCOM_CREATE_VIEW &&
+ thd->lex->sql_command != SQLCOM_SHOW_CREATE)
{
- if (!items[i]->result_as_longlong())
+ /* Search for date/time fields/functions */
+ for (i= 0; i < nitems; i++)
{
- /* Do not convert anything if a string field/function is present */
- if (!items[i]->const_item() && items[i]->result_type() ==
STRING_RESULT)
+ if (!items[i]->result_as_longlong())
{
- i= nitems;
+ /* Do not convert anything if a string field/function is present */
+ if (!items[i]->const_item() && items[i]->result_type() ==
STRING_RESULT)
+ {
+ i= nitems;
+ break;
+ }
+ continue;
+ }
+ if ((res= items[i]->real_item()->type()) == Item::FIELD_ITEM &&
+ items[i]->result_type() != INT_RESULT)
+ {
+ field= ((Item_field *)items[i]->real_item())->field;
+ break;
+ }
+ else if (res == Item::FUNC_ITEM)
+ {
+ field= items[i]->tmp_table_field_from_field_type(0,0);
+ if (field)
+ field->move_field(buff, &null_byte, 0);
break;
}
- continue;
- }
- if ((res= items[i]->real_item()->type()) == Item::FIELD_ITEM &&
- items[i]->result_type() != INT_RESULT)
- {
- field= ((Item_field *)items[i]->real_item())->field;
- break;
- }
- else if (res == Item::FUNC_ITEM)
- {
- field= items[i]->tmp_table_field_from_field_type(0, 0);
- if (field)
- field->move_field(buff, &null_byte, 0);
- break;
}
}
if (field)
@@ -412,7 +420,8 @@
agg_arg_charsets(coll, args, 2, MY_COLL_CMP_CONV, 1))
return;
-
+ args[0]->cmp_context= args[1]->cmp_context=
+ item_cmp_type(args[0]->result_type(), args[1]->result_type());
// Make a special case of compare with fields to get nicer DATE comparisons
if (functype() == LIKE_FUNC) // Disable conversion in case of LIKE function.
@@ -433,6 +442,7 @@
{
cmp.set_cmp_func(this, tmp_arg, tmp_arg+1,
INT_RESULT); // Works for all types.
+ args[0]->cmp_context= args[1]->cmp_context= INT_RESULT;
return;
}
}
@@ -447,6 +457,7 @@
{
cmp.set_cmp_func(this, tmp_arg, tmp_arg+1,
INT_RESULT); // Works for all types.
+ args[0]->cmp_context= args[1]->cmp_context= INT_RESULT;
return;
}
}
@@ -1224,6 +1235,7 @@
if (!args[0] || !args[1] || !args[2])
return;
agg_cmp_type(thd, &cmp_type, args, 3);
+ args[0]->cmp_context= args[1]->cmp_context= args[2]->cmp_context= cmp_type;
if (cmp_type == STRING_RESULT)
agg_arg_charsets(cmp_collation, args, 3, MY_COLL_CMP_CONV, 1);
--- 1.308/sql/item_func.cc 2006-08-29 18:58:58 +04:00
+++ 1.309/sql/item_func.cc 2006-08-29 18:58:58 +04:00
@@ -551,7 +551,7 @@
Item *Item_func::get_tmp_table_item(THD *thd)
{
- if (!with_sum_func && !const_item())
+ if (!with_sum_func && !const_item() && functype() != SUSERVAR_FUNC)
return new Item_field(result_field);
return copy_or_same(thd);
}
@@ -3741,30 +3741,38 @@
*/
bool
-Item_func_set_user_var::check()
+Item_func_set_user_var::check(bool use_result_field)
{
DBUG_ENTER("Item_func_set_user_var::check");
+ if (use_result_field)
+ DBUG_ASSERT(result_field);
switch (cached_result_type) {
case REAL_RESULT:
{
- save_result.vreal= args[0]->val_real();
+ save_result.vreal= use_result_field ? result_field->val_real() :
+ args[0]->val_real();
break;
}
case INT_RESULT:
{
- save_result.vint= args[0]->val_int();
- unsigned_flag= args[0]->unsigned_flag;
+ save_result.vint= use_result_field ? result_field->val_int() :
+ args[0]->val_int();
+ unsigned_flag= use_result_field ? ((Field_num*)result_field)->unsigned_flag:
+ args[0]->unsigned_flag;
break;
}
case STRING_RESULT:
{
- save_result.vstr= args[0]->val_str(&value);
+ save_result.vstr= use_result_field ? result_field->val_str(&value) :
+ args[0]->val_str(&value);
break;
}
case DECIMAL_RESULT:
{
- save_result.vdec= args[0]->val_decimal(&decimal_buff);
+ save_result.vdec= use_result_field ?
+ result_field->val_decimal(&decimal_buff) :
+ args[0]->val_decimal(&decimal_buff);
break;
}
case ROW_RESULT:
@@ -3850,7 +3858,7 @@
double Item_func_set_user_var::val_real()
{
DBUG_ASSERT(fixed == 1);
- check();
+ check(0);
update(); // Store expression
return entry->val_real(&null_value);
}
@@ -3858,7 +3866,7 @@
longlong Item_func_set_user_var::val_int()
{
DBUG_ASSERT(fixed == 1);
- check();
+ check(0);
update(); // Store expression
return entry->val_int(&null_value);
}
@@ -3866,7 +3874,7 @@
String *Item_func_set_user_var::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
- check();
+ check(0);
update(); // Store expression
return entry->val_str(&null_value, str, decimals);
}
@@ -3875,7 +3883,7 @@
my_decimal *Item_func_set_user_var::val_decimal(my_decimal *val)
{
DBUG_ASSERT(fixed == 1);
- check();
+ check(0);
update(); // Store expression
return entry->val_decimal(&null_value, val);
}
@@ -3900,6 +3908,29 @@
str->append(')');
}
+bool Item_func_set_user_var::send(Protocol *protocol, String *str_arg)
+{
+ if (result_field)
+ {
+ check(1);
+ update();
+ return protocol->store(result_field);
+ }
+ return Item::send(protocol, str_arg);
+}
+
+void Item_func_set_user_var::make_field(Send_field *tmp_field)
+{
+ if (result_field)
+ {
+ result_field->make_field(tmp_field);
+ DBUG_ASSERT(tmp_field->table_name != 0);
+ if (Item::name)
+ tmp_field->col_name=Item::name; // Use user supplied name
+ }
+ else
+ Item::make_field(tmp_field);
+}
String *
Item_func_get_user_var::val_str(String *str)
@@ -4165,7 +4196,7 @@
Item_func_set_user_var is not fixed after construction, call
fix_fields().
*/
- return (!suv || suv->fix_fields(thd, it) || suv->check() || suv->update());
+ return (!suv || suv->fix_fields(thd, it) || suv->check(0) || suv->update());
}
--- 1.144/sql/item_func.h 2006-08-29 18:58:58 +04:00
+++ 1.145/sql/item_func.h 2006-08-29 18:58:58 +04:00
@@ -54,7 +54,7 @@
SP_POINTN,SP_GEOMETRYN,SP_INTERIORRINGN,
NOT_FUNC, NOT_ALL_FUNC,
NOW_FUNC, TRIG_COND_FUNC,
- GUSERVAR_FUNC, COLLATE_FUNC,
+ SUSERVAR_FUNC, GUSERVAR_FUNC, COLLATE_FUNC,
EXTRACT_FUNC, CHAR_TYPECAST_FUNC, FUNC_SP, UDF_FUNC };
enum optimize_type { OPTIMIZE_NONE,OPTIMIZE_KEY,OPTIMIZE_OP, OPTIMIZE_NULL,
OPTIMIZE_EQUAL };
@@ -1196,13 +1196,16 @@
Item_func_set_user_var(LEX_STRING a,Item *b)
:Item_func(b), cached_result_type(INT_RESULT), name(a)
{}
+ enum Functype functype() const { return SUSERVAR_FUNC; }
double val_real();
longlong val_int();
String *val_str(String *str);
my_decimal *val_decimal(my_decimal *);
bool update_hash(void *ptr, uint length, enum Item_result type,
CHARSET_INFO *cs, Derivation dv, bool unsigned_arg= 0);
- bool check();
+ bool send(Protocol *protocol, String *str_arg);
+ void make_field(Send_field *tmp_field);
+ bool check(bool use_result_field);
bool update();
enum Item_result result_type () const { return cached_result_type; }
bool fix_fields(THD *thd, Item **ref);
--- 1.131/sql/item_timefunc.cc 2006-08-29 18:58:58 +04:00
+++ 1.132/sql/item_timefunc.cc 2006-08-29 18:58:58 +04:00
@@ -224,7 +224,7 @@
tmp= (char*) val + min(2, val_len);
l_time->day= (int) my_strtoll10(val, &tmp, &error);
/* Skip 'st, 'nd, 'th .. */
- val= tmp + min((int) (end-tmp), 2);
+ val= tmp + min((int) (val_end-tmp), 2);
break;
/* Hour */
--- 1.431/sql/mysql_priv.h 2006-08-29 18:58:58 +04:00
+++ 1.432/sql/mysql_priv.h 2006-08-29 18:58:58 +04:00
@@ -111,6 +111,15 @@
TYPELIB *ab_month_names;
TYPELIB *day_names;
TYPELIB *ab_day_names;
+#ifdef __cplusplus
+ my_locale_st(const char *name_par, const char *descr_par, bool is_ascii_par,
+ TYPELIB *month_names_par, TYPELIB *ab_month_names_par,
+ TYPELIB *day_names_par, TYPELIB *ab_day_names_par) :
+ name(name_par), description(descr_par), is_ascii(is_ascii_par),
+ month_names(month_names_par), ab_month_names(ab_month_names_par),
+ day_names(day_names_par), ab_day_names(ab_day_names_par)
+ {}
+#endif
} MY_LOCALE;
extern MY_LOCALE my_locale_en_US;
@@ -1131,6 +1140,7 @@
TABLE_LIST *tables,
TABLE_LIST **leaves,
bool select_insert,
+ ulong want_access_first,
ulong want_access);
int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
List<Item> *sum_func_list, uint wild_num);
--- 1.229/sql/opt_range.cc 2006-08-29 18:58:58 +04:00
+++ 1.230/sql/opt_range.cc 2006-08-29 18:58:58 +04:00
@@ -549,6 +549,7 @@
uint fields_bitmap_size;
MY_BITMAP needed_fields; /* bitmask of fields needed by the query */
+ MY_BITMAP tmp_covered_fields;
key_map *needed_reg; /* ptr to SQL_SELECT::needed_reg */
@@ -1916,6 +1917,7 @@
TABLE *table= param->table;
my_bitmap_map *tmp;
uint pk;
+ param->tmp_covered_fields.bitmap= 0;
param->fields_bitmap_size= table->s->column_bitmap_size;
if (!(tmp= (my_bitmap_map*) alloc_root(param->mem_root,
param->fields_bitmap_size)) ||
@@ -4494,11 +4496,15 @@
/*I=set of all covering indexes */
ror_scan_mark= tree->ror_scans;
- my_bitmap_map int_buf[MAX_KEY/(sizeof(my_bitmap_map)*8)+1];
- MY_BITMAP covered_fields;
- if (bitmap_init(&covered_fields, int_buf, param->table->s->fields, FALSE))
+ MY_BITMAP *covered_fields= ¶m->tmp_covered_fields;
+ if (!covered_fields->bitmap)
+ covered_fields->bitmap= (uchar*)alloc_root(param->mem_root,
+ param->fields_bitmap_size);
+ if (!covered_fields->bitmap ||
+ bitmap_init(covered_fields, covered_fields->bitmap,
+ param->table->s->fields, FALSE))
DBUG_RETURN(0);
- bitmap_clear_all(&covered_fields);
+ bitmap_clear_all(covered_fields);
double total_cost= 0.0f;
ha_rows records=0;
@@ -4518,7 +4524,7 @@
*/
for (ROR_SCAN_INFO **scan= ror_scan_mark; scan != ror_scans_end; ++scan)
{
- bitmap_subtract(&(*scan)->covered_fields, &covered_fields);
+ bitmap_subtract(&(*scan)->covered_fields, covered_fields);
(*scan)->used_fields_covered=
bitmap_bits_set(&(*scan)->covered_fields);
(*scan)->first_uncovered_field=
@@ -4540,8 +4546,8 @@
if (total_cost > read_time)
DBUG_RETURN(NULL);
/* F=F-covered by first(I) */
- bitmap_union(&covered_fields, &(*ror_scan_mark)->covered_fields);
- all_covered= bitmap_is_subset(¶m->needed_fields, &covered_fields);
+ bitmap_union(covered_fields, &(*ror_scan_mark)->covered_fields);
+ all_covered= bitmap_is_subset(¶m->needed_fields, covered_fields);
} while ((++ror_scan_mark < ror_scans_end) && !all_covered);
if (!all_covered || (ror_scan_mark - tree->ror_scans) == 1)
@@ -4876,25 +4882,37 @@
break;
case Item_func::BETWEEN:
- if (inv)
- {
- tree= get_ne_mm_tree(param, cond_func, field, cond_func->arguments()[1],
- cond_func->arguments()[2], cmp_type);
- }
- else
+ {
+ if (!value)
{
- tree= get_mm_parts(param, cond_func, field, Item_func::GE_FUNC,
- cond_func->arguments()[1],cmp_type);
- if (tree)
+ if (inv)
{
- tree= tree_and(param, tree, get_mm_parts(param, cond_func, field,
- Item_func::LE_FUNC,
- cond_func->arguments()[2],
- cmp_type));
+ tree= get_ne_mm_tree(param, cond_func, field, cond_func->arguments()[1],
+ cond_func->arguments()[2], cmp_type);
+ }
+ else
+ {
+ tree= get_mm_parts(param, cond_func, field, Item_func::GE_FUNC,
+ cond_func->arguments()[1],cmp_type);
+ if (tree)
+ {
+ tree= tree_and(param, tree, get_mm_parts(param, cond_func, field,
+ Item_func::LE_FUNC,
+ cond_func->arguments()[2],
+ cmp_type));
+ }
}
}
+ else
+ tree= get_mm_parts(param, cond_func, field,
+ (inv ?
+ (value == (Item*)1 ? Item_func::GT_FUNC :
+ Item_func::LT_FUNC):
+ (value == (Item*)1 ? Item_func::LE_FUNC :
+ Item_func::GE_FUNC)),
+ cond_func->arguments()[0], cmp_type);
break;
-
+ }
case Item_func::IN_FUNC:
{
Item_func_in *func=(Item_func_in*) cond_func;
@@ -4904,41 +4922,33 @@
if (func->array && func->cmp_type != ROW_RESULT)
{
/*
- We get here for conditions in form "t.key NOT IN (c1, c2, ...)"
- (where c{i} are constants).
- Our goal is to produce a SEL_ARG graph that represents intervals:
+ We get here for conditions in form "t.key NOT IN (c1, c2, ...)",
+ where c{i} are constants. Our goal is to produce a SEL_TREE that
+ represents intervals:
($MIN<t.key<c1) OR (c1<t.key<c2) OR (c2<t.key<c3) OR ...
(*)
where $MIN is either "-inf" or NULL.
- The most straightforward way to handle NOT IN would be to convert
- it to "(t.key != c1) AND (t.key != c2) AND ..." and let the range
- optimizer to build SEL_ARG graph from that. However that will cause
- the range optimizer to use O(N^2) memory (it's a bug, not filed),
- and people do use big NOT IN lists (see BUG#15872). Also, for big
- NOT IN lists constructing/using graph (*) does not make the query
- faster.
-
- So, we will handle NOT IN manually in the following way:
- * if the number of entries in the NOT IN list is less then
- NOT_IN_IGNORE_THRESHOLD, we will construct SEL_ARG graph (*)
- manually.
- * Otherwise, we will construct a smaller graph: for
- "t.key NOT IN (c1,...cN)" we construct a graph representing
- ($MIN < t.key) OR (cN < t.key) // here sequence of c_i is
- // ordered.
-
- A note about partially-covering indexes: for those (e.g. for
- "a CHAR(10), KEY(a(5))") the handling is correct (albeit not very
- efficient):
- Instead of "t.key < c1" we get "t.key <= prefix-val(c1)".
- Combining the intervals in (*) together, we get:
- (-inf<=t.key<=c1) OR (c1<=t.key<=c2) OR (c2<=t.key<=c3) OR
...
- i.e. actually we get intervals combined into one interval:
- (-inf<=t.key<=+inf). This doesn't make much sense but it doesn't
- cause any problems.
+ The most straightforward way to produce it is to convert NOT IN
+ into "(t.key != c1) AND (t.key != c2) AND ... " and let the range
+ analyzer to build SEL_TREE from that. The problem is that the
+ range analyzer will use O(N^2) memory (which is probably a bug),
+ and people do use big NOT IN lists (e.g. see BUG#15872, BUG#21282),
+ will run out of memory.
+
+ Another problem with big lists like (*) is that a big list is
+ unlikely to produce a good "range" access, while considering that
+ range access will require expensive CPU calculations (and for
+ MyISAM even index accesses). In short, big NOT IN lists are rarely
+ worth analyzing.
+
+ Considering the above, we'll handle NOT IN as follows:
+ * if the number of entries in the NOT IN list is less than
+ NOT_IN_IGNORE_THRESHOLD, construct the SEL_TREE (*) manually.
+ * Otherwise, don't produce a SEL_TREE.
*/
+#define NOT_IN_IGNORE_THRESHOLD 1000
MEM_ROOT *tmp_root= param->mem_root;
param->thd->mem_root= param->old_root;
/*
@@ -4952,9 +4962,9 @@
Item *value_item= func->array->create_item();
param->thd->mem_root= tmp_root;
- if (!value_item)
+ if (func->array->count > NOT_IN_IGNORE_THRESHOLD || !value_item)
break;
-
+
/* Get a SEL_TREE for "(-inf|NULL) < X < c_0" interval. */
uint i=0;
do
@@ -4973,45 +4983,39 @@
tree= NULL;
break;
}
-#define NOT_IN_IGNORE_THRESHOLD 1000
SEL_TREE *tree2;
- if (func->array->count < NOT_IN_IGNORE_THRESHOLD)
+ for (; i < func->array->count; i++)
{
- for (; i < func->array->count; i++)
+ if (func->array->compare_elems(i, i-1))
{
- if (func->array->compare_elems(i, i-1))
+ /* Get a SEL_TREE for "-inf < X < c_i" interval */
+ func->array->value_to_item(i, value_item);
+ tree2= get_mm_parts(param, cond_func, field, Item_func::LT_FUNC,
+ value_item, cmp_type);
+ if (!tree2)
{
- /* Get a SEL_TREE for "-inf < X < c_i" interval */
- func->array->value_to_item(i, value_item);
- tree2= get_mm_parts(param, cond_func, field, Item_func::LT_FUNC,
- value_item, cmp_type);
- if (!tree2)
- {
- tree= NULL;
- break;
- }
+ tree= NULL;
+ break;
+ }
- /* Change all intervals to be "c_{i-1} < X < c_i" */
- for (uint idx= 0; idx < param->keys; idx++)
+ /* Change all intervals to be "c_{i-1} < X < c_i" */
+ for (uint idx= 0; idx < param->keys; idx++)
+ {
+ SEL_ARG *new_interval, *last_val;
+ if (((new_interval= tree2->keys[idx])) &&
+ ((last_val= tree->keys[idx]->last())))
{
- SEL_ARG *new_interval, *last_val;
- if (((new_interval= tree2->keys[idx])) &&
- ((last_val= tree->keys[idx]->last())))
- {
- new_interval->min_value= last_val->max_value;
- new_interval->min_flag= NEAR_MIN;
- }
+ new_interval->min_value= last_val->max_value;
+ new_interval->min_flag= NEAR_MIN;
}
- /*
- The following doesn't try to allocate memory so no need to
- check for NULL.
- */
- tree= tree_or(param, tree, tree2);
}
+ /*
+ The following doesn't try to allocate memory so no need to
+ check for NULL.
+ */
+ tree= tree_or(param, tree, tree2);
}
}
- else
- func->array->value_to_item(func->array->count - 1, value_item);
if (tree && tree->type != SEL_TREE::IMPOSSIBLE)
{
@@ -5076,7 +5080,118 @@
}
DBUG_RETURN(tree);
+}
+
+
+/*
+ Build conjunction of all SEL_TREEs for a simple predicate applying equalities
+
+ SYNOPSIS
+ get_full_func_mm_tree()
+ param PARAM from SQL_SELECT::test_quick_select
+ cond_func item for the predicate
+ field_item field in the predicate
+ value constant in the predicate
+ (for BETWEEN it contains the number of the field argument,
+ for IN it's always 0)
+ inv TRUE <> NOT cond_func is considered
+ (makes sense only when cond_func is BETWEEN or IN)
+
+ DESCRIPTION
+ For a simple SARGable predicate of the form (f op c), where f is a field and
+ c is a constant, the function builds a conjunction of all SEL_TREES that can
+ be obtained by the substitution of f for all different fields equal to f.
+
+ NOTES
+ If the WHERE condition contains a predicate (fi op c),
+ then not only SELL_TREE for this predicate is built, but
+ the trees for the results of substitution of fi for
+ each fj belonging to the same multiple equality as fi
+ are built as well.
+ E.g. for WHERE t1.a=t2.a AND t2.a > 10
+ a SEL_TREE for t2.a > 10 will be built for quick select from t2
+ and
+ a SEL_TREE for t1.a > 10 will be built for quick select from t1.
+
+ A BETWEEN predicate of the form (fi [NOT] BETWEEN c1 AND c2) is treated
+ in a similar way: we build a conjuction of trees for the results
+ of all substitutions of fi for equal fj.
+ Yet a predicate of the form (c BETWEEN f1i AND f2i) is processed
+ differently. It is considered as a conjuction of two SARGable
+ predicates (f1i <= c) and (f2i <=c) and the function get_full_func_mm_tree
+ is called for each of them separately producing trees for
+ AND j (f1j <=c ) and AND j (f2j <= c)
+ After this these two trees are united in one conjunctive tree.
+ It's easy to see that the same tree is obtained for
+ AND j,k (f1j <=c AND f2k<=c)
+ which is equivalent to
+ AND j,k (c BETWEEN f1j AND f2k).
+ The validity of the processing of the predicate (c NOT BETWEEN f1i AND f2i)
+ which equivalent to (f1i > c OR f2i < c) is not so obvious. Here the
+ function get_full_func_mm_tree is called for (f1i > c) and (f2i < c)
+ producing trees for AND j (f1j > c) and AND j (f2j < c). Then this two
+ trees are united in one OR-tree. The expression
+ (AND j (f1j > c) OR AND j (f2j < c)
+ is equivalent to the expression
+ AND j,k (f1j > c OR f2k < c)
+ which is just a translation of
+ AND j,k (c NOT BETWEEN f1j AND f2k)
+
+ In the cases when one of the items f1, f2 is a constant c1 we do not create
+ a tree for it at all. It works for BETWEEN predicates but does not
+ work for NOT BETWEEN predicates as we have to evaluate the expression
+ with it. If it is TRUE then the other tree can be completely ignored.
+ We do not do it now and no trees are built in these cases for
+ NOT BETWEEN predicates.
+
+ As to IN predicates only ones of the form (f IN (c1,...,cn)),
+ where f1 is a field and c1,...,cn are constant, are considered as
+ SARGable. We never try to narrow the index scan using predicates of
+ the form (c IN (c1,...,f,...,cn)).
+
+ RETURN
+ Pointer to the tree representing the built conjunction of SEL_TREEs
+*/
+
+static SEL_TREE *get_full_func_mm_tree(PARAM *param, Item_func *cond_func,
+ Item_field *field_item, Item *value,
+ bool inv)
+{
+ SEL_TREE *tree= 0;
+ SEL_TREE *ftree= 0;
+ table_map ref_tables= 0;
+ table_map param_comp= ~(param->prev_tables | param->read_tables |
+ param->current_table);
+ DBUG_ENTER("get_full_func_mm_tree");
+ for (uint i= 0; i < cond_func->arg_count; i++)
+ {
+ Item *arg= cond_func->arguments()[i]->real_item();
+ if (arg != field_item)
+ ref_tables|= arg->used_tables();
+ }
+ Field *field= field_item->field;
+ Item_result cmp_type= field->cmp_type();
+ if (!((ref_tables | field->table->map) & param_comp))
+ ftree= get_func_mm_tree(param, cond_func, field, value, cmp_type, inv);
+ Item_equal *item_equal= field_item->item_equal;
+ if (item_equal)
+ {
+ Item_equal_iterator it(*item_equal);
+ Item_field *item;
+ while ((item= it++))
+ {
+ Field *f= item->field;
+ if (field->eq(f))
+ continue;
+ if (!((ref_tables | f->table->map) & param_comp))
+ {
+ tree= get_func_mm_tree(param, cond_func, f, value, cmp_type, inv);
+ ftree= !ftree ? tree : tree_and(param, ftree, tree);
+ }
+ }
+ }
+ DBUG_RETURN(ftree);
}
/* make a select tree of all keys in condition */
@@ -5087,7 +5202,7 @@
SEL_TREE *ftree= 0;
Item_field *field_item= 0;
bool inv= FALSE;
- Item *value;
+ Item *value= 0;
DBUG_ENTER("get_mm_tree");
if (cond->type() == Item::COND_ITEM)
@@ -5167,10 +5282,37 @@
switch (cond_func->functype()) {
case Item_func::BETWEEN:
- if (cond_func->arguments()[0]->real_item()->type() != Item::FIELD_ITEM)
- DBUG_RETURN(0);
- field_item= (Item_field*) (cond_func->arguments()[0]->real_item());
- value= NULL;
+ if (cond_func->arguments()[0]->real_item()->type() == Item::FIELD_ITEM)
+ {
+ field_item= (Item_field*) (cond_func->arguments()[0]->real_item());
+ ftree= get_full_func_mm_tree(param, cond_func, field_item, NULL, inv);
+ }
+
+ /*
+ Concerning the code below see the NOTES section in
+ the comments for the function get_full_func_mm_tree()
+ */
+ for (uint i= 1 ; i < cond_func->arg_count ; i++)
+ {
+
+ if (cond_func->arguments()[i]->real_item()->type() == Item::FIELD_ITEM)
+ {
+ field_item= (Item_field*) (cond_func->arguments()[i]->real_item());
+ SEL_TREE *tmp= get_full_func_mm_tree(param, cond_func,
+ field_item, (Item*) i, inv);
+ if (inv)
+ tree= !tree ? tmp : tree_or(param, tree, tmp);
+ else
+ tree= tree_and(param, tree, tmp);
+ }
+ else if (inv)
+ {
+ tree= 0;
+ break;
+ }
+ }
+
+ ftree = tree_and(param, ftree, tree);
break;
case Item_func::IN_FUNC:
{
@@ -5178,7 +5320,7 @@
if (func->key_item()->real_item()->type() != Item::FIELD_ITEM)
DBUG_RETURN(0);
field_item= (Item_field*) (func->key_item()->real_item());
- value= NULL;
+ ftree= get_full_func_mm_tree(param, cond_func, field_item, NULL, inv);
break;
}
case Item_func::MULT_EQUAL_FUNC:
@@ -5217,47 +5359,9 @@
}
else
DBUG_RETURN(0);
+ ftree= get_full_func_mm_tree(param, cond_func, field_item, value, inv);
}
- /*
- If the where condition contains a predicate (ti.field op const),
- then not only SELL_TREE for this predicate is built, but
- the trees for the results of substitution of ti.field for
- each tj.field belonging to the same multiple equality as ti.field
- are built as well.
- E.g. for WHERE t1.a=t2.a AND t2.a > 10
- a SEL_TREE for t2.a > 10 will be built for quick select from t2
- and
- a SEL_TREE for t1.a > 10 will be built for quick select from t1.
- */
-
- for (uint i= 0; i < cond_func->arg_count; i++)
- {
- Item *arg= cond_func->arguments()[i]->real_item();
- if (arg != field_item)
- ref_tables|= arg->used_tables();
- }
- Field *field= field_item->field;
- Item_result cmp_type= field->cmp_type();
- if (!((ref_tables | field->table->map) & param_comp))
- ftree= get_func_mm_tree(param, cond_func, field, value, cmp_type, inv);
- Item_equal *item_equal= field_item->item_equal;
- if (item_equal)
- {
- Item_equal_iterator it(*item_equal);
- Item_field *item;
- while ((item= it++))
- {
- Field *f= item->field;
- if (field->eq(f))
- continue;
- if (!((ref_tables | f->table->map) & param_comp))
- {
- tree= get_func_mm_tree(param, cond_func, f, value, cmp_type, inv);
- ftree= !ftree ? tree : tree_and(param, ftree, tree);
- }
- }
- }
DBUG_RETURN(ftree);
}
--- 1.207/sql/sql_acl.cc 2006-08-29 18:58:58 +04:00
+++ 1.208/sql/sql_acl.cc 2006-08-29 18:58:58 +04:00
@@ -1006,6 +1006,7 @@
sql_print_information("X509 issuer mismatch: should be '%s' "
"but is '%s'", acl_user->x509_issuer, ptr);
free(ptr);
+ user_access=NO_ACCESS;
break;
}
user_access= acl_user->access;
@@ -1021,11 +1022,13 @@
if (strcmp(acl_user->x509_subject,ptr))
{
if (global_system_variables.log_warnings)
- sql_print_information("X509 subject mismatch: '%s' vs '%s'",
+ sql_print_information("X509 subject mismatch: should be '%s' but is '%s'",
acl_user->x509_subject, ptr);
+ free(ptr);
+ user_access=NO_ACCESS;
+ break;
}
- else
- user_access= acl_user->access;
+ user_access= acl_user->access;
free(ptr);
}
break;
--- 1.346/sql/sql_base.cc 2006-08-29 18:58:58 +04:00
+++ 1.347/sql/sql_base.cc 2006-08-29 18:58:58 +04:00
@@ -5482,9 +5482,11 @@
TABLE_LIST *tables,
TABLE_LIST **leaves,
bool select_insert,
+ ulong_want_access_first,
ulong want_access)
{
TABLE_LIST *leaves_tmp= NULL;
+ bool first_table= true;
if (setup_tables(thd, context, from_clause, tables,
&leaves_tmp, select_insert))
@@ -5495,11 +5497,13 @@
for (; leaves_tmp; leaves_tmp= leaves_tmp->next_leaf)
{
if (leaves_tmp->belong_to_view &&
- check_single_table_access(thd, want_access, leaves_tmp))
+ check_single_table_access(thd, first_table ? want_access_first :
+ want_access, leaves_tmp))
{
tables->hide_view_error(thd);
return TRUE;
}
+ first_table= 0;
}
return FALSE;
}
--- 1.285/sql/sql_class.cc 2006-08-29 18:58:58 +04:00
+++ 1.286/sql/sql_class.cc 2006-08-29 18:58:58 +04:00
@@ -1983,7 +1983,7 @@
{
if ((xx=li++))
{
- xx->check();
+ xx->check(0);
xx->update();
}
}
--- 1.191/sql/sql_delete.cc 2006-08-29 18:58:58 +04:00
+++ 1.192/sql/sql_delete.cc 2006-08-29 18:58:58 +04:00
@@ -386,7 +386,7 @@
&thd->lex->select_lex.top_join_list,
table_list,
&select_lex->leaf_tables, FALSE,
- DELETE_ACL) ||
+ DELETE_ACL, SELECT_ACL) ||
setup_conds(thd, table_list, select_lex->leaf_tables, conds) ||
setup_ftfuncs(select_lex))
DBUG_RETURN(TRUE);
@@ -449,7 +449,7 @@
&thd->lex->select_lex.top_join_list,
lex->query_tables,
&lex->select_lex.leaf_tables, FALSE,
- DELETE_ACL))
+ DELETE_ACL, SELECT_ACL))
DBUG_RETURN(TRUE);
--- 1.220/sql/sql_insert.cc 2006-08-29 18:58:58 +04:00
+++ 1.221/sql/sql_insert.cc 2006-08-29 18:58:58 +04:00
@@ -821,7 +821,7 @@
&thd->lex->select_lex.top_join_list,
table_list,
&thd->lex->select_lex.leaf_tables,
- select_insert, SELECT_ACL))
+ select_insert, INSERT_ACL, SELECT_ACL))
DBUG_RETURN(TRUE);
if (insert_into_view && !fields.elements)
--- 1.103/sql/sql_load.cc 2006-08-29 18:58:58 +04:00
+++ 1.104/sql/sql_load.cc 2006-08-29 18:58:58 +04:00
@@ -156,6 +156,7 @@
&thd->lex->select_lex.top_join_list,
table_list,
&thd->lex->select_lex.leaf_tables, FALSE,
+ INSERT_ACL | UPDATE_ACL,
INSERT_ACL | UPDATE_ACL))
DBUG_RETURN(-1);
if (!table_list->table || // do not suport join view
--- 1.580/sql/sql_parse.cc 2006-08-29 18:58:59 +04:00
+++ 1.581/sql/sql_parse.cc 2006-08-29 18:58:59 +04:00
@@ -5354,10 +5354,21 @@
return 1;
/* Check rights on tables of subselects and implictly opened tables */
- TABLE_LIST *subselects_tables;
+ TABLE_LIST *subselects_tables, *view= all_tables->view ? all_tables : 0;
if ((subselects_tables= all_tables->next_global))
{
- if ((check_table_access(thd, SELECT_ACL, subselects_tables, 0)))
+ /*
+ Access rights asked for the first table of a view should be the same
+ as for the view
+ */
+ if (view && subselects_tables->belong_to_view == view)
+ {
+ if (check_single_table_access (thd, privilege, subselects_tables))
+ return 1;
+ subselects_tables= subselects_tables->next_global;
+ }
+ if (subselects_tables &&
+ (check_table_access(thd, SELECT_ACL, subselects_tables, 0)))
return 1;
}
return 0;
--- 1.431/sql/sql_select.cc 2006-08-29 18:58:59 +04:00
+++ 1.432/sql/sql_select.cc 2006-08-29 18:58:59 +04:00
@@ -344,7 +344,7 @@
setup_tables_and_check_access(thd, &select_lex->context, join_list,
tables_list,
&select_lex->leaf_tables, FALSE,
- SELECT_ACL)) ||
+ SELECT_ACL, SELECT_ACL)) ||
setup_wild(thd, tables_list, fields_list, &all_fields, wild_num) ||
select_lex->setup_ref_array(thd, og_num) ||
setup_fields(thd, (*rref_pointer_array), fields_list, MARK_COLUMNS_READ,
@@ -2233,6 +2233,7 @@
int ref_changed;
do
{
+ more_const_tables_found:
ref_changed = 0;
found_ref=0;
@@ -2244,6 +2245,30 @@
for (JOIN_TAB **pos=stat_vector+const_count ; (s= *pos) ; pos++)
{
table=s->table;
+
+ /*
+ If equi-join condition by a key is null rejecting and after a
+ substitution of a const table the key value happens to be null
+ then we can state that there are no matches for this equi-join.
+ */
+ if ((keyuse= s->keyuse) && *s->on_expr_ref)
+ {
+ while (keyuse->table == table)
+ {
+ if (!(keyuse->val->used_tables() & ~join->const_table_map)
&&
+ keyuse->val->is_null() && keyuse->null_rejecting)
+ {
+ s->type= JT_CONST;
+ mark_as_null_row(table);
+ found_const_table_map|= table->map;
+ join->const_table_map|= table->map;
+ set_position(join,const_count++,s,(KEYUSE*) 0);
+ goto more_const_tables_found;
+ }
+ keyuse++;
+ }
+ }
+
if (s->dependent) // If dependent on some table
{
// All dep. must be constants
@@ -2294,34 +2319,38 @@
} while (keyuse->table == table && keyuse->key == key);
if (eq_part.is_prefix(table->key_info[key].key_parts) &&
- ((table->key_info[key].flags & (HA_NOSAME | HA_END_SPACE_KEY)) ==
- HA_NOSAME) &&
!table->fulltext_searched &&
!table->pos_in_table_list->embedding)
{
- if (const_ref == eq_part)
- { // Found everything for ref.
- int tmp;
- ref_changed = 1;
- s->type= JT_CONST;
- join->const_table_map|=table->map;
- set_position(join,const_count++,s,start_keyuse);
- if (create_ref_for_key(join, s, start_keyuse,
- found_const_table_map))
- DBUG_RETURN(1);
- if ((tmp=join_read_const_table(s,
- join->positions+const_count-1)))
- {
- if (tmp > 0)
- DBUG_RETURN(1); // Fatal error
+ if ((table->key_info[key].flags & (HA_NOSAME | HA_END_SPACE_KEY))
+ == HA_NOSAME)
+ {
+ if (const_ref == eq_part)
+ { // Found everything for ref.
+ int tmp;
+ ref_changed = 1;
+ s->type= JT_CONST;
+ join->const_table_map|=table->map;
+ set_position(join,const_count++,s,start_keyuse);
+ if (create_ref_for_key(join, s, start_keyuse,
+ found_const_table_map))
+ DBUG_RETURN(1);
+ if ((tmp=join_read_const_table(s,
+ join->positions+const_count-1)))
+ {
+ if (tmp > 0)
+ DBUG_RETURN(1); // Fatal error
+ }
+ else
+ found_const_table_map|= table->map;
+ break;
}
else
- found_const_table_map|= table->map;
- break;
+ found_ref|= refs; // Table is const if all refs are const
}
- else
- found_ref|= refs; // Table is const if all refs are const
- }
+ else if (const_ref == eq_part)
+ s->const_keys.set_bit(key);
+ }
}
}
}
@@ -2727,7 +2756,8 @@
We use null_rejecting in add_not_null_conds() to add
'othertbl.field IS NOT NULL' to tab->select_cond.
*/
- (*key_fields)->null_rejecting= ((cond->functype() == Item_func::EQ_FUNC)
&&
+ (*key_fields)->null_rejecting= ((cond->functype() == Item_func::EQ_FUNC ||
+ cond->functype() == Item_func::MULT_EQUAL_FUNC)
&&
((*value)->type() == Item::FIELD_ITEM) &&
((Item_field*)*value)->field->maybe_null());
(*key_fields)++;
@@ -2827,11 +2857,12 @@
break;
case Item_func::OPTIMIZE_KEY:
{
+ Item **values;
// BETWEEN, IN, NE
if (cond_func->key_item()->real_item()->type() == Item::FIELD_ITEM
&&
!(cond_func->used_tables() & OUTER_REF_TABLE_BIT))
{
- Item **values= cond_func->arguments()+1;
+ values= cond_func->arguments()+1;
if (cond_func->functype() == Item_func::NE_FUNC &&
cond_func->arguments()[1]->real_item()->type() == Item::FIELD_ITEM
&&
!(cond_func->arguments()[0]->used_tables() & OUTER_REF_TABLE_BIT))
@@ -2844,6 +2875,22 @@
cond_func->argument_count()-1,
usable_tables);
}
+ if (cond_func->functype() == Item_func::BETWEEN)
+ {
+ values= cond_func->arguments();
+ for (uint i= 1 ; i < cond_func->argument_count() ; i++)
+ {
+ Item_field *field_item;
+ if (cond_func->arguments()[i]->real_item()->type() == Item::FIELD_ITEM
+ &&
+ !(cond_func->arguments()[i]->used_tables() & OUTER_REF_TABLE_BIT))
+ {
+ field_item= (Item_field *) (cond_func->arguments()[i]->real_item());
+ add_key_equal_fields(key_fields, *and_level, cond_func,
+ field_item, 0, values, 1, usable_tables);
+ }
+ }
+ }
break;
}
case Item_func::OPTIMIZE_OP:
@@ -3476,7 +3523,7 @@
keyuse->used_tables));
if (tmp < best_prev_record_reads)
{
- best_part_found_ref= keyuse->used_tables;
+ best_part_found_ref= keyuse->used_tables &
~join->const_table_map;
best_prev_record_reads= tmp;
}
if (rec > keyuse->ref_table_rows)
@@ -6034,7 +6081,8 @@
if (tab->cached_eq_ref_table) // If cached
return tab->eq_ref_table;
tab->cached_eq_ref_table=1;
- if (tab->type == JT_CONST) // We can skip const tables
+ /* We can skip const tables only if not an outer table */
+ if (tab->type == JT_CONST && !tab->first_inner)
return (tab->eq_ref_table=1); /* purecov: inspected */
if (tab->type != JT_EQ_REF || tab->table->maybe_null)
return (tab->eq_ref_table=0); // We must use this
@@ -6556,6 +6604,7 @@
field_item= (Item_field*) right_item;
const_item= left_item;
}
+
if (const_item &&
field_item->result_type() == const_item->result_type())
{
@@ -7213,6 +7262,7 @@
Item_func::Functype functype= func->functype();
if (right_item->eq(field,0) && left_item != value &&
+ right_item->cmp_context == field->cmp_context &&
(left_item->result_type() != STRING_RESULT ||
value->result_type() != STRING_RESULT ||
left_item->collation.collation == value->collation.collation))
@@ -7234,6 +7284,7 @@
}
}
else if (left_item->eq(field,0) && right_item != value &&
+ left_item->cmp_context == field->cmp_context &&
(right_item->result_type() != STRING_RESULT ||
value->result_type() != STRING_RESULT ||
right_item->collation.collation == value->collation.collation))
@@ -11619,6 +11670,8 @@
We must not try to use disabled keys.
*/
usable_keys= table->s->keys_in_use;
+ /* we must not consider keys that are disabled by IGNORE INDEX */
+ usable_keys.intersect(table->keys_in_use_for_query);
for (ORDER *tmp_order=order; tmp_order ; tmp_order=tmp_order->next)
{
@@ -13489,7 +13542,9 @@
{
Field *field;
- if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM)
+ if ((item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM) ||
+ (item->type() == Item::FUNC_ITEM &&
+ ((Item_func*)item)->functype() == Item_func::SUSERVAR_FUNC))
item_field= item;
else
{
--- 1.204/sql/sql_update.cc 2006-08-29 18:58:59 +04:00
+++ 1.205/sql/sql_update.cc 2006-08-29 18:58:59 +04:00
@@ -746,7 +746,7 @@
&select_lex->top_join_list,
table_list,
&select_lex->leaf_tables,
- FALSE, UPDATE_ACL) ||
+ FALSE, UPDATE_ACL, SELECT_ACL) ||
setup_conds(thd, table_list, select_lex->leaf_tables, conds) ||
select_lex->setup_ref_array(thd, order_num) ||
setup_order(thd, select_lex->ref_pointer_array,
@@ -841,7 +841,7 @@
&lex->select_lex.top_join_list,
table_list,
&lex->select_lex.leaf_tables, FALSE,
- UPDATE_ACL))
+ UPDATE_ACL, SELECT_ACL))
DBUG_RETURN(TRUE);
if (setup_fields_with_no_wrap(thd, 0, *fields, MARK_COLUMNS_WRITE, 0, 0))
--- 1.7/mysql-test/r/innodb_mysql.result 2006-08-29 18:58:59 +04:00
+++ 1.8/mysql-test/r/innodb_mysql.result 2006-08-29 18:58:59 +04:00
@@ -89,6 +89,27 @@
3 3
3 3
DROP TABLE t1, t2, t3;
+CREATE TABLE `t1` (`id1` INT) ;
+INSERT INTO `t1` (`id1`) VALUES (1),(5),(2);
+CREATE TABLE `t2` (
+`id1` INT,
+`id2` INT NOT NULL,
+`id3` INT,
+`id4` INT NOT NULL,
+UNIQUE (`id2`,`id4`),
+KEY (`id1`)
+) ENGINE=InnoDB;
+INSERT INTO `t2`(`id1`,`id2`,`id3`,`id4`) VALUES
+(1,1,1,0),
+(1,1,2,1),
+(5,1,2,2),
+(6,1,2,3),
+(1,2,2,2),
+(1,2,1,1);
+SELECT `id1` FROM `t1` WHERE `id1` NOT IN (SELECT `id1` FROM `t2` WHERE `id2` = 1 AND
`id3` = 2);
+id1
+2
+DROP TABLE t1, t2;
create table t1m (a int) engine=myisam;
create table t1i (a int) engine=innodb;
create table t2m (a int) engine=myisam;
@@ -303,6 +324,25 @@
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range NULL PRIMARY 5 NULL 3 Using index for group-by; Using temporary
drop table t1;
+CREATE TABLE t1 (id int(11) NOT NULL PRIMARY KEY, name varchar(20),
+INDEX (name)) ENGINE=InnoDB;
+CREATE TABLE t2 (id int(11) NOT NULL PRIMARY KEY, fkey int(11),
+FOREIGN KEY (fkey) REFERENCES t2(id)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1,'A1'),(2,'A2'),(3,'B');
+INSERT INTO t2 VALUES (1,1),(2,2),(3,2),(4,3),(5,3);
+EXPLAIN
+SELECT COUNT(*) FROM t2 LEFT JOIN t1 ON t2.fkey = t1.id
+WHERE t1.name LIKE 'A%';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index PRIMARY,name name 23 NULL 3 Using where; Using index
+1 SIMPLE t2 ref fkey fkey 5 test.t1.id 1 Using where; Using index
+EXPLAIN
+SELECT COUNT(*) FROM t2 LEFT JOIN t1 ON t2.fkey = t1.id
+WHERE t1.name LIKE 'A%' OR FALSE;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 index NULL fkey 5 NULL 5 Using index
+1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 test.t2.fkey 1 Using where
+DROP TABLE t1,t2;
set storage_engine=innodb;
CREATE TABLE t1 (a int, b int);
insert into t1 values (1,1),(1,2);
--- 1.7/mysql-test/t/innodb_mysql.test 2006-08-29 18:58:59 +04:00
+++ 1.8/mysql-test/t/innodb_mysql.test 2006-08-29 18:58:59 +04:00
@@ -98,6 +98,33 @@
t3.a = t2.a AND t2.b = t1.a AND t3.b = 1 AND t3.c IN (1, 2)
ORDER BY t1.b LIMIT 5;
DROP TABLE t1, t2, t3;
+
+
+# BUG#21077 (The testcase is not deterministic so correct execution doesn't
+# prove anything) For proof one should track if sequence of ha_innodb::* func
+# calls is correct.
+CREATE TABLE `t1` (`id1` INT) ;
+INSERT INTO `t1` (`id1`) VALUES (1),(5),(2);
+
+CREATE TABLE `t2` (
+ `id1` INT,
+ `id2` INT NOT NULL,
+ `id3` INT,
+ `id4` INT NOT NULL,
+ UNIQUE (`id2`,`id4`),
+ KEY (`id1`)
+) ENGINE=InnoDB;
+
+INSERT INTO `t2`(`id1`,`id2`,`id3`,`id4`) VALUES
+(1,1,1,0),
+(1,1,2,1),
+(5,1,2,2),
+(6,1,2,3),
+(1,2,2,2),
+(1,2,1,1);
+
+SELECT `id1` FROM `t1` WHERE `id1` NOT IN (SELECT `id1` FROM `t2` WHERE `id2` = 1 AND
`id3` = 2);
+DROP TABLE t1, t2;
#
# Bug #12882 min/max inconsistent on empty table
#
@@ -263,6 +290,26 @@
explain select distinct f1, f2 from t1;
drop table t1;
+#
+# Test for bug #17164: ORed FALSE blocked conversion of outer join into join
+#
+
+CREATE TABLE t1 (id int(11) NOT NULL PRIMARY KEY, name varchar(20),
+ INDEX (name)) ENGINE=InnoDB;
+CREATE TABLE t2 (id int(11) NOT NULL PRIMARY KEY, fkey int(11),
+ FOREIGN KEY (fkey) REFERENCES t2(id)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1,'A1'),(2,'A2'),(3,'B');
+INSERT INTO t2 VALUES (1,1),(2,2),(3,2),(4,3),(5,3);
+
+EXPLAIN
+SELECT COUNT(*) FROM t2 LEFT JOIN t1 ON t2.fkey = t1.id
+ WHERE t1.name LIKE 'A%';
+
+EXPLAIN
+SELECT COUNT(*) FROM t2 LEFT JOIN t1 ON t2.fkey = t1.id
+ WHERE t1.name LIKE 'A%' OR FALSE;
+
+DROP TABLE t1,t2;
#
# Test of behaviour with CREATE ... SELECT
--- 1.150/mysql-test/r/subselect.result 2006-08-29 18:58:59 +04:00
+++ 1.151/mysql-test/r/subselect.result 2006-08-29 18:58:59 +04:00
@@ -2915,6 +2915,28 @@
s1
2
drop table t1;
+create table t1 (
+retailerID varchar(8) NOT NULL,
+statusID int(10) unsigned NOT NULL,
+changed datetime NOT NULL,
+UNIQUE KEY retailerID (retailerID, statusID, changed)
+);
+INSERT INTO t1 VALUES("0026", "1", "2005-12-06 12:18:56");
+INSERT INTO t1 VALUES("0026", "2", "2006-01-06 12:25:53");
+INSERT INTO t1 VALUES("0037", "1", "2005-12-06 12:18:56");
+INSERT INTO t1 VALUES("0037", "2", "2006-01-06 12:25:53");
+INSERT INTO t1 VALUES("0048", "1", "2006-01-06 12:37:50");
+INSERT INTO t1 VALUES("0059", "1", "2006-01-06 12:37:50");
+select * from t1 r1
+where (r1.retailerID,(r1.changed)) in
+(SELECT r2.retailerId,(max(changed)) from t1 r2
+group by r2.retailerId);
+retailerID statusID changed
+0026 2 2006-01-06 12:25:53
+0037 2 2006-01-06 12:25:53
+0048 1 2006-01-06 12:37:50
+0059 1 2006-01-06 12:37:50
+drop table t1;
create table t1 (df decimal(5,1));
insert into t1 values(1.1);
insert into t1 values(2.2);
--- 1.172/mysql-test/r/view.result 2006-08-29 18:58:59 +04:00
+++ 1.173/mysql-test/r/view.result 2006-08-29 18:58:59 +04:00
@@ -2850,3 +2850,32 @@
t1
DROP TABLE t1;
DROP VIEW IF EXISTS v1;
+CREATE DATABASE bug21261DB;
+USE bug21261DB;
+CREATE TABLE t1 (x INT);
+CREATE SQL SECURITY INVOKER VIEW v1 AS SELECT x FROM t1;
+GRANT INSERT, UPDATE ON v1 TO 'user21261'@'localhost';
+GRANT INSERT, UPDATE ON t1 TO 'user21261'@'localhost';
+CREATE TABLE t2 (y INT);
+GRANT SELECT ON t2 TO 'user21261'@'localhost';
+INSERT INTO v1 (x) VALUES (5);
+UPDATE v1 SET x=1;
+GRANT SELECT ON v1 TO 'user21261'@'localhost';
+GRANT SELECT ON t1 TO 'user21261'@'localhost';
+UPDATE v1,t2 SET x=1 WHERE x=y;
+SELECT * FROM t1;
+x
+1
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'user21261'@'localhost';
+DROP USER 'user21261'@'localhost';
+DROP VIEW v1;
+DROP TABLE t1;
+DROP DATABASE bug21261DB;
+USE test;
+create table t1 (f1 datetime);
+create view v1 as select * from t1 where f1 between now() and now() + interval 1 minute;
+show create view v1;
+View Create View
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1`
AS select `t1`.`f1` AS `f1` from `t1` where (`t1`.`f1` between now() and (now() +
interval 1 minute))
+drop view v1;
+drop table t1;
--- 1.153/mysql-test/t/view.test 2006-08-29 18:58:59 +04:00
+++ 1.154/mysql-test/t/view.test 2006-08-29 18:58:59 +04:00
@@ -2723,3 +2723,45 @@
--disable_warnings
DROP VIEW IF EXISTS v1;
--enable_warnings
+
+#
+# Bug #21261: Wrong access rights was required for an insert to a view
+#
+CREATE DATABASE bug21261DB;
+USE bug21261DB;
+CONNECT (root,localhost,root,,bug21261DB);
+CONNECTION root;
+
+CREATE TABLE t1 (x INT);
+CREATE SQL SECURITY INVOKER VIEW v1 AS SELECT x FROM t1;
+GRANT INSERT, UPDATE ON v1 TO 'user21261'@'localhost';
+GRANT INSERT, UPDATE ON t1 TO 'user21261'@'localhost';
+CREATE TABLE t2 (y INT);
+GRANT SELECT ON t2 TO 'user21261'@'localhost';
+
+CONNECT (user21261, localhost, user21261,, bug21261DB);
+CONNECTION user21261;
+INSERT INTO v1 (x) VALUES (5);
+UPDATE v1 SET x=1;
+CONNECTION root;
+GRANT SELECT ON v1 TO 'user21261'@'localhost';
+GRANT SELECT ON t1 TO 'user21261'@'localhost';
+CONNECTION user21261;
+UPDATE v1,t2 SET x=1 WHERE x=y;
+CONNECTION root;
+SELECT * FROM t1;
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'user21261'@'localhost';
+DROP USER 'user21261'@'localhost';
+DROP VIEW v1;
+DROP TABLE t1;
+DROP DATABASE bug21261DB;
+USE test;
+
+#
+# Bug #15950: NOW() optimized away in VIEWs
+#
+create table t1 (f1 datetime);
+create view v1 as select * from t1 where f1 between now() and now() + interval 1 minute;
+show create view v1;
+drop view v1;
+drop table t1;
--- 1.128/sql/item_subselect.cc 2006-08-29 18:58:59 +04:00
+++ 1.129/sql/item_subselect.cc 2006-08-29 18:58:59 +04:00
@@ -1141,24 +1141,23 @@
DBUG_RETURN(RES_ERROR);
Item *item_eq=
new Item_func_eq(new
- Item_direct_ref(&select_lex->context,
- (*optimizer->get_cache())->
- addr(i),
- (char *)"<no matter>",
- (char *)in_left_expr_name),
+ Item_ref(&select_lex->context,
+ (*optimizer->get_cache())->
+ addr(i),
+ (char *)"<no matter>",
+ (char *)in_left_expr_name),
new
- Item_direct_ref(&select_lex->context,
- select_lex->ref_pointer_array + i,
- (char *)"<no matter>",
- (char *)"<list ref>")
+ Item_ref(&select_lex->context,
+ select_lex->ref_pointer_array + i,
+ (char *)"<no matter>",
+ (char *)"<list ref>")
);
Item *item_isnull=
new Item_func_isnull(new
- Item_direct_ref(&select_lex->context,
- select_lex->
- ref_pointer_array+i,
- (char *)"<no matter>",
- (char *)"<list ref>")
+ Item_ref(&select_lex->context,
+ select_lex->ref_pointer_array+i,
+ (char *)"<no matter>",
+ (char *)"<list ref>")
);
having_item=
and_items(having_item,
@@ -1168,11 +1167,11 @@
new
Item_is_not_null_test(this,
new
- Item_direct_ref(&select_lex->context,
- select_lex->
- ref_pointer_array + i,
- (char *)"<no matter>",
- (char *)"<list ref>")
+ Item_ref(&select_lex->context,
+ select_lex->
+ ref_pointer_array + i,
+ (char *)"<no matter>",
+ (char *)"<list ref>")
)
);
item_having_part2->top_level_item();
@@ -1228,11 +1227,11 @@
new
Item_is_not_null_test(this,
new
- Item_direct_ref(&select_lex->context,
- select_lex->
- ref_pointer_array + i,
- (char *)"<no matter>",
- (char *)"<list ref>")
+ Item_ref(&select_lex->context,
+ select_lex->
+ ref_pointer_array + i,
+ (char *)"<no matter>",
+ (char *)"<list ref>")
)
);
item_isnull= new
--- 1.38.3.1/innobase/btr/btr0btr.c 2006-08-29 18:58:59 +04:00
+++ 1.45/storage/innobase/btr/btr0btr.c 2006-08-29 18:58:59 +04:00
@@ -5,7 +5,7 @@
Created 6/2/1994 Heikki Tuuri
*******************************************************/
-
+
#include "btr0btr.h"
#ifdef UNIV_NONINL
@@ -56,7 +56,7 @@
which are >= P in the alphabetical order, but < P1 if there is
a next node pointer on the level, and P1 is its prefix.
-If a node pointer with a prefix P points to a non-leaf child,
+If a node pointer with a prefix P points to a non-leaf child,
then the leftmost record in the child must have the same
prefix P. If it points to a leaf node, the child is not required
to contain any record with a prefix equal to P. The leaf case
@@ -138,14 +138,14 @@
ulint space;
ulint root_page_no;
page_t* root;
-
+
space = dict_tree_get_space(tree);
root_page_no = dict_tree_get_page(tree);
root = btr_page_get(space, root_page_no, RW_X_LATCH, mtr);
ut_a((ibool)!!page_is_comp(root) ==
- UT_LIST_GET_FIRST(tree->tree_indexes)->table->comp);
-
+ dict_table_is_comp(tree->tree_index->table));
+
return(root);
}
@@ -175,21 +175,25 @@
return(prev_rec);
}
}
-
+
page = buf_frame_align(rec);
prev_page_no = btr_page_get_prev(page, mtr);
space = buf_frame_get_space_id(page);
-
+
if (prev_page_no != FIL_NULL) {
prev_page = buf_page_get_with_no_latch(space, prev_page_no,
mtr);
/* The caller must already have a latch to the brother */
ut_ad((mtr_memo_contains(mtr, buf_block_align(prev_page),
- MTR_MEMO_PAGE_S_FIX))
- || (mtr_memo_contains(mtr, buf_block_align(prev_page),
- MTR_MEMO_PAGE_X_FIX)));
+ MTR_MEMO_PAGE_S_FIX))
+ || (mtr_memo_contains(mtr, buf_block_align(prev_page),
+ MTR_MEMO_PAGE_X_FIX)));
ut_a(page_is_comp(prev_page) == page_is_comp(page));
+#ifdef UNIV_BTR_DEBUG
+ ut_a(btr_page_get_next(prev_page, mtr)
+ == buf_frame_get_page_no(page));
+#endif /* UNIV_BTR_DEBUG */
return(page_rec_get_prev(page_get_supremum_rec(prev_page)));
}
@@ -223,20 +227,24 @@
return(next_rec);
}
}
-
+
page = buf_frame_align(rec);
next_page_no = btr_page_get_next(page, mtr);
space = buf_frame_get_space_id(page);
-
+
if (next_page_no != FIL_NULL) {
next_page = buf_page_get_with_no_latch(space, next_page_no,
mtr);
/* The caller must already have a latch to the brother */
ut_ad((mtr_memo_contains(mtr, buf_block_align(next_page),
- MTR_MEMO_PAGE_S_FIX))
- || (mtr_memo_contains(mtr, buf_block_align(next_page),
- MTR_MEMO_PAGE_X_FIX)));
+ MTR_MEMO_PAGE_S_FIX))
+ || (mtr_memo_contains(mtr, buf_block_align(next_page),
+ MTR_MEMO_PAGE_X_FIX)));
+#ifdef UNIV_BTR_DEBUG
+ ut_a(btr_page_get_prev(next_page, mtr)
+ == buf_frame_get_page_no(page));
+#endif /* UNIV_BTR_DEBUG */
ut_a(page_is_comp(next_page) == page_is_comp(page));
return(page_rec_get_next(page_get_infimum_rec(next_page)));
@@ -257,11 +265,11 @@
mtr_t* mtr) /* in: mtr */
{
ut_ad(mtr_memo_contains(mtr, buf_block_align(page),
- MTR_MEMO_PAGE_X_FIX));
+ MTR_MEMO_PAGE_X_FIX));
page_create(page, mtr,
- UT_LIST_GET_FIRST(tree->tree_indexes)->table->comp);
+ dict_table_is_comp(tree->tree_index->table));
buf_block_align(page)->check_index_page_at_flush = TRUE;
-
+
btr_page_set_index_id(page, tree->id, mtr);
}
@@ -281,7 +289,7 @@
page_t* new_page;
root = btr_root_get(tree, mtr);
-
+
node_addr = flst_get_first(root + PAGE_HEADER
+ PAGE_BTR_IBUF_FREE_LIST, mtr);
ut_a(node_addr.page != FIL_NULL);
@@ -293,7 +301,7 @@
#endif /* UNIV_SYNC_DEBUG */
flst_remove(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST,
- new_page + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE,
+ new_page + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE,
mtr);
ut_ad(flst_validate(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, mtr));
@@ -328,7 +336,7 @@
}
root = btr_root_get(tree, mtr);
-
+
if (level == 0) {
seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_LEAF;
} else {
@@ -338,7 +346,7 @@
/* Parameter TRUE below states that the caller has made the
reservation for free extents, and thus we know that a page can
be allocated: */
-
+
new_page_no = fseg_alloc_free_page_general(seg_header, hint_page_no,
file_direction, TRUE, mtr);
if (new_page_no == FIL_NULL) {
@@ -351,9 +359,9 @@
#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(new_page, SYNC_TREE_NODE_NEW);
#endif /* UNIV_SYNC_DEBUG */
-
+
return(new_page);
-}
+}
/******************************************************************
Gets the number of pages in a B-tree. */
@@ -376,20 +384,20 @@
mtr_s_lock(dict_tree_get_lock(index->tree), &mtr);
root = btr_root_get(index->tree, &mtr);
-
+
if (flag == BTR_N_LEAF_PAGES) {
seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_LEAF;
-
+
fseg_n_reserved_pages(seg_header, &n, &mtr);
-
+
} else if (flag == BTR_TOTAL_SIZE) {
seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_TOP;
n = fseg_n_reserved_pages(seg_header, &dummy, &mtr);
-
+
seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_LEAF;
-
- n += fseg_n_reserved_pages(seg_header, &dummy, &mtr);
+
+ n += fseg_n_reserved_pages(seg_header, &dummy, &mtr);
} else {
ut_error;
}
@@ -397,7 +405,7 @@
mtr_commit(&mtr);
return(n);
-}
+}
/******************************************************************
Frees a page used in an ibuf tree. Puts the page to the free list of the
@@ -407,17 +415,17 @@
btr_page_free_for_ibuf(
/*===================*/
dict_tree_t* tree, /* in: index tree */
- page_t* page, /* in: page to be freed, x-latched */
+ page_t* page, /* in: page to be freed, x-latched */
mtr_t* mtr) /* in: mtr */
{
page_t* root;
ut_ad(mtr_memo_contains(mtr, buf_block_align(page),
- MTR_MEMO_PAGE_X_FIX));
+ MTR_MEMO_PAGE_X_FIX));
root = btr_root_get(tree, mtr);
-
+
flst_add_first(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST,
- page + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE, mtr);
+ page + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE, mtr);
ut_ad(flst_validate(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST,
mtr));
@@ -432,7 +440,7 @@
btr_page_free_low(
/*==============*/
dict_tree_t* tree, /* in: index tree */
- page_t* page, /* in: page to be freed, x-latched */
+ page_t* page, /* in: page to be freed, x-latched */
ulint level, /* in: page level */
mtr_t* mtr) /* in: mtr */
{
@@ -442,12 +450,12 @@
ulint page_no;
ut_ad(mtr_memo_contains(mtr, buf_block_align(page),
- MTR_MEMO_PAGE_X_FIX));
+ MTR_MEMO_PAGE_X_FIX));
/* The page gets invalid for optimistic searches: increment the frame
modify clock */
buf_frame_modify_clock_inc(page);
-
+
if (tree->type & DICT_IBUF) {
btr_page_free_for_ibuf(tree, page, mtr);
@@ -456,7 +464,7 @@
}
root = btr_root_get(tree, mtr);
-
+
if (level == 0) {
seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_LEAF;
} else {
@@ -465,9 +473,9 @@
space = buf_frame_get_space_id(page);
page_no = buf_frame_get_page_no(page);
-
+
fseg_free_page(seg_header, space, page_no, mtr);
-}
+}
/******************************************************************
Frees a file page used in an index tree. NOTE: cannot free field external
@@ -477,17 +485,17 @@
btr_page_free(
/*==========*/
dict_tree_t* tree, /* in: index tree */
- page_t* page, /* in: page to be freed, x-latched */
+ page_t* page, /* in: page to be freed, x-latched */
mtr_t* mtr) /* in: mtr */
{
ulint level;
ut_ad(mtr_memo_contains(mtr, buf_block_align(page),
- MTR_MEMO_PAGE_X_FIX));
+ MTR_MEMO_PAGE_X_FIX));
level = btr_page_get_level(page, mtr);
-
+
btr_page_free_low(tree, page, level, mtr);
-}
+}
/******************************************************************
Sets the child node file address in a node pointer. */
@@ -507,12 +515,12 @@
ut_ad(0 < btr_page_get_level(buf_frame_align(rec), mtr));
ut_ad(!rec_offs_comp(offsets) || rec_get_node_ptr_flag(rec));
- /* The child address is in the last field */
+ /* The child address is in the last field */
field = rec_get_nth_field(rec, offsets,
rec_offs_n_fields(offsets) - 1, &len);
ut_ad(len == 4);
-
+
mlog_write_ulint(field, page_no, MLOG_4BYTES, mtr);
}
@@ -536,7 +544,7 @@
page_no = btr_node_ptr_get_child_page_no(node_ptr, offsets);
page = btr_page_get(space, page_no, RW_X_LATCH, mtr);
-
+
return(page);
}
@@ -567,14 +575,14 @@
ut_ad(mtr_memo_contains(mtr, dict_tree_get_lock(tree),
MTR_MEMO_X_LOCK));
ut_a(page_rec_is_user_rec(user_rec));
-
+
ut_ad(dict_tree_get_page(tree) != buf_frame_get_page_no(page));
heap = mem_heap_create(100);
tuple = dict_tree_build_node_ptr(tree, user_rec, 0, heap,
btr_page_get_level(page, mtr));
- index = UT_LIST_GET_FIRST(tree->tree_indexes);
+ index = tree->tree_index;
/* In the following, we choose just any index from the tree as the
first parameter for btr_cur_search_to_nth_level. */
@@ -589,7 +597,7 @@
ULINT_UNDEFINED, &heap);
if (btr_node_ptr_get_child_page_no(node_ptr, offsets) !=
- buf_frame_get_page_no(page)) {
+ buf_frame_get_page_no(page)) {
rec_t* print_rec;
fputs("InnoDB: Dump of the child page:\n", stderr);
buf_page_print(buf_frame_align(page));
@@ -597,9 +605,9 @@
buf_page_print(buf_frame_align(node_ptr));
fputs("InnoDB: Corruption of an index tree: table ", stderr);
- ut_print_name(stderr, NULL, index->table_name);
+ ut_print_name(stderr, NULL, TRUE, index->table_name);
fputs(", index ", stderr);
- ut_print_name(stderr, NULL, index->name);
+ ut_print_name(stderr, NULL, FALSE, index->name);
fprintf(stderr, ",\n"
"InnoDB: father ptr page no %lu, child page no %lu\n",
(ulong)
@@ -677,13 +685,13 @@
buf_page_dbg_add_level(ibuf_hdr_frame, SYNC_TREE_NODE_NEW);
#endif /* UNIV_SYNC_DEBUG */
ut_ad(buf_frame_get_page_no(ibuf_hdr_frame)
- == IBUF_HEADER_PAGE_NO);
+ == IBUF_HEADER_PAGE_NO);
/* Allocate then the next page to the segment: it will be the
- tree root page */
+ tree root page */
- page_no = fseg_alloc_free_page(
+ page_no = fseg_alloc_free_page(
ibuf_hdr_frame + IBUF_HEADER
- + IBUF_TREE_SEG_HEADER, IBUF_TREE_ROOT_PAGE_NO,
+ + IBUF_TREE_SEG_HEADER, IBUF_TREE_ROOT_PAGE_NO,
FSP_UP, mtr);
ut_ad(page_no == IBUF_TREE_ROOT_PAGE_NO);
@@ -692,14 +700,14 @@
frame = fseg_create(space, 0, PAGE_HEADER + PAGE_BTR_SEG_TOP,
mtr);
}
-
+
if (frame == NULL) {
return(FIL_NULL);
}
page_no = buf_frame_get_page_no(frame);
-
+
#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(frame, SYNC_TREE_NODE_NEW);
#endif /* UNIV_SYNC_DEBUG */
@@ -708,9 +716,9 @@
/* It is an insert buffer tree: initialize the free list */
ut_ad(page_no == IBUF_TREE_ROOT_PAGE_NO);
-
+
flst_init(frame + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, mtr);
- } else {
+ } else {
/* It is a non-ibuf tree: create a file segment for leaf
pages */
fseg_create(space, page_no, PAGE_HEADER + PAGE_BTR_SEG_LEAF,
@@ -721,7 +729,7 @@
buf_page_dbg_add_level(frame, SYNC_TREE_NODE_NEW);
#endif /* UNIV_SYNC_DEBUG */
}
-
+
/* Create a new index page on the the allocated segment page */
page = page_create(frame, mtr, comp);
buf_block_align(page)->check_index_page_at_flush = TRUE;
@@ -731,7 +739,7 @@
/* Set the level of the new index page */
btr_page_set_level(page, 0, mtr);
-
+
/* Set the next node and previous node fields */
btr_page_set_next(page, FIL_NULL, mtr);
btr_page_set_prev(page, FIL_NULL, mtr);
@@ -739,7 +747,7 @@
/* We reset the free bits for the page to allow creation of several
trees in the same mtr, otherwise the latch on a bitmap page would
prevent it because of the latching order */
-
+
ibuf_reset_free_bits_with_type(type, page);
/* In the following assertion we test that two records of maximum
@@ -765,10 +773,10 @@
page_t* root;
mtr_t mtr;
-leaf_loop:
+leaf_loop:
mtr_start(&mtr);
-
- root = btr_page_get(space, root_page_no, RW_X_LATCH, &mtr);
+
+ root = btr_page_get(space, root_page_no, RW_X_LATCH, &mtr);
/* NOTE: page hash indexes are dropped when a page is freed inside
fsp0fsp. */
@@ -783,8 +791,8 @@
}
top_loop:
mtr_start(&mtr);
-
- root = btr_page_get(space, root_page_no, RW_X_LATCH, &mtr);
+
+ root = btr_page_get(space, root_page_no, RW_X_LATCH, &mtr);
finished = fseg_free_step_not_header(
root + PAGE_HEADER + PAGE_BTR_SEG_TOP, &mtr);
@@ -793,7 +801,7 @@
if (!finished) {
goto top_loop;
- }
+ }
}
/****************************************************************
@@ -812,14 +820,14 @@
root = btr_page_get(space, root_page_no, RW_X_LATCH, mtr);
- btr_search_drop_page_hash_index(root);
-top_loop:
+ btr_search_drop_page_hash_index(root);
+top_loop:
finished = fseg_free_step(
root + PAGE_HEADER + PAGE_BTR_SEG_TOP, mtr);
if (!finished) {
goto top_loop;
- }
+ }
}
/*****************************************************************
@@ -845,8 +853,8 @@
ulint max_ins_size2;
ut_ad(mtr_memo_contains(mtr, buf_block_align(page),
- MTR_MEMO_PAGE_X_FIX));
- ut_ad(!!page_is_comp(page) == index->table->comp);
+ MTR_MEMO_PAGE_X_FIX));
+ ut_ad(!!page_is_comp(page) == dict_table_is_comp(index->table));
data_size1 = page_get_data_size(page);
max_ins_size1 = page_get_max_insert_size_after_reorganize(page, 1);
@@ -872,7 +880,7 @@
page_create(page, mtr, page_is_comp(page));
buf_block_align(page)->check_index_page_at_flush = TRUE;
-
+
/* Copy the records from the temporary space to the recreated page;
do not copy the lock bits yet */
@@ -880,7 +888,7 @@
page_get_infimum_rec(new_page), index, mtr);
/* Copy max trx id to recreated page */
page_set_max_trx_id(page, page_get_max_trx_id(new_page));
-
+
if (!recovery) {
/* Update the record lock bitmaps */
lock_move_reorganize_page(page, new_page);
@@ -892,7 +900,7 @@
if (data_size1 != data_size2 || max_ins_size1 != max_ins_size2) {
buf_page_print(page);
buf_page_print(new_page);
- fprintf(stderr,
+ fprintf(stderr,
"InnoDB: Error: page old data size %lu new data size %lu\n"
"InnoDB: Error: page old max ins size %lu new max ins size %lu\n"
"InnoDB: Submit a detailed bug report to http://bugs.mysql.com\n",
@@ -955,7 +963,7 @@
mtr_t* mtr) /* in: mtr */
{
ut_ad(mtr_memo_contains(mtr, buf_block_align(page),
- MTR_MEMO_PAGE_X_FIX));
+ MTR_MEMO_PAGE_X_FIX));
btr_search_drop_page_hash_index(page);
/* Recreate the page: note that global data on page (possible
@@ -990,10 +998,10 @@
rec_t* rec;
mem_heap_t* heap;
dtuple_t* node_ptr;
- ulint level;
+ ulint level;
rec_t* node_ptr_rec;
page_cur_t* page_cursor;
-
+
root = btr_cur_get_page(cursor);
tree = btr_cur_get_tree(cursor);
@@ -1001,24 +1009,24 @@
ut_ad(mtr_memo_contains(mtr, dict_tree_get_lock(tree),
MTR_MEMO_X_LOCK));
ut_ad(mtr_memo_contains(mtr, buf_block_align(root),
- MTR_MEMO_PAGE_X_FIX));
+ MTR_MEMO_PAGE_X_FIX));
btr_search_drop_page_hash_index(root);
/* Allocate a new page to the tree. Root splitting is done by first
moving the root records to the new page, emptying the root, putting
a node pointer to the new page, and then splitting the new page. */
-
+
new_page = btr_page_alloc(tree, 0, FSP_NO_DIR,
btr_page_get_level(root, mtr), mtr);
btr_page_create(new_page, tree, mtr);
level = btr_page_get_level(root, mtr);
-
+
/* Set the levels of the new index page and root page */
btr_page_set_level(new_page, level, mtr);
btr_page_set_level(root, level + 1, mtr);
-
+
/* Set the next node and previous node fields of new page */
btr_page_set_next(new_page, FIL_NULL, mtr);
btr_page_set_prev(new_page, FIL_NULL, mtr);
@@ -1031,7 +1039,7 @@
perform a pessimistic update then we have stored the lock
information of the record to be inserted on the infimum of the
root page: we cannot discard the lock structs on the root page */
-
+
lock_update_root_raise(new_page, root);
/* Create a memory heap where the node pointer is stored */
@@ -1039,17 +1047,17 @@
rec = page_rec_get_next(page_get_infimum_rec(new_page));
new_page_no = buf_frame_get_page_no(new_page);
-
+
/* Build the node pointer (= node key and page address) for the
child */
node_ptr = dict_tree_build_node_ptr(tree, rec, new_page_no, heap,
- level);
+ level);
/* Reorganize the root to get free space */
btr_page_reorganize(root, cursor->index, mtr);
page_cursor = btr_cur_get_page_cur(cursor);
-
+
/* Insert node pointer to the root */
page_cur_set_before_first(root, page_cursor);
@@ -1064,7 +1072,7 @@
node of a level: */
btr_set_min_rec_mark(node_ptr_rec, page_is_comp(root), mtr);
-
+
/* Free the memory heap */
mem_heap_free(heap);
@@ -1073,15 +1081,14 @@
/* fprintf(stderr, "Root raise new page no %lu\n",
buf_frame_get_page_no(new_page)); */
- ibuf_reset_free_bits(UT_LIST_GET_FIRST(tree->tree_indexes),
- new_page);
+ ibuf_reset_free_bits(tree->tree_index, new_page);
/* Reposition the cursor to the child node */
page_cur_search(new_page, cursor->index, tuple,
PAGE_CUR_LE, page_cursor);
-
+
/* Split the child and insert tuple */
return(btr_page_split_and_insert(cursor, tuple, mtr));
-}
+}
/*****************************************************************
Decides if the page should be split at the convergence point of inserts
@@ -1105,22 +1112,22 @@
insert_point = btr_cur_get_rec(cursor);
if (page_header_get_ptr(page, PAGE_LAST_INSERT)
- == page_rec_get_next(insert_point)) {
+ == page_rec_get_next(insert_point)) {
+
+ infimum = page_get_infimum_rec(page);
- infimum = page_get_infimum_rec(page);
-
/* If the convergence is in the middle of a page, include also
the record immediately before the new insert to the upper
page. Otherwise, we could repeatedly move from page to page
lots of records smaller than the convergence point. */
if (infimum != insert_point
- && page_rec_get_next(infimum) != insert_point) {
+ && page_rec_get_next(infimum) != insert_point) {
*split_rec = insert_point;
} else {
- *split_rec = page_rec_get_next(insert_point);
- }
+ *split_rec = page_rec_get_next(insert_point);
+ }
return(TRUE);
}
@@ -1162,7 +1169,7 @@
if (page_rec_is_supremum(next_rec)) {
split_at_new:
/* Split at the new record to insert */
- *split_rec = NULL;
+ *split_rec = NULL;
} else {
rec_t* next_next_rec = page_rec_get_next(next_rec);
if (page_rec_is_supremum(next_next_rec)) {
@@ -1176,7 +1183,7 @@
index, as they can do the necessary checks of the right
search position just by looking at the records on this
page. */
-
+
*split_rec = next_next_rec;
}
@@ -1199,7 +1206,7 @@
upper half-page */
btr_cur_t* cursor, /* in: cursor at which insert
should be made */
- dtuple_t* tuple) /* in: tuple to insert */
+ dtuple_t* tuple) /* in: tuple to insert */
{
page_t* page;
ulint insert_size;
@@ -1216,7 +1223,7 @@
ulint* offsets;
page = btr_cur_get_page(cursor);
-
+
insert_size = rec_get_converted_size(cursor->index, tuple);
free_space = page_get_free_space_of_empty(page_is_comp(page));
@@ -1263,15 +1270,15 @@
}
n++;
-
+
if (incl_data + page_dir_calc_reserved_space(n)
- >= total_space / 2) {
+ >= total_space / 2) {
- if (incl_data + page_dir_calc_reserved_space(n)
- <= free_space) {
- /* The next record will be the first on
- the right half page if it is not the
- supremum record of page */
+ if (incl_data + page_dir_calc_reserved_space(n)
+ <= free_space) {
+ /* The next record will be the first on
+ the right half page if it is not the
+ supremum record of page */
if (rec == ins_rec) {
rec = NULL;
@@ -1286,7 +1293,7 @@
if (!page_rec_is_supremum(next_rec)) {
rec = next_rec;
}
- }
+ }
func_exit:
if (UNIV_LIKELY_NULL(heap)) {
@@ -1295,7 +1302,7 @@
return(rec);
}
}
-}
+}
/*****************************************************************
Returns TRUE if the insert fits on the appropriate half-page with the
@@ -1323,7 +1330,7 @@
rec_t* rec;
rec_t* end_rec;
ulint* offs;
-
+
page = btr_cur_get_page(cursor);
ut_ad(!split_rec == !offsets);
@@ -1339,11 +1346,11 @@
total_data = page_get_data_size(page) + insert_size;
total_n_recs = page_get_n_recs(page) + 1;
-
+
/* We determine which records (from rec to end_rec, not including
end_rec) will end up on the other half page from tuple when it is
inserted. */
-
+
if (split_rec == NULL) {
rec = page_rec_get_next(page_get_infimum_rec(page));
end_rec = page_rec_get_next(btr_cur_get_rec(cursor));
@@ -1351,14 +1358,14 @@
} else if (cmp_dtuple_rec(tuple, split_rec, offsets) >= 0) {
rec = page_rec_get_next(page_get_infimum_rec(page));
- end_rec = split_rec;
+ end_rec = split_rec;
} else {
rec = split_rec;
end_rec = page_get_supremum_rec(page);
}
if (total_data + page_dir_calc_reserved_space(total_n_recs)
- <= free_space) {
+ <= free_space) {
/* Ok, there will be enough available space on the
half page where the tuple is inserted */
@@ -1379,7 +1386,7 @@
total_n_recs--;
if (total_data + page_dir_calc_reserved_space(total_n_recs)
- <= free_space) {
+ <= free_space) {
/* Ok, there will be enough available space on the
half page where the tuple is inserted */
@@ -1391,7 +1398,7 @@
}
return(FALSE);
-}
+}
/***********************************************************
Inserts a data tuple to a tree on a non-leaf level. It is assumed
@@ -1406,25 +1413,22 @@
mtr_t* mtr) /* in: mtr */
{
big_rec_t* dummy_big_rec;
- btr_cur_t cursor;
+ btr_cur_t cursor;
ulint err;
rec_t* rec;
ut_ad(level > 0);
-
+
/* In the following, choose just any index from the tree as the
first parameter for btr_cur_search_to_nth_level. */
- btr_cur_search_to_nth_level(UT_LIST_GET_FIRST(tree->tree_indexes),
- level, tuple, PAGE_CUR_LE,
- BTR_CONT_MODIFY_TREE,
- &cursor, 0, mtr);
+ btr_cur_search_to_nth_level(tree->tree_index,
+ level, tuple, PAGE_CUR_LE, BTR_CONT_MODIFY_TREE,
+ &cursor, 0, mtr);
err = btr_cur_pessimistic_insert(BTR_NO_LOCKING_FLAG
- | BTR_KEEP_SYS_FLAG
- | BTR_NO_UNDO_LOG_FLAG,
- &cursor, tuple,
- &rec, &dummy_big_rec, NULL, mtr);
+ | BTR_KEEP_SYS_FLAG | BTR_NO_UNDO_LOG_FLAG,
+ &cursor, tuple, &rec, &dummy_big_rec, NULL, mtr);
ut_a(err == DB_SUCCESS);
}
@@ -1455,12 +1459,12 @@
ulint lower_page_no;
ulint upper_page_no;
dtuple_t* node_ptr_upper;
- mem_heap_t* heap;
+ mem_heap_t* heap;
ut_ad(mtr_memo_contains(mtr, buf_block_align(page),
- MTR_MEMO_PAGE_X_FIX));
+ MTR_MEMO_PAGE_X_FIX));
ut_ad(mtr_memo_contains(mtr, buf_block_align(new_page),
- MTR_MEMO_PAGE_X_FIX));
+ MTR_MEMO_PAGE_X_FIX));
ut_a(page_is_comp(page) == page_is_comp(new_page));
/* Create a memory heap where the data tuple is stored */
@@ -1477,12 +1481,12 @@
/* Look from the tree for the node pointer to page */
node_ptr = btr_page_get_father_node_ptr(tree, page, mtr);
- /* Replace the address of the old child node (= page) with the
+ /* Replace the address of the old child node (= page) with the
address of the new lower half */
btr_node_ptr_set_child_page_no(node_ptr,
rec_get_offsets(node_ptr,
- UT_LIST_GET_FIRST(tree->tree_indexes),
+ tree->tree_index,
NULL, ULINT_UNDEFINED, &heap),
lower_page_no, mtr);
mem_heap_empty(heap);
@@ -1492,7 +1496,7 @@
lower_page = page;
upper_page = new_page;
}
-
+
/* Get the level of the split pages */
level = btr_page_get_level(page, mtr);
@@ -1500,13 +1504,13 @@
half */
node_ptr_upper = dict_tree_build_node_ptr(tree, split_rec,
- upper_page_no, heap, level);
+ upper_page_no, heap, level);
/* Insert it next to the pointer to the lower half. Note that this
may generate recursion leading to a split on the higher level. */
btr_insert_on_non_leaf_level(tree, level + 1, node_ptr_upper, mtr);
-
+
/* Free the memory heap */
mem_heap_free(heap);
@@ -1515,13 +1519,17 @@
prev_page_no = btr_page_get_prev(page, mtr);
next_page_no = btr_page_get_next(page, mtr);
space = buf_frame_get_space_id(page);
-
+
/* Update page links of the level */
-
+
if (prev_page_no != FIL_NULL) {
prev_page = btr_page_get(space, prev_page_no, RW_X_LATCH, mtr);
ut_a(page_is_comp(prev_page) == page_is_comp(page));
+#ifdef UNIV_BTR_DEBUG
+ ut_a(btr_page_get_next(prev_page, mtr)
+ == buf_frame_get_page_no(page));
+#endif /* UNIV_BTR_DEBUG */
btr_page_set_next(prev_page, lower_page_no, mtr);
}
@@ -1533,7 +1541,7 @@
btr_page_set_prev(next_page, upper_page_no, mtr);
}
-
+
btr_page_set_prev(lower_page, prev_page_no, mtr);
btr_page_set_next(lower_page, upper_page_no, mtr);
btr_page_set_level(lower_page, level, mtr);
@@ -1590,7 +1598,7 @@
mem_heap_empty(heap);
offsets = NULL;
tree = btr_cur_get_tree(cursor);
-
+
ut_ad(mtr_memo_contains(mtr, dict_tree_get_lock(tree),
MTR_MEMO_X_LOCK));
#ifdef UNIV_SYNC_DEBUG
@@ -1600,9 +1608,9 @@
page = btr_cur_get_page(cursor);
ut_ad(mtr_memo_contains(mtr, buf_block_align(page),
- MTR_MEMO_PAGE_X_FIX));
+ MTR_MEMO_PAGE_X_FIX));
ut_ad(page_get_n_recs(page) >= 2);
-
+
page_no = buf_frame_get_page_no(page);
/* 1. Decide the split record; split_rec == NULL means that the
@@ -1613,7 +1621,7 @@
direction = FSP_UP;
hint_page_no = page_no + 1;
split_rec = btr_page_get_sure_split_rec(cursor, tuple);
-
+
} else if (btr_page_get_split_rec_to_right(cursor, &split_rec)) {
direction = FSP_UP;
hint_page_no = page_no + 1;
@@ -1631,7 +1639,7 @@
new_page = btr_page_alloc(tree, hint_page_no, direction,
btr_page_get_level(page, mtr), mtr);
btr_page_create(new_page, tree, mtr);
-
+
/* 3. Calculate the first record on the upper half-page, and the
first record (move_limit) on original page which ends up on the
upper half */
@@ -1646,7 +1654,7 @@
cursor->index, tuple);
move_limit = page_rec_get_next(btr_cur_get_rec(cursor));
}
-
+
/* 4. Do first the modifications in the tree structure */
btr_attach_half_pages(tree, page, first_rec, new_page, direction, mtr);
@@ -1670,7 +1678,7 @@
insert_will_fit = btr_page_insert_fits(cursor,
NULL, NULL, tuple, heap);
}
-
+
if (insert_will_fit && (btr_page_get_level(page, mtr) == 0)) {
mtr_memo_release(mtr, dict_tree_get_lock(tree),
@@ -1737,7 +1745,7 @@
mem_heap_free(heap);
return(rec);
}
-
+
/* 8. If insert did not fit, try page reorganization */
btr_page_reorganize(insert_page, cursor->index, mtr);
@@ -1749,7 +1757,7 @@
if (rec == NULL) {
/* The insert did not fit on the page: loop back to the
start of the function for a new split */
-
+
/* We play safe and reset the free bits for new_page */
ibuf_reset_free_bits(cursor->index, new_page);
@@ -1771,8 +1779,8 @@
buf_frame_get_page_no(left_page),
buf_frame_get_page_no(right_page)); */
- ut_ad(page_validate(left_page, UT_LIST_GET_FIRST(tree->tree_indexes)));
- ut_ad(page_validate(right_page, UT_LIST_GET_FIRST(tree->tree_indexes)));
+ ut_ad(page_validate(left_page, tree->tree_index));
+ ut_ad(page_validate(right_page, tree->tree_index));
mem_heap_free(heap);
return(rec);
@@ -1787,28 +1795,32 @@
dict_tree_t* tree __attribute__((unused)), /* in: index tree */
page_t* page, /* in: page to remove */
mtr_t* mtr) /* in: mtr */
-{
+{
ulint space;
ulint prev_page_no;
page_t* prev_page;
ulint next_page_no;
page_t* next_page;
-
+
ut_ad(tree && page && mtr);
ut_ad(mtr_memo_contains(mtr, buf_block_align(page),
- MTR_MEMO_PAGE_X_FIX));
+ MTR_MEMO_PAGE_X_FIX));
/* Get the previous and next page numbers of page */
prev_page_no = btr_page_get_prev(page, mtr);
next_page_no = btr_page_get_next(page, mtr);
space = buf_frame_get_space_id(page);
-
+
/* Update page links of the level */
-
+
if (prev_page_no != FIL_NULL) {
prev_page = btr_page_get(space, prev_page_no, RW_X_LATCH, mtr);
ut_a(page_is_comp(prev_page) == page_is_comp(page));
+#ifdef UNIV_BTR_DEBUG
+ ut_a(btr_page_get_next(prev_page, mtr)
+ == buf_frame_get_page_no(page));
+#endif /* UNIV_BTR_DEBUG */
btr_page_set_next(prev_page, next_page_no, mtr);
}
@@ -1817,11 +1829,15 @@
next_page = btr_page_get(space, next_page_no, RW_X_LATCH, mtr);
ut_a(page_is_comp(next_page) == page_is_comp(page));
+#ifdef UNIV_BTR_DEBUG
+ ut_a(btr_page_get_prev(next_page, mtr)
+ == buf_frame_get_page_no(page));
+#endif /* UNIV_BTR_DEBUG */
btr_page_set_prev(next_page, prev_page_no, mtr);
}
}
-
+
/********************************************************************
Writes the redo log record for setting an index record as the predefined
minimum record. */
@@ -1906,15 +1922,14 @@
btr_cur_t cursor;
ibool compressed;
ulint err;
-
+
ut_ad(mtr_memo_contains(mtr, buf_block_align(page),
MTR_MEMO_PAGE_X_FIX));
/* Delete node pointer on father page */
node_ptr = btr_page_get_father_node_ptr(tree, page, mtr);
- btr_cur_position(UT_LIST_GET_FIRST(tree->tree_indexes), node_ptr,
- &cursor);
+ btr_cur_position(tree->tree_index, node_ptr, &cursor);
compressed = btr_cur_pessimistic_delete(&err, TRUE, &cursor, FALSE,
mtr);
ut_a(err == DB_SUCCESS);
@@ -1945,33 +1960,33 @@
ut_ad(btr_page_get_prev(page, mtr) == FIL_NULL);
ut_ad(btr_page_get_next(page, mtr) == FIL_NULL);
ut_ad(mtr_memo_contains(mtr, buf_block_align(page),
- MTR_MEMO_PAGE_X_FIX));
+ MTR_MEMO_PAGE_X_FIX));
father_page = buf_frame_align(
btr_page_get_father_node_ptr(tree, page, mtr));
-
+
page_level = btr_page_get_level(page, mtr);
- index = UT_LIST_GET_FIRST(tree->tree_indexes);
+ index = tree->tree_index;
btr_search_drop_page_hash_index(page);
-
+
/* Make the father empty */
btr_page_empty(father_page, mtr);
/* Move records to the father */
- page_copy_rec_list_end(father_page, page, page_get_infimum_rec(page),
+ page_copy_rec_list_end(father_page, page, page_get_infimum_rec(page),
index, mtr);
lock_update_copy_and_discard(father_page, page);
btr_page_set_level(father_page, page_level, mtr);
/* Free the file page */
- btr_page_free(tree, page, mtr);
+ btr_page_free(tree, page, mtr);
/* We play safe and reset the free bits for the father */
ibuf_reset_free_bits(index, father_page);
ut_ad(page_validate(father_page, index));
ut_ad(btr_check_node_ptr(tree, father_page, mtr));
-}
+}
/*****************************************************************
Tries to merge the page first to the left immediate brother if such a
@@ -2014,7 +2029,7 @@
page = btr_cur_get_page(cursor);
tree = btr_cur_get_tree(cursor);
comp = page_is_comp(page);
- ut_a((ibool)!!comp == cursor->index->table->comp);
+ ut_a((ibool)!!comp == dict_table_is_comp(cursor->index->table));
ut_ad(mtr_memo_contains(mtr, dict_tree_get_lock(tree),
MTR_MEMO_X_LOCK));
@@ -2037,16 +2052,24 @@
/* Decide the page to which we try to merge and which will inherit
the locks */
- if (left_page_no != FIL_NULL) {
+ is_left = left_page_no != FIL_NULL;
+
+ if (is_left) {
- is_left = TRUE;
merge_page = btr_page_get(space, left_page_no, RW_X_LATCH,
mtr);
+#ifdef UNIV_BTR_DEBUG
+ ut_a(btr_page_get_next(merge_page, mtr)
+ == buf_frame_get_page_no(page));
+#endif /* UNIV_BTR_DEBUG */
} else if (right_page_no != FIL_NULL) {
- is_left = FALSE;
merge_page = btr_page_get(space, right_page_no, RW_X_LATCH,
mtr);
+#ifdef UNIV_BTR_DEBUG
+ ut_a(btr_page_get_prev(merge_page, mtr)
+ == buf_frame_get_page_no(page));
+#endif /* UNIV_BTR_DEBUG */
} else {
/* The page is the only one on the level, lift the records
to the father */
@@ -2054,7 +2077,7 @@
return;
}
-
+
n_recs = page_get_n_recs(page);
data_size = page_get_data_size(page);
ut_a(page_is_comp(merge_page) == comp);
@@ -2071,7 +2094,7 @@
ut_ad(page_validate(merge_page, cursor->index));
max_ins_size = page_get_max_insert_size(merge_page, n_recs);
-
+
if (data_size > max_ins_size) {
/* We have to reorganize merge_page */
@@ -2103,7 +2126,7 @@
mem_heap_t* heap = NULL;
ulint offsets_[REC_OFFS_NORMAL_SIZE];
*offsets_ = (sizeof offsets_) / sizeof *offsets_;
- /* Replace the address of the old child node (= page) with the
+ /* Replace the address of the old child node (= page) with the
address of the merge page to the right */
btr_node_ptr_set_child_page_no(node_ptr,
@@ -2115,7 +2138,7 @@
}
btr_node_ptr_delete(tree, merge_page, mtr);
}
-
+
/* Move records to the merge page */
if (is_left) {
orig_pred = page_rec_get_prev(
@@ -2136,14 +2159,14 @@
/* We have added new records to merge_page: update its free bits */
ibuf_update_free_bits_if_full(cursor->index, merge_page,
UNIV_PAGE_SIZE, ULINT_UNDEFINED);
-
+
ut_ad(page_validate(merge_page, cursor->index));
/* Free the file page */
- btr_page_free(tree, page, mtr);
+ btr_page_free(tree, page, mtr);
ut_ad(btr_check_node_ptr(tree, merge_page, mtr));
-}
+}
/*****************************************************************
Discards a page that is the only page on its level. */
@@ -2158,7 +2181,7 @@
rec_t* node_ptr;
page_t* father_page;
ulint page_level;
-
+
ut_ad(btr_page_get_prev(page, mtr) == FIL_NULL);
ut_ad(btr_page_get_next(page, mtr) == FIL_NULL);
ut_ad(mtr_memo_contains(mtr, buf_block_align(page),
@@ -2175,7 +2198,7 @@
btr_page_set_level(father_page, page_level, mtr);
/* Free the file page */
- btr_page_free(tree, page, mtr);
+ btr_page_free(tree, page, mtr);
if (buf_frame_get_page_no(father_page) == dict_tree_get_page(tree)) {
/* The father is the root page */
@@ -2183,14 +2206,13 @@
btr_page_empty(father_page, mtr);
/* We play safe and reset the free bits for the father */
- ibuf_reset_free_bits(UT_LIST_GET_FIRST(tree->tree_indexes),
- father_page);
+ ibuf_reset_free_bits(tree->tree_index, father_page);
} else {
ut_ad(page_get_n_recs(father_page) == 1);
btr_discard_only_page_on_level(tree, father_page, mtr);
}
-}
+}
/*****************************************************************
Discards a page from a B-tree. This is used to remove the last record from
@@ -2209,10 +2231,9 @@
ulint left_page_no;
ulint right_page_no;
page_t* merge_page;
- ibool is_left;
page_t* page;
rec_t* node_ptr;
-
+
page = btr_cur_get_page(cursor);
tree = btr_cur_get_tree(cursor);
@@ -2222,20 +2243,26 @@
ut_ad(mtr_memo_contains(mtr, buf_block_align(page),
MTR_MEMO_PAGE_X_FIX));
space = dict_tree_get_space(tree);
-
+
/* Decide the page which will inherit the locks */
left_page_no = btr_page_get_prev(page, mtr);
right_page_no = btr_page_get_next(page, mtr);
if (left_page_no != FIL_NULL) {
- is_left = TRUE;
merge_page = btr_page_get(space, left_page_no, RW_X_LATCH,
mtr);
+#ifdef UNIV_BTR_DEBUG
+ ut_a(btr_page_get_next(merge_page, mtr)
+ == buf_frame_get_page_no(page));
+#endif /* UNIV_BTR_DEBUG */
} else if (right_page_no != FIL_NULL) {
- is_left = FALSE;
merge_page = btr_page_get(space, right_page_no, RW_X_LATCH,
mtr);
+#ifdef UNIV_BTR_DEBUG
+ ut_a(btr_page_get_prev(merge_page, mtr)
+ == buf_frame_get_page_no(page));
+#endif /* UNIV_BTR_DEBUG */
} else {
btr_discard_only_page_on_level(tree, page, mtr);
@@ -2244,7 +2271,7 @@
ut_a(page_is_comp(merge_page) == page_is_comp(page));
btr_search_drop_page_hash_index(page);
-
+
if (left_page_no == FIL_NULL && btr_page_get_level(page, mtr) > 0) {
/* We have to mark the leftmost node pointer on the right
@@ -2255,25 +2282,25 @@
ut_ad(page_rec_is_user_rec(node_ptr));
btr_set_min_rec_mark(node_ptr, page_is_comp(merge_page), mtr);
- }
-
+ }
+
btr_node_ptr_delete(tree, page, mtr);
/* Remove the page from the level list */
btr_level_list_remove(tree, page, mtr);
- if (is_left) {
+ if (left_page_no != FIL_NULL) {
lock_update_discard(page_get_supremum_rec(merge_page), page);
} else {
lock_update_discard(page_rec_get_next(
- page_get_infimum_rec(merge_page)), page);
+ page_get_infimum_rec(merge_page)), page);
}
/* Free the file page */
- btr_page_free(tree, page, mtr);
+ btr_page_free(tree, page, mtr);
ut_ad(btr_check_node_ptr(tree, merge_page, mtr));
-}
+}
#ifdef UNIV_BTR_PRINT
/*****************************************************************
@@ -2297,7 +2324,7 @@
}
mtr_start(&mtr);
-
+
root = btr_root_get(tree, &mtr);
seg = root + PAGE_HEADER + PAGE_BTR_SEG_TOP;
@@ -2313,7 +2340,7 @@
fseg_print(seg, &mtr);
}
- mtr_commit(&mtr);
+ mtr_commit(&mtr);
}
/****************************************************************
@@ -2341,14 +2368,14 @@
ut_ad(mtr_memo_contains(mtr, buf_block_align(page),
MTR_MEMO_PAGE_X_FIX));
fprintf(stderr, "NODE ON LEVEL %lu page number %lu\n",
- (ulong) btr_page_get_level(page, mtr),
- (ulong) buf_frame_get_page_no(page));
-
+ (ulong) btr_page_get_level(page, mtr),
+ (ulong) buf_frame_get_page_no(page));
+
index = UT_LIST_GET_FIRST(tree->tree_indexes);
page_print(page, index, width, width);
-
+
n_recs = page_get_n_recs(page);
-
+
page_cur_set_before_first(page, &cursor);
page_cur_move_to_next(&cursor);
@@ -2413,6 +2440,7 @@
}
#endif /* UNIV_BTR_PRINT */
+#ifdef UNIV_DEBUG
/****************************************************************
Checks that the node pointer to a page is appropriate. */
@@ -2436,28 +2464,29 @@
}
node_ptr = btr_page_get_father_node_ptr(tree, page, mtr);
-
+
if (btr_page_get_level(page, mtr) == 0) {
return(TRUE);
}
-
+
heap = mem_heap_create(256);
-
+
node_ptr_tuple = dict_tree_build_node_ptr(
tree,
page_rec_get_next(page_get_infimum_rec(page)),
0, heap, btr_page_get_level(page, mtr));
-
+
ut_a(cmp_dtuple_rec(node_ptr_tuple, node_ptr,
rec_get_offsets(node_ptr,
- dict_tree_find_index(tree, node_ptr),
+ tree->tree_index,
NULL, ULINT_UNDEFINED, &heap)) == 0);
mem_heap_free(heap);
return(TRUE);
}
+#endif /* UNIV_DEBUG */
/****************************************************************
Display identification information for a record. */
@@ -2481,7 +2510,7 @@
ibool
btr_index_rec_validate(
-/*====================*/
+/*===================*/
/* out: TRUE if ok */
rec_t* rec, /* in: index record */
dict_index_t* index, /* in: index */
@@ -2501,18 +2530,20 @@
page = buf_frame_align(rec);
if (UNIV_UNLIKELY(index->type & DICT_UNIVERSAL)) {
- /* The insert buffer index tree can contain records from any
- other index: we cannot check the number of fields or
- their length */
+ /* The insert buffer index tree can contain records from any
+ other index: we cannot check the number of fields or
+ their length */
- return(TRUE);
+ return(TRUE);
}
- if (UNIV_UNLIKELY((ibool)!!page_is_comp(page) != index->table->comp)) {
+ if (UNIV_UNLIKELY((ibool)!!page_is_comp(page)
+ != dict_table_is_comp(index->table))) {
btr_index_rec_validate_report(page, rec, index);
fprintf(stderr, "InnoDB: compact flag=%lu, should be %lu\n",
(ulong) !!page_is_comp(page),
- (ulong) index->table->comp);
+ (ulong) dict_table_is_comp(index->table));
+
return(FALSE);
}
@@ -2546,12 +2577,12 @@
their type is CHAR. */
if ((dict_index_get_nth_field(index, i)->prefix_len == 0
- && len != UNIV_SQL_NULL && fixed_size
- && len != fixed_size)
+ && len != UNIV_SQL_NULL && fixed_size
+ && len != fixed_size)
||
(dict_index_get_nth_field(index, i)->prefix_len > 0
- && len != UNIV_SQL_NULL
- && len >
+ && len != UNIV_SQL_NULL
+ && len >
dict_index_get_nth_field(index, i)->prefix_len)) {
btr_index_rec_validate_report(page, rec, index);
@@ -2576,7 +2607,7 @@
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
- return(TRUE);
+ return(TRUE);
}
/****************************************************************
@@ -2590,9 +2621,9 @@
page_t* page, /* in: index page */
dict_index_t* index) /* in: index */
{
- page_cur_t cur;
+ page_cur_t cur;
ibool ret = TRUE;
-
+
page_cur_set_before_first(page, &cur);
page_cur_move_to_next(&cur);
@@ -2610,7 +2641,7 @@
page_cur_move_to_next(&cur);
}
- return(ret);
+ return(ret);
}
/****************************************************************
@@ -2686,12 +2717,12 @@
mtr_start(&mtr);
mtr_x_lock(dict_tree_get_lock(tree), &mtr);
-
+
page = btr_root_get(tree, &mtr);
space = buf_frame_get_space_id(page);
- index = UT_LIST_GET_FIRST(tree->tree_indexes);
+ index = tree->tree_index;
while (level != btr_page_get_level(page, &mtr)) {
@@ -2733,21 +2764,43 @@
ret = FALSE;
}
}
-
+
ut_a(btr_page_get_level(page, &mtr) == level);
right_page_no = btr_page_get_next(page, &mtr);
left_page_no = btr_page_get_prev(page, &mtr);
ut_a((page_get_n_recs(page) > 0)
- || ((level == 0) &&
+ || ((level == 0) &&
(buf_frame_get_page_no(page) == dict_tree_get_page(tree))));
if (right_page_no != FIL_NULL) {
rec_t* right_rec;
right_page = btr_page_get(space, right_page_no, RW_X_LATCH,
&mtr);
- ut_a(page_is_comp(right_page) == page_is_comp(page));
+ if (UNIV_UNLIKELY(btr_page_get_prev(right_page, &mtr)
+ != buf_frame_get_page_no(page))) {
+ btr_validate_report2(index, level, page, right_page);
+ fputs("InnoDB: broken FIL_PAGE_NEXT"
+ " or FIL_PAGE_PREV links\n", stderr);
+ buf_page_print(page);
+ buf_page_print(right_page);
+
+ ret = FALSE;
+ }
+
+ if (UNIV_UNLIKELY(page_is_comp(right_page)
+ != page_is_comp(page))) {
+ btr_validate_report2(index, level, page, right_page);
+ fputs("InnoDB: 'compact' flag mismatch\n", stderr);
+ buf_page_print(page);
+ buf_page_print(right_page);
+
+ ret = FALSE;
+
+ goto node_ptr_fails;
+ }
+
rec = page_rec_get_prev(page_get_supremum_rec(page));
right_rec = page_rec_get_next(
page_get_infimum_rec(right_page));
@@ -2755,8 +2808,8 @@
offsets, ULINT_UNDEFINED, &heap);
offsets2 = rec_get_offsets(right_rec, index,
offsets2, ULINT_UNDEFINED, &heap);
- if (cmp_rec_rec(rec, right_rec, offsets, offsets2, index)
- >= 0) {
+ if (UNIV_UNLIKELY(cmp_rec_rec(rec, right_rec,
+ offsets, offsets2, index) >= 0)) {
btr_validate_report2(index, level, page, right_page);
@@ -2776,10 +2829,10 @@
rec_print(stderr, rec, index);
putc('\n', stderr);
- ret = FALSE;
- }
+ ret = FALSE;
+ }
}
-
+
if (level > 0 && left_page_no == FIL_NULL) {
ut_a(REC_INFO_MIN_REC_FLAG & rec_get_info_bits(
page_rec_get_next(page_get_infimum_rec(page)),
@@ -2789,7 +2842,7 @@
if (buf_frame_get_page_no(page) != dict_tree_get_page(tree)) {
/* Check father node pointers */
-
+
node_ptr = btr_page_get_father_node_ptr(tree, page, &mtr);
father_page = buf_frame_align(node_ptr);
offsets = rec_get_offsets(node_ptr, index,
@@ -2822,25 +2875,25 @@
&mtr);
rec_print(stderr, rec, index);
putc('\n', stderr);
- ret = FALSE;
+ ret = FALSE;
- goto node_ptr_fails;
+ goto node_ptr_fails;
}
if (btr_page_get_level(page, &mtr) > 0) {
offsets = rec_get_offsets(node_ptr, index,
offsets, ULINT_UNDEFINED, &heap);
-
+
node_ptr_tuple = dict_tree_build_node_ptr(
tree,
page_rec_get_next(
page_get_infimum_rec(page)),
0, heap,
- btr_page_get_level(page, &mtr));
+ btr_page_get_level(page, &mtr));
if (cmp_dtuple_rec(node_ptr_tuple, node_ptr,
offsets)) {
- rec_t* first_rec = page_rec_get_next(
+ rec_t* first_rec = page_rec_get_next(
page_get_infimum_rec(page));
btr_validate_report1(index, level, page);
@@ -2855,9 +2908,9 @@
fputs("InnoDB: first rec ", stderr);
rec_print(stderr, first_rec, index);
putc('\n', stderr);
- ret = FALSE;
+ ret = FALSE;
- goto node_ptr_fails;
+ goto node_ptr_fails;
}
}
@@ -2871,10 +2924,7 @@
ut_a(node_ptr == page_rec_get_prev(
page_get_supremum_rec(father_page)));
ut_a(btr_page_get_next(father_page, &mtr) == FIL_NULL);
- }
-
- if (right_page_no != FIL_NULL) {
-
+ } else {
right_node_ptr = btr_page_get_father_node_ptr(tree,
right_page, &mtr);
if (page_rec_get_next(node_ptr) !=
@@ -2897,9 +2947,9 @@
} else {
right_father_page = buf_frame_align(
right_node_ptr);
-
+
if (right_node_ptr != page_rec_get_next(
- page_get_infimum_rec(
+ page_get_infimum_rec(
right_father_page))) {
ret = FALSE;
fputs(
@@ -2931,19 +2981,20 @@
buf_page_print(page);
buf_page_print(right_page);
}
- }
+ }
}
}
node_ptr_fails:
+ /* Commit the mini-transaction to release the latch on 'page'.
+ Re-acquire the latch on right_page, which will become 'page'
+ on the next loop. The page has already been checked. */
mtr_commit(&mtr);
if (right_page_no != FIL_NULL) {
- ulint comp = page_is_comp(page);
mtr_start(&mtr);
-
+
page = btr_page_get(space, right_page_no, RW_X_LATCH, &mtr);
- ut_a(page_is_comp(page) == comp);
goto loop;
}
--- 1.45.6.1/innobase/buf/buf0buf.c 2006-08-29 18:58:59 +04:00
+++ 1.54/storage/innobase/buf/buf0buf.c 2006-08-29 18:58:59 +04:00
@@ -1,14 +1,14 @@
/* Innobase relational database engine; Copyright (C) 2001 Innobase Oy
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License 2
as published by the Free Software Foundation in June 1991.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License 2
along with this program (in file COPYING); if not, write to the Free
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
@@ -42,7 +42,7 @@
IMPLEMENTATION OF THE BUFFER POOL
=================================
-Performance improvement:
+Performance improvement:
------------------------
Thread scheduling in NT may be so slow that the OS wait mechanism should
not be used even in waiting for disk reads to complete.
@@ -239,33 +239,33 @@
ulint
buf_calc_page_new_checksum(
/*=======================*/
- /* out: checksum */
- byte* page) /* in: buffer page */
+ /* out: checksum */
+ byte* page) /* in: buffer page */
{
- ulint checksum;
+ ulint checksum;
- /* Since the field FIL_PAGE_FILE_FLUSH_LSN, and in versions <= 4.1.x
- ..._ARCH_LOG_NO, are written outside the buffer pool to the first
- pages of data files, we have to skip them in the page checksum
- calculation.
+ /* Since the field FIL_PAGE_FILE_FLUSH_LSN, and in versions <= 4.1.x
+ ..._ARCH_LOG_NO, are written outside the buffer pool to the first
+ pages of data files, we have to skip them in the page checksum
+ calculation.
We must also skip the field FIL_PAGE_SPACE_OR_CHKSUM where the
checksum is stored, and also the last 8 bytes of page because
there we store the old formula checksum. */
-
- checksum = ut_fold_binary(page + FIL_PAGE_OFFSET,
+
+ checksum = ut_fold_binary(page + FIL_PAGE_OFFSET,
FIL_PAGE_FILE_FLUSH_LSN - FIL_PAGE_OFFSET)
- + ut_fold_binary(page + FIL_PAGE_DATA,
- UNIV_PAGE_SIZE - FIL_PAGE_DATA
- - FIL_PAGE_END_LSN_OLD_CHKSUM);
- checksum = checksum & 0xFFFFFFFFUL;
+ + ut_fold_binary(page + FIL_PAGE_DATA,
+ UNIV_PAGE_SIZE - FIL_PAGE_DATA
+ - FIL_PAGE_END_LSN_OLD_CHKSUM);
+ checksum = checksum & 0xFFFFFFFFUL;
- return(checksum);
+ return(checksum);
}
/************************************************************************
In versions < 4.0.14 and < 4.1.1 there was a bug that the checksum only
looked at the first few bytes of the page. This calculates that old
-checksum.
+checksum.
NOTE: we must first store the new formula checksum to
FIL_PAGE_SPACE_OR_CHKSUM before calculating and storing this old checksum
because this takes that field as an input! */
@@ -273,16 +273,16 @@
ulint
buf_calc_page_old_checksum(
/*=======================*/
- /* out: checksum */
- byte* page) /* in: buffer page */
+ /* out: checksum */
+ byte* page) /* in: buffer page */
{
- ulint checksum;
-
- checksum = ut_fold_binary(page, FIL_PAGE_FILE_FLUSH_LSN);
+ ulint checksum;
+
+ checksum = ut_fold_binary(page, FIL_PAGE_FILE_FLUSH_LSN);
- checksum = checksum & 0xFFFFFFFFUL;
+ checksum = checksum & 0xFFFFFFFFUL;
- return(checksum);
+ return(checksum);
}
/************************************************************************
@@ -302,11 +302,11 @@
dulint current_lsn;
#endif
if (mach_read_from_4(read_buf + FIL_PAGE_LSN + 4)
- != mach_read_from_4(read_buf + UNIV_PAGE_SIZE
- - FIL_PAGE_END_LSN_OLD_CHKSUM + 4)) {
+ != mach_read_from_4(read_buf + UNIV_PAGE_SIZE
+ - FIL_PAGE_END_LSN_OLD_CHKSUM + 4)) {
/* Stored log sequence numbers at the start and the end
- of page do not match */
+ of page do not match */
return(TRUE);
}
@@ -314,8 +314,8 @@
#ifndef UNIV_HOTBACKUP
if (recv_lsn_checks_on && log_peek_lsn(¤t_lsn)) {
if (ut_dulint_cmp(current_lsn,
- mach_read_from_8(read_buf + FIL_PAGE_LSN))
- < 0) {
+ mach_read_from_8(read_buf + FIL_PAGE_LSN))
+ < 0) {
ut_print_timestamp(stderr);
fprintf(stderr,
@@ -325,53 +325,58 @@
"InnoDB: tablespace but not the InnoDB log files. See\n"
"InnoDB: http://dev.mysql.com/doc/refman/5.0/en/forcing-recovery.html\n"
"InnoDB: for more information.\n",
- (ulong) mach_read_from_4(read_buf + FIL_PAGE_OFFSET),
- (ulong) ut_dulint_get_high(
- mach_read_from_8(read_buf + FIL_PAGE_LSN)),
- (ulong) ut_dulint_get_low(
- mach_read_from_8(read_buf + FIL_PAGE_LSN)),
- (ulong) ut_dulint_get_high(current_lsn),
- (ulong) ut_dulint_get_low(current_lsn));
+ (ulong) mach_read_from_4(read_buf + FIL_PAGE_OFFSET),
+ (ulong) ut_dulint_get_high(
+ mach_read_from_8(read_buf + FIL_PAGE_LSN)),
+ (ulong) ut_dulint_get_low(
+ mach_read_from_8(read_buf + FIL_PAGE_LSN)),
+ (ulong) ut_dulint_get_high(current_lsn),
+ (ulong) ut_dulint_get_low(current_lsn));
}
}
#endif
-
- /* If we use checksums validation, make additional check before returning
- TRUE to ensure that the checksum is not equal to BUF_NO_CHECKSUM_MAGIC which
- might be stored by InnoDB with checksums disabled.
- Otherwise, skip checksum calculation and return FALSE */
-
- if (srv_use_checksums) {
- old_checksum = buf_calc_page_old_checksum(read_buf);
-
- old_checksum_field = mach_read_from_4(read_buf + UNIV_PAGE_SIZE
- - FIL_PAGE_END_LSN_OLD_CHKSUM);
-
- /* There are 2 valid formulas for old_checksum_field:
- 1. Very old versions of InnoDB only stored 8 byte lsn to the start
- and the end of the page.
- 2. Newer InnoDB versions store the old formula checksum there. */
-
- if (old_checksum_field != mach_read_from_4(read_buf + FIL_PAGE_LSN)
- && old_checksum_field != old_checksum
- && old_checksum_field != BUF_NO_CHECKSUM_MAGIC) {
-
- return(TRUE);
- }
-
- checksum = buf_calc_page_new_checksum(read_buf);
- checksum_field = mach_read_from_4(read_buf + FIL_PAGE_SPACE_OR_CHKSUM);
-
- /* InnoDB versions < 4.0.14 and < 4.1.1 stored the space id
- (always equal to 0), to FIL_PAGE_SPACE_SPACE_OR_CHKSUM */
-
- if (checksum_field != 0 && checksum_field != checksum
- && checksum_field != BUF_NO_CHECKSUM_MAGIC) {
-
- return(TRUE);
- }
- }
-
+
+ /* If we use checksums validation, make additional check before
+ returning TRUE to ensure that the checksum is not equal to
+ BUF_NO_CHECKSUM_MAGIC which might be stored by InnoDB with checksums
+ disabled. Otherwise, skip checksum calculation and return FALSE */
+
+ if (srv_use_checksums) {
+ old_checksum = buf_calc_page_old_checksum(read_buf);
+
+ old_checksum_field = mach_read_from_4(read_buf + UNIV_PAGE_SIZE
+ - FIL_PAGE_END_LSN_OLD_CHKSUM);
+
+ /* There are 2 valid formulas for old_checksum_field:
+
+ 1. Very old versions of InnoDB only stored 8 byte lsn to the
+ start and the end of the page.
+
+ 2. Newer InnoDB versions store the old formula checksum
+ there. */
+
+ if (old_checksum_field != mach_read_from_4(read_buf
+ + FIL_PAGE_LSN)
+ && old_checksum_field != old_checksum
+ && old_checksum_field != BUF_NO_CHECKSUM_MAGIC) {
+
+ return(TRUE);
+ }
+
+ checksum = buf_calc_page_new_checksum(read_buf);
+ checksum_field = mach_read_from_4(read_buf +
+ FIL_PAGE_SPACE_OR_CHKSUM);
+
+ /* InnoDB versions < 4.0.14 and < 4.1.1 stored the space id
+ (always equal to 0), to FIL_PAGE_SPACE_SPACE_OR_CHKSUM */
+
+ if (checksum_field != 0 && checksum_field != checksum
+ && checksum_field != BUF_NO_CHECKSUM_MAGIC) {
+
+ return(TRUE);
+ }
+ }
+
return(FALSE);
}
@@ -394,12 +399,12 @@
fputs("InnoDB: End of page dump\n", stderr);
checksum = srv_use_checksums ?
- buf_calc_page_new_checksum(read_buf) : BUF_NO_CHECKSUM_MAGIC;
+ buf_calc_page_new_checksum(read_buf) : BUF_NO_CHECKSUM_MAGIC;
old_checksum = srv_use_checksums ?
- buf_calc_page_old_checksum(read_buf) : BUF_NO_CHECKSUM_MAGIC;
+ buf_calc_page_old_checksum(read_buf) : BUF_NO_CHECKSUM_MAGIC;
ut_print_timestamp(stderr);
- fprintf(stderr,
+ fprintf(stderr,
" InnoDB: Page checksum %lu, prior-to-4.0.14-form checksum %lu\n"
"InnoDB: stored checksum %lu, prior-to-4.0.14-form stored checksum %lu\n",
(ulong) checksum, (ulong) old_checksum,
@@ -418,18 +423,19 @@
(ulong) mach_read_from_4(read_buf + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID));
if (mach_read_from_2(read_buf + TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_TYPE)
- == TRX_UNDO_INSERT) {
- fprintf(stderr,
+ == TRX_UNDO_INSERT) {
+ fprintf(stderr,
"InnoDB: Page may be an insert undo log page\n");
} else if (mach_read_from_2(read_buf + TRX_UNDO_PAGE_HDR
+ TRX_UNDO_PAGE_TYPE)
- == TRX_UNDO_UPDATE) {
- fprintf(stderr,
+ == TRX_UNDO_UPDATE) {
+ fprintf(stderr,
"InnoDB: Page may be an update undo log page\n");
}
- if (fil_page_get_type(read_buf) == FIL_PAGE_INDEX) {
- fprintf(stderr,
+ switch (fil_page_get_type(read_buf)) {
+ case FIL_PAGE_INDEX:
+ fprintf(stderr,
"InnoDB: Page may be an index page where index id is %lu %lu\n",
(ulong) ut_dulint_get_high(btr_page_get_index_id(read_buf)),
(ulong) ut_dulint_get_low(btr_page_get_index_id(read_buf)));
@@ -439,19 +445,50 @@
if (dict_sys != NULL) {
- index = dict_index_find_on_id_low(
+ index = dict_index_find_on_id_low(
btr_page_get_index_id(read_buf));
- if (index) {
+ if (index) {
fputs("InnoDB: (", stderr);
dict_index_name_print(stderr, NULL, index);
fputs(")\n", stderr);
}
}
- } else if (fil_page_get_type(read_buf) == FIL_PAGE_INODE) {
+ break;
+ case FIL_PAGE_INODE:
fputs("InnoDB: Page may be an 'inode' page\n", stderr);
- } else if (fil_page_get_type(read_buf) == FIL_PAGE_IBUF_FREE_LIST) {
+ break;
+ case FIL_PAGE_IBUF_FREE_LIST:
fputs("InnoDB: Page may be an insert buffer free list page\n",
stderr);
+ break;
+ case FIL_PAGE_TYPE_ALLOCATED:
+ fputs("InnoDB: Page may be a freshly allocated page\n",
+ stderr);
+ break;
+ case FIL_PAGE_IBUF_BITMAP:
+ fputs("InnoDB: Page may be an insert buffer bitmap page\n",
+ stderr);
+ break;
+ case FIL_PAGE_TYPE_SYS:
+ fputs("InnoDB: Page may be a system page\n",
+ stderr);
+ break;
+ case FIL_PAGE_TYPE_TRX_SYS:
+ fputs("InnoDB: Page may be a transaction system page\n",
+ stderr);
+ break;
+ case FIL_PAGE_TYPE_FSP_HDR:
+ fputs("InnoDB: Page may be a file space header page\n",
+ stderr);
+ break;
+ case FIL_PAGE_TYPE_XDES:
+ fputs("InnoDB: Page may be an extent descriptor page\n",
+ stderr);
+ break;
+ case FIL_PAGE_TYPE_BLOB:
+ fputs("InnoDB: Page may be a BLOB page\n",
+ stderr);
+ break;
}
}
@@ -468,7 +505,7 @@
block->magic_n = 0;
block->state = BUF_BLOCK_NOT_USED;
-
+
block->frame = frame;
block->awe_info = NULL;
@@ -477,7 +514,7 @@
block->io_fix = 0;
block->modify_clock = ut_dulint_zero;
-
+
block->file_page_was_freed = FALSE;
block->check_index_page_at_flush = FALSE;
@@ -488,12 +525,11 @@
block->n_pointers = 0;
- rw_lock_create(&(block->lock));
+ rw_lock_create(&block->lock, SYNC_LEVEL_VARYING);
ut_ad(rw_lock_validate(&(block->lock)));
#ifdef UNIV_SYNC_DEBUG
- rw_lock_create(&(block->debug_latch));
- rw_lock_set_level(&(block->debug_latch), SYNC_NO_ORDER_CHECK);
+ rw_lock_create(&block->debug_latch, SYNC_NO_ORDER_CHECK);
#endif /* UNIV_SYNC_DEBUG */
}
@@ -519,12 +555,12 @@
byte* frame;
ulint i;
buf_block_t* block;
-
+
ut_a(max_size == curr_size);
ut_a(srv_use_awe || n_frames == max_size);
-
+
if (n_frames > curr_size) {
- fprintf(stderr,
+ fprintf(stderr,
"InnoDB: AWE: Error: you must specify in my.cnf .._awe_mem_mb larger\n"
"InnoDB: than .._buffer_pool_size. Now the former is %lu pages,\n"
"InnoDB: the latter %lu pages.\n", (ulong) curr_size, (ulong) n_frames);
@@ -536,8 +572,7 @@
/* 1. Initialize general fields
---------------------------- */
- mutex_create(&(buf_pool->mutex));
- mutex_set_level(&(buf_pool->mutex), SYNC_BUF_POOL);
+ mutex_create(&buf_pool->mutex, SYNC_BUF_POOL);
mutex_enter(&(buf_pool->mutex));
@@ -548,18 +583,18 @@
buf_pool->frame_mem = os_awe_allocate_virtual_mem_window(
UNIV_PAGE_SIZE * (n_frames + 1));
-
+
/* Allocate the physical memory for AWE and the AWE info array
for buf_pool */
if ((curr_size % ((1024 * 1024) / UNIV_PAGE_SIZE)) != 0) {
- fprintf(stderr,
+ fprintf(stderr,
"InnoDB: AWE: Error: physical memory must be allocated in full megabytes.\n"
-"InnoDB: Trying to allocate %lu database pages.\n",
+"InnoDB: Trying to allocate %lu database pages.\n",
(ulong) curr_size);
- return(NULL);
+ return(NULL);
}
if (!os_awe_allocate_physical_mem(&(buf_pool->awe_info),
@@ -611,7 +646,7 @@
}
buf_pool->blocks_of_frames = ut_malloc(sizeof(void*) * n_frames);
-
+
if (buf_pool->blocks_of_frames == NULL) {
return(NULL);
@@ -632,7 +667,7 @@
} else {
frame = NULL;
}
-
+
buf_block_init(block, frame);
if (srv_use_awe) {
@@ -653,14 +688,14 @@
buf_pool->n_pages_written = 0;
buf_pool->n_pages_created = 0;
buf_pool->n_pages_awe_remapped = 0;
-
+
buf_pool->n_page_gets = 0;
buf_pool->n_page_gets_old = 0;
buf_pool->n_pages_read_old = 0;
buf_pool->n_pages_written_old = 0;
buf_pool->n_pages_created_old = 0;
buf_pool->n_pages_awe_remapped_old = 0;
-
+
/* 2. Initialize flushing fields
---------------------------- */
UT_LIST_INIT(buf_pool->flush_list);
@@ -675,7 +710,7 @@
buf_pool->ulint_clock = 1;
buf_pool->freed_page_clock = 0;
-
+
/* 3. Initialize LRU fields
---------------------------- */
UT_LIST_INIT(buf_pool->LRU);
@@ -701,7 +736,7 @@
if (srv_use_awe) {
/* Add to the list of blocks mapped to
frames */
-
+
UT_LIST_ADD_LAST(awe_LRU_free_mapped,
buf_pool->awe_LRU_free_mapped, block);
}
@@ -714,15 +749,15 @@
mutex_exit(&(buf_pool->mutex));
if (srv_use_adaptive_hash_indexes) {
- btr_search_sys_create(
+ btr_search_sys_create(
curr_size * UNIV_PAGE_SIZE / sizeof(void*) / 64);
} else {
- /* Create only a small dummy system */
- btr_search_sys_create(1000);
+ /* Create only a small dummy system */
+ btr_search_sys_create(1000);
}
return(buf_pool);
-}
+}
/************************************************************************
Maps the page of block to a frame, if not mapped yet. Unmaps some page
@@ -755,9 +790,9 @@
bck = UT_LIST_GET_LAST(buf_pool->awe_LRU_free_mapped);
- while (bck) {
+ while (bck) {
if (bck->state == BUF_BLOCK_FILE_PAGE
- && (bck->buf_fix_count != 0 || bck->io_fix != 0)) {
+ && (bck->buf_fix_count != 0 || bck->io_fix != 0)) {
/* We have to skip this */
bck = UT_LIST_GET_PREV(awe_LRU_free_mapped, bck);
@@ -776,7 +811,7 @@
- buf_pool->frame_zero))
>> UNIV_PAGE_SIZE_SHIFT))
= block;
-
+
bck->frame = NULL;
UT_LIST_REMOVE(awe_LRU_free_mapped,
buf_pool->awe_LRU_free_mapped,
@@ -789,7 +824,7 @@
}
buf_pool->n_pages_awe_remapped++;
-
+
return;
}
}
@@ -828,7 +863,7 @@
/*=================*/
buf_block_t* block) /* in: block to make younger */
{
- if (buf_pool->freed_page_clock >= block->freed_page_clock
+ if (buf_pool->freed_page_clock >= block->freed_page_clock
+ 1 + (buf_pool->curr_size / 1024)) {
/* There has been freeing activity in the LRU list:
@@ -845,11 +880,11 @@
void
buf_page_make_young(
-/*=================*/
+/*================*/
buf_frame_t* frame) /* in: buffer frame of a file page */
{
buf_block_t* block;
-
+
mutex_enter(&(buf_pool->mutex));
block = buf_block_align(frame);
@@ -899,7 +934,7 @@
{
buf_block_free(buf_block_align(frame));
}
-
+
/************************************************************************
Returns the buffer control block if the page can be found in the buffer
pool. NOTE that it is possible that the page is not yet read
@@ -944,7 +979,7 @@
if (block) {
block->check_index_page_at_flush = FALSE;
}
-
+
mutex_exit(&(buf_pool->mutex));
}
@@ -1080,14 +1115,14 @@
ulint fix_type;
ibool success;
ibool must_read;
-
+
ut_ad(mtr);
ut_ad((rw_latch == RW_S_LATCH)
- || (rw_latch == RW_X_LATCH)
- || (rw_latch == RW_NO_LATCH));
+ || (rw_latch == RW_X_LATCH)
+ || (rw_latch == RW_NO_LATCH));
ut_ad((mode != BUF_GET_NO_LATCH) || (rw_latch == RW_NO_LATCH));
ut_ad((mode == BUF_GET) || (mode == BUF_GET_IF_IN_POOL)
- || (mode == BUF_GET_NO_LATCH) || (mode == BUF_GET_NOWAIT));
+ || (mode == BUF_GET_NO_LATCH) || (mode == BUF_GET_NOWAIT));
#ifndef UNIV_LOG_DEBUG
ut_ad(!ibuf_inside() || ibuf_page(space, offset));
#endif
@@ -1096,7 +1131,7 @@
mutex_enter_fast(&(buf_pool->mutex));
block = NULL;
-
+
if (guess) {
block = buf_block_align(guess);
@@ -1136,7 +1171,7 @@
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
must_read = FALSE;
-
+
if (block->io_fix == BUF_IO_READ) {
must_read = TRUE;
@@ -1148,7 +1183,7 @@
return(NULL);
}
- }
+ }
/* If AWE is enabled and the page is not mapped to a frame, then
map it */
@@ -1159,10 +1194,10 @@
/* We set second parameter TRUE because the block is in the
LRU list and we must put it to awe_LRU_free_mapped list once
mapped to a frame */
-
+
buf_awe_map_page_to_frame(block, TRUE);
}
-
+
#ifdef UNIV_SYNC_DEBUG
buf_block_buf_fix_inc_debug(block, file, line);
#else
@@ -1178,7 +1213,7 @@
#ifdef UNIV_DEBUG_FILE_ACCESSES
ut_a(block->file_page_was_freed == FALSE);
-#endif
+#endif
mutex_exit(&(buf_pool->mutex));
#ifdef UNIV_DEBUG
@@ -1209,7 +1244,7 @@
block->buf_fix_count--;
#ifdef UNIV_SYNC_DEBUG
rw_lock_s_unlock(&(block->debug_latch));
-#endif
+#endif
mutex_exit(&(buf_pool->mutex));
return(NULL);
@@ -1217,24 +1252,24 @@
} else if (rw_latch == RW_NO_LATCH) {
if (must_read) {
- /* Let us wait until the read operation
+ /* Let us wait until the read operation
completes */
- for (;;) {
- mutex_enter(&(buf_pool->mutex));
+ for (;;) {
+ mutex_enter(&(buf_pool->mutex));
+
+ if (block->io_fix == BUF_IO_READ) {
- if (block->io_fix == BUF_IO_READ) {
+ mutex_exit(&(buf_pool->mutex));
- mutex_exit(&(buf_pool->mutex));
-
- /* Sleep 20 milliseconds */
+ /* Sleep 20 milliseconds */
- os_thread_sleep(20000);
+ os_thread_sleep(20000);
} else {
-
- mutex_exit(&(buf_pool->mutex));
- break;
+ mutex_exit(&(buf_pool->mutex));
+
+ break;
}
}
}
@@ -1263,7 +1298,7 @@
#ifdef UNIV_IBUF_DEBUG
ut_a(ibuf_count_get(block->space, block->offset) == 0);
#endif
- return(block->frame);
+ return(block->frame);
}
/************************************************************************
@@ -1290,11 +1325,11 @@
ut_ad(mtr && block);
ut_ad((rw_latch == RW_S_LATCH) || (rw_latch == RW_X_LATCH));
-
+
mutex_enter(&(buf_pool->mutex));
/* If AWE is used, block may have a different frame now, e.g., NULL */
-
+
if (UNIV_UNLIKELY(block->state != BUF_BLOCK_FILE_PAGE)
|| UNIV_UNLIKELY(block->frame != guess)) {
exit_func:
@@ -1332,7 +1367,7 @@
if (UNIV_UNLIKELY(!success)) {
mutex_enter(&(buf_pool->mutex));
-
+
block->buf_fix_count--;
#ifdef UNIV_SYNC_DEBUG
rw_lock_s_unlock(&(block->debug_latch));
@@ -1351,7 +1386,7 @@
}
mutex_enter(&(buf_pool->mutex));
-
+
block->buf_fix_count--;
#ifdef UNIV_SYNC_DEBUG
rw_lock_s_unlock(&(block->debug_latch));
@@ -1412,20 +1447,20 @@
ut_ad(mtr);
ut_ad((rw_latch == RW_S_LATCH) || (rw_latch == RW_X_LATCH));
-
+
mutex_enter(&(buf_pool->mutex));
block = buf_block_align(guess);
if (block->state == BUF_BLOCK_REMOVE_HASH) {
- /* Another thread is just freeing the block from the LRU list
- of the buffer pool: do not try to access this page; this
+ /* Another thread is just freeing the block from the LRU list
+ of the buffer pool: do not try to access this page; this
attempt to access the page can only come through the hash
index because when the buffer block state is ..._REMOVE_HASH,
we have already removed it from the page address hash table
of the buffer pool. */
- mutex_exit(&(buf_pool->mutex));
+ mutex_exit(&(buf_pool->mutex));
return(FALSE);
}
@@ -1454,14 +1489,14 @@
file, line);
fix_type = MTR_MEMO_PAGE_X_FIX;
}
-
+
if (!success) {
mutex_enter(&(buf_pool->mutex));
-
+
block->buf_fix_count--;
#ifdef UNIV_SYNC_DEBUG
rw_lock_s_unlock(&(block->debug_latch));
-#endif
+#endif
mutex_exit(&(buf_pool->mutex));
return(FALSE);
@@ -1505,27 +1540,27 @@
/* Set the state of the block */
block->magic_n = BUF_BLOCK_MAGIC_N;
- block->state = BUF_BLOCK_FILE_PAGE;
- block->space = space;
- block->offset = offset;
+ block->state = BUF_BLOCK_FILE_PAGE;
+ block->space = space;
+ block->offset = offset;
block->lock_hash_val = 0;
block->lock_mutex = NULL;
-
+
block->freed_page_clock = 0;
block->newest_modification = ut_dulint_zero;
block->oldest_modification = ut_dulint_zero;
-
+
block->accessed = FALSE;
- block->buf_fix_count = 0;
+ block->buf_fix_count = 0;
block->io_fix = 0;
block->n_hash_helps = 0;
block->is_hashed = FALSE;
- block->n_fields = 1;
- block->n_bytes = 0;
- block->side = BTR_SEARCH_LEFT_SIDE;
+ block->n_fields = 1;
+ block->n_bytes = 0;
+ block->side = BTR_SEARCH_LEFT_SIDE;
block->file_page_was_freed = FALSE;
}
@@ -1549,31 +1584,31 @@
/* Set the state of the block */
block->magic_n = BUF_BLOCK_MAGIC_N;
- block->state = BUF_BLOCK_FILE_PAGE;
- block->space = space;
- block->offset = offset;
+ block->state = BUF_BLOCK_FILE_PAGE;
+ block->space = space;
+ block->offset = offset;
block->check_index_page_at_flush = FALSE;
block->index = NULL;
-
+
block->lock_hash_val = lock_rec_hash(space, offset);
block->lock_mutex = NULL;
-
+
/* Insert into the hash table of file pages */
- if (buf_page_hash_get(space, offset)) {
- fprintf(stderr,
+ if (buf_page_hash_get(space, offset)) {
+ fprintf(stderr,
"InnoDB: Error: page %lu %lu already found from the hash table\n",
(ulong) space,
(ulong) offset);
#ifdef UNIV_DEBUG
- buf_print();
- buf_LRU_print();
- buf_validate();
- buf_LRU_validate();
+ buf_print();
+ buf_LRU_print();
+ buf_validate();
+ buf_LRU_validate();
#endif /* UNIV_DEBUG */
- ut_a(0);
- }
+ ut_a(0);
+ }
HASH_INSERT(buf_block_t, hash, buf_pool->page_hash,
buf_page_address_fold(space, offset), block);
@@ -1582,16 +1617,16 @@
block->newest_modification = ut_dulint_zero;
block->oldest_modification = ut_dulint_zero;
-
+
block->accessed = FALSE;
- block->buf_fix_count = 0;
+ block->buf_fix_count = 0;
block->io_fix = 0;
block->n_hash_helps = 0;
block->is_hashed = FALSE;
- block->n_fields = 1;
- block->n_bytes = 0;
- block->side = BTR_SEARCH_LEFT_SIDE;
+ block->n_fields = 1;
+ block->n_bytes = 0;
+ block->side = BTR_SEARCH_LEFT_SIDE;
block->file_page_was_freed = FALSE;
}
@@ -1606,7 +1641,7 @@
on the buffer frame. The io-handler must take care that the flag is cleared
and the lock released later. This is one of the functions which perform the
state transition NOT_USED => FILE_PAGE to a block (the other is
-buf_page_create). */
+buf_page_create). */
buf_block_t*
buf_page_init_for_read(
@@ -1632,9 +1667,9 @@
ut_ad(!ibuf_bitmap_page(offset));
ut_ad(ibuf_inside());
-
+
mtr_start(&mtr);
-
+
if (!ibuf_page_low(space, offset, &mtr)) {
mtr_commit(&mtr);
@@ -1644,7 +1679,7 @@
} else {
ut_ad(mode == BUF_READ_ANY_PAGE);
}
-
+
block = buf_block_alloc();
ut_a(block);
@@ -1657,7 +1692,7 @@
}
if (*err == DB_TABLESPACE_DELETED
- || NULL != buf_page_hash_get(space, offset)) {
+ || NULL != buf_page_hash_get(space, offset)) {
/* The page belongs to a space which has been deleted or is
being deleted, or the page is already in buf_pool, return */
@@ -1674,26 +1709,26 @@
}
ut_ad(block);
-
+
buf_page_init(space, offset, block);
/* The block must be put to the LRU list, to the old blocks */
- buf_LRU_add_block(block, TRUE); /* TRUE == to old blocks */
-
+ buf_LRU_add_block(block, TRUE); /* TRUE == to old blocks */
+
block->io_fix = BUF_IO_READ;
buf_pool->n_pend_reads++;
-
+
/* We set a pass-type x-lock on the frame because then the same
thread which called for the read operation (and is running now at
this point of code) can wait for the read to complete by waiting
for the x-lock on the frame; if the x-lock were recursive, the
same thread would illegally get the x-lock before the page read
is completed. The x-lock is cleared by the io-handler thread. */
-
+
rw_lock_x_lock_gen(&(block->lock), BUF_IO_READ);
-
- mutex_exit(&(buf_pool->mutex));
+
+ mutex_exit(&(buf_pool->mutex));
if (mode == BUF_READ_IBUF_PAGES_ONLY) {
@@ -1701,7 +1736,7 @@
}
return(block);
-}
+}
/************************************************************************
Initializes a page to the buffer buf_pool. The page is usually not read
@@ -1721,11 +1756,11 @@
buf_frame_t* frame;
buf_block_t* block;
buf_block_t* free_block = NULL;
-
+
ut_ad(mtr);
free_block = buf_LRU_get_free_block();
-
+
mutex_enter(&(buf_pool->mutex));
block = buf_page_hash_get(space, offset);
@@ -1756,12 +1791,12 @@
#endif /* UNIV_DEBUG */
block = free_block;
-
+
buf_page_init(space, offset, block);
/* The block must be put to the LRU list */
buf_LRU_add_block(block, FALSE);
-
+
#ifdef UNIV_SYNC_DEBUG
buf_block_buf_fix_inc_debug(block, __FILE__, __LINE__);
#else
@@ -1770,7 +1805,7 @@
mtr_memo_push(mtr, block, MTR_MEMO_BUF_FIX);
block->accessed = TRUE;
-
+
buf_pool->n_pages_created++;
mutex_exit(&(buf_pool->mutex));
@@ -1785,6 +1820,10 @@
frame = block->frame;
+ memset(frame + FIL_PAGE_PREV, 0xff, 4);
+ memset(frame + FIL_PAGE_NEXT, 0xff, 4);
+ mach_write_to_2(frame + FIL_PAGE_TYPE, FIL_PAGE_TYPE_ALLOCATED);
+
/* Reset to zero the file flush lsn field in the page; if the first
page of an ibdata file is 'created' in this function into the buffer
pool then we lose the original contents of the file flush lsn stamp.
@@ -1816,8 +1855,7 @@
buf_block_t* block) /* in: pointer to the block in question */
{
ulint io_type;
- ulint read_page_no;
-
+
ut_ad(block);
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
@@ -1826,33 +1864,51 @@
if (io_type == BUF_IO_READ) {
/* If this page is not uninitialized and not in the
- doublewrite buffer, then the page number should be the
- same as in block */
-
- read_page_no = mach_read_from_4((block->frame)
+ doublewrite buffer, then the page number and space id
+ should be the same as in block. */
+ ulint read_page_no = mach_read_from_4((block->frame)
+ FIL_PAGE_OFFSET);
- if (read_page_no != 0
- && !trx_doublewrite_page_inside(read_page_no)
- && read_page_no != block->offset) {
+ ulint read_space_id = mach_read_from_4((block->frame)
+ + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
+ if (!block->space && trx_doublewrite_page_inside(
+ block->offset)) {
+
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+" InnoDB: Error: reading page %lu\n"
+"InnoDB: which is in the doublewrite buffer!\n",
+ (ulong) block->offset);
+ } else if (!read_space_id && !read_page_no) {
+ /* This is likely an uninitialized page. */
+ } else if ((block->space && block->space != read_space_id)
+ || block->offset != read_page_no) {
+ /* We did not compare space_id to read_space_id
+ if block->space == 0, because the field on the
+ page may contain garbage in MySQL < 4.1.1,
+ which only supported block->space == 0. */
+
+ ut_print_timestamp(stderr);
fprintf(stderr,
-"InnoDB: Error: page n:o stored in the page read in is %lu, should be %lu!\n",
- (ulong) read_page_no, (ulong) block->offset);
+" InnoDB: Error: space id and page n:o stored in the page\n"
+"InnoDB: read in are %lu:%lu, should be %lu:%lu!\n",
+ (ulong) read_space_id, (ulong) read_page_no,
+ (ulong) block->space, (ulong) block->offset);
}
/* From version 3.23.38 up we store the page checksum
to the 4 first bytes of the page end lsn field */
if (buf_page_is_corrupted(block->frame)) {
- fprintf(stderr,
+ fprintf(stderr,
"InnoDB: Database page corruption on disk or a failed\n"
"InnoDB: file read of page %lu.\n", (ulong) block->offset);
-
+
fputs(
"InnoDB: You may have to recover from a backup.\n", stderr);
buf_page_print(block->frame);
- fprintf(stderr,
+ fprintf(stderr,
"InnoDB: Database page corruption on disk or a failed\n"
"InnoDB: file read of page %lu.\n", (ulong) block->offset);
fputs(
@@ -1870,13 +1926,13 @@
"InnoDB: See also "
"InnoDB: http://dev.mysql.com/doc/refman/5.0/en/forcing-recovery.html\n"
"InnoDB: about forcing recovery.\n", stderr);
-
+
if (srv_force_recovery < SRV_FORCE_IGNORE_CORRUPT) {
fputs(
"InnoDB: Ending processing because of a corrupt database page.\n",
stderr);
- exit(1);
- }
+ exit(1);
+ }
}
if (recv_recovery_is_on()) {
@@ -1889,24 +1945,24 @@
block->space, block->offset, TRUE);
}
}
-
+
#ifdef UNIV_IBUF_DEBUG
ut_a(ibuf_count_get(block->space, block->offset) == 0);
#endif
mutex_enter(&(buf_pool->mutex));
-
+
/* Because this thread which does the unlocking is not the same that
did the locking, we use a pass value != 0 in unlock, which simply
removes the newest lock debug record, without checking the thread
id. */
block->io_fix = 0;
-
+
if (io_type == BUF_IO_READ) {
/* NOTE that the call to ibuf may have moved the ownership of
the x-latch to this OS thread: do not let this confuse you in
- debugging! */
-
+ debugging! */
+
ut_ad(buf_pool->n_pend_reads > 0);
buf_pool->n_pend_reads--;
buf_pool->n_pages_read++;
@@ -1936,7 +1992,7 @@
}
#endif /* UNIV_DEBUG */
}
-
+
mutex_exit(&(buf_pool->mutex));
#ifdef UNIV_DEBUG
@@ -1959,13 +2015,13 @@
ibool freed;
ut_ad(buf_all_freed());
-
+
freed = TRUE;
while (freed) {
freed = buf_LRU_search_and_free_block(100);
}
-
+
mutex_enter(&(buf_pool->mutex));
ut_ad(UT_LIST_GET_LEN(buf_pool->LRU) == 0);
@@ -1990,7 +2046,7 @@
ulint n_flush = 0;
ulint n_free = 0;
ulint n_page = 0;
-
+
ut_ad(buf_pool);
mutex_enter(&(buf_pool->mutex));
@@ -2007,8 +2063,8 @@
#ifdef UNIV_IBUF_DEBUG
ut_a((block->io_fix == BUF_IO_READ)
- || ibuf_count_get(block->space, block->offset)
- == 0);
+ || ibuf_count_get(block->space, block->offset)
+ == 0);
#endif
if (block->io_fix == BUF_IO_WRITE) {
@@ -2031,18 +2087,18 @@
ut_a(rw_lock_is_locked(&(block->lock),
RW_LOCK_EX));
}
-
+
n_lru++;
if (ut_dulint_cmp(block->oldest_modification,
ut_dulint_zero) > 0) {
n_flush++;
- }
-
+ }
+
} else if (block->state == BUF_BLOCK_NOT_USED) {
n_free++;
}
- }
+ }
if (n_lru + n_free > buf_pool->curr_size) {
fprintf(stderr, "n LRU %lu, n free %lu\n", (ulong) n_lru, (ulong) n_free);
@@ -2060,14 +2116,14 @@
ut_a(buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE] == n_single_flush);
ut_a(buf_pool->n_flush[BUF_FLUSH_LIST] == n_list_flush);
ut_a(buf_pool->n_flush[BUF_FLUSH_LRU] == n_lru_flush);
-
+
mutex_exit(&(buf_pool->mutex));
ut_a(buf_LRU_validate());
ut_a(buf_flush_validate());
return(TRUE);
-}
+}
/*************************************************************************
Prints info of the buffer buf_pool data structure. */
@@ -2083,9 +2139,9 @@
ulint j;
dulint id;
ulint n_found;
- buf_frame_t* frame;
+ buf_frame_t* frame;
dict_index_t* index;
-
+
ut_ad(buf_pool);
size = buf_pool->curr_size;
@@ -2094,7 +2150,7 @@
counts = mem_alloc(sizeof(ulint) * size);
mutex_enter(&(buf_pool->mutex));
-
+
fprintf(stderr,
"buf_pool size %lu\n"
"database pages %lu\n"
@@ -2115,7 +2171,7 @@
(ulong) buf_pool->n_pages_written);
/* Count the number of blocks belonging to each index in the buffer */
-
+
n_found = 0;
for (i = 0; i < size; i++) {
@@ -2153,8 +2209,8 @@
fprintf(stderr,
"Block count for index %lu in buffer is about %lu",
- (ulong) ut_dulint_get_low(index_ids[i]),
- (ulong) counts[i]);
+ (ulong) ut_dulint_get_low(index_ids[i]),
+ (ulong) counts[i]);
if (index) {
putc(' ', stderr);
@@ -2163,12 +2219,12 @@
putc('\n', stderr);
}
-
+
mem_free(index_ids);
mem_free(counts);
ut_a(buf_validate());
-}
+}
#endif /* UNIV_DEBUG */
/*************************************************************************
@@ -2177,23 +2233,24 @@
ulint
buf_get_latched_pages_number(void)
{
- buf_block_t* block;
- ulint i;
- ulint fixed_pages_number = 0;
+ buf_block_t* block;
+ ulint i;
+ ulint fixed_pages_number = 0;
- mutex_enter(&(buf_pool->mutex));
+ mutex_enter(&(buf_pool->mutex));
- for (i = 0; i < buf_pool->curr_size; i++) {
+ for (i = 0; i < buf_pool->curr_size; i++) {
- block = buf_pool_get_nth_block(buf_pool, i);
+ block = buf_pool_get_nth_block(buf_pool, i);
+
+ if (((block->buf_fix_count != 0) || (block->io_fix != 0)) &&
+ block->magic_n == BUF_BLOCK_MAGIC_N )
+ fixed_pages_number++;
+ }
- if (((block->buf_fix_count != 0) || (block->io_fix != 0)) &&
- block->magic_n == BUF_BLOCK_MAGIC_N )
- fixed_pages_number++;
- }
+ mutex_exit(&(buf_pool->mutex));
- mutex_exit(&(buf_pool->mutex));
- return fixed_pages_number;
+ return(fixed_pages_number);
}
/*************************************************************************
@@ -2222,10 +2279,10 @@
mutex_enter(&(buf_pool->mutex));
ratio = (100 * UT_LIST_GET_LEN(buf_pool->flush_list))
- / (1 + UT_LIST_GET_LEN(buf_pool->LRU)
- + UT_LIST_GET_LEN(buf_pool->free));
+ / (1 + UT_LIST_GET_LEN(buf_pool->LRU)
+ + UT_LIST_GET_LEN(buf_pool->free));
- /* 1 + is there to avoid division by zero */
+ /* 1 + is there to avoid division by zero */
mutex_exit(&(buf_pool->mutex));
@@ -2243,17 +2300,17 @@
time_t current_time;
double time_elapsed;
ulint size;
-
+
ut_ad(buf_pool);
size = buf_pool->curr_size;
mutex_enter(&(buf_pool->mutex));
-
+
if (srv_use_awe) {
fprintf(stderr,
"AWE: Buffer pool memory frames %lu\n",
(ulong) buf_pool->n_frames);
-
+
fprintf(stderr,
"AWE: Database pages and free buffers mapped in frames %lu\n",
(ulong) UT_LIST_GET_LEN(buf_pool->awe_LRU_free_mapped));
@@ -2300,13 +2357,12 @@
- buf_pool->n_pages_awe_remapped_old)
/ time_elapsed);
}
-
+
if (buf_pool->n_page_gets > buf_pool->n_page_gets_old) {
fprintf(file, "Buffer pool hit rate %lu / 1000\n",
- (ulong) (1000
- - ((1000 *
- (buf_pool->n_pages_read - buf_pool->n_pages_read_old))
- / (buf_pool->n_page_gets - buf_pool->n_page_gets_old))));
+ (ulong) (1000 -
+ ((1000 * (buf_pool->n_pages_read - buf_pool->n_pages_read_old))
+ / (buf_pool->n_page_gets - buf_pool->n_page_gets_old))));
} else {
fputs("No buffer pool page gets since the last printout\n",
file);
@@ -2328,12 +2384,12 @@
buf_refresh_io_stats(void)
/*======================*/
{
- buf_pool->last_printout_time = time(NULL);
+ buf_pool->last_printout_time = time(NULL);
buf_pool->n_page_gets_old = buf_pool->n_page_gets;
buf_pool->n_pages_read_old = buf_pool->n_pages_read;
buf_pool->n_pages_created_old = buf_pool->n_pages_created;
buf_pool->n_pages_written_old = buf_pool->n_pages_written;
- buf_pool->n_pages_awe_remapped_old = buf_pool->n_pages_awe_remapped;
+ buf_pool->n_pages_awe_remapped_old = buf_pool->n_pages_awe_remapped;
}
/*************************************************************************
@@ -2345,7 +2401,7 @@
{
buf_block_t* block;
ulint i;
-
+
ut_ad(buf_pool);
mutex_enter(&(buf_pool->mutex));
@@ -2361,15 +2417,15 @@
fprintf(stderr,
"Page %lu %lu still fixed or dirty\n",
(ulong) block->space, (ulong) block->offset);
- ut_error;
+ ut_error;
}
}
- }
+ }
mutex_exit(&(buf_pool->mutex));
return(TRUE);
-}
+}
/*************************************************************************
Checks that there currently are no pending i/o-operations for the buffer
--- 1.65.11.1/innobase/dict/dict0dict.c 2006-08-29 18:58:59 +04:00
+++ 1.84/storage/innobase/dict/dict0dict.c 2006-08-29 18:58:59 +04:00
@@ -26,6 +26,9 @@
#include "pars0sym.h"
#include "que0que.h"
#include "rem0cmp.h"
+#ifndef UNIV_HOTBACKUP
+# include "m_ctype.h" /* my_isspace() */
+#endif /* !UNIV_HOTBACKUP */
dict_sys_t* dict_sys = NULL; /* the dictionary system */
@@ -55,6 +58,42 @@
#ifndef UNIV_HOTBACKUP
/**********************************************************************
+Converts an identifier to a table name.
+
+NOTE: the prototype of this function is copied from ha_innodb.cc! If you change
+this function, you MUST change also the prototype here! */
+extern
+void
+innobase_convert_from_table_id(
+/*===========================*/
+ char* to, /* out: converted identifier */
+ const char* from, /* in: identifier to convert */
+ ulint len); /* in: length of 'to', in bytes;
+ should be at least 5 * strlen(to) + 1 */
+/**********************************************************************
+Converts an identifier to UTF-8.
+
+NOTE: the prototype of this function is copied from ha_innodb.cc! If you change
+this function, you MUST change also the prototype here! */
+extern
+void
+innobase_convert_from_id(
+/*=====================*/
+ char* to, /* out: converted identifier */
+ const char* from, /* in: identifier to convert */
+ ulint len); /* in: length of 'to', in bytes;
+ should be at least 3 * strlen(to) + 1 */
+/**********************************************************************
+Removes the filename encoding of a table or database name.
+
+NOTE: the prototype of this function is copied from ha_innodb.cc! If you change
+this function, you MUST change also the prototype here! */
+extern
+void
+innobase_convert_from_filename(
+/*===========================*/
+ char* s); /* in: identifier; out: decoded identifier */
+/**********************************************************************
Compares NUL-terminated UTF-8 strings case insensitively.
NOTE: the prototype of this function is copied from ha_innodb.cc! If you change
@@ -77,6 +116,17 @@
innobase_casedn_str(
/*================*/
char* a); /* in/out: string to put in lower case */
+
+/**************************************************************************
+Determines the connection character set.
+
+NOTE: the prototype of this function is copied from ha_innodb.cc! If you change
+this function, you MUST change also the prototype here! */
+struct charset_info_st*
+innobase_get_charset(
+/*=================*/
+ /* out: connection character set */
+ void* mysql_thd); /* in: MySQL thread handle */
#endif /* !UNIV_HOTBACKUP */
/**************************************************************************
@@ -132,7 +182,7 @@
/*=================*/
/* out: TRUE if success */
dict_table_t* table, /* in: table */
- dict_index_t* index); /* in: index */
+ dict_index_t* index); /* in: index */
/***********************************************************************
Builds the internal dictionary cache representation for a clustered
index, containing also system fields not defined by the user. */
@@ -144,7 +194,7 @@
of the clustered index */
dict_table_t* table, /* in: table */
dict_index_t* index); /* in: user representation of a clustered
- index */
+ index */
/***********************************************************************
Builds the internal dictionary cache representation for a non-clustered
index, containing also system fields not defined by the user. */
@@ -156,7 +206,7 @@
of the non-clustered index */
dict_table_t* table, /* in: table */
dict_index_t* index); /* in: user representation of a non-clustered
- index */
+ index */
/**************************************************************************
Removes a foreign constraint struct from the dictionary cache. */
static
@@ -196,9 +246,10 @@
/* Stream for storing detailed information about the latest foreign key
and unique key errors */
FILE* dict_foreign_err_file = NULL;
-mutex_t dict_foreign_err_mutex; /* mutex protecting the foreign
+mutex_t dict_foreign_err_mutex; /* mutex protecting the foreign
and unique error buffers */
-
+
+#ifndef UNIV_HOTBACKUP
/**********************************************************************
Makes all characters in a NUL-terminated UTF-8 string lower case. */
@@ -209,6 +260,7 @@
{
innobase_casedn_str(a);
}
+#endif /* !UNIV_HOTBACKUP */
/************************************************************************
Checks if the database name in two table names is the same. */
@@ -233,7 +285,7 @@
/************************************************************************
Return the end of table name where we have removed dbname and '/'. */
-static
+
const char*
dict_remove_db_name(
/*================*/
@@ -241,11 +293,10 @@
const char* name) /* in: table name in the form
dbname '/' tablename */
{
- const char* s;
- s = strchr(name, '/');
+ const char* s = strchr(name, '/');
ut_a(s);
- if (s) s++;
- return(s);
+
+ return(s + 1);
}
/************************************************************************
@@ -263,7 +314,7 @@
ut_a(s);
return(s - name);
}
-
+
/************************************************************************
Reserves the dictionary system mutex for MySQL. */
@@ -273,7 +324,7 @@
{
mutex_enter(&(dict_sys->mutex));
}
-
+
/************************************************************************
Releases the dictionary system mutex for MySQL. */
@@ -283,7 +334,7 @@
{
mutex_exit(&(dict_sys->mutex));
}
-
+
/************************************************************************
Decrements the count of open MySQL handles to a table. */
@@ -297,7 +348,7 @@
ut_a(table->n_mysql_handles_opened > 0);
table->n_mysql_handles_opened--;
-
+
mutex_exit(&(dict_sys->mutex));
}
@@ -350,7 +401,7 @@
{
return(dict_table_get_index(table, name));
}
-
+
/************************************************************************
Initializes the autoinc counter. It is not an error to initialize an already
initialized counter. */
@@ -390,7 +441,7 @@
value = table->autoinc;
table->autoinc = table->autoinc + 1;
}
-
+
mutex_exit(&(table->autoinc_mutex));
return(value);
@@ -407,7 +458,7 @@
mutex_enter(&(table->autoinc_mutex));
table->autoinc = table->autoinc - 1;
-
+
mutex_exit(&(table->autoinc_mutex));
}
@@ -431,7 +482,7 @@
} else {
value = table->autoinc;
}
-
+
mutex_exit(&(table->autoinc_mutex));
return(value);
@@ -476,7 +527,7 @@
if (value >= table->autoinc) {
table->autoinc = value + 1;
}
- }
+ }
mutex_exit(&(table->autoinc_mutex));
}
@@ -497,7 +548,7 @@
dict_col_t* col;
ulint pos;
ulint n_fields;
-
+
ut_ad(index);
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
@@ -509,7 +560,7 @@
}
n_fields = dict_index_get_n_fields(index);
-
+
for (pos = 0; pos < n_fields; pos++) {
field = dict_index_get_nth_field(index, pos);
@@ -537,7 +588,7 @@
dict_col_t* col;
ulint pos;
ulint n_fields;
-
+
ut_ad(index);
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
@@ -549,7 +600,7 @@
col = dict_table_get_nth_col(index->table, n);
n_fields = dict_index_get_n_fields(index);
-
+
for (pos = 0; pos < n_fields; pos++) {
field = dict_index_get_nth_field(index, pos);
@@ -582,21 +633,21 @@
dict_field_t* field2;
ulint n_fields;
ulint pos;
-
+
ut_ad(index);
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
field2 = dict_index_get_nth_field(index2, n);
n_fields = dict_index_get_n_fields(index);
-
+
for (pos = 0; pos < n_fields; pos++) {
field = dict_index_get_nth_field(index, pos);
if (field->col == field2->col
- && (field->prefix_len == 0
+ && (field->prefix_len == 0
|| (field->prefix_len >= field2->prefix_len
- && field2->prefix_len != 0))) {
+ && field2->prefix_len != 0))) {
return(pos);
}
@@ -606,7 +657,7 @@
}
/**************************************************************************
-Returns a table object, based on table id, and memoryfixes it. */
+Returns a table object based on table id. */
dict_table_t*
dict_table_get_on_id(
@@ -616,7 +667,7 @@
trx_t* trx) /* in: transaction handle */
{
dict_table_t* table;
-
+
if (ut_dulint_cmp(table_id, DICT_FIELDS_ID) <= 0
|| trx->dict_operation_lock_mode == RW_X_LATCH) {
/* It is a system table which will always exist in the table
@@ -628,13 +679,13 @@
ut_ad(mutex_own(&(dict_sys->mutex)));
#endif /* UNIV_SYNC_DEBUG */
- return(dict_table_get_on_id_low(table_id, trx));
+ return(dict_table_get_on_id_low(table_id));
}
mutex_enter(&(dict_sys->mutex));
- table = dict_table_get_on_id_low(table_id, trx);
-
+ table = dict_table_get_on_id_low(table_id);
+
mutex_exit(&(dict_sys->mutex));
return(table);
@@ -656,6 +707,19 @@
}
/************************************************************************
+Check whether the table uses the compact page format. */
+
+ibool
+dict_table_is_comp_noninline(
+/*=========================*/
+ /* out: TRUE if table uses the
+ compact page format */
+ const dict_table_t* table) /* in: table */
+{
+ return(dict_table_is_comp(table));
+}
+
+/************************************************************************
Checks if a column is in the ordering columns of the clustered index of a
table. Column prefixes are treated like whole columns. */
@@ -672,7 +736,7 @@
dict_col_t* col;
ulint pos;
ulint n_fields;
-
+
ut_ad(table);
col = dict_table_get_nth_col(table, n);
@@ -680,7 +744,7 @@
index = dict_table_get_first_index(table);
n_fields = dict_index_get_n_unique(index);
-
+
for (pos = 0; pos < n_fields; pos++) {
field = dict_index_get_nth_field(index, pos);
@@ -702,8 +766,7 @@
{
dict_sys = mem_alloc(sizeof(dict_sys_t));
- mutex_create(&(dict_sys->mutex));
- mutex_set_level(&(dict_sys->mutex), SYNC_DICT);
+ mutex_create(&dict_sys->mutex, SYNC_DICT);
dict_sys->table_hash = hash_create(buf_pool_get_max_size() /
(DICT_POOL_PER_TABLE_HASH *
@@ -718,44 +781,40 @@
UT_LIST_INIT(dict_sys->table_LRU);
- rw_lock_create(&dict_operation_lock);
- rw_lock_set_level(&dict_operation_lock, SYNC_DICT_OPERATION);
+ rw_lock_create(&dict_operation_lock, SYNC_DICT_OPERATION);
dict_foreign_err_file = os_file_create_tmpfile();
ut_a(dict_foreign_err_file);
- mutex_create(&dict_foreign_err_mutex);
- mutex_set_level(&dict_foreign_err_mutex, SYNC_ANY_LATCH);
+
+ mutex_create(&dict_foreign_err_mutex, SYNC_ANY_LATCH);
}
/**************************************************************************
-Returns a table object and memoryfixes it. NOTE! This is a high-level
-function to be used mainly from outside the 'dict' directory. Inside this
-directory dict_table_get_low is usually the appropriate function. */
+Returns a table object. NOTE! This is a high-level function to be used
+mainly from outside the 'dict' directory. Inside this directory
+dict_table_get_low is usually the appropriate function. */
dict_table_t*
dict_table_get(
/*===========*/
/* out: table, NULL if
does not exist */
- const char* table_name, /* in: table name */
- trx_t* trx) /* in: transaction handle or NULL */
+ const char* table_name) /* in: table name */
{
dict_table_t* table;
- UT_NOT_USED(trx);
-
mutex_enter(&(dict_sys->mutex));
-
+
table = dict_table_get_low(table_name);
mutex_exit(&(dict_sys->mutex));
if (table != NULL) {
- if (!table->stat_initialized) {
+ if (!table->stat_initialized) {
dict_update_statistics(table);
}
}
-
+
return(table);
}
@@ -767,30 +826,27 @@
/*======================================*/
/* out: table, NULL if
does not exist */
- const char* table_name, /* in: table name */
- trx_t* trx) /* in: transaction handle or NULL */
+ const char* table_name) /* in: table name */
{
dict_table_t* table;
- UT_NOT_USED(trx);
-
mutex_enter(&(dict_sys->mutex));
-
+
table = dict_table_get_low(table_name);
if (table != NULL) {
- table->n_mysql_handles_opened++;
+ table->n_mysql_handles_opened++;
}
mutex_exit(&(dict_sys->mutex));
if (table != NULL) {
- if (!table->stat_initialized && !table->ibd_file_missing) {
+ if (!table->stat_initialized && !table->ibd_file_missing) {
dict_update_statistics(table);
}
}
-
+
return(table);
}
@@ -805,7 +861,8 @@
ulint fold;
ulint id_fold;
ulint i;
-
+ ulint row_len;
+
ut_ad(table);
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex)));
@@ -813,12 +870,12 @@
ut_ad(table->n_def == table->n_cols - DATA_N_SYS_COLS);
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
ut_ad(table->cached == FALSE);
-
+
fold = ut_fold_string(table->name);
id_fold = ut_fold_dulint(table->id);
-
+
table->cached = TRUE;
-
+
/* NOTE: the system columns MUST be added in the following order
(so that they can be indexed by the numerical value of DATA_ROW_ID,
etc.) and as the last columns of the table memory object.
@@ -847,11 +904,29 @@
#endif
/* This check reminds that if a new system column is added to
- the program, it should be dealt with here */
+ the program, it should be dealt with here */
#if DATA_N_SYS_COLS != 4
#error "DATA_N_SYS_COLS != 4"
#endif
+ row_len = 0;
+ for (i = 0; i < table->n_def; i++) {
+ ulint col_len = dtype_get_max_size(
+ dict_col_get_type(dict_table_get_nth_col(table, i)));
+
+ /* If we have a single unbounded field, or several gigantic
+ fields, mark the maximum row size as ULINT_MAX. */
+ if (ut_max(col_len, row_len) >= (ULINT_MAX / 2)) {
+ row_len = ULINT_MAX;
+
+ break;
+ }
+
+ row_len += col_len;
+ }
+
+ table->max_row_size = row_len;
+
/* Look for a table with the same name: error if such exists */
{
dict_table_t* table2;
@@ -868,13 +943,6 @@
ut_a(table2 == NULL);
}
- if (table->type == DICT_TABLE_CLUSTER_MEMBER) {
-
- table->mix_id_len = mach_dulint_get_compressed_size(
- table->mix_id);
- mach_dulint_write_compressed(table->mix_id_buf, table->mix_id);
- }
-
/* Add the columns to the column hash table */
for (i = 0; i < table->n_cols; i++) {
dict_col_add_to_cache(table, dict_table_get_nth_col(table, i));
@@ -890,10 +958,7 @@
/* Add table to LRU list of tables */
UT_LIST_ADD_FIRST(table_LRU, dict_sys->table_LRU, table);
- /* If the dictionary cache grows too big, trim the table LRU list */
-
dict_sys->size += mem_heap_get_size(table->heap);
- /* dict_table_LRU_trim(); */
}
/**************************************************************************
@@ -909,7 +974,7 @@
{
dict_table_t* table;
dict_index_t* index;
-
+
table = UT_LIST_GET_FIRST(dict_sys->table_LRU);
while (table) {
@@ -951,16 +1016,16 @@
char* old_name;
ibool success;
ulint i;
-
+
ut_ad(table);
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex)));
#endif /* UNIV_SYNC_DEBUG */
old_size = mem_heap_get_size(table->heap);
-
+
fold = ut_fold_string(new_name);
-
+
/* Look for a table with the same name: error if such exists */
{
dict_table_t* table2;
@@ -969,7 +1034,7 @@
if (table2) {
fprintf(stderr,
"InnoDB: Error: dictionary cache already contains a table of name %s\n",
- new_name);
+ new_name);
return(FALSE);
}
}
@@ -1018,7 +1083,7 @@
while (index != NULL) {
index->table_name = table->name;
-
+
index = dict_table_get_next_index(index);
}
@@ -1030,7 +1095,7 @@
constraints from the dictionary cache here. The foreign key
constraints will be inherited to the new table from the
system tables through a call of dict_load_foreigns. */
-
+
/* Remove the foreign constraints from the cache */
foreign = UT_LIST_GET_LAST(table->foreign_list);
@@ -1046,14 +1111,14 @@
while (foreign != NULL) {
foreign->referenced_table = NULL;
foreign->referenced_index = NULL;
-
+
foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
}
/* Make the list of referencing constraints empty */
UT_LIST_INIT(table->referenced_list);
-
+
return(TRUE);
}
@@ -1085,10 +1150,10 @@
old_id = mem_strdup(foreign->id);
if (ut_strlen(foreign->id) > ut_strlen(old_name)
- + ((sizeof dict_ibfk) - 1)
- && 0 == ut_memcmp(foreign->id, old_name,
- ut_strlen(old_name))
- && 0 == ut_memcmp(
+ + ((sizeof dict_ibfk) - 1)
+ && 0 == ut_memcmp(foreign->id, old_name,
+ ut_strlen(old_name))
+ && 0 == ut_memcmp(
foreign->id + ut_strlen(old_name),
dict_ibfk, (sizeof dict_ibfk) - 1)) {
@@ -1096,11 +1161,11 @@
if (ut_strlen(table->name) > ut_strlen(old_name)) {
foreign->id = mem_heap_alloc(
- foreign->heap,
+ foreign->heap,
ut_strlen(table->name)
+ ut_strlen(old_id) + 1);
}
-
+
/* Replace the prefix 'databasename/tablename'
with the new names */
strcpy(foreign->id, table->name);
@@ -1112,16 +1177,16 @@
db_len = dict_get_db_name_len(table->name) + 1;
if (dict_get_db_name_len(table->name)
- > dict_get_db_name_len(foreign->id)) {
+ > dict_get_db_name_len(foreign->id)) {
foreign->id = mem_heap_alloc(
- foreign->heap,
- db_len + ut_strlen(old_id) + 1);
+ foreign->heap,
+ db_len + ut_strlen(old_id) + 1);
}
/* Replace the database prefix in id with the
one from table->name */
-
+
ut_memcpy(foreign->id, table->name, db_len);
strcpy(foreign->id + db_len,
@@ -1194,7 +1259,7 @@
dict_index_t* index;
ulint size;
ulint i;
-
+
ut_ad(table);
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex)));
@@ -1222,7 +1287,7 @@
while (foreign != NULL) {
foreign->referenced_table = NULL;
foreign->referenced_index = NULL;
-
+
foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
}
@@ -1259,38 +1324,6 @@
}
/**************************************************************************
-Frees tables from the end of table_LRU if the dictionary cache occupies
-too much space. Currently not used! */
-
-void
-dict_table_LRU_trim(void)
-/*=====================*/
-{
- dict_table_t* table;
- dict_table_t* prev_table;
-
- ut_error;
-
-#ifdef UNIV_SYNC_DEBUG
- ut_ad(mutex_own(&(dict_sys->mutex)));
-#endif /* UNIV_SYNC_DEBUG */
-
- table = UT_LIST_GET_LAST(dict_sys->table_LRU);
-
- while (table && (dict_sys->size >
- buf_pool_get_max_size() / DICT_POOL_PER_VARYING)) {
-
- prev_table = UT_LIST_GET_PREV(table_LRU, table);
-
- if (table->mem_fix == 0) {
- dict_table_remove_from_cache(table);
- }
-
- table = prev_table;
- }
-}
-
-/**************************************************************************
Adds a column to the data dictionary hash table. */
static
void
@@ -1306,7 +1339,7 @@
ut_ad(mutex_own(&(dict_sys->mutex)));
#endif /* UNIV_SYNC_DEBUG */
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
-
+
fold = ut_fold_ulint_pair(ut_fold_string(table->name),
ut_fold_string(col->name));
@@ -1316,7 +1349,7 @@
HASH_SEARCH(hash, dict_sys->col_hash, fold, col2,
(ut_strcmp(col->name, col2->name) == 0)
&& (ut_strcmp((col2->table)->name, table->name)
- == 0));
+ == 0));
ut_a(col2 == NULL);
}
@@ -1339,7 +1372,7 @@
ut_ad(mutex_own(&(dict_sys->mutex)));
#endif /* UNIV_SYNC_DEBUG */
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
-
+
fold = ut_fold_ulint_pair(ut_fold_string(table->name),
ut_fold_string(col->name));
@@ -1364,7 +1397,7 @@
ut_ad(mutex_own(&(dict_sys->mutex)));
#endif /* UNIV_SYNC_DEBUG */
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
-
+
fold = ut_fold_ulint_pair(ut_fold_string(table->name),
ut_fold_string(col->name));
@@ -1372,7 +1405,7 @@
fold = ut_fold_ulint_pair(ut_fold_string(new_name),
ut_fold_string(col->name));
-
+
HASH_INSERT(dict_col_t, hash, dict_sys->col_hash, fold, col);
}
@@ -1422,21 +1455,21 @@
{
dict_index_t* new_index;
dict_tree_t* tree;
- dict_table_t* cluster;
dict_field_t* field;
ulint n_ord;
ibool success;
ulint i;
-
+
ut_ad(index);
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex)));
#endif /* UNIV_SYNC_DEBUG */
ut_ad(index->n_def == index->n_fields);
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
-
+
ut_ad(mem_heap_validate(index->heap));
+#ifdef UNIV_DEBUG
{
dict_index_t* index2;
index2 = UT_LIST_GET_FIRST(table->indexes);
@@ -1446,10 +1479,11 @@
index2 = UT_LIST_GET_NEXT(indexes, index2);
}
-
- ut_a(UT_LIST_GET_LEN(table->indexes) == 0
- || (index->type & DICT_CLUSTERED) == 0);
}
+#endif /* UNIV_DEBUG */
+
+ ut_a(!(index->type & DICT_CLUSTERED)
+ || UT_LIST_GET_LEN(table->indexes) == 0);
success = dict_index_find_cols(table, index);
@@ -1458,7 +1492,7 @@
return(FALSE);
}
-
+
/* Build the cache internal representation of the index,
containing also the added system fields */
@@ -1469,15 +1503,15 @@
}
new_index->search_info = btr_search_info_create(new_index->heap);
-
+
/* Set the n_fields value in new_index to the actual defined
number of fields in the cache internal representation */
new_index->n_fields = new_index->n_def;
-
+
/* Add the new index as the last index for the table */
- UT_LIST_ADD_LAST(indexes, table->indexes, new_index);
+ UT_LIST_ADD_LAST(indexes, table->indexes, new_index);
new_index->table = table;
new_index->table_name = table->name;
@@ -1496,21 +1530,11 @@
dict_field_get_col(field)->ord_part++;
}
- if (table->type == DICT_TABLE_CLUSTER_MEMBER) {
- /* The index tree is found from the cluster object */
-
- cluster = dict_table_get_low(table->cluster_name);
-
- tree = dict_index_get_tree(
- UT_LIST_GET_FIRST(cluster->indexes));
- new_index->tree = tree;
- } else {
- /* Create an index tree memory object for the index */
- tree = dict_tree_create(new_index, page_no);
- ut_ad(tree);
+ /* Create an index tree memory object for the index */
+ tree = dict_tree_create(new_index, page_no);
+ ut_ad(tree);
- new_index->tree = tree;
- }
+ new_index->tree = tree;
if (!UNIV_UNLIKELY(new_index->type & DICT_UNIVERSAL)) {
@@ -1526,14 +1550,11 @@
new_index->stat_n_diff_key_vals[i] = 100;
}
}
-
+
/* Add the index to the list of indexes stored in the tree */
- UT_LIST_ADD_LAST(tree_indexes, tree->tree_indexes, new_index);
-
- /* If the dictionary cache grows too big, trim the table LRU list */
+ tree->tree_index = new_index;
dict_sys->size += mem_heap_get_size(new_index->heap);
- /* dict_table_LRU_trim(); */
dict_mem_index_free(index);
@@ -1560,7 +1581,7 @@
ut_ad(mutex_own(&(dict_sys->mutex)));
#endif /* UNIV_SYNC_DEBUG */
- ut_ad(UT_LIST_GET_LEN((index->tree)->tree_indexes) == 1);
+ ut_ad(index->tree->tree_index);
dict_tree_free(index->tree);
/* Decrement the ord_part counts in columns which are ordering */
@@ -1593,13 +1614,13 @@
/*=================*/
/* out: TRUE if success */
dict_table_t* table, /* in: table */
- dict_index_t* index) /* in: index */
+ dict_index_t* index) /* in: index */
{
dict_col_t* col;
dict_field_t* field;
ulint fold;
ulint i;
-
+
ut_ad(table && index);
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
#ifdef UNIV_SYNC_DEBUG
@@ -1610,15 +1631,15 @@
field = dict_index_get_nth_field(index, i);
fold = ut_fold_ulint_pair(ut_fold_string(table->name),
- ut_fold_string(field->name));
-
+ ut_fold_string(field->name));
+
HASH_SEARCH(hash, dict_sys->col_hash, fold, col,
(ut_strcmp(col->name, field->name) == 0)
&& (ut_strcmp((col->table)->name, table->name)
- == 0));
+ == 0));
if (col == NULL) {
- return(FALSE);
+ return(FALSE);
} else {
field->col = col;
}
@@ -1626,7 +1647,7 @@
return(TRUE);
}
-
+
/***********************************************************************
Adds a column to index. */
@@ -1635,12 +1656,11 @@
/*===============*/
dict_index_t* index, /* in: index */
dict_col_t* col, /* in: column */
- ulint order, /* in: order criterion */
ulint prefix_len) /* in: column prefix length */
{
dict_field_t* field;
- dict_mem_index_add_field(index, col->name, order, prefix_len);
+ dict_mem_index_add_field(index, col->name, prefix_len);
field = dict_index_get_nth_field(index, index->n_def - 1);
@@ -1662,17 +1682,6 @@
if (!(dtype_get_prtype(&col->type) & DATA_NOT_NULL)) {
index->n_nullable++;
}
-
- if (index->n_def > 1) {
- const dict_field_t* field2 =
- dict_index_get_nth_field(index, index->n_def - 2);
- field->fixed_offs = (!field2->fixed_len ||
- field2->fixed_offs == ULINT_UNDEFINED)
- ? ULINT_UNDEFINED
- : field2->fixed_len + field2->fixed_offs;
- } else {
- field->fixed_offs = 0;
- }
}
/***********************************************************************
@@ -1688,14 +1697,13 @@
{
dict_field_t* field;
ulint i;
-
+
/* Copy fields contained in index2 */
for (i = start; i < end; i++) {
field = dict_index_get_nth_field(index2, i);
- dict_index_add_col(index1, field->col, field->order,
- field->prefix_len);
+ dict_index_add_col(index1, field->col, field->prefix_len);
}
}
@@ -1740,8 +1748,6 @@
dtype_t* type;
ulint i;
- ut_ad(!(table->type & DICT_UNIVERSAL));
-
for (i = 0; i < dtuple_get_n_fields(tuple); i++) {
dfield_type = dfield_get_type(dtuple_get_nth_field(tuple, i));
@@ -1762,7 +1768,7 @@
of the clustered index */
dict_table_t* table, /* in: table */
dict_index_t* index) /* in: user representation of a clustered
- index */
+ index */
{
dict_index_t* new_index;
dict_field_t* field;
@@ -1780,40 +1786,24 @@
/* Create a new index object with certainly enough fields */
new_index = dict_mem_index_create(table->name,
- index->name,
- table->space,
- index->type,
- index->n_fields + table->n_cols);
+ index->name, table->space, index->type,
+ index->n_fields + table->n_cols);
/* Copy other relevant data from the old index struct to the new
struct: it inherits the values */
new_index->n_user_defined_cols = index->n_fields;
-
- new_index->id = index->id;
- if (table->type != DICT_TABLE_ORDINARY) {
- /* The index is mixed: copy common key prefix fields */
-
- dict_index_copy(new_index, index, 0, table->mix_len);
-
- /* Add the mix id column */
- dict_index_add_col(new_index,
- dict_table_get_sys_col(table, DATA_MIX_ID), 0, 0);
+ new_index->id = index->id;
- /* Copy the rest of fields */
- dict_index_copy(new_index, index, table->mix_len,
- index->n_fields);
- } else {
- /* Copy the fields of index */
- dict_index_copy(new_index, index, 0, index->n_fields);
- }
+ /* Copy the fields of index */
+ dict_index_copy(new_index, index, 0, index->n_fields);
if (UNIV_UNLIKELY(index->type & DICT_UNIVERSAL)) {
/* No fixed number of fields determines an entry uniquely */
new_index->n_uniq = ULINT_MAX;
-
+
} else if (index->type & DICT_UNIQUE) {
/* Only the fields defined so far are needed to identify
the index entry uniquely */
@@ -1831,21 +1821,27 @@
trx_id_pos = new_index->n_def;
- ut_ad(DATA_ROW_ID == 0);
- ut_ad(DATA_TRX_ID == 1);
- ut_ad(DATA_ROLL_PTR == 2);
+#if DATA_ROW_ID != 0
+# error "DATA_ROW_ID != 0"
+#endif
+#if DATA_TRX_ID != 1
+# error "DATA_TRX_ID != 1"
+#endif
+#if DATA_ROLL_PTR != 2
+# error "DATA_ROLL_PTR != 2"
+#endif
if (!(index->type & DICT_UNIQUE)) {
dict_index_add_col(new_index,
- dict_table_get_sys_col(table, DATA_ROW_ID), 0, 0);
+ dict_table_get_sys_col(table, DATA_ROW_ID), 0);
trx_id_pos++;
}
dict_index_add_col(new_index,
- dict_table_get_sys_col(table, DATA_TRX_ID), 0, 0);
-
+ dict_table_get_sys_col(table, DATA_TRX_ID), 0);
+
dict_index_add_col(new_index,
- dict_table_get_sys_col(table, DATA_ROLL_PTR), 0, 0);
+ dict_table_get_sys_col(table, DATA_ROLL_PTR), 0);
for (i = 0; i < trx_id_pos; i++) {
@@ -1859,7 +1855,7 @@
}
if (dict_index_get_nth_field(new_index, i)->prefix_len
- > 0) {
+ > 0) {
new_index->trx_id_offset = 0;
break;
@@ -1887,10 +1883,10 @@
if (field->prefix_len == 0) {
- field->col->aux = 0;
+ field->col->aux = 0;
}
}
-
+
/* Add to new_index non-system columns of table not yet included
there */
for (i = 0; i < table->n_cols - DATA_N_SYS_COLS; i++) {
@@ -1899,7 +1895,7 @@
ut_ad(col->type.mtype != DATA_SYS);
if (col->aux == ULINT_UNDEFINED) {
- dict_index_add_col(new_index, col, 0, 0);
+ dict_index_add_col(new_index, col, 0);
}
}
@@ -1914,14 +1910,14 @@
if (field->prefix_len == 0) {
- field->col->clust_pos = i;
+ field->col->clust_pos = i;
}
}
-
+
new_index->cached = TRUE;
return(new_index);
-}
+}
/***********************************************************************
Builds the internal dictionary cache representation for a non-clustered
@@ -1934,7 +1930,7 @@
of the non-clustered index */
dict_table_t* table, /* in: table */
dict_index_t* index) /* in: user representation of a non-clustered
- index */
+ index */
{
dict_field_t* field;
dict_index_t* new_index;
@@ -1950,24 +1946,21 @@
/* The clustered index should be the first in the list of indexes */
clust_index = UT_LIST_GET_FIRST(table->indexes);
-
+
ut_ad(clust_index);
ut_ad(clust_index->type & DICT_CLUSTERED);
ut_ad(!(clust_index->type & DICT_UNIVERSAL));
/* Create a new index */
new_index = dict_mem_index_create(table->name,
- index->name,
- index->space,
- index->type,
- index->n_fields
- + 1 + clust_index->n_uniq);
+ index->name, index->space, index->type,
+ index->n_fields + 1 + clust_index->n_uniq);
/* Copy other relevant data from the old index
struct to the new struct: it inherits the values */
new_index->n_user_defined_cols = index->n_fields;
-
+
new_index->id = index->id;
/* Copy fields from index to new_index */
@@ -1991,7 +1984,7 @@
if (field->prefix_len == 0) {
- field->col->aux = 0;
+ field->col->aux = 0;
}
}
@@ -2003,8 +1996,8 @@
field = dict_index_get_nth_field(clust_index, i);
if (field->col->aux == ULINT_UNDEFINED) {
- dict_index_add_col(new_index, field->col, 0,
- field->prefix_len);
+ dict_index_add_col(new_index, field->col,
+ field->prefix_len);
}
}
@@ -2022,7 +2015,7 @@
new_index->cached = TRUE;
return(new_index);
-}
+}
/*====================== FOREIGN KEY PROCESSING ========================*/
@@ -2037,7 +2030,7 @@
dict_table_t* table) /* in: InnoDB table */
{
if (UT_LIST_GET_LEN(table->referenced_list) > 0) {
-
+
return(TRUE);
}
@@ -2067,7 +2060,7 @@
ut_ad(mutex_own(&(dict_sys->mutex)));
#endif /* UNIV_SYNC_DEBUG */
ut_a(foreign);
-
+
if (foreign->referenced_table) {
UT_LIST_REMOVE(referenced_list,
foreign->referenced_table->referenced_list, foreign);
@@ -2108,7 +2101,7 @@
foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
}
-
+
foreign = UT_LIST_GET_FIRST(table->referenced_list);
while (foreign) {
@@ -2121,8 +2114,9 @@
}
return(NULL);
-}
+}
+#ifndef UNIV_HOTBACKUP
/*************************************************************************
Tries to find an index whose first fields are the columns in the array,
in the same order. */
@@ -2140,11 +2134,10 @@
only has an effect if types_idx !=
NULL. */
{
-#ifndef UNIV_HOTBACKUP
dict_index_t* index;
const char* col_name;
ulint i;
-
+
index = dict_table_get_first_index(table);
while (index != NULL) {
@@ -2157,22 +2150,22 @@
->prefix_len != 0) {
/* We do not accept column prefix
indexes here */
-
+
break;
}
if (0 != innobase_strcasecmp(columns[i],
col_name)) {
- break;
+ break;
}
if (types_idx && !cmp_types_are_equal(
- dict_index_get_nth_type(index, i),
- dict_index_get_nth_type(types_idx, i),
- check_charsets)) {
+ dict_index_get_nth_type(index, i),
+ dict_index_get_nth_type(types_idx, i),
+ check_charsets)) {
- break;
- }
+ break;
+ }
}
if (i == n_cols) {
@@ -2186,12 +2179,6 @@
}
return(NULL);
-#else /* UNIV_HOTBACKUP */
- /* This function depends on MySQL code that is not included in
- InnoDB Hot Backup builds. Besides, this function should never
- be called in InnoDB Hot Backup. */
- ut_error;
-#endif /* UNIV_HOTBACKUP */
}
/**************************************************************************
@@ -2227,7 +2214,7 @@
putc('\n', file);
if (fk->foreign_index) {
fputs("The index in the foreign key in table is ", file);
- ut_print_name(file, NULL, fk->foreign_index->name);
+ ut_print_name(file, NULL, FALSE, fk->foreign_index->name);
fputs("\n"
"See http://dev.mysql.com/doc/refman/5.0/en/innodb-foreign-key-constraints.html\n"
"for correct foreign key definition.\n",
@@ -2255,7 +2242,7 @@
dict_foreign_t* for_in_cache = NULL;
dict_index_t* index;
ibool added_to_referenced_list= FALSE;
- FILE* ef = dict_foreign_err_file;
+ FILE* ef = dict_foreign_err_file;
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex)));
@@ -2263,7 +2250,7 @@
for_table = dict_table_check_if_in_cache_low(
foreign->foreign_table_name);
-
+
ref_table = dict_table_check_if_in_cache_low(
foreign->referenced_table_name);
ut_a(for_table || ref_table);
@@ -2299,7 +2286,7 @@
mem_heap_free(foreign->heap);
}
- return(DB_CANNOT_ADD_CONSTRAINT);
+ return(DB_CANNOT_ADD_CONSTRAINT);
}
for_in_cache->referenced_table = ref_table;
@@ -2328,11 +2315,11 @@
ref_table->referenced_list,
for_in_cache);
}
-
+
mem_heap_free(foreign->heap);
}
- return(DB_CANNOT_ADD_CONSTRAINT);
+ return(DB_CANNOT_ADD_CONSTRAINT);
}
for_in_cache->foreign_table = for_table;
@@ -2390,12 +2377,13 @@
/*************************************************************************
Accepts a specified string. Comparisons are case-insensitive. */
-
+static
const char*
dict_accept(
/*========*/
/* out: if string was accepted, the pointer
is moved after that, else ptr is returned */
+ struct charset_info_st* cs,/* in: the character set of ptr */
const char* ptr, /* in: scan from this */
const char* string, /* in: accept only this string as the next
non-whitespace string */
@@ -2405,15 +2393,15 @@
const char* old_ptr2;
*success = FALSE;
-
- while (isspace(*ptr)) {
+
+ while (my_isspace(cs, *ptr)) {
ptr++;
}
old_ptr2 = ptr;
-
+
ptr = dict_scan_to(ptr, string);
-
+
if (*ptr == '\0' || old_ptr2 != ptr) {
return(old_ptr);
}
@@ -2431,12 +2419,15 @@
dict_scan_id(
/*=========*/
/* out: scanned to */
+ struct charset_info_st* cs,/* in: the character set of ptr */
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 */
+ ibool table_id,/* in: TRUE=convert the allocated id
+ as a table name; FALSE=convert to UTF-8 */
ibool accept_also_dot)
/* in: TRUE if also a dot can appear in a
non-quoted id; in a quoted id it can appear
@@ -2445,13 +2436,12 @@
char quote = '\0';
ulint len = 0;
const char* s;
- char* d;
- ulint id_len;
- byte* b;
+ char* str;
+ char* dst;
*id = NULL;
- while (isspace(*ptr)) {
+ while (my_isspace(cs, *ptr)) {
ptr++;
}
@@ -2482,9 +2472,9 @@
len++;
}
} else {
- while (!isspace(*ptr) && *ptr != '(' && *ptr != ')'
- && (accept_also_dot || *ptr != '.')
- && *ptr != ',' && *ptr != '\0') {
+ while (!my_isspace(cs, *ptr) && *ptr != '(' && *ptr != ')'
+ && (accept_also_dot || *ptr != '.')
+ && *ptr != ',' && *ptr != '\0') {
ptr++;
}
@@ -2492,43 +2482,50 @@
len = ptr - s;
}
- if (quote && heap) {
- *id = d = mem_heap_alloc(heap, len + 1);
+ if (UNIV_UNLIKELY(!heap)) {
+ /* no heap given: id will point to source string */
+ *id = s;
+ return(ptr);
+ }
+
+ if (quote) {
+ char* d;
+ str = 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);
+ len = d - str;
+ ut_ad(*s == quote);
+ ut_ad(s + 1 == ptr);
} else {
- /* no heap given: id will point to source string */
- *id = s;
+ str = mem_heap_strdupl(heap, s, len);
}
- if (heap && !quote) {
- /* EMS MySQL Manager sometimes adds characters 0xA0 (in
- latin1, a 'non-breakable space') to the end of a table name.
- But isspace(0xA0) is not true, which confuses our foreign key
- parser. After the UTF-8 conversion in ha_innodb.cc, bytes 0xC2
- and 0xA0 are at the end of the string.
-
- TODO: we should lex the string using thd->charset_info, and
- my_isspace(). Only after that, convert id names to UTF-8. */
-
- b = (byte*)(*id);
- id_len = strlen((char*) b);
-
- if (id_len >= 3 && b[id_len - 1] == 0xA0
- && b[id_len - 2] == 0xC2) {
-
- /* Strip the 2 last bytes */
+ if (!table_id) {
+convert_id:
+ /* Convert the identifier from connection character set
+ to UTF-8. */
+ len = 3 * len + 1;
+ *id = dst = mem_heap_alloc(heap, len);
+
+ innobase_convert_from_id(dst, str, len);
+ } else if (!strncmp(str, srv_mysql50_table_name_prefix,
+ sizeof srv_mysql50_table_name_prefix)) {
+ /* This is a pre-5.1 table name
+ containing chars other than [A-Za-z0-9].
+ Discard the prefix and use raw UTF-8 encoding. */
+ str += sizeof srv_mysql50_table_name_prefix;
+ len -= sizeof srv_mysql50_table_name_prefix;
+ goto convert_id;
+ } else {
+ /* Encode using filename-safe characters. */
+ len = 5 * len + 1;
+ *id = dst = mem_heap_alloc(heap, len);
- b[id_len - 2] = '\0';
- }
+ innobase_convert_from_table_id(dst, str, len);
}
return(ptr);
@@ -2541,6 +2538,7 @@
dict_scan_col(
/*==========*/
/* out: scanned to */
+ struct charset_info_st* cs,/* in: the character set of ptr */
const char* ptr, /* in: scanned to */
ibool* success,/* out: TRUE if success */
dict_table_t* table, /* in: table in which the column is */
@@ -2549,13 +2547,12 @@
const char** name) /* out,own: the column name; NULL if no name
was scannable */
{
-#ifndef UNIV_HOTBACKUP
dict_col_t* col;
ulint i;
*success = FALSE;
- ptr = dict_scan_id(ptr, heap, name, TRUE);
+ ptr = dict_scan_id(cs, ptr, heap, name, FALSE, TRUE);
if (*name == NULL) {
@@ -2566,29 +2563,23 @@
*success = TRUE;
*column = NULL;
} else {
- for (i = 0; i < dict_table_get_n_cols(table); i++) {
+ for (i = 0; i < dict_table_get_n_cols(table); i++) {
col = dict_table_get_nth_col(table, i);
if (0 == innobase_strcasecmp(col->name, *name)) {
- /* Found */
+ /* Found */
- *success = TRUE;
- *column = col;
- strcpy((char*) *name, col->name);
+ *success = TRUE;
+ *column = col;
+ strcpy((char*) *name, col->name);
- break;
+ break;
}
}
}
-
+
return(ptr);
-#else /* UNIV_HOTBACKUP */
- /* This function depends on MySQL code that is not included in
- InnoDB Hot Backup builds. Besides, this function should never
- be called in InnoDB Hot Backup. */
- ut_error;
-#endif /* UNIV_HOTBACKUP */
}
/*************************************************************************
@@ -2598,6 +2589,7 @@
dict_scan_table_name(
/*=================*/
/* out: scanned to */
+ struct charset_info_st* cs,/* in: the character set of ptr */
const char* ptr, /* in: scanned to */
dict_table_t** table, /* out: table object or NULL */
const char* name, /* in: foreign key table name */
@@ -2606,7 +2598,6 @@
const char** ref_name)/* out,own: the table name;
NULL if no name was scannable */
{
-#ifndef UNIV_HOTBACKUP
const char* database_name = NULL;
ulint database_name_len = 0;
const char* table_name = NULL;
@@ -2616,11 +2607,11 @@
*success = FALSE;
*table = NULL;
-
- ptr = dict_scan_id(ptr, heap, &scan_name, FALSE);
+
+ ptr = dict_scan_id(cs, ptr, heap, &scan_name, TRUE, FALSE);
if (scan_name == NULL) {
-
+
return(ptr); /* Syntax error */
}
@@ -2632,7 +2623,7 @@
database_name = scan_name;
database_name_len = strlen(database_name);
- ptr = dict_scan_id(ptr, heap, &table_name, FALSE);
+ ptr = dict_scan_id(cs, ptr, heap, &table_name, TRUE, FALSE);
if (table_name == NULL) {
@@ -2688,12 +2679,6 @@
*table = dict_table_get_low(ref);
return(ptr);
-#else /* UNIV_HOTBACKUP */
- /* This function depends on MySQL code that is not included in
- InnoDB Hot Backup builds. Besides, this function should never
- be called in InnoDB Hot Backup. */
- ut_error;
-#endif /* UNIV_HOTBACKUP */
}
/*************************************************************************
@@ -2703,20 +2688,21 @@
dict_skip_word(
/*===========*/
/* out: scanned to */
+ struct charset_info_st* cs,/* in: the character set of ptr */
const char* ptr, /* in: scanned to */
ibool* success)/* out: TRUE if success, FALSE if just spaces
left in string or a syntax error */
{
const char* start;
-
+
*success = FALSE;
- ptr = dict_scan_id(ptr, NULL, &start, TRUE);
+ ptr = dict_scan_id(cs, ptr, NULL, &start, FALSE, TRUE);
if (start) {
*success = TRUE;
}
-
+
return(ptr);
}
@@ -2738,8 +2724,8 @@
char* str;
const char* sptr;
char* ptr;
- /* unclosed quote character (0 if none) */
- char quote = 0;
+ /* unclosed quote character (0 if none) */
+ char quote = 0;
str = mem_alloc(strlen(sql_string) + 1);
@@ -2767,15 +2753,15 @@
/* Starting quote: remember the quote character. */
quote = *sptr;
} else if (*sptr == '#'
- || (sptr[0] == '-' && sptr[1] == '-' &&
- sptr[2] == ' ')) {
+ || (sptr[0] == '-' && sptr[1] == '-' &&
+ sptr[2] == ' ')) {
for (;;) {
/* In Unix a newline is 0x0A while in Windows
it is 0x0D followed by 0x0A */
if (*sptr == (char)0x0A
- || *sptr == (char)0x0D
- || *sptr == '\0') {
+ || *sptr == (char)0x0D
+ || *sptr == '\0') {
goto scan_more;
}
@@ -2786,7 +2772,7 @@
for (;;) {
if (*sptr == '*' && *(sptr + 1) == '/') {
- sptr += 2;
+ sptr += 2;
goto scan_more;
}
@@ -2832,10 +2818,10 @@
while (foreign) {
if (ut_strlen(foreign->id) > ((sizeof dict_ibfk) - 1) + len
- && 0 == ut_memcmp(foreign->id, table->name, len)
- && 0 == ut_memcmp(foreign->id + len,
+ && 0 == ut_memcmp(foreign->id, table->name, len)
+ && 0 == ut_memcmp(foreign->id + len,
dict_ibfk, (sizeof dict_ibfk) - 1)
- && foreign->id[len + ((sizeof dict_ibfk) - 1)] != '0') {
+ && foreign->id[len + ((sizeof dict_ibfk) - 1)] != '0') {
/* It is of the >= 4.0.18 format */
id = strtoul(foreign->id + len + ((sizeof dict_ibfk) - 1),
@@ -2889,6 +2875,7 @@
/* out: error code or DB_SUCCESS */
trx_t* trx, /* in: transaction */
mem_heap_t* heap, /* in: memory heap */
+ struct charset_info_st* cs,/* in: the character set of sql_string */
const char* sql_string,
/* in: CREATE TABLE or ALTER TABLE statement
where foreign keys are declared like:
@@ -2909,7 +2896,7 @@
ulint highest_id_so_far = 0;
dict_index_t* index;
dict_foreign_t* foreign;
- const char* ptr = sql_string;
+ const char* ptr = sql_string;
const char* start_of_latest_foreign = sql_string;
FILE* ef = dict_foreign_err_file;
const char* constraint_name;
@@ -2925,7 +2912,7 @@
dict_col_t* columns[500];
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 */
@@ -2946,14 +2933,14 @@
/* First check if we are actually doing an ALTER TABLE, and in that
case look for the table being altered */
- ptr = dict_accept(ptr, "ALTER", &success);
+ ptr = dict_accept(cs, ptr, "ALTER", &success);
if (!success) {
goto loop;
}
- ptr = dict_accept(ptr, "TABLE", &success);
+ ptr = dict_accept(cs, ptr, "TABLE", &success);
if (!success) {
@@ -2962,7 +2949,7 @@
/* We are doing an ALTER TABLE: scan the table name we are altering */
- ptr = dict_scan_table_name(ptr, &table_to_alter, name,
+ ptr = dict_scan_table_name(cs, ptr, &table_to_alter, name,
&success, heap, &referenced_table_name);
if (!success) {
fprintf(stderr,
@@ -3002,21 +2989,22 @@
of the constraint to system tables. */
ptr = ptr1;
- ptr = dict_accept(ptr, "CONSTRAINT", &success);
+ ptr = dict_accept(cs, ptr, "CONSTRAINT", &success);
ut_a(success);
- if (!isspace(*ptr) && *ptr != '"' && *ptr != '`') {
- goto loop;
+ if (!my_isspace(cs, *ptr) && *ptr != '"' && *ptr != '`') {
+ goto loop;
}
- while (isspace(*ptr)) {
+ while (my_isspace(cs, *ptr)) {
ptr++;
}
/* read constraint name unless got "CONSTRAINT FOREIGN" */
if (ptr != ptr2) {
- ptr = dict_scan_id(ptr, heap, &constraint_name, FALSE);
+ ptr = dict_scan_id(cs, ptr, heap,
+ &constraint_name, FALSE, FALSE);
}
} else {
ptr = ptr2;
@@ -3030,15 +3018,15 @@
command, determine if there are any foreign keys, and
if so, immediately reject the command if the table is a
temporary one. For now, this kludge will work. */
- if (reject_fks && (UT_LIST_GET_LEN(table->foreign_list) > 0))
- {
- return DB_CANNOT_ADD_CONSTRAINT;
+ if (reject_fks && (UT_LIST_GET_LEN(table->foreign_list) > 0)) {
+
+ return(DB_CANNOT_ADD_CONSTRAINT);
}
-
+
/**********************************************************/
/* The following call adds the foreign key constraints
to the data dictionary system tables on disk */
-
+
error = dict_create_add_foreigns_to_dictionary(
highest_id_so_far, table, trx);
return(error);
@@ -3046,28 +3034,28 @@
start_of_latest_foreign = ptr;
- ptr = dict_accept(ptr, "FOREIGN", &success);
-
+ ptr = dict_accept(cs, ptr, "FOREIGN", &success);
+
if (!success) {
goto loop;
}
- if (!isspace(*ptr)) {
- goto loop;
+ if (!my_isspace(cs, *ptr)) {
+ goto loop;
}
- ptr = dict_accept(ptr, "KEY", &success);
+ ptr = dict_accept(cs, ptr, "KEY", &success);
if (!success) {
goto loop;
}
- ptr = dict_accept(ptr, "(", &success);
+ ptr = dict_accept(cs, ptr, "(", &success);
if (!success) {
/* MySQL allows also an index id before the '('; we
skip it */
- ptr = dict_skip_word(ptr, &success);
+ ptr = dict_skip_word(cs, ptr, &success);
if (!success) {
dict_foreign_report_syntax_err(name,
@@ -3076,13 +3064,13 @@
return(DB_CANNOT_ADD_CONSTRAINT);
}
- ptr = dict_accept(ptr, "(", &success);
+ ptr = dict_accept(cs, ptr, "(", &success);
if (!success) {
/* We do not flag a syntax error here because in an
ALTER TABLE we may also have DROP FOREIGN KEY abc */
- goto loop;
+ goto loop;
}
}
@@ -3091,7 +3079,7 @@
/* 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,
+ ptr = dict_scan_col(cs, ptr, &success, table, columns + i,
heap, column_names + i);
if (!success) {
mutex_enter(&dict_foreign_err_mutex);
@@ -3104,14 +3092,14 @@
}
i++;
-
- ptr = dict_accept(ptr, ",", &success);
+
+ ptr = dict_accept(cs, ptr, ",", &success);
if (success) {
goto col_loop1;
}
-
- ptr = dict_accept(ptr, ")", &success);
+
+ ptr = dict_accept(cs, ptr, ")", &success);
if (!success) {
dict_foreign_report_syntax_err(name, start_of_latest_foreign,
@@ -3128,7 +3116,7 @@
mutex_enter(&dict_foreign_err_mutex);
dict_foreign_error_report_low(ef, name);
fputs("There is no index in table ", ef);
- ut_print_name(ef, NULL, name);
+ ut_print_name(ef, NULL, TRUE, name);
fprintf(ef, " where the columns appear\n"
"as the first columns. Constraint:\n%s\n"
"See http://dev.mysql.com/doc/refman/5.0/en/innodb-foreign-key-constraints.html\n"
@@ -3138,9 +3126,9 @@
return(DB_CANNOT_ADD_CONSTRAINT);
}
- ptr = dict_accept(ptr, "REFERENCES", &success);
+ ptr = dict_accept(cs, ptr, "REFERENCES", &success);
- if (!success || !isspace(*ptr)) {
+ if (!success || !my_isspace(cs, *ptr)) {
dict_foreign_report_syntax_err(name, start_of_latest_foreign,
ptr);
return(DB_CANNOT_ADD_CONSTRAINT);
@@ -3151,7 +3139,7 @@
foreign = dict_mem_foreign_create();
if (constraint_name) {
- ulint db_len;
+ ulint db_len;
/* Catenate 'databasename/' to the constraint name specified
by the user: we conceive the constraint as belonging to the
@@ -3179,8 +3167,8 @@
foreign->foreign_col_names[i] =
mem_heap_strdup(foreign->heap, columns[i]->name);
}
-
- ptr = dict_scan_table_name(ptr, &referenced_table, name,
+
+ ptr = dict_scan_table_name(cs, ptr, &referenced_table, name,
&success, heap, &referenced_table_name);
/* Note that referenced_table can be NULL if the user has suppressed
@@ -3198,8 +3186,8 @@
return(DB_CANNOT_ADD_CONSTRAINT);
}
-
- ptr = dict_accept(ptr, "(", &success);
+
+ ptr = dict_accept(cs, ptr, "(", &success);
if (!success) {
dict_foreign_free(foreign);
@@ -3212,10 +3200,10 @@
i = 0;
col_loop2:
- ptr = dict_scan_col(ptr, &success, referenced_table, columns + i,
+ ptr = dict_scan_col(cs, ptr, &success, referenced_table, columns + i,
heap, column_names + i);
i++;
-
+
if (!success) {
dict_foreign_free(foreign);
@@ -3229,17 +3217,17 @@
return(DB_CANNOT_ADD_CONSTRAINT);
}
- ptr = dict_accept(ptr, ",", &success);
+ ptr = dict_accept(cs, ptr, ",", &success);
if (success) {
goto col_loop2;
}
-
- ptr = dict_accept(ptr, ")", &success);
+
+ ptr = dict_accept(cs, ptr, ")", &success);
if (!success || foreign->n_fields != i) {
dict_foreign_free(foreign);
-
+
dict_foreign_report_syntax_err(name, start_of_latest_foreign,
ptr);
return(DB_CANNOT_ADD_CONSTRAINT);
@@ -3247,25 +3235,25 @@
n_on_deletes = 0;
n_on_updates = 0;
-
+
scan_on_conditions:
/* Loop here as long as we can find ON ... conditions */
- ptr = dict_accept(ptr, "ON", &success);
+ ptr = dict_accept(cs, ptr, "ON", &success);
if (!success) {
goto try_find_index;
}
- ptr = dict_accept(ptr, "DELETE", &success);
+ ptr = dict_accept(cs, ptr, "DELETE", &success);
if (!success) {
- ptr = dict_accept(ptr, "UPDATE", &success);
+ ptr = dict_accept(cs, ptr, "UPDATE", &success);
if (!success) {
dict_foreign_free(foreign);
-
+
dict_foreign_report_syntax_err(name,
start_of_latest_foreign, ptr);
return(DB_CANNOT_ADD_CONSTRAINT);
@@ -3278,13 +3266,13 @@
n_on_deletes++;
}
- ptr = dict_accept(ptr, "RESTRICT", &success);
+ ptr = dict_accept(cs, ptr, "RESTRICT", &success);
if (success) {
goto scan_on_conditions;
}
- ptr = dict_accept(ptr, "CASCADE", &success);
+ ptr = dict_accept(cs, ptr, "CASCADE", &success);
if (success) {
if (is_on_delete) {
@@ -3296,16 +3284,16 @@
goto scan_on_conditions;
}
- ptr = dict_accept(ptr, "NO", &success);
+ ptr = dict_accept(cs, ptr, "NO", &success);
if (success) {
- ptr = dict_accept(ptr, "ACTION", &success);
+ ptr = dict_accept(cs, ptr, "ACTION", &success);
if (!success) {
dict_foreign_free(foreign);
dict_foreign_report_syntax_err(name,
start_of_latest_foreign, ptr);
-
+
return(DB_CANNOT_ADD_CONSTRAINT);
}
@@ -3318,7 +3306,7 @@
goto scan_on_conditions;
}
- ptr = dict_accept(ptr, "SET", &success);
+ ptr = dict_accept(cs, ptr, "SET", &success);
if (!success) {
dict_foreign_free(foreign);
@@ -3327,7 +3315,7 @@
return(DB_CANNOT_ADD_CONSTRAINT);
}
- ptr = dict_accept(ptr, "NULL", &success);
+ ptr = dict_accept(cs, ptr, "NULL", &success);
if (!success) {
dict_foreign_free(foreign);
@@ -3362,13 +3350,13 @@
} else {
foreign->type |= DICT_FOREIGN_ON_UPDATE_SET_NULL;
}
-
+
goto scan_on_conditions;
try_find_index:
if (n_on_deletes > 1 || n_on_updates > 1) {
/* It is an error to define more than 1 action */
-
+
dict_foreign_free(foreign);
mutex_enter(&dict_foreign_err_mutex);
@@ -3416,7 +3404,7 @@
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++) {
@@ -3425,7 +3413,7 @@
}
/* We found an ok constraint definition: add to the lists */
-
+
UT_LIST_ADD_LAST(foreign_list, table->foreign_list, foreign);
if (referenced_table) {
@@ -3437,6 +3425,25 @@
goto loop;
}
+/**************************************************************************
+Determines whether a string starts with the specified keyword. */
+
+ibool
+dict_str_starts_with_keyword(
+/*=========================*/
+ /* out: TRUE if str starts
+ with keyword */
+ void* mysql_thd, /* in: MySQL thread handle */
+ const char* str, /* in: string to scan for keyword */
+ const char* keyword) /* in: keyword to look for */
+{
+ struct charset_info_st* cs = innobase_get_charset(mysql_thd);
+ ibool success;
+
+ dict_accept(cs, str, keyword, &success);
+ return(success);
+}
+
/*************************************************************************
Scans a table create SQL string and adds to the data dictionary the foreign
key constraints declared in the string. This function should be called after
@@ -3464,20 +3471,23 @@
code DB_CANNOT_ADD_CONSTRAINT if
any foreign keys are found. */
{
- char* str;
- ulint err;
- mem_heap_t* heap;
+ char* str;
+ ulint err;
+ mem_heap_t* heap;
+
+ ut_a(trx && trx->mysql_thd);
str = dict_strip_comments(sql_string);
heap = mem_heap_create(10000);
- err = dict_create_foreign_constraints_low(trx, heap, str, name,
- reject_fks);
+ err = dict_create_foreign_constraints_low(trx, heap,
+ innobase_get_charset(trx->mysql_thd),
+ str, name, reject_fks);
mem_heap_free(heap);
mem_free(str);
- return(err);
+ return(err);
}
/**************************************************************************
@@ -3499,13 +3509,18 @@
const char*** constraints_to_drop) /* out: id's of the
constraints to drop */
{
- dict_foreign_t* foreign;
- ibool success;
- char* str;
- const char* ptr;
- const char* id;
- FILE* ef = dict_foreign_err_file;
-
+ dict_foreign_t* foreign;
+ ibool success;
+ char* str;
+ const char* ptr;
+ const char* id;
+ FILE* ef = dict_foreign_err_file;
+ struct charset_info_st* cs;
+
+ ut_a(trx && trx->mysql_thd);
+
+ cs = innobase_get_charset(trx->mysql_thd);
+
*n = 0;
*constraints_to_drop = mem_heap_alloc(heap, 1000 * sizeof(char*));
@@ -3521,32 +3536,32 @@
if (*ptr == '\0') {
mem_free(str);
-
+
return(DB_SUCCESS);
}
- ptr = dict_accept(ptr, "DROP", &success);
+ ptr = dict_accept(cs, ptr, "DROP", &success);
- if (!isspace(*ptr)) {
+ if (!my_isspace(cs, *ptr)) {
- goto loop;
+ goto loop;
}
- ptr = dict_accept(ptr, "FOREIGN", &success);
-
+ ptr = dict_accept(cs, ptr, "FOREIGN", &success);
+
if (!success) {
- goto loop;
+ goto loop;
}
- ptr = dict_accept(ptr, "KEY", &success);
+ ptr = dict_accept(cs, ptr, "KEY", &success);
if (!success) {
goto syntax_error;
}
- ptr = dict_scan_id(ptr, heap, &id, TRUE);
+ ptr = dict_scan_id(cs, ptr, heap, &id, FALSE, TRUE);
if (id == NULL) {
@@ -3556,20 +3571,20 @@
ut_a(*n < 1000);
(*constraints_to_drop)[*n] = id;
(*n)++;
-
+
/* Look for the given constraint id */
foreign = UT_LIST_GET_FIRST(table->foreign_list);
while (foreign != NULL) {
if (0 == strcmp(foreign->id, id)
- || (strchr(foreign->id, '/')
- && 0 == strcmp(id,
+ || (strchr(foreign->id, '/')
+ && 0 == strcmp(id,
dict_remove_db_name(foreign->id)))) {
/* Found */
break;
}
-
+
foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
}
@@ -3579,12 +3594,12 @@
ut_print_timestamp(ef);
fputs(
" Error in dropping of a foreign key constraint of table ", ef);
- ut_print_name(ef, NULL, table->name);
+ ut_print_name(ef, NULL, TRUE, table->name);
fputs(",\n"
"in SQL command\n", ef);
fputs(str, ef);
fputs("\nCannot find a constraint with the given id ", ef);
- ut_print_name(ef, NULL, id);
+ ut_print_name(ef, NULL, FALSE, id);
fputs(".\n", ef);
mutex_exit(&dict_foreign_err_mutex);
@@ -3593,7 +3608,7 @@
return(DB_CANNOT_DROP_CONSTRAINT);
}
- goto loop;
+ goto loop;
syntax_error:
mutex_enter(&dict_foreign_err_mutex);
@@ -3601,7 +3616,7 @@
ut_print_timestamp(ef);
fputs(
" Syntax error in dropping of a foreign key constraint of table ", ef);
- ut_print_name(ef, NULL, table->name);
+ ut_print_name(ef, NULL, TRUE, table->name);
fprintf(ef, ",\n"
"close to:\n%s\n in SQL command\n%s\n", ptr, str);
mutex_exit(&dict_foreign_err_mutex);
@@ -3610,6 +3625,7 @@
return(DB_CANNOT_DROP_CONSTRAINT);
}
+#endif /* UNIV_HOTBACKUP */
/*==================== END OF FOREIGN KEY PROCESSING ====================*/
@@ -3630,7 +3646,7 @@
}
mutex_enter(&(dict_sys->mutex));
-
+
table = UT_LIST_GET_FIRST(dict_sys->table_LRU);
while (table) {
@@ -3678,14 +3694,12 @@
tree->page = page_no;
tree->id = index->id;
-
- UT_LIST_INIT(tree->tree_indexes);
- tree->magic_n = DICT_TREE_MAGIC_N;
+ tree->tree_index = NULL;
- rw_lock_create(&(tree->lock));
+ tree->magic_n = DICT_TREE_MAGIC_N;
- rw_lock_set_level(&(tree->lock), SYNC_INDEX_TREE);
+ rw_lock_create(&tree->lock, SYNC_INDEX_TREE);
return(tree);
}
@@ -3705,135 +3719,7 @@
mem_free(tree);
}
-/**************************************************************************
-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 */
-{
- dict_index_t* index;
- dict_table_t* table;
- dulint mix_id;
- ulint len;
-
- index = UT_LIST_GET_FIRST(tree->tree_indexes);
- ut_ad(index);
- table = index->table;
-
- if ((index->type & DICT_CLUSTERED)
- && UNIV_UNLIKELY(table->type != DICT_TABLE_ORDINARY)) {
-
- /* Get the mix id of the record */
- ut_a(!table->comp);
-
- mix_id = mach_dulint_read_compressed(
- rec_get_nth_field_old(rec, table->mix_len, &len));
-
- while (ut_dulint_cmp(table->mix_id, mix_id) != 0) {
-
- index = UT_LIST_GET_NEXT(tree_indexes, index);
- table = index->table;
- ut_ad(index);
- }
- }
-
- return(index);
-}
-
-/**************************************************************************
-In an index tree, finds the index corresponding to a record in the tree. */
-
-dict_index_t*
-dict_tree_find_index(
-/*=================*/
- /* out: index */
- dict_tree_t* tree, /* in: index tree */
- rec_t* rec) /* in: record for which to find correct
- index */
-{
- dict_index_t* index;
-
- index = dict_tree_find_index_low(tree, rec);
-
- return(index);
-}
-
-/**************************************************************************
-In an index tree, finds the index corresponding to a dtuple which is used
-in a search to a tree. */
-
-dict_index_t*
-dict_tree_find_index_for_tuple(
-/*===========================*/
- /* out: index; NULL if the tuple does not
- contain the mix id field in a mixed tree */
- dict_tree_t* tree, /* in: index tree */
- dtuple_t* tuple) /* in: tuple for which to find index */
-{
- dict_index_t* index;
- dict_table_t* table;
- dulint mix_id;
-
- ut_ad(dtuple_check_typed(tuple));
-
- if (UT_LIST_GET_LEN(tree->tree_indexes) == 1) {
-
- return(UT_LIST_GET_FIRST(tree->tree_indexes));
- }
-
- index = UT_LIST_GET_FIRST(tree->tree_indexes);
- ut_ad(index);
- table = index->table;
-
- if (dtuple_get_n_fields(tuple) <= table->mix_len) {
-
- return(NULL);
- }
-
- /* Get the mix id of the record */
-
- mix_id = mach_dulint_read_compressed(
- dfield_get_data(
- dtuple_get_nth_field(tuple, table->mix_len)));
-
- while (ut_dulint_cmp(table->mix_id, mix_id) != 0) {
-
- index = UT_LIST_GET_NEXT(tree_indexes, index);
- table = index->table;
- ut_ad(index);
- }
-
- return(index);
-}
-
-/***********************************************************************
-Checks if a table which is a mixed cluster member owns a record. */
-
-ibool
-dict_is_mixed_table_rec(
-/*====================*/
- /* out: TRUE if the record belongs to this
- table */
- dict_table_t* table, /* in: table in a mixed cluster */
- rec_t* rec) /* in: user record in the clustered index */
-{
- byte* mix_id_field;
- ulint len;
-
- ut_ad(!table->comp);
-
- mix_id_field = rec_get_nth_field_old(rec,
- table->mix_len, &len);
-
- return(len == table->mix_id_len
- && !ut_memcmp(table->mix_id_buf, mix_id_field, len));
-}
-
+#ifdef UNIV_DEBUG
/**************************************************************************
Checks that a tuple has n_fields_cmp value in a sensible range, so that
no comparison can occur with the page number field in a node pointer. */
@@ -3845,19 +3731,14 @@
dict_tree_t* tree, /* in: index tree */
dtuple_t* tuple) /* in: tuple used in a search */
{
- dict_index_t* index;
-
- index = dict_tree_find_index_for_tuple(tree, tuple);
-
- if (index == NULL) {
-
- return(TRUE);
- }
+ dict_index_t* index = tree->tree_index;
+ ut_a(index);
ut_a(dtuple_get_n_fields_cmp(tuple)
<= dict_index_get_n_unique_in_tree(index));
return(TRUE);
}
+#endif /* UNIV_DEBUG */
/**************************************************************************
Builds a node pointer out of a physical record and a page number. */
@@ -3871,7 +3752,7 @@
pointer */
ulint page_no,/* in: page number to put in node pointer */
mem_heap_t* heap, /* in: memory heap where pointer created */
- ulint level) /* in: level of rec in tree: 0 means leaf
+ ulint level) /* in: level of rec in tree: 0 means leaf
level */
{
dtuple_t* tuple;
@@ -3880,22 +3761,22 @@
byte* buf;
ulint n_unique;
- ind = dict_tree_find_index_low(tree, rec);
-
+ ind = tree->tree_index;
+
if (UNIV_UNLIKELY(tree->type & DICT_UNIVERSAL)) {
/* In a universal index tree, we take the whole record as
the node pointer if the reord is on the leaf level,
on non-leaf levels we remove the last field, which
contains the page number of the child page */
- ut_a(!ind->table->comp);
+ ut_a(!dict_table_is_comp(ind->table));
n_unique = rec_get_n_fields_old(rec);
if (level > 0) {
- ut_a(n_unique > 1);
- n_unique--;
+ ut_a(n_unique > 1);
+ n_unique--;
}
- } else {
+ } else {
n_unique = dict_index_get_n_unique_in_tree(ind);
}
@@ -3906,15 +3787,15 @@
levels in the tree there may be identical node pointers with a
different page number; therefore, we set the n_fields_cmp to one
less: */
-
+
dtuple_set_n_fields_cmp(tuple, n_unique);
dict_index_copy_types(tuple, ind, n_unique);
-
+
buf = mem_heap_alloc(heap, 4);
mach_write_to_4(buf, page_no);
-
+
field = dtuple_get_nth_field(tuple, n_unique);
dfield_set_data(field, buf, 4);
@@ -3927,8 +3808,8 @@
ut_ad(dtuple_check_typed(tuple));
return(tuple);
-}
-
+}
+
/**************************************************************************
Copies an initial segment of a physical record, long enough to specify an
index entry uniquely. */
@@ -3948,10 +3829,10 @@
ulint n;
UNIV_PREFETCH_R(rec);
- index = dict_tree_find_index_low(tree, rec);
+ index = tree->tree_index;
if (UNIV_UNLIKELY(tree->type & DICT_UNIVERSAL)) {
- ut_a(!index->table->comp);
+ ut_a(!dict_table_is_comp(index->table));
n = rec_get_n_fields_old(rec);
} else {
n = dict_index_get_n_unique_in_tree(index);
@@ -3976,11 +3857,12 @@
dtuple_t* tuple;
dict_index_t* ind;
- ind = dict_tree_find_index_low(tree, rec);
+ ind = tree->tree_index;
+
+ ut_ad(dict_table_is_comp(ind->table)
+ || n_fields <= rec_get_n_fields_old(rec));
- ut_ad(ind->table->comp || n_fields <= rec_get_n_fields_old(rec));
-
- tuple = dtuple_create(heap, n_fields);
+ tuple = dtuple_create(heap, n_fields);
dict_index_copy_types(tuple, ind, n_fields);
@@ -3989,8 +3871,8 @@
ut_ad(dtuple_check_typed(tuple));
return(tuple);
-}
-
+}
+
/*************************************************************************
Calculates the minimum record length in an index. */
@@ -4002,7 +3884,7 @@
ulint sum = 0;
ulint i;
- if (UNIV_LIKELY(index->table->comp)) {
+ if (dict_table_is_comp(index->table)) {
ulint nullable = 0;
sum = REC_N_NEW_EXTRA_BYTES;
for (i = 0; i < dict_index_get_n_fields(index); i++) {
@@ -4047,8 +3929,8 @@
/*=======================*/
dict_table_t* table, /* in: table */
ibool has_dict_mutex __attribute__((unused)))
- /* in: TRUE if the caller has the
- dictionary mutex */
+ /* in: TRUE if the caller has the
+ dictionary mutex */
{
dict_index_t* index;
ulint size;
@@ -4076,11 +3958,11 @@
/* Find out the sizes of the indexes and how many different values
for the key they approximately have */
- index = dict_table_get_first_index(table);
+ index = dict_table_get_first_index(table);
if (index == NULL) {
/* Table definition is corrupt */
-
+
return;
}
@@ -4099,7 +3981,7 @@
}
index->stat_n_leaf_pages = size;
-
+
btr_estimate_number_of_different_key_vals(index);
index = dict_table_get_next_index(index);
@@ -4117,7 +3999,7 @@
table->stat_initialized = TRUE;
- table->stat_modified_counter = 0;
+ table->stat_modified_counter = 0;
}
/*************************************************************************
@@ -4133,6 +4015,18 @@
}
/**************************************************************************
+A noninlined version of dict_table_get_low. */
+
+dict_table_t*
+dict_table_get_low_noninlined(
+/*==========================*/
+ /* out: table, NULL if not found */
+ const char* table_name) /* in: table name */
+{
+ return(dict_table_get_low(table_name));
+}
+
+/**************************************************************************
Prints info of a foreign key constraint. */
static
void
@@ -4156,7 +4050,7 @@
fprintf(stderr, " )\n"
" REFERENCES %s (",
foreign->referenced_table_name);
-
+
for (i = 0; i < foreign->n_fields; i++) {
fprintf(stderr, " %s", foreign->referenced_col_names[i]);
}
@@ -4192,7 +4086,7 @@
table = dict_table_get_low(name);
ut_a(table);
-
+
dict_table_print_low(table);
mutex_exit(&(dict_sys->mutex));
}
@@ -4214,7 +4108,7 @@
#endif /* UNIV_SYNC_DEBUG */
dict_update_statistics_low(table, TRUE);
-
+
fprintf(stderr,
"--------------------------------------\n"
"TABLE: name %s, id %lu %lu, columns %lu, indexes %lu, appr.rows %lu\n"
@@ -4223,7 +4117,7 @@
(ulong) ut_dulint_get_high(table->id),
(ulong) ut_dulint_get_low(table->id),
(ulong) table->n_cols,
- (ulong) UT_LIST_GET_LEN(table->indexes),
+ (ulong) UT_LIST_GET_LEN(table->indexes),
(ulong) table->stat_n_rows);
for (i = 0; i < table->n_cols - 1; i++) {
@@ -4301,7 +4195,7 @@
}
fprintf(stderr,
- " INDEX: name %s, id %lu %lu, fields %lu/%lu, type %lu\n"
+ " INDEX: name %s, id %lu %lu, fields %lu/%lu, uniq %lu, type %lu\n"
" root page %lu, appr.key vals %lu,"
" leaf pages %lu, size pages %lu\n"
" FIELDS: ",
@@ -4309,12 +4203,14 @@
(ulong) ut_dulint_get_high(tree->id),
(ulong) ut_dulint_get_low(tree->id),
(ulong) index->n_user_defined_cols,
- (ulong) index->n_fields, (ulong) index->type,
+ (ulong) index->n_fields,
+ (ulong) index->n_uniq,
+ (ulong) index->type,
(ulong) tree->page,
(ulong) n_vals,
(ulong) index->stat_n_leaf_pages,
(ulong) index->stat_index_size);
-
+
for (i = 0; i < index->n_fields; i++) {
dict_field_print_low(dict_index_get_nth_field(index, i));
}
@@ -4360,7 +4256,7 @@
{
const char* stripped_id;
ulint i;
-
+
if (strchr(foreign->id, '/')) {
/* Strip the preceding database name from the constraint id */
stripped_id = foreign->id + 1
@@ -4370,23 +4266,23 @@
}
putc(',', file);
-
+
if (add_newline) {
/* SHOW CREATE TABLE wants constraints each printed nicely
on its own line, while error messages want no newlines
inserted. */
fputs("\n ", file);
}
-
+
fputs(" CONSTRAINT ", file);
- ut_print_name(file, trx, stripped_id);
+ ut_print_name(file, trx, FALSE, stripped_id);
fputs(" FOREIGN KEY (", file);
for (i = 0;;) {
- ut_print_name(file, trx, foreign->foreign_col_names[i]);
+ ut_print_name(file, trx, FALSE, foreign->foreign_col_names[i]);
if (++i < foreign->n_fields) {
fputs(", ", file);
- } else {
+ } else {
break;
}
}
@@ -4396,7 +4292,7 @@
if (dict_tables_have_same_db(foreign->foreign_table_name,
foreign->referenced_table_name)) {
/* Do not print the database name of the referenced table */
- ut_print_name(file, trx, dict_remove_db_name(
+ ut_print_name(file, trx, TRUE, dict_remove_db_name(
foreign->referenced_table_name));
} else {
/* Look for the '/' in the table name */
@@ -4406,9 +4302,10 @@
i++;
}
- ut_print_namel(file, trx, foreign->referenced_table_name, i);
+ ut_print_namel(file, trx, TRUE,
+ foreign->referenced_table_name, i);
putc('.', file);
- ut_print_name(file, trx,
+ ut_print_name(file, trx, TRUE,
foreign->referenced_table_name + i + 1);
}
@@ -4416,7 +4313,8 @@
putc('(', file);
for (i = 0;;) {
- ut_print_name(file, trx, foreign->referenced_col_names[i]);
+ ut_print_name(file, trx, FALSE,
+ foreign->referenced_col_names[i]);
if (++i < foreign->n_fields) {
fputs(", ", file);
} else {
@@ -4429,7 +4327,7 @@
if (foreign->type & DICT_FOREIGN_ON_DELETE_CASCADE) {
fputs(" ON DELETE CASCADE", file);
}
-
+
if (foreign->type & DICT_FOREIGN_ON_DELETE_SET_NULL) {
fputs(" ON DELETE SET NULL", file);
}
@@ -4441,7 +4339,7 @@
if (foreign->type & DICT_FOREIGN_ON_UPDATE_CASCADE) {
fputs(" ON UPDATE CASCADE", file);
}
-
+
if (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL) {
fputs(" ON UPDATE SET NULL", file);
}
@@ -4490,12 +4388,12 @@
putc(' ', file);
}
- ut_print_name(file, trx,
+ ut_print_name(file, trx, FALSE,
foreign->foreign_col_names[i]);
}
fputs(") REFER ", file);
- ut_print_name(file, trx,
+ ut_print_name(file, trx, TRUE,
foreign->referenced_table_name);
putc('(', file);
@@ -4503,7 +4401,7 @@
if (i) {
putc(' ', file);
}
- ut_print_name(file, trx,
+ ut_print_name(file, trx, FALSE,
foreign->referenced_col_names[i]);
}
@@ -4512,7 +4410,7 @@
if (foreign->type == DICT_FOREIGN_ON_DELETE_CASCADE) {
fputs(" ON DELETE CASCADE", file);
}
-
+
if (foreign->type == DICT_FOREIGN_ON_DELETE_SET_NULL) {
fputs(" ON DELETE SET NULL", file);
}
@@ -4524,7 +4422,7 @@
if (foreign->type & DICT_FOREIGN_ON_UPDATE_CASCADE) {
fputs(" ON UPDATE CASCADE", file);
}
-
+
if (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL) {
fputs(" ON UPDATE SET NULL", file);
}
@@ -4550,7 +4448,7 @@
const dict_index_t* index) /* in: index to print */
{
fputs("index ", file);
- ut_print_name(file, trx, index->name);
+ ut_print_name(file, trx, FALSE, index->name);
fputs(" of table ", file);
- ut_print_name(file, trx, index->table_name);
+ ut_print_name(file, trx, TRUE, index->table_name);
}
--- 1.54.11.1/innobase/fil/fil0fil.c 2006-08-29 18:58:59 +04:00
+++ 1.66/storage/innobase/fil/fil0fil.c 2006-08-29 18:58:59 +04:00
@@ -27,7 +27,7 @@
#include "mtr0log.h"
#include "dict0dict.h"
-
+
/*
IMPLEMENTATION OF THE TABLESPACE MEMORY CACHE
=============================================
@@ -69,7 +69,7 @@
certainly prevents the OS from fragmenting disk space, but it is not clear
if it really adds speed. We measured on the Pentium 100 MHz + NT + NTFS file
system + EIDE Conner disk only a negligible difference in speed when reading
-from a file, versus reading from a raw disk.
+from a file, versus reading from a raw disk.
To have fast access to a tablespace or a log file, we put the data structures
to a hash table. Each tablespace and log file is given an unique 32-bit
@@ -90,7 +90,7 @@
const char* fil_path_to_mysql_datadir = ".";
/* The number of fsyncs done to the log */
-ulint fil_n_log_flushes = 0;
+ulint fil_n_log_flushes = 0;
ulint fil_n_pending_log_flushes = 0;
ulint fil_n_pending_tablespace_flushes = 0;
@@ -117,7 +117,7 @@
ulint n_pending_flushes;
/* count of pending flushes on this file;
closing of the file is not allowed if
- this is > 0 */
+ this is > 0 */
ib_longlong modification_counter;/* when we write to the file we
increment this by one */
ib_longlong flush_counter;/* up to what modification_counter value
@@ -165,7 +165,7 @@
ulint size; /* space size in pages; 0 if a single-table
tablespace whose size we do not know yet;
last incomplete megabytes in data files may be
- ignored if space == 0 */
+ ignored if space == 0 */
ulint n_reserved_extents;
/* number of reserved free extents for
ongoing operations like B-tree page split */
@@ -177,7 +177,7 @@
may need to access the ibuf bitmap page in the
tablespade: dropping of the tablespace is
forbidden if this is > 0 */
- hash_node_t hash; /* hash chain node */
+ hash_node_t hash; /* hash chain node */
hash_node_t name_hash;/* hash chain the name_hash table */
rw_lock_t latch; /* latch protecting the file space storage
allocation */
@@ -251,6 +251,9 @@
initialized. */
fil_system_t* fil_system = NULL;
+/* The tablespace memory cache hash table size */
+#define FIL_SYSTEM_HASH_SIZE 50 /* TODO: make bigger! */
+
/************************************************************************
NOTE: you must call fil_mutex_enter_and_prepare_for_io() first!
@@ -464,7 +467,7 @@
node->modification_counter = 0;
node->flush_counter = 0;
-
+
HASH_SEARCH(hash, system->spaces, id, space, space->id == id);
if (!space) {
@@ -488,7 +491,7 @@
node->space = space;
UT_LIST_ADD_LAST(chain, space->chain, node);
-
+
mutex_exit(&(system->mutex));
}
@@ -507,10 +510,12 @@
ulint size_low;
ulint size_high;
ibool ret;
+ ibool success;
+#ifndef UNIV_HOTBACKUP
byte* buf2;
byte* page;
- ibool success;
ulint space_id;
+#endif /* !UNIV_HOTBACKUP */
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(system->mutex)));
@@ -543,24 +548,24 @@
ut_a(0);
}
- ut_a(space->purpose != FIL_LOG);
- ut_a(space->id != 0);
-
os_file_get_size(node->handle, &size_low, &size_high);
size_bytes = (((ib_longlong)size_high) << 32)
- + (ib_longlong)size_low;
+ + (ib_longlong)size_low;
#ifdef UNIV_HOTBACKUP
node->size = (ulint) (size_bytes / UNIV_PAGE_SIZE);
#else
+ ut_a(space->purpose != FIL_LOG);
+ ut_a(space->id != 0);
+
if (size_bytes < FIL_IBD_FILE_INITIAL_SIZE * UNIV_PAGE_SIZE) {
- fprintf(stderr,
+ fprintf(stderr,
"InnoDB: Error: the size of single-table tablespace file %s\n"
"InnoDB: is only %lu %lu, should be at least %lu!\n", node->name,
(ulong) size_high,
(ulong) size_low, (ulong) (4 * UNIV_PAGE_SIZE));
-
+
ut_a(0);
}
@@ -576,22 +581,22 @@
space_id = fsp_header_get_space_id(page);
ut_free(buf2);
-
+
/* Close the file now that we have read the space id from it */
os_file_close(node->handle);
if (space_id == ULINT_UNDEFINED || space_id == 0) {
- fprintf(stderr,
+ fprintf(stderr,
"InnoDB: Error: tablespace id %lu in file %s is not sensible\n",
(ulong) space_id,
node->name);
-
- ut_a(0);
+
+ ut_a(0);
}
if (space_id != space->id) {
- fprintf(stderr,
+ fprintf(stderr,
"InnoDB: Error: tablespace id is %lu in the data dictionary\n"
"InnoDB: but in file %s it is %lu!\n", space->id, node->name, space_id);
@@ -614,20 +619,20 @@
unbuffered async I/O mode, though global variables may make
os_file_create() to fall back to the normal file I/O mode. */
- if (space->purpose == FIL_LOG) {
+ if (space->purpose == FIL_LOG) {
node->handle = os_file_create(node->name, OS_FILE_OPEN,
OS_FILE_AIO, OS_LOG_FILE, &ret);
} else if (node->is_raw_disk) {
node->handle = os_file_create(node->name,
- OS_FILE_OPEN_RAW,
+ OS_FILE_OPEN_RAW,
OS_FILE_AIO, OS_DATA_FILE, &ret);
} else {
node->handle = os_file_create(node->name, OS_FILE_OPEN,
OS_FILE_AIO, OS_DATA_FILE, &ret);
}
-
+
ut_a(ret);
-
+
node->open = TRUE;
system->n_open++;
@@ -683,7 +688,7 @@
fil_try_to_close_file_in_LRU(
/*=========================*/
/* out: TRUE if success, FALSE if should retry
- later; since i/o's generally complete in <
+ later; since i/o's generally complete in <
100 ms, and as InnoDB writes at most 128 pages
from the buffer pool in a batch, and then
immediately flushes the files, there is a good
@@ -707,22 +712,22 @@
while (node != NULL) {
if (node->modification_counter == node->flush_counter
- && node->n_pending_flushes == 0) {
+ && node->n_pending_flushes == 0) {
fil_node_close_file(node, system);
-
+
return(TRUE);
}
-
+
if (print_info && node->n_pending_flushes > 0) {
fputs("InnoDB: cannot close file ", stderr);
ut_print_filename(stderr, node->name);
fprintf(stderr, ", because n_pending_flushes %lu\n",
- (ulong) node->n_pending_flushes);
+ (ulong) node->n_pending_flushes);
}
if (print_info
- && node->modification_counter != node->flush_counter) {
+ && node->modification_counter != node->flush_counter) {
fputs("InnoDB: cannot close file ", stderr);
ut_print_filename(stderr, node->name);
fprintf(stderr,
@@ -849,7 +854,7 @@
/* Flush tablespaces so that we can close modified files in the LRU
list */
- fil_flush_file_spaces(FIL_TABLESPACE);
+ fil_flush_file_spaces(FIL_TABLESPACE);
count++;
@@ -880,7 +885,7 @@
node->modification_counter = node->flush_counter;
if (space->is_in_unflushed_spaces
- && fil_space_is_flushed(space)) {
+ && fil_space_is_flushed(space)) {
space->is_in_unflushed_spaces = FALSE;
@@ -893,7 +898,7 @@
}
space->size -= node->size;
-
+
UT_LIST_REMOVE(chain, space->chain, node);
mem_free(node->name);
@@ -921,7 +926,7 @@
HASH_SEARCH(hash, system->spaces, id, space, space->id == id);
ut_a(space);
-
+
while (trunc_len > 0) {
node = UT_LIST_GET_FIRST(space->chain);
@@ -930,8 +935,8 @@
trunc_len -= node->size * UNIV_PAGE_SIZE;
fil_node_free(node, system, space);
- }
-
+ }
+
mutex_exit(&(system->mutex));
}
@@ -948,7 +953,7 @@
ulint purpose)/* in: FIL_TABLESPACE, or FIL_LOG if log */
{
fil_system_t* system = fil_system;
- fil_space_t* space;
+ fil_space_t* space;
ulint namesake_id;
try_again:
/*printf(
@@ -1036,7 +1041,7 @@
space->size = 0;
space->n_reserved_extents = 0;
-
+
space->n_pending_flushes = 0;
space->n_pending_ibuf_merges = 0;
@@ -1044,10 +1049,9 @@
space->magic_n = FIL_SPACE_MAGIC_N;
space->ibuf_data = NULL;
-
- rw_lock_create(&(space->latch));
- rw_lock_set_level(&(space->latch), SYNC_FSP);
-
+
+ rw_lock_create(&space->latch, SYNC_FSP);
+
HASH_INSERT(fil_space_t, hash, system->spaces, id, space);
HASH_INSERT(fil_space_t, name_hash, system->name_hash,
@@ -1055,7 +1059,7 @@
space->is_in_unflushed_spaces = FALSE;
UT_LIST_ADD_LAST(space_list, system->space_list, space);
-
+
mutex_exit(&(system->mutex));
return(TRUE);
@@ -1082,8 +1086,8 @@
id = system->max_assigned_id;
if (id > (SRV_LOG_SPACE_FIRST_ID / 2) && (id % 1000000UL == 0)) {
- ut_print_timestamp(stderr);
- fprintf(stderr,
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
"InnoDB: Warning: you are running out of new single-table tablespace id's.\n"
"InnoDB: Current counter is %lu and it must not exceed %lu!\n"
"InnoDB: To reset the counter to zero you have to dump all your tables and\n"
@@ -1092,8 +1096,8 @@
}
if (id >= SRV_LOG_SPACE_FIRST_ID) {
- ut_print_timestamp(stderr);
- fprintf(stderr,
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
"InnoDB: You have run out of single-table tablespace id's!\n"
"InnoDB: Current counter is %lu.\n"
"InnoDB: To reset the counter to zero you have to dump all your tables and\n"
@@ -1135,14 +1139,14 @@
"InnoDB: it is not there.\n", (ulong) id);
mutex_exit(&(system->mutex));
-
+
return(FALSE);
}
HASH_DELETE(fil_space_t, hash, system->spaces, id, space);
HASH_SEARCH(name_hash, system->name_hash, ut_fold_string(space->name),
- namespace, 0 == strcmp(space->name, namespace->name));
+ namespace, 0 == strcmp(space->name, namespace->name));
ut_a(namespace);
ut_a(space == namespace);
@@ -1167,8 +1171,8 @@
fil_node_free(fil_node, system, space);
fil_node = UT_LIST_GET_FIRST(space->chain);
- }
-
+ }
+
ut_a(0 == UT_LIST_GET_LEN(space->chain));
mutex_exit(&(system->mutex));
@@ -1214,7 +1218,7 @@
/* out: space size, 0 if space not found */
ulint id) /* in: space id */
{
- fil_system_t* system = fil_system;
+ fil_system_t* system = fil_system;
fil_node_t* node;
fil_space_t* space;
ulint size;
@@ -1247,7 +1251,7 @@
}
size = space->size;
-
+
mutex_exit(&(system->mutex));
return(size);
@@ -1270,7 +1274,7 @@
}
return(FALSE);
-}
+}
/********************************************************************
Creates a the tablespace memory cache. */
@@ -1290,9 +1294,7 @@
system = mem_alloc(sizeof(fil_system_t));
- mutex_create(&(system->mutex));
-
- mutex_set_level(&(system->mutex), SYNC_ANY_LATCH);
+ mutex_create(&system->mutex, SYNC_ANY_LATCH);
system->spaces = hash_create(hash_size);
system->name_hash = hash_create(hash_size);
@@ -1321,17 +1323,11 @@
/*=====*/
ulint max_n_open) /* in: max number of open files */
{
- ulint hash_size;
-
ut_a(fil_system == NULL);
- if (srv_file_per_table) {
- hash_size = 50000;
- } else {
- hash_size = 5000;
- }
-
- fil_system = fil_system_create(hash_size, max_n_open);
+ /*printf("Initializing the tablespace cache with max %lu open files\n",
+ max_n_open); */
+ fil_system = fil_system_create(FIL_SYSTEM_HASH_SIZE, max_n_open);
}
/***********************************************************************
@@ -1369,8 +1365,8 @@
"InnoDB: tablespace files open for the whole time mysqld is running, and\n"
"InnoDB: needs to open also some .ibd files if the file-per-table storage\n"
"InnoDB: model is used. Current open files %lu, max allowed open files %lu.\n",
- (ulong) system->n_open,
- (ulong) system->max_n_open);
+ (ulong) system->n_open,
+ (ulong) system->max_n_open);
}
node = UT_LIST_GET_NEXT(chain, node);
}
@@ -1453,7 +1449,7 @@
space = UT_LIST_GET_FIRST(fil_system->space_list);
ut_a(space);
- ut_a(space->purpose == FIL_TABLESPACE);
+ ut_a(space->purpose == FIL_TABLESPACE);
space->ibuf_data = ibuf_data_init_for_space(space->id);
}
@@ -1484,7 +1480,7 @@
fil_write(TRUE, space_id, sum_of_sizes, 0, UNIV_PAGE_SIZE, buf, NULL);
- return(DB_SUCCESS);
+ return(DB_SUCCESS);
}
/********************************************************************
@@ -1504,9 +1500,9 @@
ulint err;
mutex_enter(&(fil_system->mutex));
-
+
space = UT_LIST_GET_FIRST(fil_system->space_list);
-
+
while (space) {
/* We only write the lsn to all existing data files which have
been open during the lifetime of the mysqld process; they are
@@ -1515,7 +1511,7 @@
always open. */
if (space->purpose == FIL_TABLESPACE
- && space->id == 0) {
+ && space->id == 0) {
sum_of_sizes = 0;
node = UT_LIST_GET_FIRST(space->chain);
@@ -1568,7 +1564,7 @@
buf2 = ut_malloc(2 * UNIV_PAGE_SIZE);
/* Align the memory for a possible read from a raw device */
buf = ut_align(buf2, UNIV_PAGE_SIZE);
-
+
os_file_read(data_file, buf, 0, 0, UNIV_PAGE_SIZE);
flushed_lsn = mach_read_from_8(buf + FIL_PAGE_FILE_FLUSH_LSN);
@@ -1616,7 +1612,7 @@
{
fil_system_t* system = fil_system;
fil_space_t* space;
-
+
mutex_enter(&(system->mutex));
HASH_SEARCH(hash, system->spaces, id, space, space->id == id);
@@ -1645,12 +1641,12 @@
void
fil_decr_pending_ibuf_merges(
-/*========================*/
+/*=========================*/
ulint id) /* in: space id */
{
fil_system_t* system = fil_system;
fil_space_t* space;
-
+
mutex_enter(&(system->mutex));
HASH_SEARCH(hash, system->spaces, id, space, space->id == id);
@@ -1711,7 +1707,7 @@
const char* name, /* in: table name in the familiar
'databasename/tablename' format, or
the file path in the case of
- MLOG_FILE_DELETE */
+ MLOG_FILE_DELETE */
const char* new_name, /* in: if type is MLOG_FILE_RENAME,
the new table name in the
'databasename/tablename' format */
@@ -1770,13 +1766,13 @@
byte*
fil_op_log_parse_or_replay(
/*=======================*/
- /* out: end of log record, or NULL if the
+ /* out: end of log record, or NULL if the
record was not completely contained between
ptr and end_ptr */
- byte* ptr, /* in: buffer containing the log record body,
+ byte* ptr, /* in: buffer containing the log record body,
or an initial segment of it, if the record does
not fir completely between ptr and end_ptr */
- byte* end_ptr, /* in: buffer end */
+ byte* end_ptr, /* in: buffer end */
ulint type, /* in: the type of this log record */
ibool do_replay, /* in: TRUE if we want to replay the
operation, and not just parse the log record */
@@ -1799,7 +1795,7 @@
ptr += 2;
if (end_ptr < ptr + name_len) {
-
+
return(NULL);
}
@@ -1814,11 +1810,11 @@
}
new_name_len = mach_read_from_2(ptr);
-
+
ptr += 2;
if (end_ptr < ptr + new_name_len) {
-
+
return(NULL);
}
@@ -1844,7 +1840,7 @@
/* Let us try to perform the file operation, if sensible. Note that
ibbackup has at this stage already read in all space id info to the
fil0fil.c data structures.
-
+
NOTE that our algorithm is not guaranteed to work correctly if there
were renames of tables during the backup. See ibbackup code for more
on the problem. */
@@ -1863,12 +1859,12 @@
/* Create the database directory for the new name, if
it does not exist yet */
fil_create_directory_for_tablename(new_name);
-
+
/* Rename the table if there is not yet a tablespace
with the same name */
if (fil_get_space_id_for_table(new_name)
- == ULINT_UNDEFINED) {
+ == ULINT_UNDEFINED) {
/* We do not care of the old name, that is
why we pass NULL as the first argument */
ut_a(fil_rename_tablespace(NULL, space_id,
@@ -1890,7 +1886,7 @@
ut_a(space_id != 0);
- ut_a(DB_SUCCESS ==
+ ut_a(DB_SUCCESS ==
fil_create_new_single_table_tablespace(
&space_id, name, FALSE,
FIL_IBD_FILE_INITIAL_SIZE));
@@ -1969,9 +1965,9 @@
(ulong) id);
mutex_exit(&(system->mutex));
-
+
return(FALSE);
- }
+ }
ut_a(space);
ut_a(space->n_pending_ibuf_merges == 0);
@@ -2074,7 +2070,7 @@
fprintf(stderr,
"InnoDB: Warning: cannot delete tablespace %lu in DISCARD TABLESPACE.\n"
"InnoDB: But let us remove the insert buffer entries for this tablespace.\n",
- (ulong) id);
+ (ulong) id);
}
/* Remove all insert buffer entries for the tablespace */
@@ -2098,9 +2094,9 @@
fil_system_t* system = fil_system;
fil_space_t* space2;
const char* old_name = space->name;
-
+
HASH_SEARCH(name_hash, system->name_hash, ut_fold_string(old_name),
- space2, 0 == strcmp(old_name, space2->name));
+ space2, 0 == strcmp(old_name, space2->name));
if (space != space2) {
fputs("InnoDB: Error: cannot find ", stderr);
ut_print_filename(stderr, old_name);
@@ -2110,12 +2106,12 @@
}
HASH_SEARCH(name_hash, system->name_hash, ut_fold_string(path),
- space2, 0 == strcmp(path, space2->name));
+ space2, 0 == strcmp(path, space2->name));
if (space2 != NULL) {
fputs("InnoDB: Error: ", stderr);
ut_print_filename(stderr, path);
fputs(" is already in tablespace memory cache\n", stderr);
-
+
return(FALSE);
}
@@ -2187,11 +2183,11 @@
fil_node_t* node;
ulint count = 0;
char* path;
- ibool old_name_was_specified = TRUE;
+ ibool old_name_was_specified = TRUE;
char* old_path;
ut_a(id != 0);
-
+
if (old_name == NULL) {
old_name = "(name not specified)";
old_name_was_specified = FALSE;
@@ -2300,7 +2296,7 @@
mutex_exit(&(system->mutex));
-#ifndef UNIV_HOTBACKUP
+#ifndef UNIV_HOTBACKUP
if (success) {
mtr_t mtr;
@@ -2338,7 +2334,7 @@
tablespace file in pages,
must be >= FIL_IBD_FILE_INITIAL_SIZE */
{
- os_file_t file;
+ os_file_t file;
ibool ret;
ulint err;
byte* buf2;
@@ -2349,9 +2345,9 @@
ut_a(size >= FIL_IBD_FILE_INITIAL_SIZE);
path = fil_make_ibd_name(tablename, is_temp);
-
+
file = os_file_create(path, OS_FILE_CREATE, OS_FILE_NORMAL,
- OS_DATA_FILE, &ret);
+ OS_DATA_FILE, &ret);
if (ret == FALSE) {
ut_print_timestamp(stderr);
fputs(" InnoDB: Error creating file ", stderr);
@@ -2359,11 +2355,11 @@
fputs(".\n", stderr);
/* The following call will print an error message */
-
+
err = os_file_get_last_error(TRUE);
-
+
if (err == OS_FILE_ALREADY_EXISTS) {
- fputs(
+ fputs(
"InnoDB: The file already exists though the corresponding table did not\n"
"InnoDB: exist in the InnoDB data dictionary. Have you moved InnoDB\n"
"InnoDB: .ibd files around without using the SQL commands\n"
@@ -2393,7 +2389,7 @@
page = ut_align(buf2, UNIV_PAGE_SIZE);
ret = os_file_set_size(path, file, size * UNIV_PAGE_SIZE, 0);
-
+
if (!ret) {
ut_free(buf2);
os_file_close(file);
@@ -2431,7 +2427,7 @@
memset(page, '\0', UNIV_PAGE_SIZE);
- fsp_header_write_space_id(page, *space_id);
+ fsp_header_write_space_id(page, *space_id);
buf_flush_init_for_writing(page, ut_dulint_zero, *space_id, 0);
@@ -2464,14 +2460,14 @@
}
success = fil_space_create(path, *space_id, FIL_TABLESPACE);
-
+
if (!success) {
goto error_exit2;
- }
+ }
fil_node_create(path, size, *space_id, FALSE);
-#ifndef UNIV_HOTBACKUP
+#ifndef UNIV_HOTBACKUP
{
mtr_t mtr;
@@ -2527,7 +2523,7 @@
ut_print_timestamp(stderr);
- fputs(
+ fputs(
" InnoDB: Error: trying to open a table, but could not\n"
"InnoDB: open the tablespace file ", stderr);
ut_print_filename(stderr, filepath);
@@ -2561,17 +2557,17 @@
}
space_id = fsp_header_get_space_id(page);
-
+
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: Flush lsn in the tablespace file %lu to be imported\n"
"InnoDB: is %lu %lu, which exceeds current system lsn %lu %lu.\n"
"InnoDB: We reset the lsn's in the file ",
- (ulong) space_id,
- (ulong) ut_dulint_get_high(flush_lsn),
- (ulong) ut_dulint_get_low(flush_lsn),
- (ulong) ut_dulint_get_high(current_lsn),
- (ulong) ut_dulint_get_low(current_lsn));
+ (ulong) space_id,
+ (ulong) ut_dulint_get_high(flush_lsn),
+ (ulong) ut_dulint_get_low(flush_lsn),
+ (ulong) ut_dulint_get_high(current_lsn),
+ (ulong) ut_dulint_get_low(current_lsn));
ut_print_filename(stderr, filepath);
fputs(".\n", stderr);
@@ -2594,9 +2590,9 @@
space_id = mach_read_from_4(page
+ FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
page_no = mach_read_from_4(page + FIL_PAGE_OFFSET);
-
+
buf_flush_init_for_writing(page, current_lsn, space_id,
- page_no);
+ page_no);
success = os_file_write(filepath, file, page,
(ulint)(offset & 0xFFFFFFFFUL),
(ulint)(offset >> 32), UNIV_PAGE_SIZE);
@@ -2679,7 +2675,7 @@
ut_print_timestamp(stderr);
- fputs(
+ fputs(
" InnoDB: Error: trying to open a table, but could not\n"
"InnoDB: open the tablespace file ", stderr);
ut_print_filename(stderr, filepath);
@@ -2720,7 +2716,7 @@
if (space_id != id) {
ut_print_timestamp(stderr);
- fputs(
+ fputs(
" InnoDB: Error: tablespace id in file ", stderr);
ut_print_filename(stderr, filepath);
fprintf(stderr, " is %lu, but in the InnoDB\n"
@@ -2799,13 +2795,14 @@
#ifdef UNIV_HOTBACKUP
fil_space_t* space;
#endif
- filepath = mem_alloc(strlen(dbname) + strlen(filename)
+ filepath = mem_alloc(strlen(dbname) + strlen(filename)
+ strlen(fil_path_to_mysql_datadir) + 3);
sprintf(filepath, "%s/%s/%s", fil_path_to_mysql_datadir, dbname,
filename);
srv_normalize_path_for_win(filepath);
#ifdef __WIN__
+# ifndef UNIV_HOTBACKUP
/* If lower_case_table_names is 0 or 2, then MySQL allows database
directory names with upper case letters. On Windows, all table and
database names in InnoDB are internally always in lower case. Put the
@@ -2813,6 +2810,7 @@
internal data dictionary. */
dict_casedn_str(filepath);
+# endif /* !UNIV_HOTBACKUP */
#endif
file = os_file_create_simple_no_error_handling(filepath, OS_FILE_OPEN,
OS_FILE_READ_ONLY, &success);
@@ -2820,7 +2818,7 @@
/* The following call prints an error message */
os_file_get_last_error(TRUE);
- fprintf(stderr,
+ fprintf(stderr,
"InnoDB: Error: could not open single-table tablespace file\n"
"InnoDB: %s!\n"
"InnoDB: We do not continue the crash recovery, because the table may become\n"
@@ -2854,7 +2852,7 @@
/* The following call prints an error message */
os_file_get_last_error(TRUE);
- fprintf(stderr,
+ fprintf(stderr,
"InnoDB: Error: could not measure the size of single-table tablespace file\n"
"InnoDB: %s!\n"
"InnoDB: We do not continue crash recovery, because the table will become\n"
@@ -2892,7 +2890,7 @@
size = (((ib_longlong)size_high) << 32) + (ib_longlong)size_low;
#ifndef UNIV_HOTBACKUP
if (size < FIL_IBD_FILE_INITIAL_SIZE * UNIV_PAGE_SIZE) {
- fprintf(stderr,
+ fprintf(stderr,
"InnoDB: Error: the size of single-table tablespace file %s\n"
"InnoDB: is only %lu %lu, should be at least %lu!", filepath,
(ulong) size_high,
@@ -2921,7 +2919,7 @@
#ifndef UNIV_HOTBACKUP
if (space_id == ULINT_UNDEFINED || space_id == 0) {
- fprintf(stderr,
+ fprintf(stderr,
"InnoDB: Error: tablespace id %lu in file %s is not sensible\n",
(ulong) space_id,
filepath);
@@ -3031,7 +3029,7 @@
return(ret);
}
-
+
fprintf(stderr,
"InnoDB: Error: os_file_readdir_next_file() returned -1 in\n"
"InnoDB: directory %s\n"
@@ -3063,7 +3061,7 @@
os_file_dir_t dbdir;
os_file_stat_t dbinfo;
os_file_stat_t fileinfo;
- ulint err = DB_SUCCESS;
+ ulint err = DB_SUCCESS;
/* The datadir of MySQL is always the default directory of mysqld */
@@ -3086,9 +3084,9 @@
/* printf("Looking at %s in datadir\n", dbinfo.name); */
if (dbinfo.type == OS_FILE_TYPE_FILE
- || dbinfo.type == OS_FILE_TYPE_UNKNOWN) {
+ || dbinfo.type == OS_FILE_TYPE_UNKNOWN) {
- goto next_datadir_item;
+ goto next_datadir_item;
}
/* We found a symlink or a directory; try opening it to see
@@ -3121,19 +3119,19 @@
&fileinfo);
while (ret == 0) {
/* printf(
-" Looking at file %s\n", fileinfo.name); */
+ " Looking at file %s\n", fileinfo.name); */
- if (fileinfo.type == OS_FILE_TYPE_DIR) {
+ if (fileinfo.type == OS_FILE_TYPE_DIR) {
- goto next_file_item;
+ goto next_file_item;
}
/* We found a symlink or a file */
if (strlen(fileinfo.name) > 4
- && 0 == strcmp(fileinfo.name +
+ && 0 == strcmp(fileinfo.name +
strlen(fileinfo.name) - 4,
".ibd")) {
- /* The name ends in .ibd; try opening
+ /* The name ends in .ibd; try opening
the file */
fil_load_single_table_tablespace(
dbinfo.name, fileinfo.name);
@@ -3153,7 +3151,7 @@
err = DB_ERROR;
}
}
-
+
next_datadir_item:
ret = fil_file_readdir_next_file(&err,
fil_path_to_mysql_datadir,
@@ -3183,7 +3181,7 @@
fil_print_orphaned_tablespaces(void)
/*================================*/
{
- fil_system_t* system = fil_system;
+ fil_system_t* system = fil_system;
fil_space_t* space;
mutex_enter(&(system->mutex));
@@ -3191,7 +3189,7 @@
space = UT_LIST_GET_FIRST(system->space_list);
while (space) {
- if (space->purpose == FIL_TABLESPACE && space->id != 0
+ if (space->purpose == FIL_TABLESPACE && space->id != 0
&& !space->mark) {
fputs("InnoDB: Warning: tablespace ", stderr);
ut_print_filename(stderr, space->name);
@@ -3202,7 +3200,7 @@
space = UT_LIST_GET_NEXT(space_list, space);
}
- mutex_exit(&(system->mutex));
+ mutex_exit(&(system->mutex));
}
/***********************************************************************
@@ -3326,7 +3324,7 @@
0 == strcmp(namespace->name, path));
if (space && space == namespace) {
/* Found */
-
+
if (mark_space) {
space->mark = TRUE;
}
@@ -3338,16 +3336,16 @@
}
if (!print_error_if_does_not_exist) {
-
+
mem_free(path);
mutex_exit(&(system->mutex));
-
+
return(FALSE);
}
if (space == NULL) {
if (namespace == NULL) {
- ut_print_timestamp(stderr);
+ ut_print_timestamp(stderr);
fputs(" InnoDB: Error: table ", stderr);
ut_print_filename(stderr, name);
fprintf(stderr, "\n"
@@ -3359,7 +3357,7 @@
"InnoDB: table still exists in the InnoDB internal data dictionary.\n",
(ulong) id);
} else {
- ut_print_timestamp(stderr);
+ ut_print_timestamp(stderr);
fputs(" InnoDB: Error: table ", stderr);
ut_print_filename(stderr, name);
fprintf(stderr, "\n"
@@ -3440,7 +3438,7 @@
0 == strcmp(namespace->name, path));
if (namespace) {
id = namespace->id;
- }
+ }
mem_free(path);
@@ -3489,11 +3487,11 @@
*actual_size = space->size;
- mutex_exit(&(system->mutex));
+ mutex_exit(&(system->mutex));
return(TRUE);
}
-
+
node = UT_LIST_GET_LAST(space->chain);
fil_node_prepare_for_io(node, system, space);
@@ -3517,7 +3515,7 @@
/ (4096 * ((1024 * 1024) / UNIV_PAGE_SIZE));
offset_low = ((start_page_no - file_start_page_no)
% (4096 * ((1024 * 1024) / UNIV_PAGE_SIZE)))
- * UNIV_PAGE_SIZE;
+ * UNIV_PAGE_SIZE;
#ifdef UNIV_HOTBACKUP
success = os_file_write(node->name, node->handle, buf,
offset_low, offset_high,
@@ -3537,7 +3535,7 @@
} else {
/* Let us measure the size of the file to determine
how much we were able to extend it */
-
+
n_pages = ((ulint)
(os_file_get_size_as_iblonglong(node->handle)
/ UNIV_PAGE_SIZE)) - node->size;
@@ -3570,9 +3568,9 @@
#endif /* !UNIV_HOTBACKUP */
/*
- printf("Extended %s to %lu, actual size %lu pages\n", space->name,
- size_after_extend, *actual_size); */
- mutex_exit(&(system->mutex));
+ printf("Extended %s to %lu, actual size %lu pages\n", space->name,
+ size_after_extend, *actual_size); */
+ mutex_exit(&(system->mutex));
fil_flush(space_id);
@@ -3590,7 +3588,7 @@
fil_extend_tablespaces_to_stored_len(void)
/*======================================*/
{
- fil_system_t* system = fil_system;
+ fil_system_t* system = fil_system;
fil_space_t* space;
byte* buf;
ulint actual_size;
@@ -3605,11 +3603,11 @@
space = UT_LIST_GET_FIRST(system->space_list);
while (space) {
- ut_a(space->purpose == FIL_TABLESPACE);
+ ut_a(space->purpose == FIL_TABLESPACE);
mutex_exit(&(system->mutex)); /* no need to protect with a
- mutex, because this is a single-
- threaded operation */
+ mutex, because this is a
+ single-threaded operation */
error = fil_read(TRUE, space->id, 0, 0, UNIV_PAGE_SIZE, buf,
NULL);
ut_a(error == DB_SUCCESS);
@@ -3625,7 +3623,7 @@
"InnoDB: size after extension %lu pages\n"
"InnoDB: Check that you have free disk space and retry!\n", space->name,
size_in_header, actual_size);
- exit(1);
+ exit(1);
}
mutex_enter(&(system->mutex));
@@ -3670,7 +3668,7 @@
space->n_reserved_extents += n_to_reserve;
success = TRUE;
}
-
+
mutex_exit(&(system->mutex));
return(success);
@@ -3696,9 +3694,9 @@
ut_a(space);
ut_a(space->n_reserved_extents >= n_reserved);
-
+
space->n_reserved_extents -= n_reserved;
-
+
mutex_exit(&(system->mutex));
}
@@ -3720,11 +3718,11 @@
mutex_enter(&(system->mutex));
HASH_SEARCH(hash, system->spaces, id, space, space->id == id);
-
+
ut_a(space);
n = space->n_reserved_extents;
-
+
mutex_exit(&(system->mutex));
return(n);
@@ -3751,7 +3749,7 @@
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(system->mutex)));
#endif /* UNIV_SYNC_DEBUG */
-
+
if (system->n_open > system->max_n_open + 5) {
ut_print_timestamp(stderr);
fprintf(stderr,
@@ -3768,7 +3766,7 @@
}
if (node->n_pending == 0 && space->purpose == FIL_TABLESPACE
- && space->id != 0) {
+ && space->id != 0) {
/* The node is in the LRU list, remove it */
ut_a(UT_LIST_GET_LEN(system->LRU) > 0);
@@ -3799,7 +3797,7 @@
#endif /* UNIV_SYNC_DEBUG */
ut_a(node->n_pending > 0);
-
+
node->n_pending--;
if (type == OS_FILE_WRITE) {
@@ -3814,7 +3812,7 @@
node->space);
}
}
-
+
if (node->n_pending == 0 && node->space->purpose == FIL_TABLESPACE
&& node->space->id != 0) {
/* The node must be put back to the LRU list */
@@ -3889,13 +3887,13 @@
ibool ret;
ulint is_log;
ulint wake_later;
-
+
is_log = type & OS_FILE_LOG;
type = type & ~OS_FILE_LOG;
wake_later = type & OS_AIO_SIMULATED_WAKE_LATER;
type = type & ~OS_AIO_SIMULATED_WAKE_LATER;
-
+
ut_ad(byte_offset < UNIV_PAGE_SIZE);
ut_ad(buf);
ut_ad(len > 0);
@@ -3921,17 +3919,17 @@
mode = OS_AIO_NORMAL;
}
- if (type == OS_FILE_READ) {
- srv_data_read+= len;
- } else if (type == OS_FILE_WRITE) {
- srv_data_written+= len;
- }
+ if (type == OS_FILE_READ) {
+ srv_data_read+= len;
+ } else if (type == OS_FILE_WRITE) {
+ srv_data_written+= len;
+ }
/* Reserve the fil_system mutex and make sure that we can open at
least one file while holding it, if the file is not already open */
fil_mutex_enter_and_prepare_for_io(space_id);
-
+
HASH_SEARCH(hash, system->spaces, space_id, space,
space->id == space_id);
if (!space) {
@@ -3955,7 +3953,7 @@
if (node == NULL) {
fil_report_invalid_page_access(block_offset, space_id,
space->name, byte_offset, len, type);
-
+
ut_error;
}
@@ -3973,15 +3971,15 @@
block_offset -= node->size;
node = UT_LIST_GET_NEXT(chain, node);
}
- }
-
+ }
+
/* Open file if closed */
fil_node_prepare_for_io(node, system, space);
/* Check that at least the start offset is within the bounds of a
single-table tablespace */
if (space->purpose == FIL_TABLESPACE && space->id != 0
- && node->size <= block_offset) {
+ && node->size <= block_offset) {
fil_report_invalid_page_access(block_offset, space_id,
space->name, byte_offset, len, type);
@@ -3999,7 +3997,7 @@
+ byte_offset;
ut_a(node->size - block_offset >=
- (byte_offset + len + (UNIV_PAGE_SIZE - 1)) / UNIV_PAGE_SIZE);
+ (byte_offset + len + (UNIV_PAGE_SIZE - 1)) / UNIV_PAGE_SIZE);
/* Do aio */
@@ -4025,7 +4023,7 @@
if (mode == OS_AIO_SYNC) {
/* The i/o operation is already completed when we return from
os_aio: */
-
+
mutex_enter(&(system->mutex));
fil_node_complete_io(node, system, type);
@@ -4104,21 +4102,21 @@
fil_aio_wait(
/*=========*/
ulint segment) /* in: the number of the segment in the aio
- array to wait for */
+ array to wait for */
{
fil_system_t* system = fil_system;
- ibool ret;
+ ibool ret;
fil_node_t* fil_node;
void* message;
ulint type;
-
+
ut_ad(fil_validate());
if (os_aio_use_native_aio) {
srv_set_io_thread_op_info(segment, "native aio handle");
#ifdef WIN_ASYNC_IO
ret = os_aio_windows_handle(segment, 0, &fil_node,
- &message, &type);
+ &message, &type);
#elif defined(POSIX_ASYNC_IO)
ret = os_aio_posix_handle(segment, &fil_node, &message);
#else
@@ -4129,9 +4127,9 @@
srv_set_io_thread_op_info(segment, "simulated aio handle");
ret = os_aio_simulated_handle(segment, &fil_node,
- &message, &type);
+ &message, &type);
}
-
+
ut_a(ret);
srv_set_io_thread_op_info(segment, "complete io for fil node");
@@ -4176,7 +4174,7 @@
ib_longlong old_mod_counter;
mutex_enter(&(system->mutex));
-
+
HASH_SEARCH(hash, system->spaces, space_id, space,
space->id == space_id);
if (!space || space->is_being_deleted) {
@@ -4209,7 +4207,7 @@
goto skip_flush;
}
#endif
-retry:
+retry:
if (node->n_pending_flushes > 0) {
/* We want to avoid calling os_file_flush() on
the file twice at the same time, because we do
@@ -4239,7 +4237,7 @@
/* fprintf(stderr, "Flushing to file %s\n",
node->name); */
- os_file_flush(file);
+ os_file_flush(file);
mutex_enter(&(system->mutex));
@@ -4249,7 +4247,7 @@
node->flush_counter = old_mod_counter;
if (space->is_in_unflushed_spaces
- && fil_space_is_flushed(space)) {
+ && fil_space_is_flushed(space)) {
space->is_in_unflushed_spaces = FALSE;
@@ -4267,7 +4265,7 @@
}
node = UT_LIST_GET_NEXT(chain, node);
- }
+ }
space->n_pending_flushes--;
@@ -4293,8 +4291,8 @@
while (space) {
if (space->purpose == purpose && !space->is_being_deleted) {
- space->n_pending_flushes++; /* prevent dropping of the
- space while we are
+ space->n_pending_flushes++; /* prevent dropping of
+ the space while we are
flushing */
mutex_exit(&(system->mutex));
@@ -4306,7 +4304,7 @@
}
space = UT_LIST_GET_NEXT(unflushed_spaces, space);
}
-
+
mutex_exit(&(system->mutex));
}
@@ -4317,13 +4315,13 @@
fil_validate(void)
/*==============*/
/* out: TRUE if ok */
-{
+{
fil_system_t* system = fil_system;
fil_space_t* space;
fil_node_t* fil_node;
ulint n_open = 0;
ulint i;
-
+
mutex_enter(&(system->mutex));
/* Look for spaces in the hash table */
@@ -4331,9 +4329,9 @@
for (i = 0; i < hash_get_n_cells(system->spaces); i++) {
space = HASH_GET_FIRST(system->spaces, i);
-
+
while (space != NULL) {
- UT_LIST_VALIDATE(chain, fil_node_t, space->chain);
+ UT_LIST_VALIDATE(chain, fil_node_t, space->chain);
fil_node = UT_LIST_GET_FIRST(space->chain);
@@ -4365,7 +4363,7 @@
fil_node = UT_LIST_GET_NEXT(LRU, fil_node);
}
-
+
mutex_exit(&(system->mutex));
return(TRUE);
@@ -4408,13 +4406,13 @@
void
fil_page_set_type(
/*==============*/
- byte* page, /* in: file page */
+ byte* page, /* in: file page */
ulint type) /* in: type */
{
ut_ad(page);
mach_write_to_2(page + FIL_PAGE_TYPE, type);
-}
+}
/*************************************************************************
Gets the file page type. */
@@ -4424,7 +4422,7 @@
/*==============*/
/* out: type; NOTE that if the type has not been
written to page, the return value not defined */
- byte* page) /* in: file page */
+ byte* page) /* in: file page */
{
ut_ad(page);
--- 1.25.2.1/innobase/fsp/fsp0fsp.c 2006-08-29 18:58:59 +04:00
+++ 1.29/storage/innobase/fsp/fsp0fsp.c 2006-08-29 18:58:59 +04:00
@@ -33,9 +33,9 @@
/* The data structures in files are defined just as byte strings in C */
typedef byte fsp_header_t;
-typedef byte xdes_t;
+typedef byte xdes_t;
-/* SPACE HEADER
+/* SPACE HEADER
============
File space header data structure: this data structure is contained in the
@@ -92,7 +92,7 @@
#define FSP_FREE_ADD 4 /* this many free extents are added
to the free list from above
FSP_FREE_LIMIT at a time */
-
+
/* FILE SEGMENT INODE
==================
@@ -142,7 +142,7 @@
single page */
#define FSEG_MAGIC_N_VALUE 97937874
-
+
#define FSEG_FILLFACTOR 8 /* If this value is x, then if
the number of unused but reserved
pages in a segment is less than
@@ -152,7 +152,7 @@
be added to the segment in
fseg_alloc_free_page. Otherwise, we
use unused pages of the segment. */
-
+
#define FSEG_FRAG_LIMIT FSEG_FRAG_ARR_N_SLOTS
/* If the segment has >= this many
used pages, it may be expanded by
@@ -166,7 +166,7 @@
list of the extent: at most
FSEG_FREE_LIST_MAX_LEN many */
#define FSEG_FREE_LIST_MAX_LEN 4
-
+
/* EXTENT DESCRIPTOR
=================
@@ -186,7 +186,7 @@
/* Descriptor bitmap of the pages
in the extent */
/*-------------------------------------*/
-
+
#define XDES_BITS_PER_PAGE 2 /* How many bits are there per page */
#define XDES_FREE_BIT 0 /* Index of the bit which tells if
the page is free */
@@ -208,7 +208,7 @@
/* Offset of the descriptor array on a descriptor page */
#define XDES_ARR_OFFSET (FSP_HEADER_OFFSET + FSP_HEADER_SIZE)
-
+
/**************************************************************************
Returns an extent to the free list of a space. */
static
@@ -236,7 +236,7 @@
fseg_n_reserved_pages_low(
/*======================*/
/* out: number of reserved pages */
- fseg_inode_t* header, /* in: segment inode */
+ fseg_inode_t* header, /* in: segment inode */
ulint* used, /* out: number of pages used (<= reserved) */
mtr_t* mtr); /* in: mtr handle */
/************************************************************************
@@ -290,7 +290,7 @@
/* out: the allocated page number, FIL_NULL
if no page could be allocated */
ulint space, /* in: space */
- fseg_inode_t* seg_inode, /* in: segment inode */
+ fseg_inode_t* seg_inode, /* in: segment inode */
ulint hint, /* in: hint of which page would be desirable */
byte direction, /* in: if the new page is needed because
of an index page split, and records are
@@ -354,17 +354,17 @@
MTR_MEMO_PAGE_X_FIX));
ut_ad((bit == XDES_FREE_BIT) || (bit == XDES_CLEAN_BIT));
ut_ad(offset < FSP_EXTENT_SIZE);
-
+
index = bit + XDES_BITS_PER_PAGE * offset;
byte_index = index / 8;
bit_index = index % 8;
-
+
return(ut_bit_get_nth(
mtr_read_ulint(descr + XDES_BITMAP + byte_index,
MLOG_1BYTE, mtr),
- bit_index));
-}
+ bit_index));
+}
/**************************************************************************
Sets a descriptor bit of a page. */
@@ -383,7 +383,7 @@
ulint byte_index;
ulint bit_index;
ulint descr_byte;
-
+
ut_ad(mtr_memo_contains(mtr, buf_block_align(descr),
MTR_MEMO_PAGE_X_FIX));
ut_ad((bit == XDES_FREE_BIT) || (bit == XDES_CLEAN_BIT));
@@ -400,7 +400,7 @@
mlog_write_ulint(descr + XDES_BITMAP + byte_index, descr_byte,
MLOG_1BYTE, mtr);
-}
+}
/**************************************************************************
Looks for a descriptor bit having the desired value. Starts from hint
@@ -419,7 +419,7 @@
mtr_t* mtr) /* in: mtr */
{
ulint i;
-
+
ut_ad(descr && mtr);
ut_ad(val <= TRUE);
ut_ad(hint < FSP_EXTENT_SIZE);
@@ -438,9 +438,9 @@
return(i);
}
}
-
- return(ULINT_UNDEFINED);
-}
+
+ return(ULINT_UNDEFINED);
+}
/**************************************************************************
Looks for a descriptor bit having the desired value. Scans the extent in
@@ -458,7 +458,7 @@
mtr_t* mtr) /* in: mtr */
{
ulint i;
-
+
ut_ad(descr && mtr);
ut_ad(val <= TRUE);
ut_ad(hint < FSP_EXTENT_SIZE);
@@ -477,9 +477,9 @@
return(i);
}
}
-
- return(ULINT_UNDEFINED);
-}
+
+ return(ULINT_UNDEFINED);
+}
/**************************************************************************
Returns the number of used pages in a descriptor. */
@@ -493,7 +493,7 @@
{
ulint i;
ulint count = 0;
-
+
ut_ad(descr && mtr);
ut_ad(mtr_memo_contains(mtr, buf_block_align(descr),
MTR_MEMO_PAGE_X_FIX));
@@ -503,8 +503,8 @@
}
}
- return(count);
-}
+ return(count);
+}
/**************************************************************************
Returns true if extent contains no used pages. */
@@ -558,7 +558,7 @@
ut_ad(mtr_memo_contains(mtr, buf_block_align(descr),
MTR_MEMO_PAGE_X_FIX));
- mlog_write_ulint(descr + XDES_STATE, state, MLOG_4BYTES, mtr);
+ mlog_write_ulint(descr + XDES_STATE, state, MLOG_4BYTES, mtr);
}
/**************************************************************************
@@ -575,7 +575,7 @@
ut_ad(mtr_memo_contains(mtr, buf_block_align(descr),
MTR_MEMO_PAGE_X_FIX));
- return(mtr_read_ulint(descr + XDES_STATE, MLOG_4BYTES, mtr));
+ return(mtr_read_ulint(descr + XDES_STATE, MLOG_4BYTES, mtr));
}
/**************************************************************************
@@ -599,7 +599,7 @@
}
xdes_set_state(descr, XDES_FREE, mtr);
-}
+}
/************************************************************************
Calculates the page where the descriptor of a page resides. */
@@ -610,8 +610,10 @@
/* out: descriptor page offset */
ulint offset) /* in: page offset */
{
- ut_ad(UNIV_PAGE_SIZE > XDES_ARR_OFFSET
- + (XDES_DESCRIBED_PER_PAGE / FSP_EXTENT_SIZE) * XDES_SIZE);
+#if UNIV_PAGE_SIZE <= XDES_ARR_OFFSET \
+ + (XDES_DESCRIBED_PER_PAGE / FSP_EXTENT_SIZE) * XDES_SIZE
+# error
+#endif
return(ut_2pow_round(offset, XDES_DESCRIBED_PER_PAGE));
}
@@ -644,7 +646,7 @@
space or if offset > free limit */
fsp_header_t* sp_header,/* in: space header, x-latched */
ulint space, /* in: space id */
- ulint offset, /* in: page offset;
+ ulint offset, /* in: page offset;
if equal to the free limit,
we try to add new extents to
the space free list */
@@ -687,10 +689,10 @@
#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(descr_page, SYNC_FSP_PAGE);
#endif /* UNIV_SYNC_DEBUG */
- }
+ }
return(descr_page + XDES_ARR_OFFSET
- + XDES_SIZE * xdes_calc_descriptor_index(offset));
+ + XDES_SIZE * xdes_calc_descriptor_index(offset));
}
/************************************************************************
@@ -718,7 +720,7 @@
+ buf_page_get(space, 0, RW_X_LATCH, mtr);
#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(sp_header, SYNC_FSP_PAGE);
-#endif /* UNIV_SYNC_DEBUG */
+#endif /* UNIV_SYNC_DEBUG */
return(xdes_get_descriptor_with_space_hdr(sp_header, space, offset,
mtr));
}
@@ -789,13 +791,13 @@
static
void
fsp_init_file_page_low(
-/*=====================*/
+/*===================*/
byte* ptr) /* in: pointer to a page */
{
page_t* page;
page = buf_frame_align(ptr);
- buf_block_align(page)->check_index_page_at_flush = FALSE;
+ buf_block_align(page)->check_index_page_at_flush = FALSE;
#ifdef UNIV_BASIC_LOG_DEBUG
memset(page, 0xff, UNIV_PAGE_SIZE);
@@ -807,7 +809,6 @@
/***************************************************************
Inits a file page whose prior contents should be ignored. */
-
static
void
fsp_init_file_page(
@@ -816,10 +817,10 @@
mtr_t* mtr) /* in: mtr */
{
fsp_init_file_page_low(page);
-
+
mlog_write_initial_log_record(page, MLOG_INIT_FILE_PAGE, mtr);
}
-
+
/***************************************************************
Parses a redo log record of a file page init. */
@@ -836,7 +837,7 @@
if (page) {
fsp_init_file_page_low(page);
}
-
+
return(ptr);
}
@@ -872,11 +873,11 @@
/*============*/
ulint space, /* in: space id */
ulint size, /* in: current size in blocks */
- mtr_t* mtr) /* in: mini-transaction handle */
+ mtr_t* mtr) /* in: mini-transaction handle */
{
fsp_header_t* header;
page_t* page;
-
+
ut_ad(mtr);
mtr_x_lock(fil_space_get_latch(space), mtr);
@@ -891,22 +892,26 @@
fsp_init_file_page(page, mtr);
+ mlog_write_ulint(page + FIL_PAGE_TYPE, FIL_PAGE_TYPE_FSP_HDR,
+ MLOG_2BYTES, mtr);
+
header = FSP_HEADER_OFFSET + page;
mlog_write_ulint(header + FSP_SPACE_ID, space, MLOG_4BYTES, mtr);
+ mlog_write_ulint(header + FSP_NOT_USED, 0, MLOG_4BYTES, mtr);
+
+ mlog_write_ulint(header + FSP_SIZE, size, MLOG_4BYTES, mtr);
+ mlog_write_ulint(header + FSP_FREE_LIMIT, 0, MLOG_4BYTES, mtr);
+ mlog_write_ulint(header + FSP_LOWEST_NO_WRITE, 0, MLOG_4BYTES, mtr);
+ mlog_write_ulint(header + FSP_FRAG_N_USED, 0, MLOG_4BYTES, mtr);
- mlog_write_ulint(header + FSP_SIZE, size, MLOG_4BYTES, mtr);
- mlog_write_ulint(header + FSP_FREE_LIMIT, 0, MLOG_4BYTES, mtr);
- mlog_write_ulint(header + FSP_LOWEST_NO_WRITE, 0, MLOG_4BYTES, mtr);
- mlog_write_ulint(header + FSP_FRAG_N_USED, 0, MLOG_4BYTES, mtr);
-
flst_init(header + FSP_FREE, mtr);
flst_init(header + FSP_FREE_FRAG, mtr);
flst_init(header + FSP_FULL_FRAG, mtr);
flst_init(header + FSP_SEG_INODES_FULL, mtr);
flst_init(header + FSP_SEG_INODES_FREE, mtr);
- mlog_write_dulint(header + FSP_SEG_ID, ut_dulint_create(0, 1), mtr);
+ mlog_write_dulint(header + FSP_SEG_ID, ut_dulint_create(0, 1), mtr);
if (space == 0) {
fsp_fill_free_list(FALSE, space, header, mtr);
btr_create(DICT_CLUSTERED | DICT_UNIVERSAL | DICT_IBUF, space,
@@ -933,10 +938,10 @@
id = mach_read_from_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
if (id != fsp_id) {
- fprintf(stderr,
+ fprintf(stderr,
"InnoDB: Error: space id in fsp header %lu, but in the page header %lu\n",
- (ulong) fsp_id,
- (ulong) id);
+ (ulong) fsp_id, (ulong) id);
+
return(ULINT_UNDEFINED);
}
@@ -951,21 +956,21 @@
/*================*/
ulint space, /* in: space id */
ulint size_inc,/* in: size increment in pages */
- mtr_t* mtr) /* in: mini-transaction handle */
+ mtr_t* mtr) /* in: mini-transaction handle */
{
fsp_header_t* header;
ulint size;
-
+
ut_ad(mtr);
- mtr_x_lock(fil_space_get_latch(space), mtr);
+ mtr_x_lock(fil_space_get_latch(space), mtr);
header = fsp_get_space_header(space, mtr);
size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, mtr);
mlog_write_ulint(header + FSP_SIZE, size + size_inc, MLOG_4BYTES,
- mtr);
+ mtr);
}
/**************************************************************************
@@ -985,17 +990,17 @@
mtr_t mtr;
ut_a(space == 0); /* We have only one log_fsp_current_... variable */
-
+
mtr_start(&mtr);
- mtr_x_lock(fil_space_get_latch(space), &mtr);
+ mtr_x_lock(fil_space_get_latch(space), &mtr);
header = fsp_get_space_header(space, &mtr);
limit = mtr_read_ulint(header + FSP_FREE_LIMIT, MLOG_4BYTES, &mtr);
limit = limit / ((1024 * 1024) / UNIV_PAGE_SIZE);
-
+
log_fsp_current_free_limit_set_and_checkpoint(limit);
mtr_commit(&mtr);
@@ -1019,10 +1024,10 @@
mtr_t mtr;
ut_a(space == 0); /* We have only one log_fsp_current_... variable */
-
+
mtr_start(&mtr);
- mtr_x_lock(fil_space_get_latch(space), &mtr);
+ mtr_x_lock(fil_space_get_latch(space), &mtr);
header = fsp_get_space_header(space, &mtr);
@@ -1053,14 +1058,14 @@
ut_a(space != 0);
size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, mtr);
-
+
ut_a(page_no >= size);
success = fil_extend_space_to_desired_size(&actual_size, space,
page_no + 1);
/* actual_size now has the space size in pages; it may be less than
we wanted if we ran out of disk space */
-
+
mlog_write_ulint(header + FSP_SIZE, actual_size, MLOG_4BYTES, mtr);
return(success);
@@ -1116,10 +1121,10 @@
size_increase = SRV_AUTO_EXTEND_INCREMENT;
}
} else {
- if (space == 0) {
+ if (space == 0) {
size_increase = SRV_AUTO_EXTEND_INCREMENT;
} else {
- /* We extend single-table tablespaces first one extent
+ /* We extend single-table tablespaces first one extent
at a time, but for bigger tablespaces more. It is not
enough to extend always by one extent, because some
extents are frag page extents. */
@@ -1135,14 +1140,14 @@
*actual_increase = new_size - old_size;
- return(FALSE);
+ return(FALSE);
}
size = FSP_EXTENT_SIZE;
}
if (size < 32 * FSP_EXTENT_SIZE) {
- size_increase = FSP_EXTENT_SIZE;
+ size_increase = FSP_EXTENT_SIZE;
} else {
/* Below in fsp_fill_free_list() we assume
that we add at most FSP_FREE_ADD extents at
@@ -1151,18 +1156,18 @@
}
}
}
-
+
if (size_increase == 0) {
return(TRUE);
}
-
+
success = fil_extend_space_to_desired_size(&actual_size, space,
size + size_increase);
/* We ignore any fragments of a full megabyte when storing the size
to the space header */
- mlog_write_ulint(header + FSP_SIZE,
+ mlog_write_ulint(header + FSP_SIZE,
ut_calc_align_down(actual_size, (1024 * 1024) / UNIV_PAGE_SIZE),
MLOG_4BYTES, mtr);
new_size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, mtr);
@@ -1192,7 +1197,7 @@
ulint limit;
ulint size;
xdes_t* descr;
- ulint count = 0;
+ ulint count = 0;
ulint frag_n_used;
page_t* descr_page;
page_t* ibuf_page;
@@ -1201,7 +1206,7 @@
mtr_t ibuf_mtr;
ut_ad(header && mtr);
-
+
/* Check if we can fill free list from above the free list limit */
size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, mtr);
limit = mtr_read_ulint(header + FSP_FREE_LIMIT, MLOG_4BYTES, mtr);
@@ -1223,17 +1228,17 @@
}
i = limit;
-
+
while ((init_space && i < 1)
- || ((i + FSP_EXTENT_SIZE <= size) && (count < FSP_FREE_ADD))) {
+ || ((i + FSP_EXTENT_SIZE <= size) && (count < FSP_FREE_ADD))) {
mlog_write_ulint(header + FSP_FREE_LIMIT, i + FSP_EXTENT_SIZE,
- MLOG_4BYTES, mtr);
+ MLOG_4BYTES, mtr);
/* Update the free limit info in the log system and make
a checkpoint */
if (space == 0) {
- log_fsp_current_free_limit_set_and_checkpoint(
+ log_fsp_current_free_limit_set_and_checkpoint(
(i + FSP_EXTENT_SIZE)
/ ((1024 * 1024) / UNIV_PAGE_SIZE));
}
@@ -1252,13 +1257,15 @@
SYNC_FSP_PAGE);
#endif /* UNIV_SYNC_DEBUG */
fsp_init_file_page(descr_page, mtr);
+ mlog_write_ulint(descr_page + FIL_PAGE_TYPE,
+ FIL_PAGE_TYPE_XDES, MLOG_2BYTES, mtr);
}
/* Initialize the ibuf bitmap page in a separate
mini-transaction because it is low in the latching
order, and we must be able to release its latch
before returning from the fsp routine */
-
+
mtr_start(&ibuf_mtr);
ibuf_page = buf_page_create(space,
@@ -1279,7 +1286,9 @@
mtr);
xdes_init(descr, mtr);
- ut_ad(XDES_DESCRIBED_PER_PAGE % FSP_EXTENT_SIZE == 0);
+#if XDES_DESCRIBED_PER_PAGE % FSP_EXTENT_SIZE
+# error "XDES_DESCRIBED_PER_PAGE % FSP_EXTENT_SIZE != 0"
+#endif
if (0 == i % XDES_DESCRIBED_PER_PAGE) {
@@ -1289,24 +1298,24 @@
xdes_set_bit(descr, XDES_FREE_BIT, 0, FALSE, mtr);
xdes_set_bit(descr, XDES_FREE_BIT,
- FSP_IBUF_BITMAP_OFFSET, FALSE, mtr);
+ FSP_IBUF_BITMAP_OFFSET, FALSE, mtr);
xdes_set_state(descr, XDES_FREE_FRAG, mtr);
flst_add_last(header + FSP_FREE_FRAG,
- descr + XDES_FLST_NODE, mtr);
+ descr + XDES_FLST_NODE, mtr);
frag_n_used = mtr_read_ulint(header + FSP_FRAG_N_USED,
- MLOG_4BYTES, mtr);
+ MLOG_4BYTES, mtr);
mlog_write_ulint(header + FSP_FRAG_N_USED,
- frag_n_used + 2, MLOG_4BYTES, mtr);
+ frag_n_used + 2, MLOG_4BYTES, mtr);
} else {
flst_add_last(header + FSP_FREE,
- descr + XDES_FLST_NODE, mtr);
+ descr + XDES_FLST_NODE, mtr);
count++;
}
i += FSP_EXTENT_SIZE;
}
-}
+}
/**************************************************************************
Allocates a new free extent. */
@@ -1325,7 +1334,7 @@
fsp_header_t* header;
fil_addr_t first;
xdes_t* descr;
-
+
ut_ad(mtr);
header = fsp_get_space_header(space, mtr);
@@ -1334,7 +1343,7 @@
if (descr && (xdes_get_state(descr, mtr) == XDES_FREE)) {
/* Ok, we can take this extent */
- } else {
+ } else {
/* Take the first extent in the free list */
first = flst_get_first(header + FSP_FREE, mtr);
@@ -1348,7 +1357,7 @@
return(NULL); /* No free extents left */
}
-
+
descr = xdes_lst_get_descriptor(space, first, mtr);
}
@@ -1378,7 +1387,7 @@
ulint page_no;
ulint space_size;
ibool success;
-
+
ut_ad(mtr);
header = fsp_get_space_header(space, mtr);
@@ -1399,7 +1408,7 @@
extent containing a descriptor page is added to the
FREE_FRAG list. But we will allocate our page from the
the free extent anyway. */
-
+
descr = fsp_alloc_free_extent(space, hint, mtr);
if (descr == NULL) {
@@ -1436,22 +1445,22 @@
space_size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, mtr);
if (space_size <= page_no) {
- /* It must be that we are extending a single-table tablespace
+ /* It must be that we are extending a single-table tablespace
whose size is still < 64 pages */
ut_a(space != 0);
if (page_no >= FSP_EXTENT_SIZE) {
- fprintf(stderr,
+ fprintf(stderr,
"InnoDB: Error: trying to extend a single-table tablespace %lu\n"
"InnoDB: by single page(s) though the space size %lu. Page no %lu.\n",
(ulong) space, (ulong) space_size, (ulong) page_no);
return(FIL_NULL);
}
success = fsp_try_extend_data_file_with_pages(space, page_no,
- header, mtr);
+ header, mtr);
if (!success) {
/* No disk space left */
- return(FIL_NULL);
+ return(FIL_NULL);
}
}
@@ -1468,7 +1477,7 @@
flst_remove(header + FSP_FREE_FRAG, descr + XDES_FLST_NODE,
mtr);
xdes_set_state(descr, XDES_FULL_FRAG, mtr);
-
+
flst_add_last(header + FSP_FULL_FRAG, descr + XDES_FLST_NODE,
mtr);
mlog_write_ulint(header + FSP_FRAG_N_USED,
@@ -1479,17 +1488,17 @@
/* Initialize the allocated page to the buffer pool, so that it can
be obtained immediately with buf_page_get without need for a disk
read. */
-
+
buf_page_create(space, page_no, mtr);
- page = buf_page_get(space, page_no, RW_X_LATCH, mtr);
+ page = buf_page_get(space, page_no, RW_X_LATCH, mtr);
#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(page, SYNC_FSP_PAGE);
#endif /* UNIV_SYNC_DEBUG */
/* Prior contents of the page should be ignored */
fsp_init_file_page(page, mtr);
-
+
return(page_no);
}
@@ -1507,7 +1516,7 @@
xdes_t* descr;
ulint state;
ulint frag_n_used;
-
+
ut_ad(mtr);
/* fprintf(stderr, "Freeing page %lu in space %lu\n", page, space); */
@@ -1517,7 +1526,7 @@
descr = xdes_get_descriptor_with_space_hdr(header, space, page, mtr);
state = xdes_get_state(descr, mtr);
-
+
if (state != XDES_FREE_FRAG && state != XDES_FULL_FRAG) {
fprintf(stderr,
"InnoDB: Error: File space extent descriptor of page %lu has state %lu\n",
@@ -1526,7 +1535,7 @@
fputs("InnoDB: Dump of descriptor: ", stderr);
ut_print_buf(stderr, ((byte*)descr) - 50, 200);
putc('\n', stderr);
-
+
if (state == XDES_FREE) {
/* We put here some fault tolerance: if the page
is already free, return without doing anything! */
@@ -1572,11 +1581,11 @@
}
if (xdes_is_free(descr, mtr)) {
- /* The extent has become free: move it to another list */
+ /* The extent has become free: move it to another list */
flst_remove(header + FSP_FREE_FRAG, descr + XDES_FLST_NODE,
mtr);
fsp_free_extent(space, page, mtr);
- }
+ }
}
/**************************************************************************
@@ -1591,7 +1600,7 @@
{
fsp_header_t* header;
xdes_t* descr;
-
+
ut_ad(mtr);
header = fsp_get_space_header(space, mtr);
@@ -1629,7 +1638,7 @@
}
/**************************************************************************
-Looks for a used segment inode on a segment inode page. */
+Looks for a used segment inode on a segment inode page. */
static
ulint
fsp_seg_inode_page_find_used(
@@ -1649,7 +1658,7 @@
if (ut_dulint_cmp(mach_read_from_8(inode + FSEG_ID),
ut_dulint_zero) != 0) {
/* This is used */
-
+
return(i);
}
}
@@ -1658,7 +1667,7 @@
}
/**************************************************************************
-Looks for an unused segment inode on a segment inode page. */
+Looks for an unused segment inode on a segment inode page. */
static
ulint
fsp_seg_inode_page_find_free(
@@ -1679,7 +1688,7 @@
if (ut_dulint_cmp(mach_read_from_8(inode + FSEG_ID),
ut_dulint_zero) == 0) {
/* This is unused */
-
+
return(i);
}
}
@@ -1704,7 +1713,7 @@
ulint i;
space = buf_frame_get_space_id(space_header);
-
+
page_no = fsp_alloc_free_page(space, 0, mtr);
if (page_no == FIL_NULL) {
@@ -1712,11 +1721,12 @@
return(FALSE);
}
- page = buf_page_get(space, page_no, RW_X_LATCH, mtr);
+ page = buf_page_get(space, page_no, RW_X_LATCH, mtr);
buf_block_align(page)->check_index_page_at_flush = FALSE;
- fil_page_set_type(page, FIL_PAGE_INODE);
+ mlog_write_ulint(page + FIL_PAGE_TYPE, FIL_PAGE_INODE,
+ MLOG_2BYTES, mtr);
#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(page, SYNC_FSP_PAGE);
#endif /* UNIV_SYNC_DEBUG */
@@ -1749,7 +1759,7 @@
fseg_inode_t* inode;
ibool success;
ulint n;
-
+
if (flst_get_len(space_header + FSP_SEG_INODES_FREE, mtr) == 0) {
/* Allocate a new segment inode page */
@@ -1776,7 +1786,7 @@
inode = fsp_seg_inode_page_get_nth_inode(page, n, mtr);
if (ULINT_UNDEFINED == fsp_seg_inode_page_find_free(page, n + 1,
- mtr)) {
+ mtr)) {
/* There are no other unused headers left on the page: move it
to another list */
@@ -1787,7 +1797,7 @@
page + FSEG_INODE_PAGE_NODE, mtr);
}
- return(inode);
+ return(inode);
}
/**************************************************************************
@@ -1802,7 +1812,7 @@
{
page_t* page;
fsp_header_t* space_header;
-
+
page = buf_frame_align(inode);
space_header = fsp_get_space_header(space, mtr);
@@ -1820,9 +1830,9 @@
page + FSEG_INODE_PAGE_NODE, mtr);
}
- mlog_write_dulint(inode + FSEG_ID, ut_dulint_zero, mtr);
- mlog_write_ulint(inode + FSEG_MAGIC_N, 0, MLOG_4BYTES, mtr);
-
+ mlog_write_dulint(inode + FSEG_ID, ut_dulint_zero, mtr);
+ mlog_write_ulint(inode + FSEG_MAGIC_N, 0, MLOG_4BYTES, mtr);
+
if (ULINT_UNDEFINED == fsp_seg_inode_page_find_used(page, mtr)) {
/* There are no other used headers left on the page: free it */
@@ -1849,10 +1859,10 @@
inode_addr.page = mach_read_from_4(header + FSEG_HDR_PAGE_NO);
inode_addr.boffset = mach_read_from_2(header + FSEG_HDR_OFFSET);
-
+
inode = fut_get_ptr(mach_read_from_4(header + FSEG_HDR_SPACE),
inode_addr, RW_X_LATCH, mtr);
-
+
ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE);
return(inode);
@@ -1865,7 +1875,7 @@
fseg_get_nth_frag_page_no(
/*======================*/
/* out: page number, FIL_NULL if not in use */
- fseg_inode_t* inode, /* in: segment inode */
+ fseg_inode_t* inode, /* in: segment inode */
ulint n, /* in: slot index */
mtr_t* mtr __attribute__((unused))) /* in: mtr handle */
{
@@ -1883,7 +1893,7 @@
void
fseg_set_nth_frag_page_no(
/*======================*/
- fseg_inode_t* inode, /* in: segment inode */
+ fseg_inode_t* inode, /* in: segment inode */
ulint n, /* in: slot index */
ulint page_no,/* in: page number to set */
mtr_t* mtr) /* in: mtr handle */
@@ -1905,7 +1915,7 @@
/*==========================*/
/* out: slot index; ULINT_UNDEFINED if none
found */
- fseg_inode_t* inode, /* in: segment inode */
+ fseg_inode_t* inode, /* in: segment inode */
mtr_t* mtr) /* in: mtr handle */
{
ulint i;
@@ -1933,7 +1943,7 @@
| Thread |
|---|
| • bk commit into 5.1 tree (evgen:1.2286) | eugene | 30 Aug |