Commit 21601b51 authored by peter@mysql.com's avatar peter@mysql.com
Browse files

Merge mysql.com:/home/pz/mysql/mysql-4.0-root

into mysql.com:/home/pz/mysql/mysql-4.0
parents 46b504d8 db169310
Loading
Loading
Loading
Loading
+9 −5
Original line number Diff line number Diff line
@@ -23510,17 +23510,21 @@ will be logged in the execution order.
Updates to non-transactional tables are stored in the binary log
immediately after execution.  For transactional tables such as @code{BDB}
or @code{InnoDB} tables, all updates (@code{UPDATE}, @code{DELETE}
or @code{INSERT}) that change tables are cached until a @code{COMMIT}.
or @code{INSERT}) that change tables are cached until a @code{COMMIT} command
is sent to the server. At this point mysqld writes the whole transaction to
the binary log before the @code{COMMIT} is executed.
Every thread will, on start, allocate a buffer of @code{binlog_cache_size}
to buffer queries.  If a query is bigger than this, the thread will open
a temporary file to handle the bigger cache.  The temporary file will
a temporary file to store the transcation.  The temporary file will
be deleted when the thread ends.
The @code{max_binlog_cache_size} can be used to restrict the total size used
to cache a multi-query transaction.
The @code{max_binlog_cache_size} (default 4G) can be used to restrict
the total size used to cache a multi-query transaction.  If a transaction is
bigger than this it will fail and roll back.
If you are using the update or binary log, concurrent inserts will
not work together with @code{CREATE ... SELECT} and @code{INSERT ... SELECT}.
be converted to normal inserts when using @code{CREATE ... SELECT} and
@code{INSERT ... SELECT}.
This is to ensure that you can recreate an exact copy of your tables by
applying the log on a backup.
+11 −7
Original line number Diff line number Diff line
@@ -1060,20 +1060,24 @@ dict_create_or_check_foreign_constraint_tables(void)
            	return(DB_SUCCESS);
        }

	mutex_exit(&(dict_sys->mutex));

	trx = trx_allocate_for_mysql();
	
	trx->op_info = (char *) "creating foreign key sys tables";

	row_mysql_lock_data_dictionary(trx);

	if (table1) {
		fprintf(stderr,
		"InnoDB: dropping incompletely created SYS_FOREIGN table\n");
		row_drop_table_for_mysql((char *) "SYS_FOREIGN", trx, TRUE);
		row_drop_table_for_mysql((char *) "SYS_FOREIGN", trx);
	}

	if (table2) {
		fprintf(stderr,
	"InnoDB: dropping incompletely created SYS_FOREIGN_COLS table\n");
		row_drop_table_for_mysql((char *) "SYS_FOREIGN_COLS",trx,TRUE);
		row_drop_table_for_mysql((char *) "SYS_FOREIGN_COLS", trx);
	}

	fprintf(stderr,
@@ -1122,8 +1126,8 @@ dict_create_or_check_foreign_constraint_tables(void)
		fprintf(stderr,
		"InnoDB: dropping incompletely created SYS_FOREIGN tables\n");

		row_drop_table_for_mysql((char *) "SYS_FOREIGN", trx, TRUE);
		row_drop_table_for_mysql((char *) "SYS_FOREIGN_COLS",trx,TRUE);
		row_drop_table_for_mysql((char *) "SYS_FOREIGN", trx);
		row_drop_table_for_mysql((char *) "SYS_FOREIGN_COLS", trx);

		error = DB_MUST_GET_MORE_FILE_SPACE;
	}
@@ -1132,6 +1136,8 @@ dict_create_or_check_foreign_constraint_tables(void)
	
	trx->op_info = (char *) "";

	row_mysql_unlock_data_dictionary(trx);

  	trx_free_for_mysql(trx);

  	if (error == DB_SUCCESS) {
@@ -1139,8 +1145,6 @@ dict_create_or_check_foreign_constraint_tables(void)
		"InnoDB: Foreign key constraint system tables created\n");
	}

	mutex_exit(&(dict_sys->mutex));

	return(error);
}

