summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/item_strfunc.h2
-rw-r--r--sql/log_event.cc2
-rw-r--r--sql/mysql_priv.h5
-rw-r--r--sql/sql_base.cc4
-rw-r--r--sql/sql_insert.cc19
-rw-r--r--sql/sql_lex.cc1
-rw-r--r--sql/sql_load.cc65
-rw-r--r--sql/sql_parse.cc3
-rw-r--r--sql/sql_yacc.yy2
-rw-r--r--sql/table.cc29
-rw-r--r--sql/table.h2
11 files changed, 93 insertions, 41 deletions
diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h
index 357ce0af45a..49429a55cac 100644
--- a/sql/item_strfunc.h
+++ b/sql/item_strfunc.h
@@ -218,7 +218,7 @@ public:
Item_func_substr_index(Item *a,Item *b,Item *c) :Item_str_func(a,b,c) {}
String *val_str(String *);
void fix_length_and_dec();
- const char *func_name() const { return "substr_index"; }
+ const char *func_name() const { return "substring_index"; }
};
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 01dcb2af21c..c2a684ffe03 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -2548,7 +2548,7 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli,
thd->net.pkt_nr = net->pkt_nr;
}
if (mysql_load(thd, &ex, &tables, field_list, handle_dup, net != 0,
- TL_WRITE))
+ TL_WRITE, 0))
thd->query_error = 1;
if (thd->cuted_fields)
{
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index a10722cd726..d8916149b77 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -838,9 +838,10 @@ inline TABLE_LIST *find_table_in_local_list(TABLE_LIST *table,
bool eval_const_cond(COND *cond);
/* sql_load.cc */
-int mysql_load(THD *thd,sql_exchange *ex, TABLE_LIST *table_list,
+int mysql_load(THD *thd, sql_exchange *ex, TABLE_LIST *table_list,
List<Item> &fields, enum enum_duplicates handle_duplicates,
- bool local_file,thr_lock_type lock_type);
+ bool local_file, thr_lock_type lock_type,
+ bool ignore_check_option_errors);
int write_record(THD *thd, TABLE *table, COPY_INFO *info);
/* sql_manager.cc */
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 8199c6fcdce..4f273fbd0c4 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -2697,7 +2697,9 @@ bool setup_tables(THD *thd, TABLE_LIST *tables, Item **conds)
table->keys_in_use_for_query.subtract(map);
}
table->used_keys.intersect(table->keys_in_use_for_query);
- if (table_list->ancestor && table_list->setup_ancestor(thd, conds))
+ if (table_list->ancestor &&
+ table_list->setup_ancestor(thd, conds,
+ table_list->effective_with_check))
DBUG_RETURN(1);
}
if (tablenr > MAX_TABLES)
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 36ac56799de..d9002c2da29 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -319,14 +319,6 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
break;
}
}
- if ((res= table_list->view_check_option(thd, ignore_err)) ==
- VIEW_CHECK_SKIP)
- continue;
- else if (res == VIEW_CHECK_ERROR)
- {
- error= 1;
- break;
- }
/*
FIXME: Actually we should do this before
@@ -336,6 +328,17 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
table->triggers->process_triggers(thd, TRG_EVENT_INSERT,
TRG_ACTION_BEFORE);
+ if ((res= table_list->view_check_option(thd,
+ (values_list.elements == 1 ?
+ 0 :
+ ignore_err))) ==
+ VIEW_CHECK_SKIP)
+ continue;
+ else if (res == VIEW_CHECK_ERROR)
+ {
+ error= 1;
+ break;
+ }
#ifndef EMBEDDED_LIBRARY
if (lock_type == TL_WRITE_DELAYED)
{
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 59dc1a7ee8b..73f99d0dd68 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -1616,6 +1616,7 @@ bool st_lex::can_use_merged()
case SQLCOM_INSERT_SELECT:
case SQLCOM_REPLACE:
case SQLCOM_REPLACE_SELECT:
+ case SQLCOM_LOAD:
return TRUE;
default:
return FALSE;
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index 28de2b9d116..95025a8fd77 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -71,16 +71,19 @@ public:
void set_io_cache_arg(void* arg) { cache.arg = arg; }
};
-static int read_fixed_length(THD *thd,COPY_INFO &info,TABLE *table,
+static int read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
List<Item> &fields, READ_INFO &read_info,
- ulong skip_lines);
-static int read_sep_field(THD *thd,COPY_INFO &info,TABLE *table,
+ ulong skip_lines,
+ bool ignore_check_option_errors);
+static int read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
List<Item> &fields, READ_INFO &read_info,
- String &enclosed, ulong skip_lines);
+ String &enclosed, ulong skip_lines,
+ bool ignore_check_option_errors);
int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
List<Item> &fields, enum enum_duplicates handle_duplicates,
- bool read_file_from_client,thr_lock_type lock_type)
+ bool read_file_from_client,thr_lock_type lock_type,
+ bool ignore_check_option_errors)
{
char name[FN_REFLEN];
File file;
@@ -88,6 +91,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
int error;
String *field_term=ex->field_term,*escaped=ex->escaped;
String *enclosed=ex->enclosed;
+ Item *unused_conds;
bool is_fifo=0;
#ifndef EMBEDDED_LIBRARY
LOAD_FILE_INFO lf_info;
@@ -117,8 +121,9 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
table_list->lock_type= lock_type;
if ((res= open_and_lock_tables(thd, table_list)))
DBUG_RETURN(res);
- /* TODO: add key check when we will support VIEWs in LOAD */
- if (!table_list->updatable)
+ if (setup_tables(thd, table_list, &unused_conds))
+ DBUG_RETURN(-1);
+ if (!table_list->updatable || check_key_in_view(thd, table_list))
{
my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "LOAD");
DBUG_RETURN(-1);
@@ -294,11 +299,12 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
MODE_STRICT_ALL_TABLES)));
if (!field_term->length() && !enclosed->length())
- error=read_fixed_length(thd,info,table,fields,read_info,
- skip_lines);
+ error= read_fixed_length(thd, info, table_list, fields,read_info,
+ skip_lines, ignore_check_option_errors);
else
- error=read_sep_field(thd,info,table,fields,read_info,*enclosed,
- skip_lines);
+ error= read_sep_field(thd, info, table_list, fields, read_info,
+ *enclosed, skip_lines,
+ ignore_check_option_errors);
if (table->file->end_bulk_insert())
error=1; /* purecov: inspected */
table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
@@ -401,11 +407,13 @@ err:
****************************************************************************/
static int
-read_fixed_length(THD *thd,COPY_INFO &info,TABLE *table,List<Item> &fields,
- READ_INFO &read_info, ulong skip_lines)
+read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
+ List<Item> &fields, READ_INFO &read_info, ulong skip_lines,
+ bool ignore_check_option_errors)
{
List_iterator_fast<Item> it(fields);
Item_field *sql_field;
+ TABLE *table= table_list->table;
ulonglong id;
bool no_trans_update;
DBUG_ENTER("read_fixed_length");
@@ -472,6 +480,17 @@ read_fixed_length(THD *thd,COPY_INFO &info,TABLE *table,List<Item> &fields,
ER_WARN_TOO_MANY_RECORDS,
ER(ER_WARN_TOO_MANY_RECORDS), thd->row_count);
}
+
+ switch(table_list->view_check_option(thd,
+ ignore_check_option_errors))
+ {
+ case VIEW_CHECK_SKIP:
+ read_info.next_line();
+ goto continue_loop;
+ case VIEW_CHECK_ERROR:
+ DBUG_RETURN(-1);
+ }
+
if (thd->killed || write_record(thd,table,&info))
DBUG_RETURN(1);
thd->no_trans_update= no_trans_update;
@@ -496,6 +515,7 @@ read_fixed_length(THD *thd,COPY_INFO &info,TABLE *table,List<Item> &fields,
ER(ER_WARN_TOO_MANY_RECORDS), thd->row_count);
}
thd->row_count++;
+continue_loop:;
}
if (id && !read_info.error)
thd->insert_id(id); // For binary/update log
@@ -505,12 +525,14 @@ read_fixed_length(THD *thd,COPY_INFO &info,TABLE *table,List<Item> &fields,
static int
-read_sep_field(THD *thd,COPY_INFO &info,TABLE *table,
+read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
List<Item> &fields, READ_INFO &read_info,
- String &enclosed, ulong skip_lines)
+ String &enclosed, ulong skip_lines,
+ bool ignore_check_option_errors)
{
List_iterator_fast<Item> it(fields);
Item_field *sql_field;
+ TABLE *table= table_list->table;
uint enclosed_length;
ulonglong id;
bool no_trans_update;
@@ -580,6 +602,18 @@ read_sep_field(THD *thd,COPY_INFO &info,TABLE *table,
ER(ER_WARN_TOO_FEW_RECORDS), thd->row_count);
}
}
+
+ switch(table_list->view_check_option(thd,
+ ignore_check_option_errors))
+ {
+ case VIEW_CHECK_SKIP:
+ read_info.next_line();
+ goto continue_loop;
+ case VIEW_CHECK_ERROR:
+ DBUG_RETURN(-1);
+ }
+
+
if (thd->killed || write_record(thd, table, &info))
DBUG_RETURN(1);
/*
@@ -605,6 +639,7 @@ read_sep_field(THD *thd,COPY_INFO &info,TABLE *table,
DBUG_RETURN(1);
}
thd->row_count++;
+continue_loop:;
}
if (id && !read_info.error)
thd->insert_id(id); // For binary/update log
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index f93aaf09933..54a1240c0ab 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -3135,7 +3135,8 @@ unsent_create_error:
goto error;
}
res= mysql_load(thd, lex->exchange, first_table, lex->field_list,
- lex->duplicates, (bool) lex->local_file, lex->lock_option);
+ lex->duplicates, (bool) lex->local_file,
+ lex->lock_option, lex->duplicates == DUP_IGNORE);
break;
}
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index d2964df008b..6fb13684098 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -7921,7 +7921,7 @@ check_option:
/* empty */
{ Lex->create_view_check= VIEW_CHECK_NONE; }
| WITH CHECK_SYM OPTION
- { Lex->create_view_check= VIEW_CHECK_LOCAL; }
+ { Lex->create_view_check= VIEW_CHECK_CASCADED; }
| WITH CASCADED CHECK_SYM OPTION
{ Lex->create_view_check= VIEW_CHECK_CASCADED; }
| WITH LOCAL_SYM CHECK_SYM OPTION
diff --git a/sql/table.cc b/sql/table.cc
index bfe5395c3db..e372de57177 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -1497,8 +1497,10 @@ void st_table_list::set_ancestor()
SYNOPSIS
st_table_list::setup_ancestor()
- thd - thread handler
- conds - condition of this JOIN
+ thd - thread handler
+ conds - condition of this JOIN
+ check_opt_type - WHITH CHECK OPTION type (VIEW_CHECK_NONE,
+ VIEW_CHECK_LOCAL, VIEW_CHECK_CASCADED)
DESCRIPTION
It is:
@@ -1513,7 +1515,8 @@ void st_table_list::set_ancestor()
1 - error
*/
-bool st_table_list::setup_ancestor(THD *thd, Item **conds)
+bool st_table_list::setup_ancestor(THD *thd, Item **conds,
+ uint8 check_opt_type)
{
Item **transl;
SELECT_LEX *select= &view->select_lex;
@@ -1527,7 +1530,10 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds)
DBUG_ENTER("st_table_list::setup_ancestor");
if (ancestor->ancestor &&
- ancestor->setup_ancestor(thd, conds))
+ ancestor->setup_ancestor(thd, conds,
+ (check_opt_type == VIEW_CHECK_CASCADED ?
+ VIEW_CHECK_CASCADED :
+ VIEW_CHECK_NONE)))
DBUG_RETURN(1);
if (field_translation)
@@ -1586,23 +1592,26 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds)
field_translation= transl;
/* TODO: sort this list? Use hash for big number of fields */
- if (where)
+ if (where ||
+ (check_opt_type == VIEW_CHECK_CASCADED &&
+ ancestor->check_option))
{
Item_arena *arena= thd->current_arena, backup;
TABLE_LIST *tbl= this;
if (arena->is_conventional())
arena= 0; // For easier test
- if (!where->fixed && where->fix_fields(thd, ancestor, &where))
+ if (where && !where->fixed && where->fix_fields(thd, ancestor, &where))
goto err;
if (arena)
thd->set_n_backup_item_arena(arena, &backup);
- if (effective_with_check)
+ if (check_opt_type)
{
- check_option= where->copy_andor_structure(thd);
- if (effective_with_check == VIEW_CHECK_CASCADED)
+ if (where)
+ check_option= where->copy_andor_structure(thd);
+ if (check_opt_type == VIEW_CHECK_CASCADED)
{
check_option= and_conds(check_option, ancestor->check_option);
}
@@ -1612,7 +1621,7 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds)
check that it is not VIEW in which we insert with INSERT SELECT
(in this case we can't add view WHERE condition to main SELECT_LEX)
*/
- if (!no_where_clause)
+ if (where && !no_where_clause)
{
/* Go up to join tree and try to find left join */
for (; tbl; tbl= tbl->embedding)
diff --git a/sql/table.h b/sql/table.h
index 605cd516d9c..3e2a61d5a21 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -283,7 +283,7 @@ typedef struct st_table_list
void calc_md5(char *buffer);
void set_ancestor();
int view_check_option(THD *thd, bool ignore_failure);
- bool setup_ancestor(THD *thd, Item **conds);
+ bool setup_ancestor(THD *thd, Item **conds, uint8 check_option);
bool placeholder() {return derived || view; }
void print(THD *thd, String *str);
inline st_table_list *next_independent()