Merge istruewing@bk-internal.mysql.com:/home/bk/mysql-5.0
into mysql.com:/home/mydev/mysql-5.0-bug10932 sql/mysql_priv.h: Auto merged
This commit is contained in:
commit
02f90923cf
@ -904,6 +904,7 @@ btr_search_drop_page_hash_index(
|
||||
ulint* folds;
|
||||
ulint i;
|
||||
mem_heap_t* heap;
|
||||
dict_index_t* index;
|
||||
ulint* offsets;
|
||||
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
@ -932,11 +933,16 @@ btr_search_drop_page_hash_index(
|
||||
|
||||
n_fields = block->curr_n_fields;
|
||||
n_bytes = block->curr_n_bytes;
|
||||
index = block->index;
|
||||
|
||||
ut_a(n_fields + n_bytes > 0);
|
||||
/* NOTE: The fields of block must not be accessed after
|
||||
releasing btr_search_latch, as the index page might only
|
||||
be s-latched! */
|
||||
|
||||
rw_lock_s_unlock(&btr_search_latch);
|
||||
|
||||
ut_a(n_fields + n_bytes > 0);
|
||||
|
||||
n_recs = page_get_n_recs(page);
|
||||
|
||||
/* Calculate and cache fold values into an array for fast deletion
|
||||
@ -949,14 +955,6 @@ btr_search_drop_page_hash_index(
|
||||
rec = page_get_infimum_rec(page);
|
||||
rec = page_rec_get_next(rec);
|
||||
|
||||
if (!page_rec_is_supremum(rec)) {
|
||||
ut_a(n_fields <= rec_get_n_fields(rec, block->index));
|
||||
|
||||
if (n_bytes > 0) {
|
||||
ut_a(n_fields < rec_get_n_fields(rec, block->index));
|
||||
}
|
||||
}
|
||||
|
||||
tree_id = btr_page_get_index_id(page);
|
||||
|
||||
prev_fold = 0;
|
||||
@ -964,18 +962,12 @@ btr_search_drop_page_hash_index(
|
||||
heap = NULL;
|
||||
offsets = NULL;
|
||||
|
||||
if (block->index == NULL) {
|
||||
|
||||
mem_analyze_corruption((byte*)block);
|
||||
|
||||
ut_a(block->index != NULL);
|
||||
}
|
||||
|
||||
while (!page_rec_is_supremum(rec)) {
|
||||
/* FIXME: in a mixed tree, not all records may have enough
|
||||
ordering fields: */
|
||||
offsets = rec_get_offsets(rec, block->index,
|
||||
offsets, n_fields + (n_bytes > 0), &heap);
|
||||
offsets = rec_get_offsets(rec, index, offsets,
|
||||
n_fields + (n_bytes > 0), &heap);
|
||||
ut_a(rec_offs_n_fields(offsets) == n_fields + (n_bytes > 0));
|
||||
fold = rec_fold(rec, offsets, n_fields, n_bytes, tree_id);
|
||||
|
||||
if (fold == prev_fold && prev_fold != 0) {
|
||||
|
@ -2104,8 +2104,11 @@ dict_foreign_find_index(
|
||||
dict_table_t* table, /* in: table */
|
||||
const char** columns,/* in: array of column names */
|
||||
ulint n_cols, /* in: number of columns */
|
||||
dict_index_t* types_idx)/* in: NULL or an index to whose types the
|
||||
column types must match */
|
||||
dict_index_t* types_idx, /* in: NULL or an index to whose types the
|
||||
column types must match */
|
||||
ibool check_charsets) /* in: whether to check charsets.
|
||||
only has an effect if types_idx !=
|
||||
NULL. */
|
||||
{
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
dict_index_t* index;
|
||||
@ -2135,7 +2138,8 @@ dict_foreign_find_index(
|
||||
|
||||
if (types_idx && !cmp_types_are_equal(
|
||||
dict_index_get_nth_type(index, i),
|
||||
dict_index_get_nth_type(types_idx, i))) {
|
||||
dict_index_get_nth_type(types_idx, i),
|
||||
check_charsets)) {
|
||||
|
||||
break;
|
||||
}
|
||||
@ -2212,7 +2216,8 @@ dict_foreign_add_to_cache(
|
||||
/*======================*/
|
||||
/* out: DB_SUCCESS or error code */
|
||||
dict_foreign_t* foreign, /* in, own: foreign key constraint */
|
||||
ibool check_types) /* in: TRUE=check type compatibility */
|
||||
ibool check_charsets) /* in: TRUE=check charset
|
||||
compatibility */
|
||||
{
|
||||
dict_table_t* for_table;
|
||||
dict_table_t* ref_table;
|
||||
@ -2248,16 +2253,10 @@ dict_foreign_add_to_cache(
|
||||
}
|
||||
|
||||
if (for_in_cache->referenced_table == NULL && ref_table) {
|
||||
dict_index_t* types_idx;
|
||||
if (check_types) {
|
||||
types_idx = for_in_cache->foreign_index;
|
||||
} else {
|
||||
types_idx = NULL;
|
||||
}
|
||||
index = dict_foreign_find_index(ref_table,
|
||||
(const char**) for_in_cache->referenced_col_names,
|
||||
for_in_cache->n_fields,
|
||||
types_idx);
|
||||
for_in_cache->foreign_index, check_charsets);
|
||||
|
||||
if (index == NULL) {
|
||||
dict_foreign_error_report(ef, for_in_cache,
|
||||
@ -2281,16 +2280,10 @@ dict_foreign_add_to_cache(
|
||||
}
|
||||
|
||||
if (for_in_cache->foreign_table == NULL && for_table) {
|
||||
dict_index_t* types_idx;
|
||||
if (check_types) {
|
||||
types_idx = for_in_cache->referenced_index;
|
||||
} else {
|
||||
types_idx = NULL;
|
||||
}
|
||||
index = dict_foreign_find_index(for_table,
|
||||
(const char**) for_in_cache->foreign_col_names,
|
||||
for_in_cache->n_fields,
|
||||
types_idx);
|
||||
for_in_cache->referenced_index, check_charsets);
|
||||
|
||||
if (index == NULL) {
|
||||
dict_foreign_error_report(ef, for_in_cache,
|
||||
@ -3097,7 +3090,7 @@ col_loop1:
|
||||
/* Try to find an index which contains the columns
|
||||
as the first fields and in the right order */
|
||||
|
||||
index = dict_foreign_find_index(table, column_names, i, NULL);
|
||||
index = dict_foreign_find_index(table, column_names, i, NULL, TRUE);
|
||||
|
||||
if (!index) {
|
||||
mutex_enter(&dict_foreign_err_mutex);
|
||||
@ -3362,8 +3355,7 @@ try_find_index:
|
||||
|
||||
if (referenced_table) {
|
||||
index = dict_foreign_find_index(referenced_table,
|
||||
column_names, i,
|
||||
foreign->foreign_index);
|
||||
column_names, i, foreign->foreign_index, TRUE);
|
||||
if (!index) {
|
||||
dict_foreign_free(foreign);
|
||||
mutex_enter(&dict_foreign_err_mutex);
|
||||
|
@ -1091,7 +1091,7 @@ dict_load_foreign(
|
||||
/* out: DB_SUCCESS or error code */
|
||||
const char* id, /* in: foreign constraint id as a
|
||||
null-terminated string */
|
||||
ibool check_types)/* in: TRUE=check type compatibility */
|
||||
ibool check_charsets)/* in: TRUE=check charset compatibility */
|
||||
{
|
||||
dict_foreign_t* foreign;
|
||||
dict_table_t* sys_foreign;
|
||||
@ -1204,7 +1204,7 @@ dict_load_foreign(
|
||||
a new foreign key constraint but loading one from the data
|
||||
dictionary. */
|
||||
|
||||
return(dict_foreign_add_to_cache(foreign, check_types));
|
||||
return(dict_foreign_add_to_cache(foreign, check_charsets));
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
@ -1219,7 +1219,8 @@ dict_load_foreigns(
|
||||
/*===============*/
|
||||
/* out: DB_SUCCESS or error code */
|
||||
const char* table_name, /* in: table name */
|
||||
ibool check_types) /* in: TRUE=check type compatibility */
|
||||
ibool check_charsets) /* in: TRUE=check charset
|
||||
compatibility */
|
||||
{
|
||||
btr_pcur_t pcur;
|
||||
mem_heap_t* heap;
|
||||
@ -1319,7 +1320,7 @@ loop:
|
||||
|
||||
/* Load the foreign constraint definition to the dictionary cache */
|
||||
|
||||
err = dict_load_foreign(id, check_types);
|
||||
err = dict_load_foreign(id, check_charsets);
|
||||
|
||||
if (err != DB_SUCCESS) {
|
||||
btr_pcur_close(&pcur);
|
||||
|
@ -745,8 +745,6 @@ struct buf_block_struct{
|
||||
buffer pool which are index pages,
|
||||
but this flag is not set because
|
||||
we do not keep track of all pages */
|
||||
dict_index_t* index; /* index for which the adaptive
|
||||
hash index has been created */
|
||||
/* 2. Page flushing fields */
|
||||
|
||||
UT_LIST_NODE_T(buf_block_t) flush_list;
|
||||
@ -833,7 +831,7 @@ struct buf_block_struct{
|
||||
records with the same prefix should be
|
||||
indexed in the hash index */
|
||||
|
||||
/* The following 4 fields are protected by btr_search_latch: */
|
||||
/* The following 6 fields are protected by btr_search_latch: */
|
||||
|
||||
ibool is_hashed; /* TRUE if hash index has already been
|
||||
built on this page; note that it does
|
||||
@ -850,6 +848,12 @@ struct buf_block_struct{
|
||||
ulint curr_side; /* BTR_SEARCH_LEFT_SIDE or
|
||||
BTR_SEARCH_RIGHT_SIDE in hash
|
||||
indexing */
|
||||
dict_index_t* index; /* Index for which the adaptive
|
||||
hash index has been created.
|
||||
This field may only be modified
|
||||
while holding an s-latch or x-latch
|
||||
on block->lock and an x-latch on
|
||||
btr_search_latch. */
|
||||
/* 6. Debug fields */
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
rw_lock_t debug_latch; /* in the debug version, each thread
|
||||
|
@ -197,7 +197,8 @@ dict_foreign_add_to_cache(
|
||||
/*======================*/
|
||||
/* out: DB_SUCCESS or error code */
|
||||
dict_foreign_t* foreign, /* in, own: foreign key constraint */
|
||||
ibool check_types); /* in: TRUE=check type compatibility */
|
||||
ibool check_charsets);/* in: TRUE=check charset
|
||||
compatibility */
|
||||
/*************************************************************************
|
||||
Checks if a table is referenced by foreign keys. */
|
||||
|
||||
|
@ -82,7 +82,8 @@ dict_load_foreigns(
|
||||
/*===============*/
|
||||
/* out: DB_SUCCESS or error code */
|
||||
const char* table_name, /* in: table name */
|
||||
ibool check_types); /* in: TRUE=check type compatibility */
|
||||
ibool check_charsets);/* in: TRUE=check charsets
|
||||
compatibility */
|
||||
/************************************************************************
|
||||
Prints to the standard output information on all tables found in the data
|
||||
dictionary system table. */
|
||||
|
@ -24,7 +24,8 @@ cmp_types_are_equal(
|
||||
/* out: TRUE if the types are considered
|
||||
equal in comparisons */
|
||||
dtype_t* type1, /* in: type 1 */
|
||||
dtype_t* type2); /* in: type 2 */
|
||||
dtype_t* type2, /* in: type 2 */
|
||||
ibool check_charsets); /* in: whether to check charsets */
|
||||
/*****************************************************************
|
||||
This function is used to compare two data fields for which we know the
|
||||
data type. */
|
||||
|
@ -99,7 +99,8 @@ cmp_types_are_equal(
|
||||
/* out: TRUE if the types are considered
|
||||
equal in comparisons */
|
||||
dtype_t* type1, /* in: type 1 */
|
||||
dtype_t* type2) /* in: type 2 */
|
||||
dtype_t* type2, /* in: type 2 */
|
||||
ibool check_charsets) /* in: whether to check charsets */
|
||||
{
|
||||
if (dtype_is_non_binary_string_type(type1->mtype, type1->prtype)
|
||||
&& dtype_is_non_binary_string_type(type2->mtype, type2->prtype)) {
|
||||
@ -107,12 +108,12 @@ cmp_types_are_equal(
|
||||
/* Both are non-binary string types: they can be compared if
|
||||
and only if the charset-collation is the same */
|
||||
|
||||
if (dtype_get_charset_coll(type1->prtype)
|
||||
== dtype_get_charset_coll(type2->prtype)) {
|
||||
if (check_charsets) {
|
||||
return(dtype_get_charset_coll(type1->prtype)
|
||||
== dtype_get_charset_coll(type2->prtype));
|
||||
} else {
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
if (dtype_is_binary_string_type(type1->mtype, type1->prtype)
|
||||
|
@ -2132,7 +2132,7 @@ row_table_add_foreign_constraints(
|
||||
|
||||
if (err == DB_SUCCESS) {
|
||||
/* Check that also referencing constraints are ok */
|
||||
err = dict_load_foreigns(name, trx->check_foreigns);
|
||||
err = dict_load_foreigns(name, TRUE);
|
||||
}
|
||||
|
||||
if (err != DB_SUCCESS) {
|
||||
@ -3590,7 +3590,8 @@ row_rename_table_for_mysql(
|
||||
mem_heap_t* heap = NULL;
|
||||
const char** constraints_to_drop = NULL;
|
||||
ulint n_constraints_to_drop = 0;
|
||||
ibool recovering_temp_table = FALSE;
|
||||
ibool recovering_temp_table = FALSE;
|
||||
ibool old_is_tmp, new_is_tmp;
|
||||
ulint len;
|
||||
ulint i;
|
||||
ibool success;
|
||||
@ -3630,6 +3631,9 @@ row_rename_table_for_mysql(
|
||||
trx->op_info = "renaming table";
|
||||
trx_start_if_not_started(trx);
|
||||
|
||||
old_is_tmp = row_is_mysql_tmp_table_name(old_name);
|
||||
new_is_tmp = row_is_mysql_tmp_table_name(new_name);
|
||||
|
||||
if (row_mysql_is_recovered_tmp_table(new_name)) {
|
||||
|
||||
recovering_temp_table = TRUE;
|
||||
@ -3676,7 +3680,7 @@ row_rename_table_for_mysql(
|
||||
len = (sizeof str1) + (sizeof str2) + (sizeof str3) + (sizeof str5) - 4
|
||||
+ ut_strlenq(new_name, '\'') + ut_strlenq(old_name, '\'');
|
||||
|
||||
if (row_is_mysql_tmp_table_name(new_name)) {
|
||||
if (new_is_tmp) {
|
||||
db_name_len = dict_get_db_name_len(old_name) + 1;
|
||||
|
||||
/* MySQL is doing an ALTER TABLE command and it renames the
|
||||
@ -3829,7 +3833,7 @@ row_rename_table_for_mysql(
|
||||
the table is stored in a single-table tablespace */
|
||||
|
||||
success = dict_table_rename_in_cache(table, new_name,
|
||||
!row_is_mysql_tmp_table_name(new_name));
|
||||
!new_is_tmp);
|
||||
if (!success) {
|
||||
trx->error_state = DB_SUCCESS;
|
||||
trx_general_rollback_for_mysql(trx, FALSE, NULL);
|
||||
@ -3846,19 +3850,16 @@ row_rename_table_for_mysql(
|
||||
goto funct_exit;
|
||||
}
|
||||
|
||||
err = dict_load_foreigns(new_name, trx->check_foreigns);
|
||||
/* We only want to switch off some of the type checking in
|
||||
an ALTER, not in a RENAME. */
|
||||
|
||||
err = dict_load_foreigns(new_name,
|
||||
old_is_tmp ? trx->check_foreigns : TRUE);
|
||||
|
||||
if (row_is_mysql_tmp_table_name(old_name)) {
|
||||
if (err != DB_SUCCESS) {
|
||||
ut_print_timestamp(stderr);
|
||||
|
||||
/* MySQL is doing an ALTER TABLE command and it
|
||||
renames the created temporary table to the name
|
||||
of the original table. In the ALTER TABLE we maybe
|
||||
created some FOREIGN KEY constraints for the temporary
|
||||
table. But we want to load also the foreign key
|
||||
constraint definitions for the original table name. */
|
||||
|
||||
if (err != DB_SUCCESS) {
|
||||
ut_print_timestamp(stderr);
|
||||
if (old_is_tmp) {
|
||||
fputs(" InnoDB: Error: in ALTER TABLE ",
|
||||
stderr);
|
||||
ut_print_name(stderr, trx, new_name);
|
||||
@ -3866,36 +3867,23 @@ row_rename_table_for_mysql(
|
||||
"InnoDB: has or is referenced in foreign key constraints\n"
|
||||
"InnoDB: which are not compatible with the new table definition.\n",
|
||||
stderr);
|
||||
|
||||
ut_a(dict_table_rename_in_cache(table,
|
||||
old_name, FALSE));
|
||||
trx->error_state = DB_SUCCESS;
|
||||
trx_general_rollback_for_mysql(trx, FALSE,
|
||||
NULL);
|
||||
trx->error_state = DB_SUCCESS;
|
||||
}
|
||||
} else {
|
||||
if (err != DB_SUCCESS) {
|
||||
|
||||
ut_print_timestamp(stderr);
|
||||
|
||||
} else {
|
||||
fputs(
|
||||
" InnoDB: Error: in RENAME TABLE table ",
|
||||
stderr);
|
||||
ut_print_name(stderr, trx, new_name);
|
||||
fputs("\n"
|
||||
"InnoDB: is referenced in foreign key constraints\n"
|
||||
"InnoDB: which are not compatible with the new table definition.\n",
|
||||
"InnoDB: is referenced in foreign key constraints\n"
|
||||
"InnoDB: which are not compatible with the new table definition.\n",
|
||||
stderr);
|
||||
|
||||
ut_a(dict_table_rename_in_cache(table,
|
||||
old_name, FALSE));
|
||||
|
||||
trx->error_state = DB_SUCCESS;
|
||||
trx_general_rollback_for_mysql(trx, FALSE,
|
||||
NULL);
|
||||
trx->error_state = DB_SUCCESS;
|
||||
}
|
||||
|
||||
ut_a(dict_table_rename_in_cache(table,
|
||||
old_name, FALSE));
|
||||
trx->error_state = DB_SUCCESS;
|
||||
trx_general_rollback_for_mysql(trx, FALSE,
|
||||
NULL);
|
||||
trx->error_state = DB_SUCCESS;
|
||||
}
|
||||
}
|
||||
funct_exit:
|
||||
|
@ -2437,7 +2437,9 @@ a b
|
||||
20 NULL
|
||||
drop table t1;
|
||||
create table t1 (v varchar(65530), key(v));
|
||||
ERROR HY000: Can't create table './test/t1' (errno: 139)
|
||||
Warnings:
|
||||
Warning 1071 Specified key was too long; max key length is 767 bytes
|
||||
drop table t1;
|
||||
create table t1 (v varchar(65536));
|
||||
Warnings:
|
||||
Note 1246 Converting column 'v' from VARCHAR to TEXT
|
||||
@ -2577,22 +2579,49 @@ create table t8 (col1 blob, index(col1(767)))
|
||||
character set = latin1 engine = innodb;
|
||||
create table t9 (col1 varchar(512), col2 varchar(512), index(col1, col2))
|
||||
character set = latin1 engine = innodb;
|
||||
show create table t9;
|
||||
Table Create Table
|
||||
t9 CREATE TABLE `t9` (
|
||||
`col1` varchar(512) default NULL,
|
||||
`col2` varchar(512) default NULL,
|
||||
KEY `col1` (`col1`,`col2`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1
|
||||
drop table t1, t2, t3, t4, t5, t6, t7, t8, t9;
|
||||
create table t1 (col1 varchar(768), index (col1))
|
||||
create table t1 (col1 varchar(768), index(col1))
|
||||
character set = latin1 engine = innodb;
|
||||
ERROR HY000: Can't create table './test/t1.frm' (errno: 139)
|
||||
create table t2 (col1 varchar(768) primary key)
|
||||
Warnings:
|
||||
Warning 1071 Specified key was too long; max key length is 767 bytes
|
||||
create table t2 (col1 varbinary(768), index(col1))
|
||||
character set = latin1 engine = innodb;
|
||||
ERROR HY000: Can't create table './test/t2.frm' (errno: 139)
|
||||
create table t3 (col1 varbinary(768) primary key)
|
||||
Warnings:
|
||||
Warning 1071 Specified key was too long; max key length is 767 bytes
|
||||
create table t3 (col1 text, index(col1(768)))
|
||||
character set = latin1 engine = innodb;
|
||||
ERROR HY000: Can't create table './test/t3.frm' (errno: 139)
|
||||
create table t4 (col1 text, index(col1(768)))
|
||||
Warnings:
|
||||
Warning 1071 Specified key was too long; max key length is 767 bytes
|
||||
create table t4 (col1 blob, index(col1(768)))
|
||||
character set = latin1 engine = innodb;
|
||||
ERROR HY000: Can't create table './test/t4.frm' (errno: 139)
|
||||
create table t5 (col1 blob, index(col1(768)))
|
||||
Warnings:
|
||||
Warning 1071 Specified key was too long; max key length is 767 bytes
|
||||
show create table t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`col1` varchar(768) default NULL,
|
||||
KEY `col1` (`col1`(767))
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1
|
||||
drop table t1, t2, t3, t4;
|
||||
create table t1 (col1 varchar(768) primary key)
|
||||
character set = latin1 engine = innodb;
|
||||
ERROR HY000: Can't create table './test/t5.frm' (errno: 139)
|
||||
ERROR 42000: Specified key was too long; max key length is 767 bytes
|
||||
create table t2 (col1 varbinary(768) primary key)
|
||||
character set = latin1 engine = innodb;
|
||||
ERROR 42000: Specified key was too long; max key length is 767 bytes
|
||||
create table t3 (col1 text, primary key(col1(768)))
|
||||
character set = latin1 engine = innodb;
|
||||
ERROR 42000: Specified key was too long; max key length is 767 bytes
|
||||
create table t4 (col1 blob, primary key(col1(768)))
|
||||
character set = latin1 engine = innodb;
|
||||
ERROR 42000: Specified key was too long; max key length is 767 bytes
|
||||
CREATE TABLE t1
|
||||
(
|
||||
id INT PRIMARY KEY
|
||||
@ -2772,6 +2801,38 @@ insert into t2 values (4,_ucs2 0x05612020,_ucs2 0x05612020,'taken');
|
||||
drop table t1;
|
||||
drop table t2;
|
||||
commit;
|
||||
set foreign_key_checks=0;
|
||||
create table t2 (a int primary key, b int, foreign key (b) references t1(a)) engine = innodb;
|
||||
create table t1(a char(10) primary key, b varchar(20)) engine = innodb;
|
||||
ERROR HY000: Can't create table './test/t1.frm' (errno: 150)
|
||||
set foreign_key_checks=1;
|
||||
drop table t2;
|
||||
set foreign_key_checks=0;
|
||||
create table t1(a varchar(10) primary key) engine = innodb DEFAULT CHARSET=latin1;
|
||||
create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb DEFAULT CHARSET=utf8;
|
||||
ERROR HY000: Can't create table './test/t2.frm' (errno: 150)
|
||||
set foreign_key_checks=1;
|
||||
drop table t1;
|
||||
set foreign_key_checks=0;
|
||||
create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb;
|
||||
create table t1(a varchar(10) primary key) engine = innodb;
|
||||
alter table t1 modify column a int;
|
||||
Got one of the listed errors
|
||||
set foreign_key_checks=1;
|
||||
drop table t2,t1;
|
||||
set foreign_key_checks=0;
|
||||
create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb DEFAULT CHARSET=latin1;
|
||||
create table t1(a varchar(10) primary key) engine = innodb DEFAULT CHARSET=latin1;
|
||||
alter table t1 convert to character set utf8;
|
||||
set foreign_key_checks=1;
|
||||
drop table t2,t1;
|
||||
set foreign_key_checks=0;
|
||||
create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb DEFAULT CHARSET=latin1;
|
||||
create table t3(a varchar(10) primary key) engine = innodb DEFAULT CHARSET=utf8;
|
||||
rename table t3 to t1;
|
||||
ERROR HY000: Error on rename of './test/t3' to './test/t1' (errno: 150)
|
||||
set foreign_key_checks=1;
|
||||
drop table t2,t3;
|
||||
create table t1 (a varchar(255) character set utf8,
|
||||
b varchar(255) character set utf8,
|
||||
c varchar(255) character set utf8,
|
||||
|
@ -4153,4 +4153,43 @@ A local variable in a nested compound statement takes precedence over table colu
|
||||
a - local variable in a nested compound statement
|
||||
A local variable in a nested compound statement takes precedence over table column in cursors
|
||||
a - local variable in a nested compound statement
|
||||
drop schema if exists mysqltest1|
|
||||
Warnings:
|
||||
Note 1008 Can't drop database 'mysqltest1'; database doesn't exist
|
||||
drop schema if exists mysqltest2|
|
||||
Warnings:
|
||||
Note 1008 Can't drop database 'mysqltest2'; database doesn't exist
|
||||
drop schema if exists mysqltest3|
|
||||
Warnings:
|
||||
Note 1008 Can't drop database 'mysqltest3'; database doesn't exist
|
||||
create schema mysqltest1|
|
||||
create schema mysqltest2|
|
||||
create schema mysqltest3|
|
||||
use mysqltest3|
|
||||
create procedure mysqltest1.p1 (out prequestid varchar(100))
|
||||
begin
|
||||
call mysqltest2.p2('call mysqltest3.p3(1, 2)');
|
||||
end|
|
||||
create procedure mysqltest2.p2(in psql text)
|
||||
begin
|
||||
declare lsql text;
|
||||
set @lsql= psql;
|
||||
prepare lstatement from @lsql;
|
||||
execute lstatement;
|
||||
deallocate prepare lstatement;
|
||||
end|
|
||||
create procedure mysqltest3.p3(in p1 int)
|
||||
begin
|
||||
select p1;
|
||||
end|
|
||||
call mysqltest1.p1(@rs)|
|
||||
ERROR 42000: Incorrect number of arguments for PROCEDURE mysqltest3.p3; expected 1, got 2
|
||||
call mysqltest1.p1(@rs)|
|
||||
ERROR 42000: Incorrect number of arguments for PROCEDURE mysqltest3.p3; expected 1, got 2
|
||||
call mysqltest1.p1(@rs)|
|
||||
ERROR 42000: Incorrect number of arguments for PROCEDURE mysqltest3.p3; expected 1, got 2
|
||||
drop schema if exists mysqltest1|
|
||||
drop schema if exists mysqltest2|
|
||||
drop schema if exists mysqltest3|
|
||||
use test|
|
||||
drop table t1,t2;
|
||||
|
@ -114,3 +114,26 @@ drop table t1;
|
||||
select hex(cast(0x10 as binary(2)));
|
||||
hex(cast(0x10 as binary(2)))
|
||||
1000
|
||||
create table t1 (b binary(2), vb varbinary(2));
|
||||
insert into t1 values(0x4120, 0x4120);
|
||||
insert into t1 values(0x412020, 0x412020);
|
||||
Warnings:
|
||||
Warning 1265 Data truncated for column 'b' at row 1
|
||||
Warning 1265 Data truncated for column 'vb' at row 1
|
||||
drop table t1;
|
||||
create table t1 (c char(2), vc varchar(2));
|
||||
insert into t1 values(0x4120, 0x4120);
|
||||
insert into t1 values(0x412020, 0x412020);
|
||||
Warnings:
|
||||
Note 1265 Data truncated for column 'vc' at row 1
|
||||
drop table t1;
|
||||
set @old_sql_mode= @@sql_mode, sql_mode= 'traditional';
|
||||
create table t1 (b binary(2), vb varbinary(2));
|
||||
insert into t1 values(0x4120, 0x4120);
|
||||
insert into t1 values(0x412020, NULL);
|
||||
ERROR 22001: Data too long for column 'b' at row 1
|
||||
insert into t1 values(NULL, 0x412020);
|
||||
ERROR 22001: Data too long for column 'vb' at row 1
|
||||
drop table t1;
|
||||
set @@sql_mode= @old_sql_mode;
|
||||
End of 5.0 tests
|
||||
|
@ -1356,8 +1356,8 @@ source include/varchar.inc;
|
||||
# Clean up filename -- embedded server reports whole path without .frm,
|
||||
# regular server reports relative path with .frm (argh!)
|
||||
--replace_result \\ / $MYSQL_TEST_DIR . /var/master-data/ / t1.frm t1
|
||||
--error 1005
|
||||
create table t1 (v varchar(65530), key(v));
|
||||
drop table t1;
|
||||
create table t1 (v varchar(65536));
|
||||
show create table t1;
|
||||
drop table t1;
|
||||
@ -1485,7 +1485,7 @@ CREATE TEMPORARY TABLE t2
|
||||
DROP TABLE t1;
|
||||
|
||||
#
|
||||
# Test that index column max sizes are checked (bug #13315)
|
||||
# Test that index column max sizes are honored (bug #13315)
|
||||
#
|
||||
|
||||
# prefix index
|
||||
@ -1512,22 +1512,36 @@ create table t8 (col1 blob, index(col1(767)))
|
||||
create table t9 (col1 varchar(512), col2 varchar(512), index(col1, col2))
|
||||
character set = latin1 engine = innodb;
|
||||
|
||||
show create table t9;
|
||||
|
||||
drop table t1, t2, t3, t4, t5, t6, t7, t8, t9;
|
||||
|
||||
--error 1005
|
||||
create table t1 (col1 varchar(768), index (col1))
|
||||
# these should have their index length trimmed
|
||||
create table t1 (col1 varchar(768), index(col1))
|
||||
character set = latin1 engine = innodb;
|
||||
--error 1005
|
||||
create table t2 (col1 varchar(768) primary key)
|
||||
create table t2 (col1 varbinary(768), index(col1))
|
||||
character set = latin1 engine = innodb;
|
||||
--error 1005
|
||||
create table t3 (col1 varbinary(768) primary key)
|
||||
create table t3 (col1 text, index(col1(768)))
|
||||
character set = latin1 engine = innodb;
|
||||
--error 1005
|
||||
create table t4 (col1 text, index(col1(768)))
|
||||
create table t4 (col1 blob, index(col1(768)))
|
||||
character set = latin1 engine = innodb;
|
||||
--error 1005
|
||||
create table t5 (col1 blob, index(col1(768)))
|
||||
|
||||
show create table t1;
|
||||
|
||||
drop table t1, t2, t3, t4;
|
||||
|
||||
# these should be refused
|
||||
--error 1071
|
||||
create table t1 (col1 varchar(768) primary key)
|
||||
character set = latin1 engine = innodb;
|
||||
--error 1071
|
||||
create table t2 (col1 varbinary(768) primary key)
|
||||
character set = latin1 engine = innodb;
|
||||
--error 1071
|
||||
create table t3 (col1 text, primary key(col1(768)))
|
||||
character set = latin1 engine = innodb;
|
||||
--error 1071
|
||||
create table t4 (col1 blob, primary key(col1(768)))
|
||||
character set = latin1 engine = innodb;
|
||||
|
||||
#
|
||||
@ -1752,6 +1766,56 @@ drop table t1;
|
||||
drop table t2;
|
||||
commit;
|
||||
|
||||
# tests for bugs #9802 and #13778
|
||||
|
||||
# test that FKs between invalid types are not accepted
|
||||
|
||||
set foreign_key_checks=0;
|
||||
create table t2 (a int primary key, b int, foreign key (b) references t1(a)) engine = innodb;
|
||||
-- error 1005
|
||||
create table t1(a char(10) primary key, b varchar(20)) engine = innodb;
|
||||
set foreign_key_checks=1;
|
||||
drop table t2;
|
||||
|
||||
# test that FKs between different charsets are not accepted in CREATE even
|
||||
# when f_k_c is 0
|
||||
|
||||
set foreign_key_checks=0;
|
||||
create table t1(a varchar(10) primary key) engine = innodb DEFAULT CHARSET=latin1;
|
||||
-- error 1005
|
||||
create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb DEFAULT CHARSET=utf8;
|
||||
set foreign_key_checks=1;
|
||||
drop table t1;
|
||||
|
||||
# test that invalid datatype conversions with ALTER are not allowed
|
||||
|
||||
set foreign_key_checks=0;
|
||||
create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb;
|
||||
create table t1(a varchar(10) primary key) engine = innodb;
|
||||
-- error 1025,1025
|
||||
alter table t1 modify column a int;
|
||||
set foreign_key_checks=1;
|
||||
drop table t2,t1;
|
||||
|
||||
# test that charset conversions with ALTER are allowed when f_k_c is 0
|
||||
|
||||
set foreign_key_checks=0;
|
||||
create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb DEFAULT CHARSET=latin1;
|
||||
create table t1(a varchar(10) primary key) engine = innodb DEFAULT CHARSET=latin1;
|
||||
alter table t1 convert to character set utf8;
|
||||
set foreign_key_checks=1;
|
||||
drop table t2,t1;
|
||||
|
||||
# test that RENAME does not allow invalid charsets when f_k_c is 0
|
||||
|
||||
set foreign_key_checks=0;
|
||||
create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb DEFAULT CHARSET=latin1;
|
||||
create table t3(a varchar(10) primary key) engine = innodb DEFAULT CHARSET=utf8;
|
||||
-- error 1025
|
||||
rename table t3 to t1;
|
||||
set foreign_key_checks=1;
|
||||
drop table t2,t3;
|
||||
|
||||
#
|
||||
# Test that we can create a large (>1K) key
|
||||
#
|
||||
|
@ -4947,6 +4947,52 @@ begin
|
||||
end|
|
||||
call p1("a - stored procedure parameter")|
|
||||
|
||||
#
|
||||
# A test case for Bug#15392 "Server crashes during prepared statement
|
||||
# execute": make sure that stored procedure check for error conditions
|
||||
# properly and do not continue execution if an error has been set.
|
||||
#
|
||||
# It's necessary to use several DBs because in the original code
|
||||
# the successful return of mysql_change_db overrode the error from
|
||||
# execution.
|
||||
drop schema if exists mysqltest1|
|
||||
drop schema if exists mysqltest2|
|
||||
drop schema if exists mysqltest3|
|
||||
create schema mysqltest1|
|
||||
create schema mysqltest2|
|
||||
create schema mysqltest3|
|
||||
use mysqltest3|
|
||||
|
||||
create procedure mysqltest1.p1 (out prequestid varchar(100))
|
||||
begin
|
||||
call mysqltest2.p2('call mysqltest3.p3(1, 2)');
|
||||
end|
|
||||
|
||||
create procedure mysqltest2.p2(in psql text)
|
||||
begin
|
||||
declare lsql text;
|
||||
set @lsql= psql;
|
||||
prepare lstatement from @lsql;
|
||||
execute lstatement;
|
||||
deallocate prepare lstatement;
|
||||
end|
|
||||
|
||||
create procedure mysqltest3.p3(in p1 int)
|
||||
begin
|
||||
select p1;
|
||||
end|
|
||||
|
||||
--error ER_SP_WRONG_NO_OF_ARGS
|
||||
call mysqltest1.p1(@rs)|
|
||||
--error ER_SP_WRONG_NO_OF_ARGS
|
||||
call mysqltest1.p1(@rs)|
|
||||
--error ER_SP_WRONG_NO_OF_ARGS
|
||||
call mysqltest1.p1(@rs)|
|
||||
drop schema if exists mysqltest1|
|
||||
drop schema if exists mysqltest2|
|
||||
drop schema if exists mysqltest3|
|
||||
use test|
|
||||
|
||||
#
|
||||
# BUG#NNNN: New bug synopsis
|
||||
#
|
||||
|
@ -68,3 +68,27 @@ drop table t1;
|
||||
|
||||
# check that cast appends trailing zeros
|
||||
select hex(cast(0x10 as binary(2)));
|
||||
|
||||
#
|
||||
# Bug #14299: BINARY space truncation should cause warning or error
|
||||
#
|
||||
create table t1 (b binary(2), vb varbinary(2));
|
||||
insert into t1 values(0x4120, 0x4120);
|
||||
insert into t1 values(0x412020, 0x412020);
|
||||
drop table t1;
|
||||
create table t1 (c char(2), vc varchar(2));
|
||||
insert into t1 values(0x4120, 0x4120);
|
||||
insert into t1 values(0x412020, 0x412020);
|
||||
drop table t1;
|
||||
|
||||
set @old_sql_mode= @@sql_mode, sql_mode= 'traditional';
|
||||
create table t1 (b binary(2), vb varbinary(2));
|
||||
insert into t1 values(0x4120, 0x4120);
|
||||
--error ER_DATA_TOO_LONG
|
||||
insert into t1 values(0x412020, NULL);
|
||||
--error ER_DATA_TOO_LONG
|
||||
insert into t1 values(NULL, 0x412020);
|
||||
drop table t1;
|
||||
set @@sql_mode= @old_sql_mode;
|
||||
|
||||
--echo End of 5.0 tests
|
||||
|
57
sql/field.cc
57
sql/field.cc
@ -5855,44 +5855,52 @@ int Field_string::store(const char *from,uint length,CHARSET_INFO *cs)
|
||||
char buff[STRING_BUFFER_USUAL_SIZE];
|
||||
String tmpstr(buff,sizeof(buff), &my_charset_bin);
|
||||
uint copy_length;
|
||||
|
||||
|
||||
/* See the comment for Field_long::store(long long) */
|
||||
DBUG_ASSERT(table->in_use == current_thd);
|
||||
|
||||
|
||||
/* Convert character set if necessary */
|
||||
if (String::needs_conversion(length, cs, field_charset, ¬_used))
|
||||
{
|
||||
{
|
||||
uint conv_errors;
|
||||
tmpstr.copy(from, length, cs, field_charset, &conv_errors);
|
||||
from= tmpstr.ptr();
|
||||
length= tmpstr.length();
|
||||
length= tmpstr.length();
|
||||
if (conv_errors)
|
||||
error= 2;
|
||||
}
|
||||
|
||||
/*
|
||||
Make sure we don't break a multibyte sequence
|
||||
as well as don't copy a malformed data.
|
||||
*/
|
||||
/* Make sure we don't break a multibyte sequence or copy malformed data. */
|
||||
copy_length= field_charset->cset->well_formed_len(field_charset,
|
||||
from,from+length,
|
||||
field_length/
|
||||
field_charset->mbmaxlen,
|
||||
&well_formed_error);
|
||||
memcpy(ptr,from,copy_length);
|
||||
if (copy_length < field_length) // Append spaces if shorter
|
||||
|
||||
/* Append spaces if the string was shorter than the field. */
|
||||
if (copy_length < field_length)
|
||||
field_charset->cset->fill(field_charset,ptr+copy_length,
|
||||
field_length-copy_length,
|
||||
field_length-copy_length,
|
||||
field_charset->pad_char);
|
||||
|
||||
|
||||
/*
|
||||
Check if we lost any important data (anything in a binary string,
|
||||
or any non-space in others).
|
||||
*/
|
||||
if ((copy_length < length) && table->in_use->count_cuted_fields)
|
||||
{ // Check if we loosed some info
|
||||
const char *end=from+length;
|
||||
from+= copy_length;
|
||||
from+= field_charset->cset->scan(field_charset, from, end,
|
||||
MY_SEQ_SPACES);
|
||||
if (from != end)
|
||||
{
|
||||
if (binary())
|
||||
error= 2;
|
||||
else
|
||||
{
|
||||
const char *end=from+length;
|
||||
from+= copy_length;
|
||||
from+= field_charset->cset->scan(field_charset, from, end,
|
||||
MY_SEQ_SPACES);
|
||||
if (from != end)
|
||||
error= 2;
|
||||
}
|
||||
}
|
||||
if (error)
|
||||
{
|
||||
@ -6271,12 +6279,15 @@ int Field_varstring::store(const char *from,uint length,CHARSET_INFO *cs)
|
||||
if ((copy_length < length) && table->in_use->count_cuted_fields &&
|
||||
!error_code)
|
||||
{
|
||||
const char *end= from + length;
|
||||
from+= copy_length;
|
||||
from+= field_charset->cset->scan(field_charset, from, end, MY_SEQ_SPACES);
|
||||
/* If we lost only spaces then produce a NOTE, not a WARNING */
|
||||
if (from == end)
|
||||
level= MYSQL_ERROR::WARN_LEVEL_NOTE;
|
||||
if (!binary())
|
||||
{
|
||||
const char *end= from + length;
|
||||
from+= copy_length;
|
||||
from+= field_charset->cset->scan(field_charset, from, end, MY_SEQ_SPACES);
|
||||
/* If we lost only spaces then produce a NOTE, not a WARNING */
|
||||
if (from == end)
|
||||
level= MYSQL_ERROR::WARN_LEVEL_NOTE;
|
||||
}
|
||||
error_code= WARN_DATA_TRUNCATED;
|
||||
}
|
||||
if (error_code)
|
||||
|
@ -2519,6 +2519,12 @@ ha_innobase::open(
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
uint
|
||||
ha_innobase::max_supported_key_part_length() const
|
||||
{
|
||||
return(DICT_MAX_INDEX_COL_LEN - 1);
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
Closes a handle to an InnoDB table. */
|
||||
|
||||
@ -4675,6 +4681,9 @@ create_index(
|
||||
0, prefix_len);
|
||||
}
|
||||
|
||||
/* Even though we've defined max_supported_key_part_length, we
|
||||
still do our own checking using field_lengths to be absolutely
|
||||
sure we don't create too long indexes. */
|
||||
error = row_create_index_for_mysql(index, trx, field_lengths);
|
||||
|
||||
error = convert_error_code_to_mysql(error, NULL);
|
||||
|
@ -110,7 +110,7 @@ class ha_innobase: public handler
|
||||
but currently MySQL does not work with keys
|
||||
whose size is > MAX_KEY_LENGTH */
|
||||
uint max_supported_key_length() const { return 3500; }
|
||||
uint max_supported_key_part_length() const { return 3500; }
|
||||
uint max_supported_key_part_length() const;
|
||||
const key_map *keys_to_use_for_scanning() { return &key_map_full; }
|
||||
bool has_transactions() { return 1;}
|
||||
|
||||
|
@ -5165,7 +5165,7 @@ void Item_trigger_field::setup_field(THD *thd, TABLE *table)
|
||||
set field_idx properly.
|
||||
*/
|
||||
(void)find_field_in_table(thd, table, field_name, (uint) strlen(field_name),
|
||||
0, 0, &field_idx, 0);
|
||||
0, &field_idx);
|
||||
thd->set_query_id= save_set_query_id;
|
||||
triggers= table->triggers;
|
||||
}
|
||||
|
42
sql/item.h
42
sql/item.h
@ -326,6 +326,48 @@ struct Name_resolution_context: Sql_alloc
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
Store and restore the current state of a name resolution context.
|
||||
*/
|
||||
|
||||
class Name_resolution_context_state
|
||||
{
|
||||
private:
|
||||
TABLE_LIST *save_table_list;
|
||||
TABLE_LIST *save_first_name_resolution_table;
|
||||
TABLE_LIST *save_next_name_resolution_table;
|
||||
bool save_resolve_in_select_list;
|
||||
|
||||
public:
|
||||
TABLE_LIST *save_next_local;
|
||||
|
||||
public:
|
||||
/* Save the state of a name resolution context. */
|
||||
void save_state(Name_resolution_context *context, TABLE_LIST *table_list)
|
||||
{
|
||||
save_table_list= context->table_list;
|
||||
save_first_name_resolution_table= context->first_name_resolution_table;
|
||||
save_next_name_resolution_table= (context->first_name_resolution_table) ?
|
||||
context->first_name_resolution_table->
|
||||
next_name_resolution_table :
|
||||
NULL;
|
||||
save_resolve_in_select_list= context->resolve_in_select_list;
|
||||
save_next_local= table_list->next_local;
|
||||
}
|
||||
|
||||
/* Restore a name resolution context from saved state. */
|
||||
void restore_state(Name_resolution_context *context, TABLE_LIST *table_list)
|
||||
{
|
||||
table_list->next_local= save_next_local;
|
||||
context->table_list= save_table_list;
|
||||
context->first_name_resolution_table= save_first_name_resolution_table;
|
||||
if (context->first_name_resolution_table)
|
||||
context->first_name_resolution_table->
|
||||
next_name_resolution_table= save_next_name_resolution_table;
|
||||
context->resolve_in_select_list= save_resolve_in_select_list;
|
||||
}
|
||||
};
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
typedef bool (Item::*Item_processor)(byte *arg);
|
||||
|
@ -795,18 +795,15 @@ find_field_in_tables(THD *thd, Item_ident *item,
|
||||
bool check_privileges, bool register_tree_change);
|
||||
Field *
|
||||
find_field_in_table_ref(THD *thd, TABLE_LIST *table_list,
|
||||
const char *name, const char *item_name,
|
||||
const char *table_name, const char *db_name,
|
||||
uint length, Item **ref,
|
||||
bool check_grants_table, bool check_grants_view,
|
||||
bool allow_rowid,
|
||||
const char *name, uint length,
|
||||
const char *item_name, const char *db_name,
|
||||
const char *table_name, Item **ref,
|
||||
bool check_privileges, bool allow_rowid,
|
||||
uint *cached_field_index_ptr,
|
||||
bool register_tree_change, TABLE_LIST **actual_table);
|
||||
Field *
|
||||
find_field_in_table(THD *thd, TABLE *table, const char *name,
|
||||
uint length, bool check_grants, bool allow_rowid,
|
||||
uint *cached_field_index_ptr,
|
||||
Security_context *sctx);
|
||||
find_field_in_table(THD *thd, TABLE *table, const char *name, uint length,
|
||||
bool allow_rowid, uint *cached_field_index_ptr);
|
||||
|
||||
#ifdef HAVE_OPENSSL
|
||||
#include <openssl/des.h>
|
||||
@ -922,8 +919,9 @@ create_field * new_create_field(THD *thd, char *field_name, enum_field_types typ
|
||||
uint uint_geom_type);
|
||||
void store_position_for_column(const char *name);
|
||||
bool add_to_list(THD *thd, SQL_LIST &list,Item *group,bool asc);
|
||||
Name_resolution_context *make_join_on_context(THD *thd, TABLE_LIST *left_op,
|
||||
TABLE_LIST *right_op);
|
||||
bool push_new_name_resolution_context(THD *thd,
|
||||
TABLE_LIST *left_op,
|
||||
TABLE_LIST *right_op);
|
||||
void add_join_on(TABLE_LIST *b,Item *expr);
|
||||
void add_join_natural(TABLE_LIST *a,TABLE_LIST *b,List<String> *using_fields);
|
||||
bool add_proc_to_list(THD *thd, Item *item);
|
||||
|
@ -1137,10 +1137,12 @@ int sp_head::execute(THD *thd)
|
||||
original thd->db will then have been freed */
|
||||
if (dbchanged)
|
||||
{
|
||||
/* No access check when changing back to where we came from.
|
||||
(It would generate an error from mysql_change_db() when olddb=="") */
|
||||
/*
|
||||
No access check when changing back to where we came from.
|
||||
(It would generate an error from mysql_change_db() when olddb=="")
|
||||
*/
|
||||
if (! thd->killed)
|
||||
ret= mysql_change_db(thd, olddb, 1);
|
||||
ret|= (int) mysql_change_db(thd, olddb, 1);
|
||||
}
|
||||
m_flags&= ~IS_INVOKED;
|
||||
DBUG_PRINT("info", ("first free for 0x%lx --: 0x%lx->0x%lx, level: %lu, flags %x",
|
||||
@ -1519,13 +1521,12 @@ int sp_head::execute_procedure(THD *thd, List<Item> *args)
|
||||
|
||||
suv= new Item_func_set_user_var(guv->get_name(), item);
|
||||
/*
|
||||
we do not check suv->fixed, because it can't be fixed after
|
||||
creation
|
||||
Item_func_set_user_var is not fixed after construction,
|
||||
call fix_fields().
|
||||
*/
|
||||
suv->fix_fields(thd, &item);
|
||||
suv->fix_length_and_dec();
|
||||
suv->check();
|
||||
suv->update();
|
||||
if ((ret= test(!suv || suv->fix_fields(thd, &item) ||
|
||||
suv->check() || suv->update())))
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2097,7 +2098,7 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp,
|
||||
|
||||
cleanup_items() is called in sp_head::execute()
|
||||
*/
|
||||
return res;
|
||||
return res || thd->net.report_error;
|
||||
}
|
||||
|
||||
|
||||
|
106
sql/sql_acl.cc
106
sql/sql_acl.cc
@ -2761,8 +2761,9 @@ bool mysql_table_grant(THD *thd, TABLE_LIST *table_list,
|
||||
uint unused_field_idx= NO_CACHED_FIELD_INDEX;
|
||||
TABLE_LIST *dummy;
|
||||
Field *f=find_field_in_table_ref(thd, table_list, column->column.ptr(),
|
||||
column->column.length(),
|
||||
column->column.ptr(), NULL, NULL,
|
||||
column->column.length(), 0, 1, 1, 0,
|
||||
NULL, TRUE, FALSE,
|
||||
&unused_field_idx, FALSE, &dummy);
|
||||
if (f == (Field*)0)
|
||||
{
|
||||
@ -3616,11 +3617,28 @@ err:
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Check column rights in given security context
|
||||
|
||||
SYNOPSIS
|
||||
check_grant_column()
|
||||
thd thread handler
|
||||
grant grant information structure
|
||||
db_name db name
|
||||
table_name table name
|
||||
name column name
|
||||
length column name length
|
||||
sctx security context
|
||||
|
||||
RETURN
|
||||
FALSE OK
|
||||
TRUE access denied
|
||||
*/
|
||||
|
||||
bool check_grant_column(THD *thd, GRANT_INFO *grant,
|
||||
const char *db_name, const char *table_name,
|
||||
const char *name, uint length, uint show_tables)
|
||||
const char *name, uint length, Security_context *sctx)
|
||||
{
|
||||
Security_context *sctx= thd->security_ctx;
|
||||
GRANT_TABLE *grant_table;
|
||||
GRANT_COLUMN *grant_column;
|
||||
ulong want_access= grant->want_privilege & ~grant->privilege;
|
||||
@ -3651,31 +3669,77 @@ bool check_grant_column(THD *thd, GRANT_INFO *grant,
|
||||
rw_unlock(&LOCK_grant);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
#ifdef NOT_USED
|
||||
if (show_tables && (grant_column || grant->privilege & COL_ACLS))
|
||||
{
|
||||
rw_unlock(&LOCK_grant); /* purecov: deadcode */
|
||||
DBUG_RETURN(0); /* purecov: deadcode */
|
||||
}
|
||||
#endif
|
||||
|
||||
err:
|
||||
rw_unlock(&LOCK_grant);
|
||||
if (!show_tables)
|
||||
{
|
||||
char command[128];
|
||||
get_privilege_desc(command, sizeof(command), want_access);
|
||||
my_error(ER_COLUMNACCESS_DENIED_ERROR, MYF(0),
|
||||
command,
|
||||
sctx->priv_user,
|
||||
sctx->host_or_ip,
|
||||
name,
|
||||
table_name);
|
||||
}
|
||||
char command[128];
|
||||
get_privilege_desc(command, sizeof(command), want_access);
|
||||
my_error(ER_COLUMNACCESS_DENIED_ERROR, MYF(0),
|
||||
command,
|
||||
sctx->priv_user,
|
||||
sctx->host_or_ip,
|
||||
name,
|
||||
table_name);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Check the access right to a column depending on the type of table.
|
||||
|
||||
SYNOPSIS
|
||||
check_column_grant_in_table_ref()
|
||||
thd thread handler
|
||||
table_ref table reference where to check the field
|
||||
name name of field to check
|
||||
length length of name
|
||||
|
||||
DESCRIPTION
|
||||
Check the access rights to a column depending on the type of table
|
||||
reference where the column is checked. The function provides a
|
||||
generic interface to check column access rights that hides the
|
||||
heterogeneity of the column representation - whether it is a view
|
||||
or a stored table colum.
|
||||
|
||||
RETURN
|
||||
FALSE OK
|
||||
TRUE access denied
|
||||
*/
|
||||
|
||||
bool check_column_grant_in_table_ref(THD *thd, TABLE_LIST * table_ref,
|
||||
const char *name, uint length)
|
||||
{
|
||||
GRANT_INFO *grant;
|
||||
const char *db_name;
|
||||
const char *table_name;
|
||||
Security_context *sctx= test(table_ref->security_ctx) ?
|
||||
table_ref->security_ctx : thd->security_ctx;
|
||||
|
||||
if (table_ref->view || table_ref->field_translation)
|
||||
{
|
||||
/* View or derived information schema table. */
|
||||
grant= &(table_ref->grant);
|
||||
db_name= table_ref->view_db.str;
|
||||
table_name= table_ref->view_name.str;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Normal or temporary table. */
|
||||
TABLE *table= table_ref->table;
|
||||
grant= &(table->grant);
|
||||
db_name= table->s->db;
|
||||
table_name= table->s->table_name;
|
||||
}
|
||||
|
||||
if (grant->want_privilege)
|
||||
return check_grant_column(thd, grant, db_name, table_name, name,
|
||||
length, sctx);
|
||||
else
|
||||
return FALSE;
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool check_grant_all_columns(THD *thd, ulong want_access, GRANT_INFO *grant,
|
||||
const char* db_name, const char *table_name,
|
||||
Field_iterator *fields)
|
||||
|
@ -204,7 +204,9 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
|
||||
uint show_command, uint number, bool dont_print_error);
|
||||
bool check_grant_column (THD *thd, GRANT_INFO *grant,
|
||||
const char *db_name, const char *table_name,
|
||||
const char *name, uint length, uint show_command=0);
|
||||
const char *name, uint length, Security_context *sctx);
|
||||
bool check_column_grant_in_table_ref(THD *thd, TABLE_LIST * table_ref,
|
||||
const char *name, uint length);
|
||||
bool check_grant_all_columns(THD *thd, ulong want_access, GRANT_INFO *grant,
|
||||
const char* db_name, const char *table_name,
|
||||
Field_iterator *fields);
|
||||
|
208
sql/sql_base.cc
208
sql/sql_base.cc
@ -2714,47 +2714,6 @@ static void update_field_dependencies(THD *thd, Field *field, TABLE *table)
|
||||
}
|
||||
|
||||
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
/*
|
||||
Check column rights in given security context
|
||||
|
||||
SYNOPSIS
|
||||
check_grant_column_in_sctx()
|
||||
thd thread handler
|
||||
grant grant information structure
|
||||
db db name
|
||||
table table name
|
||||
name column name
|
||||
length column name length
|
||||
check_grants need to check grants
|
||||
sctx 0 or security context
|
||||
|
||||
RETURN
|
||||
FALSE OK
|
||||
TRUE access denied
|
||||
*/
|
||||
|
||||
static bool check_grant_column_in_sctx(THD *thd, GRANT_INFO *grant,
|
||||
const char *db, const char *table,
|
||||
const char *name, uint length,
|
||||
bool check_grants,
|
||||
Security_context *sctx)
|
||||
{
|
||||
if (!check_grants)
|
||||
return FALSE;
|
||||
Security_context *save_security_ctx= thd->security_ctx;
|
||||
bool res;
|
||||
if (sctx)
|
||||
{
|
||||
thd->security_ctx= sctx;
|
||||
}
|
||||
res= check_grant_column(thd, grant, db, table, name, length);
|
||||
thd->security_ctx= save_security_ctx;
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
Find a field by name in a view that uses merge algorithm.
|
||||
|
||||
@ -2763,11 +2722,10 @@ static bool check_grant_column_in_sctx(THD *thd, GRANT_INFO *grant,
|
||||
thd thread handler
|
||||
table_list view to search for 'name'
|
||||
name name of field
|
||||
item_name name of item if it will be created (VIEW)
|
||||
length length of name
|
||||
item_name name of item if it will be created (VIEW)
|
||||
ref expression substituted in VIEW should be passed
|
||||
using this reference (return view_ref_found)
|
||||
check_grants do check columns grants for view?
|
||||
register_tree_change TRUE if ref is not stack variable and we
|
||||
need register changes in item tree
|
||||
|
||||
@ -2779,8 +2737,8 @@ static bool check_grant_column_in_sctx(THD *thd, GRANT_INFO *grant,
|
||||
|
||||
static Field *
|
||||
find_field_in_view(THD *thd, TABLE_LIST *table_list,
|
||||
const char *name, const char *item_name,
|
||||
uint length, Item **ref, bool check_grants,
|
||||
const char *name, uint length,
|
||||
const char *item_name, Item **ref,
|
||||
bool register_tree_change)
|
||||
{
|
||||
DBUG_ENTER("find_field_in_view");
|
||||
@ -2797,24 +2755,13 @@ find_field_in_view(THD *thd, TABLE_LIST *table_list,
|
||||
{
|
||||
if (!my_strcasecmp(system_charset_info, field_it.name(), name))
|
||||
{
|
||||
if (table_list->schema_table_reformed)
|
||||
/*
|
||||
Translation table items are always Item_fields and fixed already
|
||||
('mysql_schema_table' function). So we can return ->field. It is
|
||||
used only for 'show & where' commands.
|
||||
*/
|
||||
DBUG_RETURN(((Item_field*) (field_it.item()))->field);
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
if (check_grant_column_in_sctx(thd, &table_list->grant,
|
||||
table_list->view_db.str,
|
||||
table_list->view_name.str, name, length,
|
||||
check_grants,
|
||||
table_list->security_ctx))
|
||||
DBUG_RETURN(WRONG_GRANT);
|
||||
#endif
|
||||
// in PS use own arena or data will be freed after prepare
|
||||
if (register_tree_change)
|
||||
arena= thd->activate_stmt_arena_if_needed(&backup);
|
||||
/*
|
||||
create_item() may, or may not create a new Item, depending on
|
||||
the column reference. See create_view_field() for details.
|
||||
*/
|
||||
Item *item= field_it.create_item(thd);
|
||||
if (register_tree_change && arena)
|
||||
thd->restore_active_arena(arena, &backup);
|
||||
@ -2856,7 +2803,6 @@ find_field_in_view(THD *thd, TABLE_LIST *table_list,
|
||||
length [in] length of name
|
||||
ref [in/out] if 'name' is resolved to a view field, ref is
|
||||
set to point to the found view field
|
||||
check_grants [in] do check columns grants?
|
||||
register_tree_change [in] TRUE if ref is not stack variable and we
|
||||
need register changes in item tree
|
||||
actual_table [out] the original table reference where the field
|
||||
@ -2877,8 +2823,7 @@ find_field_in_view(THD *thd, TABLE_LIST *table_list,
|
||||
|
||||
static Field *
|
||||
find_field_in_natural_join(THD *thd, TABLE_LIST *table_ref, const char *name,
|
||||
uint length, Item **ref, bool check_grants,
|
||||
bool register_tree_change,
|
||||
uint length, Item **ref, bool register_tree_change,
|
||||
TABLE_LIST **actual_table)
|
||||
{
|
||||
List_iterator_fast<Natural_join_column>
|
||||
@ -2903,23 +2848,16 @@ find_field_in_natural_join(THD *thd, TABLE_LIST *table_ref, const char *name,
|
||||
break;
|
||||
}
|
||||
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
if (check_grants && nj_col->check_grants(thd, name, length))
|
||||
DBUG_RETURN(WRONG_GRANT);
|
||||
#endif
|
||||
|
||||
if (nj_col->view_field)
|
||||
{
|
||||
Item *item;
|
||||
/*
|
||||
The found field is a view field, we do as in find_field_in_view()
|
||||
and return a pointer to pointer to the Item of that field.
|
||||
*/
|
||||
if (register_tree_change)
|
||||
arena= thd->activate_stmt_arena_if_needed(&backup);
|
||||
|
||||
/*
|
||||
create_item() may, or may not create a new Item, depending on the
|
||||
column reference. See create_view_field() for details.
|
||||
*/
|
||||
item= nj_col->create_item(thd);
|
||||
|
||||
if (register_tree_change && arena)
|
||||
thd->restore_active_arena(arena, &backup);
|
||||
|
||||
@ -2965,7 +2903,6 @@ find_field_in_natural_join(THD *thd, TABLE_LIST *table_ref, const char *name,
|
||||
table table where to search for the field
|
||||
name name of field
|
||||
length length of name
|
||||
check_grants do check columns grants?
|
||||
allow_rowid do allow finding of "_rowid" field?
|
||||
cached_field_index_ptr cached position in field list (used to speedup
|
||||
lookup for fields in prepared tables)
|
||||
@ -2977,9 +2914,7 @@ find_field_in_natural_join(THD *thd, TABLE_LIST *table_ref, const char *name,
|
||||
|
||||
Field *
|
||||
find_field_in_table(THD *thd, TABLE *table, const char *name, uint length,
|
||||
bool check_grants, bool allow_rowid,
|
||||
uint *cached_field_index_ptr,
|
||||
Security_context *sctx)
|
||||
bool allow_rowid, uint *cached_field_index_ptr)
|
||||
{
|
||||
Field **field_ptr, *field;
|
||||
uint cached_field_index= *cached_field_index_ptr;
|
||||
@ -3018,13 +2953,6 @@ find_field_in_table(THD *thd, TABLE *table, const char *name, uint length,
|
||||
|
||||
update_field_dependencies(thd, field, table);
|
||||
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
if (check_grant_column_in_sctx(thd, &table->grant,
|
||||
table->s->db, table->s->table_name,
|
||||
name, length,
|
||||
check_grants, sctx))
|
||||
field= WRONG_GRANT;
|
||||
#endif
|
||||
DBUG_RETURN(field);
|
||||
}
|
||||
|
||||
@ -3037,14 +2965,13 @@ find_field_in_table(THD *thd, TABLE *table, const char *name, uint length,
|
||||
thd [in] thread handler
|
||||
table_list [in] table reference to search
|
||||
name [in] name of field
|
||||
item_name [in] name of item if it will be created (VIEW)
|
||||
table_name [in] optional table name that qualifies the field
|
||||
db_name [in] optional database name that qualifies the
|
||||
length [in] field length of name
|
||||
item_name [in] name of item if it will be created (VIEW)
|
||||
db_name [in] optional database name that qualifies the
|
||||
table_name [in] optional table name that qualifies the field
|
||||
ref [in/out] if 'name' is resolved to a view field, ref
|
||||
is set to point to the found view field
|
||||
check_grants_table [in] do check columns grants for table?
|
||||
check_grants_view [in] do check columns grants for view?
|
||||
check_privileges [in] check privileges
|
||||
allow_rowid [in] do allow finding of "_rowid" field?
|
||||
cached_field_index_ptr [in] cached position in field list (used to
|
||||
speedup lookup for fields in prepared tables)
|
||||
@ -3074,11 +3001,11 @@ find_field_in_table(THD *thd, TABLE *table, const char *name, uint length,
|
||||
|
||||
Field *
|
||||
find_field_in_table_ref(THD *thd, TABLE_LIST *table_list,
|
||||
const char *name, const char *item_name,
|
||||
const char *table_name, const char *db_name,
|
||||
uint length, Item **ref,
|
||||
bool check_grants_table, bool check_grants_view,
|
||||
bool allow_rowid, uint *cached_field_index_ptr,
|
||||
const char *name, uint length,
|
||||
const char *item_name, const char *db_name,
|
||||
const char *table_name, Item **ref,
|
||||
bool check_privileges, bool allow_rowid,
|
||||
uint *cached_field_index_ptr,
|
||||
bool register_tree_change, TABLE_LIST **actual_table)
|
||||
{
|
||||
Field *fld;
|
||||
@ -3123,8 +3050,7 @@ find_field_in_table_ref(THD *thd, TABLE_LIST *table_list,
|
||||
if (table_list->field_translation)
|
||||
{
|
||||
/* 'table_list' is a view or an information schema table. */
|
||||
if ((fld= find_field_in_view(thd, table_list, name, item_name, length,
|
||||
ref, check_grants_view,
|
||||
if ((fld= find_field_in_view(thd, table_list, name, length, item_name, ref,
|
||||
register_tree_change)))
|
||||
*actual_table= table_list;
|
||||
}
|
||||
@ -3133,20 +3059,9 @@ find_field_in_table_ref(THD *thd, TABLE_LIST *table_list,
|
||||
/* 'table_list' is a stored table. */
|
||||
DBUG_ASSERT(table_list->table);
|
||||
if ((fld= find_field_in_table(thd, table_list->table, name, length,
|
||||
check_grants_table, allow_rowid,
|
||||
cached_field_index_ptr,
|
||||
table_list->security_ctx)))
|
||||
allow_rowid,
|
||||
cached_field_index_ptr)))
|
||||
*actual_table= table_list;
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
/* check for views with temporary table algorithm */
|
||||
if (check_grants_view && table_list->view &&
|
||||
fld && fld != WRONG_GRANT &&
|
||||
check_grant_column(thd, &table_list->grant,
|
||||
table_list->view_db.str,
|
||||
table_list->view_name.str,
|
||||
name, length))
|
||||
fld= WRONG_GRANT;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -3163,11 +3078,10 @@ find_field_in_table_ref(THD *thd, TABLE_LIST *table_list,
|
||||
TABLE_LIST *table;
|
||||
while ((table= it++))
|
||||
{
|
||||
if ((fld= find_field_in_table_ref(thd, table, name, item_name,
|
||||
table_name, db_name, length, ref,
|
||||
check_grants_table,
|
||||
check_grants_view,
|
||||
allow_rowid, cached_field_index_ptr,
|
||||
if ((fld= find_field_in_table_ref(thd, table, name, length, item_name,
|
||||
db_name, table_name, ref,
|
||||
check_privileges, allow_rowid,
|
||||
cached_field_index_ptr,
|
||||
register_tree_change, actual_table)))
|
||||
DBUG_RETURN(fld);
|
||||
}
|
||||
@ -3180,11 +3094,16 @@ find_field_in_table_ref(THD *thd, TABLE_LIST *table_list,
|
||||
directly the top-most NATURAL/USING join.
|
||||
*/
|
||||
fld= find_field_in_natural_join(thd, table_list, name, length, ref,
|
||||
/* TIMOUR_TODO: check this with Sanja */
|
||||
check_grants_table || check_grants_view,
|
||||
register_tree_change, actual_table);
|
||||
}
|
||||
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
/* Check if there are sufficient access rights to the found field. */
|
||||
if (fld && check_privileges &&
|
||||
check_column_grant_in_table_ref(thd, *actual_table, name, length))
|
||||
fld= WRONG_GRANT;
|
||||
#endif
|
||||
|
||||
DBUG_RETURN(fld);
|
||||
}
|
||||
|
||||
@ -3266,21 +3185,11 @@ find_field_in_tables(THD *thd, Item_ident *item,
|
||||
*/
|
||||
if (table_ref->table && !table_ref->view)
|
||||
found= find_field_in_table(thd, table_ref->table, name, length,
|
||||
test(table_ref->table->
|
||||
grant.want_privilege) &&
|
||||
check_privileges,
|
||||
1, &(item->cached_field_index),
|
||||
table_ref->security_ctx);
|
||||
TRUE, &(item->cached_field_index));
|
||||
else
|
||||
found= find_field_in_table_ref(thd, table_ref, name, item->name,
|
||||
NULL, NULL, length, ref,
|
||||
(table_ref->table &&
|
||||
test(table_ref->table->grant.
|
||||
want_privilege) &&
|
||||
check_privileges),
|
||||
(test(table_ref->grant.want_privilege) &&
|
||||
check_privileges),
|
||||
1, &(item->cached_field_index),
|
||||
found= find_field_in_table_ref(thd, table_ref, name, length, item->name,
|
||||
NULL, NULL, ref, check_privileges,
|
||||
TRUE, &(item->cached_field_index),
|
||||
register_tree_change,
|
||||
&actual_table);
|
||||
if (found)
|
||||
@ -3320,17 +3229,9 @@ find_field_in_tables(THD *thd, Item_ident *item,
|
||||
for (; cur_table != last_table ;
|
||||
cur_table= cur_table->next_name_resolution_table)
|
||||
{
|
||||
Field *cur_field= find_field_in_table_ref(thd, cur_table, name, item->name,
|
||||
table_name, db,
|
||||
length, ref,
|
||||
(cur_table->table &&
|
||||
test(cur_table->table->grant.
|
||||
want_privilege) &&
|
||||
check_privileges),
|
||||
(test(cur_table->grant.
|
||||
want_privilege)
|
||||
&& check_privileges),
|
||||
allow_rowid,
|
||||
Field *cur_field= find_field_in_table_ref(thd, cur_table, name, length,
|
||||
item->name, db, table_name, ref,
|
||||
check_privileges, allow_rowid,
|
||||
&(item->cached_field_index),
|
||||
register_tree_change,
|
||||
&actual_table);
|
||||
@ -3738,7 +3639,7 @@ mark_common_columns(THD *thd, TABLE_LIST *table_ref_1, TABLE_LIST *table_ref_2,
|
||||
{
|
||||
bool is_created_1;
|
||||
bool found= FALSE;
|
||||
if (!(nj_col_1= it_1.get_or_create_column_ref(thd, &is_created_1)))
|
||||
if (!(nj_col_1= it_1.get_or_create_column_ref(&is_created_1)))
|
||||
goto err;
|
||||
field_name_1= nj_col_1->name();
|
||||
|
||||
@ -3759,7 +3660,7 @@ mark_common_columns(THD *thd, TABLE_LIST *table_ref_1, TABLE_LIST *table_ref_2,
|
||||
bool is_created_2;
|
||||
Natural_join_column *cur_nj_col_2;
|
||||
const char *cur_field_name_2;
|
||||
if (!(cur_nj_col_2= it_2.get_or_create_column_ref(thd, &is_created_2)))
|
||||
if (!(cur_nj_col_2= it_2.get_or_create_column_ref(&is_created_2)))
|
||||
goto err;
|
||||
cur_field_name_2= cur_nj_col_2->name();
|
||||
|
||||
@ -3951,13 +3852,7 @@ store_natural_using_join_columns(THD *thd, TABLE_LIST *natural_using_join,
|
||||
/* Append the columns of the first join operand. */
|
||||
for (it_1.set(table_ref_1); !it_1.end_of_fields(); it_1.next())
|
||||
{
|
||||
if (!(nj_col_1= it_1.get_or_create_column_ref(thd, &is_created)))
|
||||
goto err;
|
||||
/*
|
||||
The following assert checks that mark_common_columns() was run and
|
||||
we created the list table_ref_1->join_columns.
|
||||
*/
|
||||
DBUG_ASSERT(!is_created);
|
||||
nj_col_1= it_1.get_natural_column_ref();
|
||||
if (nj_col_1->is_common)
|
||||
{
|
||||
natural_using_join->join_columns->push_back(nj_col_1);
|
||||
@ -4003,13 +3898,7 @@ store_natural_using_join_columns(THD *thd, TABLE_LIST *natural_using_join,
|
||||
/* Append the non-equi-join columns of the second join operand. */
|
||||
for (it_2.set(table_ref_2); !it_2.end_of_fields(); it_2.next())
|
||||
{
|
||||
if (!(nj_col_2= it_2.get_or_create_column_ref(thd, &is_created)))
|
||||
goto err;
|
||||
/*
|
||||
The following assert checks that mark_common_columns() was run and
|
||||
we created the list table_ref_2->join_columns.
|
||||
*/
|
||||
DBUG_ASSERT(!is_created);
|
||||
nj_col_2= it_2.get_natural_column_ref();
|
||||
if (!nj_col_2->is_common)
|
||||
non_join_columns->push_back(nj_col_2);
|
||||
else
|
||||
@ -4743,8 +4632,7 @@ insert_fields(THD *thd, Name_resolution_context *context, const char *db_name,
|
||||
because it was already created and stored with the natural join.
|
||||
*/
|
||||
Natural_join_column *nj_col;
|
||||
if (!(nj_col= field_iterator.get_or_create_column_ref(thd,
|
||||
&is_created)))
|
||||
if (!(nj_col= field_iterator.get_or_create_column_ref(&is_created)))
|
||||
DBUG_RETURN(TRUE);
|
||||
DBUG_ASSERT(nj_col->table_field && !is_created);
|
||||
field_table= nj_col->table_ref->table;
|
||||
|
@ -108,11 +108,7 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list,
|
||||
{ // Part field list
|
||||
SELECT_LEX *select_lex= &thd->lex->select_lex;
|
||||
Name_resolution_context *context= &select_lex->context;
|
||||
TABLE_LIST *save_next_local;
|
||||
TABLE_LIST *save_table_list;
|
||||
TABLE_LIST *save_first_name_resolution_table;
|
||||
TABLE_LIST *save_next_name_resolution_table;
|
||||
bool save_resolve_in_select_list;
|
||||
Name_resolution_context_state ctx_state;
|
||||
int res;
|
||||
|
||||
if (fields.elements != values.elements)
|
||||
@ -125,14 +121,7 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list,
|
||||
select_lex->no_wrap_view_item= TRUE;
|
||||
|
||||
/* Save the state of the current name resolution context. */
|
||||
save_table_list= context->table_list;
|
||||
save_first_name_resolution_table= context->first_name_resolution_table;
|
||||
save_next_name_resolution_table= (context->first_name_resolution_table) ?
|
||||
context->first_name_resolution_table->
|
||||
next_name_resolution_table :
|
||||
NULL;
|
||||
save_resolve_in_select_list= context->resolve_in_select_list;
|
||||
save_next_local= table_list->next_local;
|
||||
ctx_state.save_state(context, table_list);
|
||||
|
||||
/*
|
||||
Perform name resolution only in the first table - 'table_list',
|
||||
@ -143,13 +132,7 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list,
|
||||
res= setup_fields(thd, 0, fields, 1, 0, 0);
|
||||
|
||||
/* Restore the current context. */
|
||||
table_list->next_local= save_next_local;
|
||||
context->table_list= save_table_list;
|
||||
context->first_name_resolution_table= save_first_name_resolution_table;
|
||||
if (context->first_name_resolution_table)
|
||||
context->first_name_resolution_table->
|
||||
next_name_resolution_table= save_next_name_resolution_table;
|
||||
context->resolve_in_select_list= save_resolve_in_select_list;
|
||||
ctx_state.restore_state(context, table_list);
|
||||
thd->lex->select_lex.no_wrap_view_item= FALSE;
|
||||
|
||||
if (res)
|
||||
@ -280,13 +263,10 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
|
||||
ulonglong id;
|
||||
COPY_INFO info;
|
||||
TABLE *table= 0;
|
||||
TABLE_LIST *save_table_list;
|
||||
TABLE_LIST *save_next_local;
|
||||
TABLE_LIST *save_first_name_resolution_table;
|
||||
TABLE_LIST *save_next_name_resolution_table;
|
||||
List_iterator_fast<List_item> its(values_list);
|
||||
List_item *values;
|
||||
Name_resolution_context *context;
|
||||
Name_resolution_context_state ctx_state;
|
||||
#ifndef EMBEDDED_LIBRARY
|
||||
char *query= thd->query;
|
||||
#endif
|
||||
@ -367,13 +347,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
|
||||
|
||||
context= &thd->lex->select_lex.context;
|
||||
/* Save the state of the current name resolution context. */
|
||||
save_table_list= context->table_list;
|
||||
save_first_name_resolution_table= context->first_name_resolution_table;
|
||||
save_next_name_resolution_table= (context->first_name_resolution_table) ?
|
||||
context->first_name_resolution_table->
|
||||
next_name_resolution_table :
|
||||
NULL;
|
||||
save_next_local= table_list->next_local;
|
||||
ctx_state.save_state(context, table_list);
|
||||
|
||||
/*
|
||||
Perform name resolution only in the first table - 'table_list',
|
||||
@ -397,16 +371,11 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
|
||||
its.rewind ();
|
||||
|
||||
/* Restore the current context. */
|
||||
table_list->next_local= save_next_local;
|
||||
context->first_name_resolution_table= save_first_name_resolution_table;
|
||||
if (context->first_name_resolution_table)
|
||||
context->first_name_resolution_table->
|
||||
next_name_resolution_table= save_next_name_resolution_table;
|
||||
ctx_state.restore_state(context, table_list);
|
||||
|
||||
/*
|
||||
Fill in the given fields and dump it to the table file
|
||||
*/
|
||||
|
||||
info.records= info.deleted= info.copied= info.updated= 0;
|
||||
info.ignore= ignore;
|
||||
info.handle_duplicates=duplic;
|
||||
@ -814,11 +783,7 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list,
|
||||
{
|
||||
SELECT_LEX *select_lex= &thd->lex->select_lex;
|
||||
Name_resolution_context *context= &select_lex->context;
|
||||
TABLE_LIST *save_table_list;
|
||||
TABLE_LIST *save_next_local;
|
||||
TABLE_LIST *save_first_name_resolution_table;
|
||||
TABLE_LIST *save_next_name_resolution_table;
|
||||
bool save_resolve_in_select_list;
|
||||
Name_resolution_context_state ctx_state;
|
||||
bool insert_into_view= (table_list->view != 0);
|
||||
bool res= 0;
|
||||
DBUG_ENTER("mysql_prepare_insert");
|
||||
@ -858,15 +823,7 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list,
|
||||
DBUG_RETURN(TRUE);
|
||||
|
||||
/* Save the state of the current name resolution context. */
|
||||
save_table_list= context->table_list;
|
||||
/* Here first_name_resolution_table points to the first select table. */
|
||||
save_first_name_resolution_table= context->first_name_resolution_table;
|
||||
save_next_name_resolution_table= (context->first_name_resolution_table) ?
|
||||
context->first_name_resolution_table->
|
||||
next_name_resolution_table :
|
||||
NULL;
|
||||
save_resolve_in_select_list= context->resolve_in_select_list;
|
||||
save_next_local= table_list->next_local;
|
||||
ctx_state.save_state(context, table_list);
|
||||
|
||||
/*
|
||||
Perform name resolution only in the first table - 'table_list',
|
||||
@ -891,23 +848,17 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list,
|
||||
*/
|
||||
if (select_lex->group_list.elements == 0)
|
||||
{
|
||||
context->table_list->next_local= save_next_local;
|
||||
context->table_list->next_local= ctx_state.save_next_local;
|
||||
/* first_name_resolution_table was set by resolve_in_table_list_only() */
|
||||
context->first_name_resolution_table->
|
||||
next_name_resolution_table= save_next_local;
|
||||
next_name_resolution_table= ctx_state.save_next_local;
|
||||
}
|
||||
if (!res)
|
||||
res= setup_fields(thd, 0, update_values, 1, 0, 0);
|
||||
}
|
||||
|
||||
/* Restore the current context. */
|
||||
table_list->next_local= save_next_local;
|
||||
context->table_list= save_table_list;
|
||||
context->first_name_resolution_table= save_first_name_resolution_table;
|
||||
if (context->first_name_resolution_table)
|
||||
context->first_name_resolution_table->
|
||||
next_name_resolution_table= save_next_name_resolution_table;
|
||||
context->resolve_in_select_list= save_resolve_in_select_list;
|
||||
ctx_state.restore_state(context, table_list);
|
||||
|
||||
if (res)
|
||||
DBUG_RETURN(res);
|
||||
@ -2176,17 +2127,10 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
|
||||
{
|
||||
/* Save the state of the current name resolution context. */
|
||||
Name_resolution_context *context= &lex->select_lex.context;
|
||||
TABLE_LIST *save_table_list;
|
||||
TABLE_LIST *save_next_local;
|
||||
TABLE_LIST *save_first_name_resolution_table;
|
||||
TABLE_LIST *save_next_name_resolution_table;
|
||||
save_table_list= context->table_list;
|
||||
save_first_name_resolution_table= context->first_name_resolution_table;
|
||||
save_next_name_resolution_table= (context->first_name_resolution_table) ?
|
||||
context->first_name_resolution_table->
|
||||
next_name_resolution_table :
|
||||
NULL;
|
||||
save_next_local= table_list->next_local;
|
||||
Name_resolution_context_state ctx_state;
|
||||
|
||||
/* Save the state of the current name resolution context. */
|
||||
ctx_state.save_state(context, table_list);
|
||||
|
||||
/* Perform name resolution only in the first table - 'table_list'. */
|
||||
table_list->next_local= 0;
|
||||
@ -2202,20 +2146,15 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
|
||||
*/
|
||||
if (lex->select_lex.group_list.elements == 0)
|
||||
{
|
||||
context->table_list->next_local= save_next_local;
|
||||
context->table_list->next_local= ctx_state.save_next_local;
|
||||
/* first_name_resolution_table was set by resolve_in_table_list_only() */
|
||||
context->first_name_resolution_table->
|
||||
next_name_resolution_table= save_next_local;
|
||||
next_name_resolution_table= ctx_state.save_next_local;
|
||||
}
|
||||
res= res || setup_fields(thd, 0, *info.update_values, 1, 0, 0);
|
||||
|
||||
/* Restore the current context. */
|
||||
table_list->next_local= save_next_local;
|
||||
context->first_name_resolution_table= save_first_name_resolution_table;
|
||||
if (context->first_name_resolution_table)
|
||||
context->first_name_resolution_table->
|
||||
next_name_resolution_table= save_next_name_resolution_table;
|
||||
|
||||
ctx_state.restore_state(context, table_list);
|
||||
}
|
||||
|
||||
lex->current_select= lex_current_select_save;
|
||||
|
@ -1127,6 +1127,11 @@ void st_select_lex::init_query()
|
||||
/*
|
||||
Add the name resolution context of the current (sub)query to the
|
||||
stack of contexts for the whole query.
|
||||
TODO:
|
||||
push_context may return an error if there is no memory for a new
|
||||
element in the stack, however this method has no return value,
|
||||
thus push_context should be moved to a place where query
|
||||
initialization is checked for failure.
|
||||
*/
|
||||
parent_lex->push_context(&context);
|
||||
cond_count= with_wild= 0;
|
||||
|
@ -1006,9 +1006,9 @@ typedef struct st_lex
|
||||
}
|
||||
void cleanup_after_one_table_open();
|
||||
|
||||
void push_context(Name_resolution_context *context)
|
||||
bool push_context(Name_resolution_context *context)
|
||||
{
|
||||
context_stack.push_front(context);
|
||||
return context_stack.push_front(context);
|
||||
}
|
||||
|
||||
void pop_context()
|
||||
|
@ -266,10 +266,21 @@ protected:
|
||||
ls.elements= elm;
|
||||
}
|
||||
public:
|
||||
base_list_iterator(base_list &list_par)
|
||||
:list(&list_par), el(&list_par.first), prev(0), current(0)
|
||||
base_list_iterator()
|
||||
:list(0), el(0), prev(0), current(0)
|
||||
{}
|
||||
|
||||
base_list_iterator(base_list &list_par)
|
||||
{ init(list_par); }
|
||||
|
||||
inline void init(base_list &list_par)
|
||||
{
|
||||
list= &list_par;
|
||||
el= &list_par.first;
|
||||
prev= 0;
|
||||
current= 0;
|
||||
}
|
||||
|
||||
inline void *next(void)
|
||||
{
|
||||
prev=el;
|
||||
@ -364,6 +375,8 @@ template <class T> class List_iterator :public base_list_iterator
|
||||
{
|
||||
public:
|
||||
List_iterator(List<T> &a) : base_list_iterator(a) {}
|
||||
List_iterator() : base_list_iterator() {}
|
||||
inline void init(List<T> &a) { base_list_iterator::init(a); }
|
||||
inline T* operator++(int) { return (T*) base_list_iterator::next(); }
|
||||
inline T *replace(T *a) { return (T*) base_list_iterator::replace(a); }
|
||||
inline T *replace(List<T> &a) { return (T*) base_list_iterator::replace(a); }
|
||||
@ -385,6 +398,8 @@ protected:
|
||||
|
||||
public:
|
||||
inline List_iterator_fast(List<T> &a) : base_list_iterator(a) {}
|
||||
inline List_iterator_fast() : base_list_iterator() {}
|
||||
inline void init(List<T> &a) { base_list_iterator::init(a); }
|
||||
inline T* operator++(int) { return (T*) base_list_iterator::next_fast(); }
|
||||
inline void rewind(void) { base_list_iterator::rewind(); }
|
||||
void sublist(List<T> &list_arg, uint el_arg)
|
||||
|
@ -6583,36 +6583,39 @@ void st_select_lex::set_lock_for_tables(thr_lock_type lock_type)
|
||||
|
||||
|
||||
/*
|
||||
Create a new name resolution context for a JOIN ... ON clause.
|
||||
Push a new name resolution context for a JOIN ... ON clause to the
|
||||
context stack of a query block.
|
||||
|
||||
SYNOPSIS
|
||||
make_join_on_context()
|
||||
push_new_name_resolution_context()
|
||||
thd pointer to current thread
|
||||
left_op left operand of the JOIN
|
||||
right_op rigth operand of the JOIN
|
||||
|
||||
DESCRIPTION
|
||||
Create a new name resolution context for a JOIN ... ON clause,
|
||||
and set the first and last leaves of the list of table references
|
||||
to be used for name resolution.
|
||||
set the first and last leaves of the list of table references
|
||||
to be used for name resolution, and push the newly created
|
||||
context to the stack of contexts of the query.
|
||||
|
||||
RETURN
|
||||
A new context if all is OK
|
||||
NULL - if a memory allocation error occured
|
||||
FALSE if all is OK
|
||||
TRUE if a memory allocation error occured
|
||||
*/
|
||||
|
||||
Name_resolution_context *
|
||||
make_join_on_context(THD *thd, TABLE_LIST *left_op, TABLE_LIST *right_op)
|
||||
bool
|
||||
push_new_name_resolution_context(THD *thd,
|
||||
TABLE_LIST *left_op, TABLE_LIST *right_op)
|
||||
{
|
||||
Name_resolution_context *on_context;
|
||||
if (!(on_context= new (thd->mem_root) Name_resolution_context))
|
||||
return NULL;
|
||||
return TRUE;
|
||||
on_context->init();
|
||||
on_context->first_name_resolution_table=
|
||||
left_op->first_leaf_for_name_resolution();
|
||||
on_context->last_name_resolution_table=
|
||||
right_op->last_leaf_for_name_resolution();
|
||||
return on_context;
|
||||
return thd->lex->push_context(on_context);
|
||||
}
|
||||
|
||||
|
||||
|
@ -5185,10 +5185,8 @@ join_table:
|
||||
{
|
||||
YYERROR_UNLESS($1 && ($$=$3));
|
||||
/* Change the current name resolution context to a local context. */
|
||||
Name_resolution_context *on_context;
|
||||
if (!(on_context= make_join_on_context(YYTHD,$1,$3)))
|
||||
if (push_new_name_resolution_context(YYTHD, $1, $3))
|
||||
YYABORT;
|
||||
Lex->push_context(on_context);
|
||||
}
|
||||
expr
|
||||
{
|
||||
@ -5200,10 +5198,8 @@ join_table:
|
||||
{
|
||||
YYERROR_UNLESS($1 && ($$=$3));
|
||||
/* Change the current name resolution context to a local context. */
|
||||
Name_resolution_context *on_context;
|
||||
if (!(on_context= make_join_on_context(YYTHD,$1,$3)))
|
||||
if (push_new_name_resolution_context(YYTHD, $1, $3))
|
||||
YYABORT;
|
||||
Lex->push_context(on_context);
|
||||
}
|
||||
expr
|
||||
{
|
||||
@ -5230,10 +5226,8 @@ join_table:
|
||||
ON
|
||||
{
|
||||
/* Change the current name resolution context to a local context. */
|
||||
Name_resolution_context *on_context;
|
||||
if (!(on_context= make_join_on_context(YYTHD,$1,$5)))
|
||||
if (push_new_name_resolution_context(YYTHD, $1, $5))
|
||||
YYABORT;
|
||||
Lex->push_context(on_context);
|
||||
}
|
||||
expr
|
||||
{
|
||||
@ -5263,10 +5257,8 @@ join_table:
|
||||
ON
|
||||
{
|
||||
/* Change the current name resolution context to a local context. */
|
||||
Name_resolution_context *on_context;
|
||||
if (!(on_context= make_join_on_context(YYTHD,$1,$5)))
|
||||
if (push_new_name_resolution_context(YYTHD, $1, $5))
|
||||
YYABORT;
|
||||
Lex->push_context(on_context);
|
||||
}
|
||||
expr
|
||||
{
|
||||
@ -5327,10 +5319,9 @@ table_factor:
|
||||
ON
|
||||
{
|
||||
/* Change the current name resolution context to a local context. */
|
||||
Name_resolution_context *on_context;
|
||||
if (!(on_context= make_join_on_context(YYTHD,$3,$7)))
|
||||
if (push_new_name_resolution_context(YYTHD, $3, $7))
|
||||
YYABORT;
|
||||
Lex->push_context(on_context);
|
||||
|
||||
}
|
||||
expr '}'
|
||||
{
|
||||
|
110
sql/table.cc
110
sql/table.cc
@ -2606,60 +2606,6 @@ GRANT_INFO *Natural_join_column::grant()
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
|
||||
/*
|
||||
Check the access rights for the current join column.
|
||||
columns.
|
||||
|
||||
SYNOPSIS
|
||||
Natural_join_column::check_grants()
|
||||
|
||||
DESCRIPTION
|
||||
Check the access rights to a column from a natural join in a generic
|
||||
way that hides the heterogeneity of the column representation - whether
|
||||
it is a view or a stored table colum.
|
||||
|
||||
RETURN
|
||||
FALSE The column can be accessed
|
||||
TRUE There are no access rights to all equivalent columns
|
||||
*/
|
||||
|
||||
bool
|
||||
Natural_join_column::check_grants(THD *thd, const char *name, uint length)
|
||||
{
|
||||
GRANT_INFO *grant;
|
||||
const char *db_name;
|
||||
const char *table_name;
|
||||
Security_context *save_security_ctx= thd->security_ctx;
|
||||
Security_context *new_sctx= table_ref->security_ctx;
|
||||
bool res;
|
||||
|
||||
if (view_field)
|
||||
{
|
||||
DBUG_ASSERT(table_field == NULL);
|
||||
grant= &(table_ref->grant);
|
||||
db_name= table_ref->view_db.str;
|
||||
table_name= table_ref->view_name.str;
|
||||
}
|
||||
else
|
||||
{
|
||||
DBUG_ASSERT(table_field && view_field == NULL);
|
||||
grant= &(table_ref->table->grant);
|
||||
db_name= table_ref->table->s->db;
|
||||
table_name= table_ref->table->s->table_name;
|
||||
}
|
||||
|
||||
if (new_sctx)
|
||||
thd->security_ctx= new_sctx;
|
||||
res= check_grant_column(thd, grant, db_name, table_name, name, length);
|
||||
thd->security_ctx= save_security_ctx;
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void Field_iterator_view::set(TABLE_LIST *table)
|
||||
{
|
||||
DBUG_ASSERT(table->field_translation);
|
||||
@ -2702,8 +2648,9 @@ Item *create_view_field(THD *thd, TABLE_LIST *view, Item **field_ref,
|
||||
if (view->schema_table_reformed)
|
||||
{
|
||||
/*
|
||||
In case of SHOW command (schema_table_reformed set) all items are
|
||||
fixed
|
||||
Translation table items are always Item_fields and already fixed
|
||||
('mysql_schema_table' function). So we can return directly the
|
||||
field. This case happens only for 'show & where' commands.
|
||||
*/
|
||||
DBUG_ASSERT(field && field->fixed);
|
||||
DBUG_RETURN(field);
|
||||
@ -2735,21 +2682,14 @@ Item *create_view_field(THD *thd, TABLE_LIST *view, Item **field_ref,
|
||||
void Field_iterator_natural_join::set(TABLE_LIST *table_ref)
|
||||
{
|
||||
DBUG_ASSERT(table_ref->join_columns);
|
||||
delete column_ref_it;
|
||||
|
||||
/*
|
||||
TODO: try not to allocate new iterator every time. If we have to,
|
||||
then check for out of memory condition.
|
||||
*/
|
||||
column_ref_it= new List_iterator_fast<Natural_join_column>
|
||||
(*(table_ref->join_columns));
|
||||
cur_column_ref= (*column_ref_it)++;
|
||||
column_ref_it.init(*(table_ref->join_columns));
|
||||
cur_column_ref= column_ref_it++;
|
||||
}
|
||||
|
||||
|
||||
void Field_iterator_natural_join::next()
|
||||
{
|
||||
cur_column_ref= (*column_ref_it)++;
|
||||
cur_column_ref= column_ref_it++;
|
||||
DBUG_ASSERT(!cur_column_ref || ! cur_column_ref->table_field ||
|
||||
cur_column_ref->table_ref->table ==
|
||||
cur_column_ref->table_field->table);
|
||||
@ -2876,7 +2816,6 @@ GRANT_INFO *Field_iterator_table_ref::grant()
|
||||
|
||||
SYNOPSIS
|
||||
Field_iterator_table_ref::get_or_create_column_ref()
|
||||
thd [in] pointer to current thread
|
||||
is_created [out] set to TRUE if the column was created,
|
||||
FALSE if we return an already created colum
|
||||
|
||||
@ -2889,7 +2828,7 @@ GRANT_INFO *Field_iterator_table_ref::grant()
|
||||
*/
|
||||
|
||||
Natural_join_column *
|
||||
Field_iterator_table_ref::get_or_create_column_ref(THD *thd, bool *is_created)
|
||||
Field_iterator_table_ref::get_or_create_column_ref(bool *is_created)
|
||||
{
|
||||
Natural_join_column *nj_col;
|
||||
|
||||
@ -2923,6 +2862,41 @@ Field_iterator_table_ref::get_or_create_column_ref(THD *thd, bool *is_created)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Return an existing reference to a column of a natural/using join.
|
||||
|
||||
SYNOPSIS
|
||||
Field_iterator_table_ref::get_natural_column_ref()
|
||||
|
||||
DESCRIPTION
|
||||
The method should be called in contexts where it is expected that
|
||||
all natural join columns are already created, and that the column
|
||||
being retrieved is a Natural_join_column.
|
||||
|
||||
RETURN
|
||||
# Pointer to a column of a natural join (or its operand)
|
||||
NULL No memory to allocate the column
|
||||
*/
|
||||
|
||||
Natural_join_column *
|
||||
Field_iterator_table_ref::get_natural_column_ref()
|
||||
{
|
||||
Natural_join_column *nj_col;
|
||||
|
||||
DBUG_ASSERT(field_it == &natural_join_it);
|
||||
/*
|
||||
The field belongs to a NATURAL join, therefore the column reference was
|
||||
already created via one of the two constructor calls above. In this case
|
||||
we just return the already created column reference.
|
||||
*/
|
||||
nj_col= natural_join_it.column_ref();
|
||||
DBUG_ASSERT(nj_col &&
|
||||
(!nj_col->table_field ||
|
||||
nj_col->table_ref->table == nj_col->table_field->table));
|
||||
return nj_col;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
** Instansiate templates
|
||||
*****************************************************************************/
|
||||
|
12
sql/table.h
12
sql/table.h
@ -407,9 +407,6 @@ public:
|
||||
const char *table_name();
|
||||
const char *db_name();
|
||||
GRANT_INFO *grant();
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
bool check_grants(THD *thd, const char *name, uint length);
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@ -734,11 +731,11 @@ public:
|
||||
|
||||
class Field_iterator_natural_join: public Field_iterator
|
||||
{
|
||||
List_iterator_fast<Natural_join_column> *column_ref_it;
|
||||
List_iterator_fast<Natural_join_column> column_ref_it;
|
||||
Natural_join_column *cur_column_ref;
|
||||
public:
|
||||
Field_iterator_natural_join() :column_ref_it(NULL), cur_column_ref(NULL) {}
|
||||
~Field_iterator_natural_join() { delete column_ref_it; }
|
||||
Field_iterator_natural_join() :cur_column_ref(NULL) {}
|
||||
~Field_iterator_natural_join() {}
|
||||
void set(TABLE_LIST *table);
|
||||
void next();
|
||||
bool end_of_fields() { return !cur_column_ref; }
|
||||
@ -785,7 +782,8 @@ public:
|
||||
GRANT_INFO *grant();
|
||||
Item *create_item(THD *thd) { return field_it->create_item(thd); }
|
||||
Field *field() { return field_it->field(); }
|
||||
Natural_join_column *get_or_create_column_ref(THD *thd, bool *is_created);
|
||||
Natural_join_column *get_or_create_column_ref(bool *is_created);
|
||||
Natural_join_column *get_natural_column_ref();
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user