+188 −31
Original line number Diff line number Diff line
@@ -30,13 +30,16 @@ Created 1/8/1996 Heikki Tuuri
dict_sys_t*	dict_sys	= NULL;	/* the dictionary system */

rw_lock_t	dict_operation_lock;	/* table create, drop, etc. reserve
					this in X-mode, implicit or backround
					this in X-mode; implicit or backround
					operations purge, rollback, foreign
					key checks reserve this in S-mode; we
					cannot trust that MySQL protects
					implicit or background operations
					from dropping a table: this is our
					mechanism */
					a table drop since MySQL does not
					know of them; therefore we need this;
					NOTE: a transaction which reserves
					this must keep book on the mode in
					trx->dict_operation_lock_mode */

#define	DICT_HEAP_SIZE		100	/* initial memory heap size when
					creating a table or index object */
@@ -182,6 +185,58 @@ dict_foreign_free(
/*==============*/
	dict_foreign_t*	foreign);	/* in, own: foreign key struct */

/************************************************************************
Checks if the database name in two table names is the same. */
static
ibool
dict_tables_have_same_db(
/*=====================*/
			/* out: TRUE if same db name */
	char*	name1,	/* in: table name in the form dbname '/' tablename */
	char*	name2)	/* in: table name in the form dbname '/' tablename */
{
	ulint	i;

	for (i = 0; i < 100000; i++) {
		if (name1[i] == '/' && name2[i] == '/') {

			return(TRUE);
		}

		if (name1[i] != name2[i]) {

			return(FALSE);
		}
	}

	ut_a(0);

	return(FALSE);
}

/************************************************************************
Return the end of table name where we have removed dbname and '/'. */
static
char*
dict_remove_db_name(
/*================*/
			/* out: table name */
	char*	name)	/* in: table name in the form dbname '/' tablename */
{
	ulint	i;

	for (i = 0; i < 100000 ; i++) {
		if (name[i] == '/') {

			return(name + i + 1);
		}
	}

	ut_a(0);

	return(NULL);
}
	
/************************************************************************
Reserves the dictionary system mutex for MySQL. */

@@ -1926,7 +1981,8 @@ dict_scan_col(

	old_ptr = ptr;
	
	while (!isspace(*ptr) && *ptr != ',' && *ptr != ')' && 	*ptr != '`') {
	while (!isspace(*ptr) && *ptr != ',' && *ptr != ')' && 	*ptr != '`'
	       && *ptr != '\0') {

		ptr++;
	}
@@ -2000,7 +2056,7 @@ dict_scan_table_name(

	old_ptr = ptr;
	
	while (!isspace(*ptr) && *ptr != '(' && *ptr != '`') {
	while (!isspace(*ptr) && *ptr != '(' && *ptr != '`' && *ptr != '\0') {
		if (*ptr == '.') {
			dot_ptr = ptr;
		}
@@ -2025,7 +2081,13 @@ dict_scan_table_name(
		ut_cpy_in_lower_case(second_table_name + i, old_ptr,
				     				ptr - old_ptr);
#else
		ut_memcpy(second_table_name + i, old_ptr, ptr - old_ptr);
		if (srv_lower_case_table_names) {
			ut_cpy_in_lower_case(second_table_name + i, old_ptr,
				     				ptr - old_ptr);
		} else {
			ut_memcpy(second_table_name + i, old_ptr,
								ptr - old_ptr);
		}
#endif
		second_table_name[i + (ptr - old_ptr)] = '\0';
	} else {
@@ -2033,7 +2095,12 @@ dict_scan_table_name(
		ut_cpy_in_lower_case(second_table_name, old_ptr,
								ptr - old_ptr);
#else
		if (srv_lower_case_table_names) {
			ut_cpy_in_lower_case(second_table_name, old_ptr,
				   			ptr - old_ptr);
		} else {
			ut_memcpy(second_table_name, old_ptr, ptr - old_ptr);
		}
#endif
		second_table_name[dot_ptr - old_ptr] = '/';
		second_table_name[ptr - old_ptr] = '\0';
@@ -2050,6 +2117,44 @@ dict_scan_table_name(
	return(ptr);
}

/*************************************************************************
Skips one 'word', like an id. For the lexical definition of 'word', see the
code below. */
static
char*
dict_skip_word(
/*===========*/
			/* out: scanned to */
	char*	ptr,	/* in: scanned to */
	ibool*	success)/* out: TRUE if success, FALSE if just spaces left in
			string */
{
	*success = FALSE;

	while (isspace(*ptr)) {
		ptr++;
	}

	if (*ptr == '\0') {

		return(ptr);
	}

	if (*ptr == '`') {
		ptr++;
	}
	
	while (!isspace(*ptr) && *ptr != ',' && *ptr != '(' && 	*ptr != '`'
	       && *ptr != '\0') {

		ptr++;
	}

	*success = TRUE;

	return(ptr);
}

/*************************************************************************
Returns the number of opening brackets '(' subtracted by the number
of closing brackets ')' between string and ptr. */
@@ -2119,7 +2224,6 @@ dict_create_foreign_constraints(
	if (table == NULL) {
		return(DB_ERROR);
	}

loop:
	ptr = dict_scan_to(ptr, (char *) "FOREIGN");

@@ -2148,7 +2252,19 @@ dict_create_foreign_constraints(
	ptr = dict_accept(ptr, (char *) "(", &success);

	if (!success) {
		goto loop;
		/* MySQL allows also an index id before the '('; we
		skip it */
		ptr = dict_skip_word(ptr, &success);

		if (!success) {
			return(DB_CANNOT_ADD_CONSTRAINT);
		}

		ptr = dict_accept(ptr, (char *) "(", &success);

		if (!success) {
			return(DB_CANNOT_ADD_CONSTRAINT);
		}
	}

	i = 0;
@@ -2223,6 +2339,7 @@ dict_create_foreign_constraints(

	if (!success) {
		dict_foreign_free(foreign);

		return(DB_CANNOT_ADD_CONSTRAINT);
	}

@@ -2236,6 +2353,7 @@ dict_create_foreign_constraints(
	
	if (!success) {
		dict_foreign_free(foreign);

		return(DB_CANNOT_ADD_CONSTRAINT);
	}

@@ -2263,14 +2381,20 @@ dict_create_foreign_constraints(
	ptr = dict_accept(ptr, "DELETE", &success);

	if (!success) {
		dict_foreign_free(foreign);
		
		return(DB_CANNOT_ADD_CONSTRAINT);
	}

	ptr = dict_accept(ptr, "RESTRICT", &success);

	if (success) {
		goto try_find_index;
	}

	ptr = dict_accept(ptr, "CASCADE", &success);

	if (success) {

		foreign->type = DICT_FOREIGN_ON_DELETE_CASCADE;

		goto try_find_index;
@@ -2279,13 +2403,19 @@ dict_create_foreign_constraints(
	ptr = dict_accept(ptr, "SET", &success);

	if (!success) {
		dict_foreign_free(foreign);
		
		goto try_find_index;
		return(DB_CANNOT_ADD_CONSTRAINT);
	}

	ptr = dict_accept(ptr, "NULL", &success);

	if (success) {
	if (!success) {
		dict_foreign_free(foreign);
		
		return(DB_CANNOT_ADD_CONSTRAINT);
	}

	for (j = 0; j < foreign->n_fields; j++) {
		if ((dict_index_get_nth_type(
				foreign->foreign_index, j)->prtype)
@@ -2295,16 +2425,25 @@ dict_create_foreign_constraints(
			if the column is not allowed to be NULL! */

			dict_foreign_free(foreign);

			return(DB_CANNOT_ADD_CONSTRAINT);
		}
	}

	foreign->type = DICT_FOREIGN_ON_DELETE_SET_NULL;
	
		goto try_find_index;
try_find_index:
	/* We check that there are no superfluous words like 'ON UPDATE ...'
	which we do not support yet. */

	ptr = dict_accept(ptr, (char *) "ON", &success);

	if (success) {
		dict_foreign_free(foreign);

		return(DB_CANNOT_ADD_CONSTRAINT);
	}
	
try_find_index:
	/* Try to find an index which contains the columns as the first fields
	and in the right order, and the types are the same as in
	foreign->foreign_index */
@@ -2351,6 +2490,7 @@ dict_create_foreign_constraints(
					referenced_table->referenced_list,
								foreign);
	}

	goto loop;
}

@@ -2849,6 +2989,14 @@ dict_update_statistics_low(
	ulint		size;
	ulint		sum_of_index_sizes	= 0;

	/* If we have set a high innodb_force_recovery level, do not calculate
	statistics, as a badly corrupted index can cause a crash in it. */

	if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {

		return;
	}

	/* Find out the sizes of the indexes and how many different values
	for the key they approximately have */

@@ -3152,6 +3300,14 @@ dict_print_info_on_foreign_keys_in_create_format(
			}
		}

		if (dict_tables_have_same_db(table->name,
					foreign->referenced_table_name)) {
			/* Do not print the database name of the referenced
			table */
			buf2 += sprintf(buf2, ") REFERENCES `%s` (",
					dict_remove_db_name(
					foreign->referenced_table_name));
		} else {
			buf2 += sprintf(buf2, ") REFERENCES `%s` (",
					foreign->referenced_table_name);
			/* Change the '/' in the table name to '.' */
@@ -3164,6 +3320,7 @@ dict_print_info_on_foreign_keys_in_create_format(
					break;
				}
			}
		}
	
		for (i = 0; i < foreign->n_fields; i++) {
		        if ((ulint)(buf2 - buf) >= len) {
+1 −0
Original line number Diff line number Diff line
@@ -334,6 +334,7 @@ extern ibool recv_no_ibuf_operations;
extern ibool		recv_needed_recovery;

extern ibool		recv_is_making_a_backup;
extern ulint		recv_max_parsed_page_no;

/* Size of the parsing buffer; it must accommodate RECV_SCAN_SIZE many
times! */ 
+27 −12
Original line number Diff line number Diff line
@@ -230,18 +230,35 @@ row_update_cascade_for_mysql(
				or set null operation */
	dict_table_t*	table);	/* in: table where we do the operation */
/*************************************************************************
Locks the data dictionary exclusively for performing a table create
operation. */
Locks the data dictionary exclusively for performing a table create or other
data dictionary modification operation. */

void
row_mysql_lock_data_dictionary(void);
/*================================*/
row_mysql_lock_data_dictionary(
/*===========================*/
	trx_t*	trx);	/* in: transaction */
/*************************************************************************
Unlocks the data dictionary exclusively lock. */
Unlocks the data dictionary exclusive lock. */

void
row_mysql_unlock_data_dictionary(void);
/*==================================*/
row_mysql_unlock_data_dictionary(
/*=============================*/
	trx_t*	trx);	/* in: transaction */
/*************************************************************************
Locks the data dictionary in shared mode from modifications, for performing
foreign key check, rollback, or other operation invisible to MySQL. */

void
row_mysql_freeze_data_dictionary(
/*=============================*/
	trx_t*	trx);	/* in: transaction */
/*************************************************************************
Unlocks the data dictionary shared lock. */

void
row_mysql_unfreeze_data_dictionary(
/*===============================*/
	trx_t*	trx);	/* in: transaction */
/*************************************************************************
Does a table creation operation for MySQL. If the name of the created
table ends to characters INNODB_MONITOR, then this also starts
@@ -312,9 +329,7 @@ row_drop_table_for_mysql(
/*=====================*/
			/* out: error code or DB_SUCCESS */
	char*	name,	/* in: table name */
	trx_t*	trx,		/* in: transaction handle */
	ibool	has_dict_mutex);/* in: TRUE if the caller already owns the
				dictionary system mutex */
	trx_t*	trx);	/* in: transaction handle */
/*************************************************************************
Drops a database for MySQL. */

Loading