diff --git a/sql/datadict.cc b/sql/datadict.cc
index 62d60ed..2f01bf2 100644
--- a/sql/datadict.cc
+++ b/sql/datadict.cc
@@ -169,7 +169,7 @@ bool dd_recreate_table(THD *thd, const char *db, const char *table_name,
   }
 
   /* Attempt to reconstruct the table. */
-  error= ha_create_table(thd, path, db, table_name, &create_info, NULL);
+  error= ha_create_table(thd, path, db, table_name, &create_info, NULL, 0);
 
   DBUG_RETURN(error);
 }
diff --git a/sql/handler.cc b/sql/handler.cc
index 1f8daf3..a44e3b1 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -4630,7 +4630,8 @@ void handler::update_global_index_stats()
 */
 int ha_create_table(THD *thd, const char *path,
                     const char *db, const char *table_name,
-                    HA_CREATE_INFO *create_info, LEX_CUSTRING *frm)
+                    HA_CREATE_INFO *create_info, LEX_CUSTRING *frm,
+                    ulong privilege)
 {
   int error= 1;
   TABLE table;
@@ -4667,7 +4668,8 @@ int ha_create_table(THD *thd, const char *path,
 
   share.m_psi= PSI_CALL_get_table_share(temp_table, &share);
 
-  if (open_table_from_share(thd, &share, "", 0, READ_ALL, 0, &table, true))
+  if (open_table_from_share(thd, &share, "", 0, READ_ALL, 0,
+                            &table, true, privilege))
     goto err;
 
   update_create_info_from_table(create_info, &table);
diff --git a/sql/handler.h b/sql/handler.h
index 2e219d5..e488f79 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -4043,7 +4043,8 @@ void ha_checkpoint_state(bool disable);
 void ha_commit_checkpoint_request(void *cookie, void (*pre_hook)(void *));
 int ha_create_table(THD *thd, const char *path,
                     const char *db, const char *table_name,
-                    HA_CREATE_INFO *create_info, LEX_CUSTRING *frm);
+                    HA_CREATE_INFO *create_info, LEX_CUSTRING *frm,
+                    ulong privilege);
 int ha_delete_table(THD *thd, handlerton *db_type, const char *path,
                     const char *db, const char *alias, bool generate_warning);
 
diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc
index a6b97ce..f761db4 100644
--- a/sql/sql_admin.cc
+++ b/sql/sql_admin.cc
@@ -135,7 +135,7 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list,
     if (share == NULL)
       DBUG_RETURN(0);				// Can't open frm file
 
-    if (open_table_from_share(thd, share, "", 0, 0, 0, &tmp_table, FALSE))
+    if (open_table_from_share(thd, share, "", 0, 0, 0, &tmp_table, FALSE, 0))
     {
       tdc_release_share(share);
       DBUG_RETURN(0);                           // Out of memory
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 13b8625..68aed5c 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -2511,7 +2511,7 @@ bool open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
                                          HA_TRY_READ_ONLY),
                                  (READ_KEYINFO | COMPUTE_TYPES |
                                   EXTRA_RECORD),
-                                 thd->open_options, table, FALSE);
+                                 thd->open_options, table, FALSE, 0);
 
     if (error)
     {
@@ -3346,7 +3346,7 @@ static bool auto_repair_table(THD *thd, TABLE_LIST *table_list)
                                     HA_TRY_READ_ONLY),
                             READ_KEYINFO | COMPUTE_TYPES | EXTRA_RECORD,
                             ha_open_options | HA_OPEN_FOR_REPAIR,
-                            entry, FALSE) || ! entry->file ||
+                            entry, FALSE, 0) || ! entry->file ||
       (entry->file->is_crashed() && entry->file->ha_check_and_repair(thd)))
   {
     /* Give right error message */
@@ -5621,7 +5621,8 @@ TABLE *open_table_uncached(THD *thd, handlerton *hton,
                            const char *path, const char *db,
                            const char *table_name,
                            bool add_to_temporary_tables_list,
-                           bool open_in_engine)
+                           bool open_in_engine,
+                           ulong privilege)
 {
   TABLE *tmp_table;
   TABLE_SHARE *share;
@@ -5681,7 +5682,7 @@ TABLE *open_table_uncached(THD *thd, handlerton *hton,
                               Set "is_create_table" if the table does not
                               exist in SE
                             */
-                            open_in_engine ? false : true))
+                            open_in_engine ? false : true, privilege))
   {
     /* No need to lock share->mutex as this is not needed for tmp tables */
     free_table_share(share);
@@ -5690,7 +5691,7 @@ TABLE *open_table_uncached(THD *thd, handlerton *hton,
   }
 
   tmp_table->reginfo.lock_type= TL_WRITE;	 // Simulate locked
-  tmp_table->grant.privilege= TMP_TABLE_ACLS;
+  tmp_table->grant.privilege= privilege;
   share->tmp_table= (tmp_table->file->has_transactions() ? 
                      TRANSACTIONAL_TMP_TABLE : NON_TRANSACTIONAL_TMP_TABLE);
 
diff --git a/sql/sql_base.h b/sql/sql_base.h
index a6d9019..d9b1a1f 100644
--- a/sql/sql_base.h
+++ b/sql/sql_base.h
@@ -130,7 +130,7 @@ bool get_key_map_from_key_list(key_map *map, TABLE *table,
 TABLE *open_table_uncached(THD *thd, handlerton *hton, const char *path,
                            const char *db, const char *table_name,
                            bool add_to_temporary_tables_list,
-                           bool open_in_engine);
+                           bool open_in_engine, ulong privilege);
 TABLE *find_locked_table(TABLE *list, const char *db, const char *table_name);
 TABLE *find_write_locked_table(TABLE *list, const char *db,
                                const char *table_name);
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 1ec33a0..d0cb0f7 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -3952,6 +3952,7 @@ static TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
       }
       /* Restore */
       create_table->open_strategy= save_open_strategy;
+      create_table->table->grant.privilege= create_table->grant.privilege;
     }
     else
     {
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 5635e9a..55cc4be 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -6936,6 +6936,17 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
 #ifdef WITH_PARTITION_STORAGE_ENGINE
   ptr->partition_names= partition_names;
 #endif /* WITH_PARTITION_STORAGE_ENGINE */
+#ifdef NO_EMBEDDED_ACCESS_CHECKS
+  /*
+    Plugins (e.g. CONNECT engine) should not depend on whether
+    embedded library is built with or without NO_EMBEDDED_ACCESS_CHECKS.
+    ha_xxx::external_lock() expects that tables->grant.privilege
+    is initialized to allow all privileges if NO_EMBEDDED_ACCESS_CHECKS.
+    E.g. ha_connect::external_lock() needs FILE_ACL.
+  */
+  ptr->grant.privilege= ~NO_ACCESS;
+#endif
+
   /* Link table in global list (all used tables) */
   lex->add_to_query_tables(ptr);
 
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 2413cb5..fd2c118 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -4634,7 +4634,7 @@ static int fill_schema_table_from_frm(THD *thd, TABLE_LIST *tables,
 
   if (!open_table_from_share(thd, share, table_name->str, 0,
                              (EXTRA_RECORD | OPEN_FRM_FILE_ONLY),
-                             thd->open_options, &tbl, FALSE))
+                             thd->open_options, &tbl, FALSE, 0))
   {
     tbl.s= share;
     table_list.table= &tbl;
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 20cfcca..bf1e4fb 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -4837,7 +4837,8 @@ int create_table_impl(THD *thd,
     */
 
     TABLE *table= open_table_uncached(thd, create_info->db_type, path,
-                                      db, table_name, true, true);
+                                      db, table_name, true, true,
+                                      TMP_TABLE_ACLS);
 
     if (!table)
     {
@@ -4871,7 +4872,7 @@ int create_table_impl(THD *thd,
 
     bool result= (open_table_def(thd, &share, GTS_TABLE) ||
                   open_table_from_share(thd, &share, "", 0, (uint) READ_ALL,
-                                        0, &table, true));
+                                        0, &table, true, 0));
     if (!result)
       (void) closefrm(&table, 0);
 
@@ -8720,7 +8721,15 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
                                              alter_ctx.get_tmp_path(),
                                              alter_ctx.new_db,
                                              alter_ctx.tmp_name,
-                                             true, false)))
+                                             true, false,
+                                             /*
+                                               Some engine, e.g. CONNECT,
+                                               need to know if FILE_ACL
+                                               presents.
+                                             */
+                                             TMP_TABLE_ACLS |
+                                             (table_list->grant.privilege &
+                                             FILE_ACL))))
       goto err_new_table_cleanup;
 
     /* Set markers for fields in TABLE object for altered table. */
@@ -8865,7 +8874,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
 
   if (ha_create_table(thd, alter_ctx.get_tmp_path(),
                       alter_ctx.new_db, alter_ctx.tmp_name,
-                      create_info, &frm))
+                      create_info, &frm, table_list->grant.privilege))
     goto err_new_table_cleanup;
 
   /* Mark that we have created table in storage engine. */
@@ -8876,7 +8885,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
     if (!open_table_uncached(thd, new_db_type,
                              alter_ctx.get_tmp_path(),
                              alter_ctx.new_db, alter_ctx.tmp_name,
-                             true, true))
+                             true, true, TMP_TABLE_ACLS))
       goto err_new_table_cleanup;
   }
 
@@ -8897,7 +8906,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
     /* Open our intermediate table. */
     new_table= open_table_uncached(thd, new_db_type, alter_ctx.get_tmp_path(),
                                    alter_ctx.new_db, alter_ctx.tmp_name,
-                                   true, true);
+                                   true, true, table_list->grant.privilege);
   }
   if (!new_table)
     goto err_new_table_cleanup;
@@ -9111,7 +9120,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
     TABLE *t_table;
     t_table= open_table_uncached(thd, new_db_type, alter_ctx.get_new_path(),
                                  alter_ctx.new_db, alter_ctx.new_name,
-                                 false, true);
+                                 false, true, TMP_TABLE_ACLS);
     if (t_table)
       intern_close_table(t_table);
     else
diff --git a/sql/sql_truncate.cc b/sql/sql_truncate.cc
index 05869b7..92acf32 100644
--- a/sql/sql_truncate.cc
+++ b/sql/sql_truncate.cc
@@ -297,7 +297,8 @@ static bool recreate_temporary_table(THD *thd, TABLE *table)
 
   if ((new_table= open_table_uncached(thd, table_type, share->path.str,
                                       share->db.str,
-                                      share->table_name.str, true, true)))
+                                      share->table_name.str, true, true,
+                                      TMP_TABLE_ACLS)))
   {
     error= FALSE;
     thd->thread_specific_used= TRUE;
diff --git a/sql/table.cc b/sql/table.cc
index 053269a..4cd4fa3 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -2543,7 +2543,8 @@ bool unpack_vcol_info_from_frm(THD *thd,
 enum open_frm_error open_table_from_share(THD *thd, TABLE_SHARE *share,
                        const char *alias, uint db_stat, uint prgflag,
                        uint ha_open_flags, TABLE *outparam,
-                       bool is_create_table)
+                       bool is_create_table,
+                       ulong privilege)
 {
   enum open_frm_error error;
   uint records, i, bitmap_size;
@@ -2559,6 +2560,7 @@ enum open_frm_error open_table_from_share(THD *thd, TABLE_SHARE *share,
 
   error= OPEN_FRM_ERROR_ALREADY_ISSUED; // for OOM errors below
   bzero((char*) outparam, sizeof(*outparam));
+  outparam->grant.privilege= privilege;
   outparam->in_use= thd;
   outparam->s= share;
   outparam->db_stat= db_stat;
diff --git a/sql/table.h b/sql/table.h
index 39faa8b..6a668b0 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -2557,7 +2557,7 @@ void init_mdl_requests(TABLE_LIST *table_list);
 enum open_frm_error open_table_from_share(THD *thd, TABLE_SHARE *share,
                        const char *alias, uint db_stat, uint prgflag,
                        uint ha_open_flags, TABLE *outparam,
-                       bool is_create_table);
+                       bool is_create_table, ulong privilege);
 bool unpack_vcol_info_from_frm(THD *thd, MEM_ROOT *mem_root,
                                TABLE *table, Field *field,
                                LEX_STRING *vcol_expr, bool *error_reported);
diff --git a/sql/unireg.cc b/sql/unireg.cc
index 12d3c26..e8fa92e 100644
--- a/sql/unireg.cc
+++ b/sql/unireg.cc
@@ -375,7 +375,7 @@ int rea_create_table(THD *thd, LEX_CUSTRING *frm,
 
   if (!no_ha_create_table)
   {
-    if (ha_create_table(thd, path, db, table_name, create_info, frm))
+    if (ha_create_table(thd, path, db, table_name, create_info, frm, 0))
       goto err_part;
   }
 
diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc
index c2fb648..51e7102 100644
--- a/storage/connect/ha_connect.cc
+++ b/storage/connect/ha_connect.cc
@@ -955,7 +955,7 @@ ulonglong ha_connect::table_flags() const
       flags|= (HA_HAS_RECORDS | HA_STATS_RECORDS_IS_EXACT);
 
     // No data change on ALTER for outward tables
-    if (!IsFileType(type) || hp->FileExists(pos->filename, true))
+    if (!IsFileType(type) || hp->FileExists(pos->filename, true, true))
       flags|= HA_NO_COPY_ON_ALTER;
 
     } // endif pos
@@ -3964,7 +3964,21 @@ int ha_connect::delete_all_rows()
 } // end of delete_all_rows
 
 
-bool ha_connect::check_privileges(THD *thd, PTOS options, char *dbn)
+/**
+  Check privileges.
+  @param THD                   - Current thread
+  @param options               - Connect table options
+  @param dbn                   - database name
+  @param using_table_privilege - whether check table->grant.privilege,
+                                 or execute check_access(FILE_ACL).
+
+  Using table->grant.privilege is important in cases when we need to take into
+  account privileges of the VIEW definer when accessing to a view created with
+    "CREATE VIEW v1 SQL SECURITY DEFINER".
+  See ha_connect::check_privileges_external_lock() for details.
+*/
+bool ha_connect::check_privileges(THD *thd, PTOS options, char *dbn,
+                                  bool using_table_privilege)
 {
   const char *db= (dbn && *dbn) ? dbn : NULL;
   TABTYPE     type=GetRealType(options);
@@ -4020,7 +4034,33 @@ bool ha_connect::check_privileges(THD *thd, PTOS options, char *dbn)
     case TAB_MAC:
     case TAB_WMI:
     case TAB_OEM:
-      return check_access(thd, FILE_ACL, db, NULL, NULL, 0, 0);
+      if (using_table_privilege)
+      {
+        // Called from ::external_lock(), respect VIEW's definer
+        if (table->grant.privilege & FILE_ACL)
+          return false;
+        else
+        {
+          my_error(ER_ACCESS_DENIED_ERROR, MYF(0),
+                   thd->security_ctx->priv_user,
+                   thd->security_ctx->priv_host,
+                   (thd->password ?  ER(ER_YES) : ER(ER_NO)));
+          return true;
+        }
+      }
+      else
+      {
+        /*
+          Called from ::create() or ::delete_or_rename_table().
+          TODO:
+          - change create() to use table->grant.privilege as well
+            (needs some additional refactoring in /sql)
+          - change delete_or_rename_table() not to require FILE_ACL,
+            This should be safe, as DROP and RENAME queries do not
+            actually read or modify the underlying data file.
+        */
+        return check_access(thd, FILE_ACL, db, NULL, NULL, 0, 0);
+      }
 
     // This is temporary until a solution is found
     case TAB_TBL:
@@ -4061,6 +4101,15 @@ bool ha_connect::IsSameIndex(PIXDEF xp1, PIXDEF xp2)
   return b;
 } // end of IsSameIndex
 
+
+void ha_connect::report_unsupported_sql_command(PGLOBAL g, THD *thd)
+{
+  htrc("Unsupported sql_command=%d\n", thd_sql_command(thd));
+  strcpy(g->Message, "CONNECT Unsupported command");
+  my_message(ER_NOT_ALLOWED_COMMAND, g->Message, MYF(0));
+}
+
+
 MODE ha_connect::CheckMode(PGLOBAL g, THD *thd,
                            MODE newmode, bool *chk, bool *cras)
 {
@@ -4121,9 +4170,7 @@ MODE ha_connect::CheckMode(PGLOBAL g, THD *thd,
 //        } // endif partitioned
 
       default:
-        htrc("Unsupported sql_command=%d\n", thd_sql_command(thd));
-        strcpy(g->Message, "CONNECT Unsupported command");
-        my_message(ER_NOT_ALLOWED_COMMAND, g->Message, MYF(0));
+        report_unsupported_sql_command(g, thd);
         newmode= MODE_ERROR;
         break;
       } // endswitch newmode
@@ -4175,9 +4222,7 @@ MODE ha_connect::CheckMode(PGLOBAL g, THD *thd,
         newmode= MODE_READ;
         break;
       default:
-        htrc("Unsupported sql_command=%d\n", thd_sql_command(thd));
-        strcpy(g->Message, "CONNECT Unsupported command");
-        my_message(ER_NOT_ALLOWED_COMMAND, g->Message, MYF(0));
+        report_unsupported_sql_command(g, thd);
         newmode= MODE_ERROR;
         break;
       } // endswitch newmode
@@ -4190,6 +4235,43 @@ MODE ha_connect::CheckMode(PGLOBAL g, THD *thd,
   return newmode;
 } // end of check_mode
 
+
+/**
+  A check_privileges() wrapper for external_lock().
+*/
+bool ha_connect::check_privileges_external_lock(PGLOBAL g, THD *thd,
+                                                PTOS options)
+{
+  switch (thd_sql_command(thd))
+  {
+  case SQLCOM_SELECT:
+  case SQLCOM_UPDATE:
+  case SQLCOM_INSERT:
+  case SQLCOM_DELETE:
+  case SQLCOM_REPLACE:
+  case SQLCOM_LOAD:
+  case SQLCOM_CREATE_TABLE:
+  case SQLCOM_INSERT_SELECT:
+  case SQLCOM_REPLACE_SELECT:
+  case SQLCOM_UPDATE_MULTI:
+  case SQLCOM_DELETE_MULTI:
+  case SQLCOM_TRUNCATE:
+  case SQLCOM_LOCK_TABLES:
+  case SQLCOM_DROP_TABLE:
+  case SQLCOM_RENAME_TABLE:
+  case SQLCOM_CREATE_VIEW:
+  case SQLCOM_DROP_INDEX:
+  case SQLCOM_CREATE_INDEX:
+  case SQLCOM_OPTIMIZE:
+  case SQLCOM_ALTER_TABLE:
+    return check_privileges(thd, options, table->s->db.str, true);
+  default:
+    report_unsupported_sql_command(g, thd);
+  }
+  return true;                       // Something went wrong, deny access.
+}
+
+
 int ha_connect::start_stmt(THD *thd, thr_lock_type lock_type)
 {
   int     rc= 0;
@@ -4410,7 +4492,7 @@ int ha_connect::external_lock(THD *thd, int lock_type)
 
   DBUG_ASSERT(table && table->s);
 
-  if (check_privileges(thd, options, table->s->db.str)) {
+  if (check_privileges_external_lock(g, thd, options)) {
     strcpy(g->Message, "This operation requires the FILE privilege");
     htrc("%s\n", g->Message);
     DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
@@ -4661,7 +4743,7 @@ int ha_connect::delete_or_rename_table(const char *name, const char *to)
     if (!open_table_def(thd, share)) {
       // Now we can work
       if ((pos= share->option_struct)) {
-        if (check_privileges(thd, pos, db))
+        if (check_privileges(thd, pos, db, false))
           rc= HA_ERR_INTERNAL_ERROR;         // ???
         else
           if (IsFileType(GetRealType(pos)) && !pos->filename)
@@ -5670,6 +5752,14 @@ int ha_connect::create(const char *name, TABLE *table_arg,
   PGLOBAL g= xp->g;
 
   DBUG_ENTER("ha_connect::create");
+  /*
+    This assignment fixes sporadic test failures if some
+    "ALTER TABLE t1 ADD KEY(a)" query exits on ER_ACCESS_DENIED_ERROR
+    (e.g. on missing FILE_ACL). All following "CREATE TABLE" failed with
+    "ERROR 1105: CONNECT index modification should be in-place"
+    TODO: check with Olivier.
+  */
+  g->Xchk= NULL;
   int  sqlcom= thd_sql_command(table_arg->in_use);
   PTOS options= GetTableOptionStruct(table_arg->s);
 
@@ -5699,7 +5789,7 @@ int ha_connect::create(const char *name, TABLE *table_arg,
     DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
   } // endif ttp
 
-  if (check_privileges(thd, options, GetDBfromName(name)))
+  if (check_privileges(thd, options, GetDBfromName(name), false))
     DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
 
   inward= IsFileType(type) && !options->filename;
@@ -6066,7 +6156,7 @@ int ha_connect::create(const char *name, TABLE *table_arg,
 #endif   // WITH_PARTITION_STORAGE_ENGINE
 
     if (g->Alchecked == 0 &&
-        (!IsFileType(type) || FileExists(options->filename, false))) {
+        (!IsFileType(type) || FileExists(options->filename, false, true))) {
       if (part_info) {
         sprintf(g->Message, "Data repartition in %s is unchecked", partname); 
         push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message);
@@ -6146,7 +6236,7 @@ int ha_connect::create(const char *name, TABLE *table_arg,
   - file does not exist or is void
   - user has file privilege
 */
-bool ha_connect::FileExists(const char *fn, bool bf)
+bool ha_connect::FileExists(const char *fn, bool bf, bool check_privilege)
 {
   if (!fn || !*fn)
     return false;
@@ -6159,8 +6249,7 @@ bool ha_connect::FileExists(const char *fn, bool bf)
     int   n;
     struct stat info;
 
-    if (check_access(ha_thd(), FILE_ACL, table->s->db.str,
-                     NULL, NULL, 0, 0))
+    if (check_privilege && !(table->grant.privilege & FILE_ACL))
       return true;
 
 #if defined(__WIN__)
@@ -6426,7 +6515,7 @@ ha_connect::check_if_supported_inplace_alter(TABLE *altered_table,
       char *fn= GetStringOption("filename");
       tshp= NULL;
 
-      if (FileExists(fn, false)) {
+      if (FileExists(fn, false, false)) {
         strcpy(g->Message, "Operation denied. Table data would be lost.");
         my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
         DBUG_RETURN(HA_ALTER_ERROR);
diff --git a/storage/connect/ha_connect.h b/storage/connect/ha_connect.h
index 611f9ba..89af0df 100644
--- a/storage/connect/ha_connect.h
+++ b/storage/connect/ha_connect.h
@@ -213,7 +213,7 @@ class ha_connect: public handler
   bool     SetIntegerOption(char *opname, int n);
   bool     SameInt(TABLE *tab, char *opn);
   bool     SameBool(TABLE *tab, char *opn);
-  bool     FileExists(const char *fn, bool bf);
+  bool     FileExists(const char *fn, bool bf, bool check_privilege);
   bool     NoFieldOptionChange(TABLE *tab);
   PFOS     GetFieldOptionStruct(Field *fp);
   void    *GetColumnOption(PGLOBAL g, void *field, PCOLINFO pcf);
@@ -534,8 +534,11 @@ int index_prev(uchar *buf);
 private:
   DsMrr_impl ds_mrr;
 
+  void report_unsupported_sql_command(PGLOBAL g, THD *thd);
 protected:
-  bool check_privileges(THD *thd, PTOS options, char *dbn);
+  bool check_privileges(THD *thd, PTOS options, char *dbn,
+                        bool using_table_privilege);
+  bool check_privileges_external_lock(PGLOBAL g, THD *thd, PTOS options);
   MODE CheckMode(PGLOBAL g, THD *thd, MODE newmode, bool *chk, bool *cras);
   char *GetDBfromName(const char *name);
 
diff --git a/storage/connect/mysql-test/connect/r/grant.result b/storage/connect/mysql-test/connect/r/grant.result
index ba57287..9a0a549 100644
--- a/storage/connect/mysql-test/connect/r/grant.result
+++ b/storage/connect/mysql-test/connect/r/grant.result
@@ -46,7 +46,7 @@ ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
 SELECT user();
 user()
 root@localhost
-CREATE VIEW v1 AS SELECT * FROM t1;
+CREATE SQL SECURITY INVOKER VIEW v1 AS SELECT * FROM t1;
 SELECT user();
 user()
 user@localhost
@@ -130,7 +130,7 @@ ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
 SELECT user();
 user()
 root@localhost
-CREATE VIEW v1 AS SELECT * FROM t1;
+CREATE SQL SECURITY INVOKER VIEW v1 AS SELECT * FROM t1;
 SELECT user();
 user()
 user@localhost
@@ -224,7 +224,7 @@ ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
 SELECT user();
 user()
 root@localhost
-CREATE VIEW v1 AS SELECT * FROM t1;
+CREATE SQL SECURITY INVOKER VIEW v1 AS SELECT * FROM t1;
 SELECT user();
 user()
 user@localhost
@@ -318,7 +318,7 @@ ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
 SELECT user();
 user()
 root@localhost
-CREATE VIEW v1 AS SELECT * FROM t1;
+CREATE SQL SECURITY INVOKER VIEW v1 AS SELECT * FROM t1;
 SELECT user();
 user()
 user@localhost
@@ -412,7 +412,7 @@ ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
 SELECT user();
 user()
 root@localhost
-CREATE VIEW v1 AS SELECT * FROM t1;
+CREATE SQL SECURITY INVOKER VIEW v1 AS SELECT * FROM t1;
 SELECT user();
 user()
 user@localhost
@@ -506,7 +506,7 @@ ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
 SELECT user();
 user()
 root@localhost
-CREATE VIEW v1 AS SELECT * FROM t1;
+CREATE SQL SECURITY INVOKER VIEW v1 AS SELECT * FROM t1;
 SELECT user();
 user()
 user@localhost
diff --git a/storage/connect/mysql-test/connect/r/grant2.result b/storage/connect/mysql-test/connect/r/grant2.result
new file mode 100644
index 0000000..b99841e
--- /dev/null
+++ b/storage/connect/mysql-test/connect/r/grant2.result
@@ -0,0 +1,667 @@
+#
+# MDEV-7574 Security definer views don't work with CONNECT ODBC tables
+#
+GRANT ALL PRIVILEGES ON *.* TO user@localhost;
+REVOKE FILE ON *.* FROM user@localhost;
+# Testing SQLCOM_SELECT
+CREATE TABLE t1 (a INT) ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t1.fix';
+INSERT INTO t1 VALUES (10);
+CREATE SQL SECURITY INVOKER VIEW v1_invoker AS SELECT * FROM t1;
+CREATE SQL SECURITY DEFINER VIEW v1_definer AS SELECT * FROM t1;
+SELECT * FROM t1;
+a
+10
+SELECT * FROM v1_invoker;
+a
+10
+SELECT * FROM v1_definer;
+a
+10
+SELECT * FROM t1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+SELECT * FROM v1_invoker;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+SELECT * FROM v1_definer;
+a
+10
+DROP VIEW v1_invoker, v1_definer;
+DROP TABLE t1;
+# Testing SQLCOM_UPDATE
+CREATE TABLE t1 (a INT) ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t1.fix';
+INSERT INTO t1 VALUES (10);
+CREATE SQL SECURITY INVOKER VIEW v1_invoker AS SELECT * FROM t1;
+CREATE SQL SECURITY DEFINER VIEW v1_definer AS SELECT * FROM t1;
+UPDATE t1 SET a=11;
+UPDATE v1_invoker SET a=12;
+UPDATE v1_definer SET a=13;
+UPDATE t1 SET a=21;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+UPDATE v1_invoker SET a=22;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+UPDATE v1_definer SET a=23;
+DROP VIEW v1_invoker, v1_definer;
+DROP TABLE t1;
+# Testing SQLCOM_INSERT
+CREATE TABLE t1 (a INT) ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t1.fix';
+INSERT INTO t1 VALUES (10);
+CREATE SQL SECURITY INVOKER VIEW v1_invoker AS SELECT * FROM t1;
+CREATE SQL SECURITY DEFINER VIEW v1_definer AS SELECT * FROM t1;
+INSERT INTO t1 VALUES (11);
+INSERT INTO v1_invoker VALUES (12);
+INSERT INTO v1_definer VALUES (13);
+INSERT INTO t1 VALUES (21);
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+INSERT INTO v1_invoker VALUES (22);
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+INSERT INTO v1_definer VALUES (23);
+DROP VIEW v1_invoker, v1_definer;
+DROP TABLE t1;
+# Testing SQLCOM_REPLACE
+CREATE TABLE t1 (a INT) ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t1.fix';
+INSERT INTO t1 VALUES (10);
+CREATE SQL SECURITY INVOKER VIEW v1_invoker AS SELECT * FROM t1;
+CREATE SQL SECURITY DEFINER VIEW v1_definer AS SELECT * FROM t1;
+REPLACE INTO t1 VALUES (11);
+ERROR 42000: CONNECT Unsupported command
+REPLACE INTO v1_invoker VALUES (12);
+ERROR 42000: CONNECT Unsupported command
+REPLACE INTO v1_definer VALUES (13);
+ERROR 42000: CONNECT Unsupported command
+REPLACE INTO t1 VALUES (21);
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+REPLACE INTO v1_invoker VALUES (22);
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+REPLACE INTO v1_definer VALUES (23);
+ERROR 42000: CONNECT Unsupported command
+DROP VIEW v1_invoker, v1_definer;
+DROP TABLE t1;
+# Testing SQLCOM_DELETE
+CREATE TABLE t1 (a INT) ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t1.fix';
+INSERT INTO t1 VALUES (10),(11),(12),(13),(21),(22),(23);
+CREATE SQL SECURITY INVOKER VIEW v1_invoker AS SELECT * FROM t1;
+CREATE SQL SECURITY DEFINER VIEW v1_definer AS SELECT * FROM t1;
+DELETE FROM t1 WHERE a=11;
+DELETE FROM v1_invoker WHERE a=12;
+DELETE FROM v1_definer WHERE a=13;
+DELETE FROM t1 WHERE a=21;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DELETE FROM v1_invoker WHERE a=22;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DELETE FROM v1_definer WHERE a=23;
+DROP VIEW v1_invoker, v1_definer;
+DROP TABLE t1;
+# Testing SQLCOM_LOAD
+CREATE TABLE t1 (a VARCHAR(128)) ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t1.fix';
+INSERT INTO t1 VALUES (10);
+CREATE SQL SECURITY INVOKER VIEW v1_invoker AS SELECT * FROM t1;
+CREATE SQL SECURITY DEFINER VIEW v1_definer AS SELECT * FROM t1;
+LOAD DATA LOCAL INFILE 'MTR_SUITE_DIR/std_data/boys.txt' INTO TABLE t1;
+LOAD DATA LOCAL INFILE 'MTR_SUITE_DIR/std_data/boys.txt' INTO TABLE v1_invoker;
+LOAD DATA LOCAL INFILE 'MTR_SUITE_DIR/std_data/boys.txt' INTO TABLE v1_definer;
+LOAD DATA LOCAL INFILE 'MTR_SUITE_DIR/std_data/boys.txt' INTO TABLE t1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+LOAD DATA LOCAL INFILE 'MTR_SUITE_DIR/std_data/boys.txt' INTO TABLE v1_invoker;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+LOAD DATA LOCAL INFILE 'MTR_SUITE_DIR/std_data/boys.txt' INTO TABLE v1_definer;
+DROP VIEW v1_invoker, v1_definer;
+DROP TABLE t1;
+# Testing SQLCOM_TRUNCATE
+CREATE TABLE t1 (a INT) ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t1.fix';
+INSERT INTO t1 VALUES (10);
+TRUNCATE TABLE t1;
+INSERT INTO t1 VALUES (11);
+TRUNCATE TABLE t1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DROP TABLE t1;
+# Testing SQLCOM_DROP_TABLE
+CREATE TABLE t1 (a INT) ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t1.fix';
+INSERT INTO t1 VALUES (10);
+DROP TABLE t1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DROP TABLE t1;
+# Testing SQLCOM_DROP_VIEW
+# DROP VIEW does not need FILE_ACL.
+CREATE TABLE t1 (a INT) ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t1.fix';
+INSERT INTO t1 VALUES (10),(11),(12),(13),(21),(22),(23);
+CREATE SQL SECURITY INVOKER VIEW v1_invoker AS SELECT * FROM t1;
+CREATE SQL SECURITY DEFINER VIEW v1_definer AS SELECT * FROM t1;
+DROP VIEW v1_invoker, v1_definer;
+CREATE SQL SECURITY INVOKER VIEW v1_invoker AS SELECT * FROM t1;
+CREATE SQL SECURITY DEFINER VIEW v1_definer AS SELECT * FROM t1;
+DROP VIEW v1_invoker;
+DROP VIEW v1_definer;
+DROP TABLE t1;
+# Testing SQLCOM_CREATE_TABLE
+CREATE TABLE t1 (a INT) ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t1.fix';
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+# Testing SQLCOM_LOCK_TABLES
+CREATE TABLE t1 (a INT) ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t1.fix';
+INSERT INTO t1 VALUES (10);
+CREATE SQL SECURITY INVOKER VIEW v1_invoker AS SELECT * FROM t1;
+CREATE SQL SECURITY DEFINER VIEW v1_definer AS SELECT * FROM t1;
+LOCK TABLE t1 READ;
+UNLOCK TABLES;
+LOCK TABLE t1 WRITE;
+UNLOCK TABLES;
+LOCK TABLE v1_invoker READ;
+UNLOCK TABLES;
+LOCK TABLE v1_invoker WRITE;
+UNLOCK TABLES;
+LOCK TABLE v1_definer READ;
+UNLOCK TABLES;
+LOCK TABLE v1_definer WRITE;
+UNLOCK TABLES;
+LOCK TABLE t1 READ;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+LOCK TABLE t1 WRITE;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+LOCK TABLE v1_invoker READ;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+LOCK TABLE v1_invoker WRITE;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+LOCK TABLE v1_definer READ;
+UNLOCK TABLES;
+LOCK TABLE v1_definer WRITE;
+UNLOCK TABLES;
+DROP VIEW v1_invoker, v1_definer;
+DROP TABLE t1;
+# Testing SQLCOM_UPDATE_MULTI
+CREATE TABLE t1 (a INT) ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t1.fix';
+CREATE TABLE t2 (a INT) ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t2.fix';
+CREATE TABLE t3 (a INT);
+INSERT INTO t1 VALUES (10);
+INSERT INTO t2 VALUES (20);
+INSERT INTO t3 VALUES (30);
+CREATE SQL SECURITY INVOKER VIEW v1_invoker AS SELECT * FROM t1;
+CREATE SQL SECURITY DEFINER VIEW v1_definer AS SELECT * FROM t1;
+CREATE SQL SECURITY INVOKER VIEW v2_invoker AS SELECT * FROM t2;
+CREATE SQL SECURITY DEFINER VIEW v2_definer AS SELECT * FROM t2;
+UPDATE t1         a1,t1         a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE t1         a1,t2         a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE t1         a1,t3         a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE t1         a1,v1_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE t1         a1,v1_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE t1         a1,v2_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE t1         a1,v2_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE t2         a1,t1         a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE t2         a1,t2         a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE t2         a1,t3         a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE t2         a1,v1_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE t2         a1,v1_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE t2         a1,v2_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE t2         a1,v2_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE t3         a1,t1         a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE t3         a1,t2         a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE t3         a1,t3         a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE t3         a1,v1_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE t3         a1,v1_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE t3         a1,v2_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE t3         a1,v2_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v1_invoker a1,t1         a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v1_invoker a1,t2         a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v1_invoker a1,t3         a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v1_invoker a1,v1_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v1_invoker a1,v1_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v1_invoker a1,v2_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v1_invoker a1,v2_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v1_definer a1,t1         a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v1_definer a1,t2         a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v1_definer a1,t3         a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v1_definer a1,v1_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v1_definer a1,v1_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v1_definer a1,v2_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v1_definer a1,v2_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v2_invoker a1,t1         a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v2_invoker a1,t2         a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v2_invoker a1,t3         a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v2_invoker a1,v1_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v2_invoker a1,v1_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v2_invoker a1,v2_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v2_invoker a1,v2_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v2_definer a1,t1         a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v2_definer a1,t2         a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v2_definer a1,t3         a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v2_definer a1,v1_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v2_definer a1,v1_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v2_definer a1,v2_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v2_definer a1,v2_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE t1         a1,t1         a2 SET a1.a=50 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+UPDATE t1         a1,t2         a2 SET a1.a=50 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+UPDATE t1         a1,t3         a2 SET a1.a=50 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+UPDATE t1         a1,v1_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+UPDATE t1         a1,v1_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+UPDATE t1         a1,v2_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+UPDATE t1         a1,v2_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+UPDATE t2         a1,t1         a2 SET a1.a=50 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+UPDATE t2         a1,t2         a2 SET a1.a=50 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+UPDATE t2         a1,t3         a2 SET a1.a=50 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+UPDATE t2         a1,v1_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+UPDATE t2         a1,v1_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+UPDATE t2         a1,v2_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+UPDATE t2         a1,v2_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+UPDATE t3         a1,t1         a2 SET a1.a=50 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+UPDATE t3         a1,t2         a2 SET a1.a=50 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+UPDATE t3         a1,t3         a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE t3         a1,v1_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+UPDATE t3         a1,v1_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE t3         a1,v2_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+UPDATE t3         a1,v2_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v1_invoker a1,t1         a2 SET a1.a=50 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+UPDATE v1_invoker a1,t2         a2 SET a1.a=50 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+UPDATE v1_invoker a1,t3         a2 SET a1.a=50 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+UPDATE v1_invoker a1,v1_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+UPDATE v1_invoker a1,v1_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+UPDATE v1_invoker a1,v2_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+UPDATE v1_invoker a1,v2_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+UPDATE v1_definer a1,t1         a2 SET a1.a=50 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+UPDATE v1_definer a1,t2         a2 SET a1.a=50 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+UPDATE v1_definer a1,t3         a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v1_definer a1,v1_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+UPDATE v1_definer a1,v1_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v1_definer a1,v2_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+UPDATE v1_definer a1,v2_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v2_invoker a1,t1         a2 SET a1.a=50 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+UPDATE v2_invoker a1,t2         a2 SET a1.a=50 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+UPDATE v2_invoker a1,t3         a2 SET a1.a=50 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+UPDATE v2_invoker a1,v1_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+UPDATE v2_invoker a1,v1_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+UPDATE v2_invoker a1,v2_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+UPDATE v2_invoker a1,v2_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+UPDATE v2_definer a1,t1         a2 SET a1.a=50 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+UPDATE v2_definer a1,t2         a2 SET a1.a=50 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+UPDATE v2_definer a1,t3         a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v2_definer a1,v1_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+UPDATE v2_definer a1,v1_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v2_definer a1,v2_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+UPDATE v2_definer a1,v2_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
+DROP VIEW v1_invoker, v1_definer, v2_invoker, v2_definer;
+DROP TABLE t1, t2, t3;
+# Testing SQLCOM_DELETE_MULTI
+CREATE TABLE t1 (a INT) ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t1.fix';
+CREATE TABLE t2 (a INT) ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t2.fix';
+CREATE TABLE t3 (a INT);
+INSERT INTO t1 VALUES (10);
+INSERT INTO t2 VALUES (20);
+INSERT INTO t3 VALUES (30);
+CREATE SQL SECURITY INVOKER VIEW v1_invoker AS SELECT * FROM t1;
+CREATE SQL SECURITY DEFINER VIEW v1_definer AS SELECT * FROM t1;
+CREATE SQL SECURITY INVOKER VIEW v2_invoker AS SELECT * FROM t2;
+CREATE SQL SECURITY DEFINER VIEW v2_definer AS SELECT * FROM t2;
+DELETE a1 FROM t1         a1,t1         a2 WHERE a1.a=a2.a;
+DELETE a1 FROM t1         a1,t2         a2 WHERE a1.a=a2.a;
+DELETE a1 FROM t1         a1,t3         a2 WHERE a1.a=a2.a;
+DELETE a1 FROM t1         a1,v1_invoker a2 WHERE a1.a=a2.a;
+DELETE a1 FROM t1         a1,v1_definer a2 WHERE a1.a=a2.a;
+DELETE a1 FROM t1         a1,v2_invoker a2 WHERE a1.a=a2.a;
+DELETE a1 FROM t1         a1,v2_definer a2 WHERE a1.a=a2.a;
+DELETE a1 FROM t2         a1,t1         a2 WHERE a1.a=a2.a;
+DELETE a1 FROM t2         a1,t2         a2 WHERE a1.a=a2.a;
+DELETE a1 FROM t2         a1,t3         a2 WHERE a1.a=a2.a;
+DELETE a1 FROM t2         a1,v1_invoker a2 WHERE a1.a=a2.a;
+DELETE a1 FROM t2         a1,v1_definer a2 WHERE a1.a=a2.a;
+DELETE a1 FROM t2         a1,v2_invoker a2 WHERE a1.a=a2.a;
+DELETE a1 FROM t2         a1,v2_definer a2 WHERE a1.a=a2.a;
+DELETE a1 FROM t3         a1,t1         a2 WHERE a1.a=a2.a;
+DELETE a1 FROM t3         a1,t2         a2 WHERE a1.a=a2.a;
+DELETE a1 FROM t3         a1,t3         a2 WHERE a1.a=a2.a;
+DELETE a1 FROM t3         a1,v1_invoker a2 WHERE a1.a=a2.a;
+DELETE a1 FROM t3         a1,v1_definer a2 WHERE a1.a=a2.a;
+DELETE a1 FROM t3         a1,v2_invoker a2 WHERE a1.a=a2.a;
+DELETE a1 FROM t3         a1,v2_definer a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v1_invoker a1,t1         a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v1_invoker a1,t2         a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v1_invoker a1,t3         a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v1_invoker a1,v1_invoker a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v1_invoker a1,v1_definer a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v1_invoker a1,v2_invoker a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v1_invoker a1,v2_definer a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v1_definer a1,t1         a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v1_definer a1,t2         a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v1_definer a1,t3         a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v1_definer a1,v1_invoker a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v1_definer a1,v1_definer a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v1_definer a1,v2_invoker a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v1_definer a1,v2_definer a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v2_invoker a1,t1         a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v2_invoker a1,t2         a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v2_invoker a1,t3         a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v2_invoker a1,v1_invoker a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v2_invoker a1,v1_definer a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v2_invoker a1,v2_invoker a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v2_invoker a1,v2_definer a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v2_definer a1,t1         a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v2_definer a1,t2         a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v2_definer a1,t3         a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v2_definer a1,v1_invoker a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v2_definer a1,v1_definer a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v2_definer a1,v2_invoker a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v2_definer a1,v2_definer a2 WHERE a1.a=a2.a;
+DELETE a1 FROM t1         a1,t1         a2 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DELETE a1 FROM t1         a1,t2         a2 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DELETE a1 FROM t1         a1,t3         a2 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DELETE a1 FROM t1         a1,v1_invoker a2 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DELETE a1 FROM t1         a1,v1_definer a2 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DELETE a1 FROM t1         a1,v2_invoker a2 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DELETE a1 FROM t1         a1,v2_definer a2 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DELETE a1 FROM t2         a1,t1         a2 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DELETE a1 FROM t2         a1,t2         a2 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DELETE a1 FROM t2         a1,t3         a2 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DELETE a1 FROM t2         a1,v1_invoker a2 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DELETE a1 FROM t2         a1,v1_definer a2 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DELETE a1 FROM t2         a1,v2_invoker a2 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DELETE a1 FROM t2         a1,v2_definer a2 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DELETE a1 FROM t3         a1,t1         a2 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DELETE a1 FROM t3         a1,t2         a2 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DELETE a1 FROM t3         a1,t3         a2 WHERE a1.a=a2.a;
+DELETE a1 FROM t3         a1,v1_invoker a2 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DELETE a1 FROM t3         a1,v1_definer a2 WHERE a1.a=a2.a;
+DELETE a1 FROM t3         a1,v2_invoker a2 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DELETE a1 FROM t3         a1,v2_definer a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v1_invoker a1,t1         a2 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DELETE a1 FROM v1_invoker a1,t2         a2 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DELETE a1 FROM v1_invoker a1,t3         a2 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DELETE a1 FROM v1_invoker a1,v1_invoker a2 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DELETE a1 FROM v1_invoker a1,v1_definer a2 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DELETE a1 FROM v1_invoker a1,v2_invoker a2 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DELETE a1 FROM v1_invoker a1,v2_definer a2 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DELETE a1 FROM v1_definer a1,t1         a2 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DELETE a1 FROM v1_definer a1,t2         a2 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DELETE a1 FROM v1_definer a1,t3         a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v1_definer a1,v1_invoker a2 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DELETE a1 FROM v1_definer a1,v1_definer a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v1_definer a1,v2_invoker a2 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DELETE a1 FROM v1_definer a1,v2_definer a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v2_invoker a1,t1         a2 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DELETE a1 FROM v2_invoker a1,t2         a2 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DELETE a1 FROM v2_invoker a1,t3         a2 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DELETE a1 FROM v2_invoker a1,v1_invoker a2 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DELETE a1 FROM v2_invoker a1,v1_definer a2 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DELETE a1 FROM v2_invoker a1,v2_invoker a2 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DELETE a1 FROM v2_invoker a1,v2_definer a2 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DELETE a1 FROM v2_definer a1,t1         a2 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DELETE a1 FROM v2_definer a1,t2         a2 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DELETE a1 FROM v2_definer a1,t3         a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v2_definer a1,v1_invoker a2 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DELETE a1 FROM v2_definer a1,v1_definer a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v2_definer a1,v2_invoker a2 WHERE a1.a=a2.a;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DELETE a1 FROM v2_definer a1,v2_definer a2 WHERE a1.a=a2.a;
+DROP VIEW v1_invoker, v1_definer, v2_invoker, v2_definer;
+DROP TABLE t1, t2, t3;
+# Testing SQLCOM_CREATE_VIEW
+CREATE TABLE t1 (a INT) ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t1.fix';
+INSERT INTO t1 VALUES (10);
+CREATE SQL SECURITY INVOKER VIEW v1_invoker AS SELECT * FROM t1;
+CREATE SQL SECURITY DEFINER VIEW v1_definer AS SELECT * FROM t1;
+CREATE VIEW v2 AS SELECT * FROM v1_invoker;
+DROP VIEW v2;
+CREATE VIEW v2 AS SELECT * FROM v1_definer;
+DROP VIEW v2;
+CREATE VIEW v2 AS SELECT * FROM t1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+CREATE VIEW v2 AS SELECT * FROM v1_invoker;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+CREATE VIEW v2 AS SELECT * FROM v1_definer;
+DROP VIEW v2;
+DROP VIEW v1_invoker, v1_definer;
+DROP TABLE t1;
+# Testing SQLCOM_INSERT_SELECT
+CREATE TABLE t1 (a INT) ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t1.fix';
+INSERT INTO t1 VALUES (10);
+CREATE SQL SECURITY INVOKER VIEW v1_invoker AS SELECT * FROM t1;
+CREATE SQL SECURITY DEFINER VIEW v1_definer AS SELECT * FROM t1;
+INSERT INTO t1         SELECT * FROM t1         WHERE a=20;
+INSERT INTO t1         SELECT * FROM v1_invoker WHERE a=20;
+INSERT INTO t1         SELECT * FROM v1_definer WHERE a=20;
+INSERT INTO v1_invoker SELECT * FROM t1         WHERE a=20;
+INSERT INTO v1_invoker SELECT * FROM v1_invoker WHERE a=20;
+INSERT INTO v1_invoker SELECT * FROM v1_definer WHERE a=20;
+INSERT INTO v1_definer SELECT * FROM t1         WHERE a=20;
+INSERT INTO v1_definer SELECT * FROM v1_invoker WHERE a=20;
+INSERT INTO v1_definer SELECT * FROM v1_definer WHERE a=20;
+INSERT INTO t1         SELECT * FROM t1         WHERE a=20;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+INSERT INTO t1         SELECT * FROM v1_invoker WHERE a=20;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+INSERT INTO t1         SELECT * FROM v1_definer WHERE a=20;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+INSERT INTO v1_invoker SELECT * FROM t1         WHERE a=20;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+INSERT INTO v1_invoker SELECT * FROM v1_invoker WHERE a=20;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+INSERT INTO v1_invoker SELECT * FROM v1_definer WHERE a=20;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+INSERT INTO v1_definer SELECT * FROM t1         WHERE a=20;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+INSERT INTO v1_definer SELECT * FROM v1_invoker WHERE a=20;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+INSERT INTO v1_definer SELECT * FROM v1_definer WHERE a=20;
+DROP VIEW v1_invoker, v1_definer;
+DROP TABLE t1;
+# Testing SQLCOM_REPLACE_SELECT
+CREATE TABLE t1 (a INT) ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t1.fix';
+INSERT INTO t1 VALUES (10);
+CREATE SQL SECURITY INVOKER VIEW v1_invoker AS SELECT * FROM t1;
+CREATE SQL SECURITY DEFINER VIEW v1_definer AS SELECT * FROM t1;
+REPLACE INTO t1         SELECT * FROM t1         WHERE a=20;
+ERROR 42000: CONNECT Unsupported command
+REPLACE INTO t1         SELECT * FROM v1_invoker WHERE a=20;
+ERROR 42000: CONNECT Unsupported command
+REPLACE INTO t1         SELECT * FROM v1_definer WHERE a=20;
+ERROR 42000: CONNECT Unsupported command
+REPLACE INTO v1_invoker SELECT * FROM t1         WHERE a=20;
+ERROR 42000: CONNECT Unsupported command
+REPLACE INTO v1_invoker SELECT * FROM v1_invoker WHERE a=20;
+ERROR 42000: CONNECT Unsupported command
+REPLACE INTO v1_invoker SELECT * FROM v1_definer WHERE a=20;
+ERROR 42000: CONNECT Unsupported command
+REPLACE INTO v1_definer SELECT * FROM t1         WHERE a=20;
+ERROR 42000: CONNECT Unsupported command
+REPLACE INTO v1_definer SELECT * FROM v1_invoker WHERE a=20;
+ERROR 42000: CONNECT Unsupported command
+REPLACE INTO v1_definer SELECT * FROM v1_definer WHERE a=20;
+ERROR 42000: CONNECT Unsupported command
+REPLACE INTO t1         SELECT * FROM t1         WHERE a=20;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+REPLACE INTO t1         SELECT * FROM v1_invoker WHERE a=20;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+REPLACE INTO t1         SELECT * FROM v1_definer WHERE a=20;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+REPLACE INTO v1_invoker SELECT * FROM t1         WHERE a=20;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+REPLACE INTO v1_invoker SELECT * FROM v1_invoker WHERE a=20;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+REPLACE INTO v1_invoker SELECT * FROM v1_definer WHERE a=20;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+REPLACE INTO v1_definer SELECT * FROM t1         WHERE a=20;
+ERROR 42000: CONNECT Unsupported command
+REPLACE INTO v1_definer SELECT * FROM v1_invoker WHERE a=20;
+ERROR 42000: CONNECT Unsupported command
+REPLACE INTO v1_definer SELECT * FROM v1_definer WHERE a=20;
+ERROR 42000: CONNECT Unsupported command
+DROP VIEW v1_invoker, v1_definer;
+DROP TABLE t1;
+# Testing SQLCOM_RENAME_TABLE
+CREATE TABLE t1 (a INT) ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t1.fix';
+INSERT INTO t1 VALUES (10);
+RENAME TABLE t1 TO t2;
+SHOW CREATE TABLE t2;
+Table	Create Table
+t2	CREATE TABLE `t2` (
+  `a` int(11) DEFAULT NULL
+) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`=fix `FILE_NAME`='t1.fix'
+RENAME TABLE t2 TO t1;
+RENAME TABLE t1 TO t2;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DROP TABLE t1;
+# Testing SQLCOM_ALTER_TABLE (for ALTER..RENAME)
+CREATE TABLE t1 (a INT) ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t1.fix';
+INSERT INTO t1 VALUES (10);
+ALTER TABLE t1 RENAME TO t2;
+SHOW CREATE TABLE t2;
+Table	Create Table
+t2	CREATE TABLE `t2` (
+  `a` int(11) DEFAULT NULL
+) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`=fix `FILE_NAME`='t1.fix'
+ALTER TABLE t2 RENAME TO t1;
+ALTER TABLE t1 RENAME TO t2;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DROP TABLE t1;
+# Testing SQLCOM_ALTER_TABLE (changing ENGINE to non-CONNECT)
+CREATE TABLE t1 (a INT) ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t1.fix';
+INSERT INTO t1 VALUES (10);
+ALTER TABLE t1 ENGINE=MyISAM;
+DROP TABLE t1;
+CREATE TABLE t1 (a INT) ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t1.fix';
+INSERT INTO t1 VALUES (10);
+ALTER TABLE t1 ENGINE=MyISAM;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DROP TABLE t1;
+# Testing SQLCOM_ALTER_TABLE (changing ENGINE to CONNECT)
+CREATE TABLE t1 (a INT) ENGINE=MyISAM;
+INSERT INTO t1 VALUES (10);
+SELECT * FROM t1;
+a
+10
+ALTER TABLE t1 ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t1.fix';
+DROP TABLE t1;
+CREATE TABLE t1 (a INT) ENGINE=MyISAM;
+INSERT INTO t1 VALUES (10);
+ALTER TABLE t1 ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t1.fix';
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DROP TABLE t1;
+# Testing SQLCOM_OPTIMIZE
+CREATE TABLE t1 (a INT NOT NULL, KEY(a)) ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t1.fix';
+INSERT INTO t1 VALUES (10);
+OPTIMIZE TABLE t1;
+Table	Op	Msg_type	Msg_text
+test.t1	optimize	status	OK
+OPTIMIZE TABLE t1;
+Table	Op	Msg_type	Msg_text
+test.t1	optimize	Error	Access denied for user 'user'@'localhost' (using password: NO)
+test.t1	optimize	Error	Can't lock file (errno: 122 "Internal (unspecified) error in handler")
+test.t1	optimize	error	Corrupt
+DROP TABLE t1;
+# Testing SQLCOM_ALTER_TABLE (adding columns)
+CREATE TABLE t1 (a INT) ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t1.fix';
+INSERT INTO t1 VALUES (10);
+ALTER TABLE t1 ADD b INT;
+Warnings:
+Warning	1105	This is an outward table, table data were not modified.
+ALTER TABLE t1 ADD c INT;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DROP TABLE t1;
+# Testing SQLCOM_ALTER_TABLE (removing columns)
+CREATE TABLE t1 (a INT,b INT,c INT) ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t1.fix';
+INSERT INTO t1 VALUES (10,10,10);
+ALTER TABLE t1 DROP b;
+Warnings:
+Warning	1105	This is an outward table, table data were not modified.
+ALTER TABLE t1 DROP c;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DROP TABLE t1;
+# Testing SQLCOM_ALTER_TABLE (adding keys)
+CREATE TABLE t1 (a INT NOT NULL,b INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t1.fix';
+INSERT INTO t1 VALUES (10,10);
+ALTER TABLE t1 ADD KEY(a);
+ALTER TABLE t1 ADD KEY(b);
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DROP TABLE t1;
+# Testing SQLCOM_ALTER_TABLE (removing keys)
+CREATE TABLE t1 (a INT NOT NULL,b INT NOT NULL, KEY a(a), KEY b(b)) ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t1.fix';
+INSERT INTO t1 VALUES (10,10);
+ALTER TABLE t1 DROP KEY a;
+ALTER TABLE t1 DROP KEY b;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DROP TABLE t1;
+# Testing SQLCOM_CREATE_INDEX and SQLCOM_DROP_INDEX
+CREATE TABLE t1 (a INT NOT NULL,b INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t1.fix';
+INSERT INTO t1 VALUES (10,10);
+CREATE INDEX a ON t1 (a);
+DROP INDEX a ON t1;
+CREATE INDEX a ON t1 (a);
+CREATE INDEX b ON t1 (b);
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DROP INDEX a ON t1;
+ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+DROP TABLE t1;
+DROP USER user@localhost;
diff --git a/storage/connect/mysql-test/connect/r/ini_grant.result b/storage/connect/mysql-test/connect/r/ini_grant.result
index c3acf7c..1901142 100644
--- a/storage/connect/mysql-test/connect/r/ini_grant.result
+++ b/storage/connect/mysql-test/connect/r/ini_grant.result
@@ -59,7 +59,7 @@ ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
 SELECT user();
 user()
 root@localhost
-CREATE VIEW v1 AS SELECT * FROM t1;
+CREATE SQL SECURITY INVOKER VIEW v1 AS SELECT * FROM t1;
 SELECT user();
 user()
 user@localhost
diff --git a/storage/connect/mysql-test/connect/r/mysql_grant.result b/storage/connect/mysql-test/connect/r/mysql_grant.result
index f8d0ee6..554e6f4 100644
--- a/storage/connect/mysql-test/connect/r/mysql_grant.result
+++ b/storage/connect/mysql-test/connect/r/mysql_grant.result
@@ -40,7 +40,7 @@ ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
 SELECT user();
 user()
 root@localhost
-CREATE VIEW v1 AS SELECT * FROM t1;
+CREATE SQL SECURITY INVOKER VIEW v1 AS SELECT * FROM t1;
 SELECT user();
 user()
 user@localhost
diff --git a/storage/connect/mysql-test/connect/r/odbc_sqlite3_grant.result b/storage/connect/mysql-test/connect/r/odbc_sqlite3_grant.result
index 364f340..06b4239 100644
--- a/storage/connect/mysql-test/connect/r/odbc_sqlite3_grant.result
+++ b/storage/connect/mysql-test/connect/r/odbc_sqlite3_grant.result
@@ -49,10 +49,11 @@ ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
 CREATE VIEW v1 AS SELECT * FROM t1;
 ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
 # Testing a VIEW created with FILE privileges but accessed with no FILE
+# using SQL SECIRITY INVOKER
 SELECT user();
 user()
 root@localhost
-CREATE VIEW v1 AS SELECT * FROM t1;
+CREATE SQL SECURITY INVOKER VIEW v1 AS SELECT * FROM t1;
 SELECT user();
 user()
 user@localhost
@@ -64,6 +65,19 @@ UPDATE v1 SET a=123;
 ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
 DELETE FROM v1;
 ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
+# Testing a VIEW created with FILE privileges but accessed with no FILE
+# using SQL SECIRITY DEFINER
+DROP VIEW v1;
+SELECT user();
+user()
+root@localhost
+CREATE SQL SECURITY DEFINER VIEW v1 AS SELECT * FROM t1;
+SELECT user();
+user()
+user@localhost
+SELECT * FROM v1 WHERE a='test1';
+a
+test1
 SELECT user();
 user()
 root@localhost
diff --git a/storage/connect/mysql-test/connect/r/xml_grant.result b/storage/connect/mysql-test/connect/r/xml_grant.result
index ea38e57..f6dc725 100644
--- a/storage/connect/mysql-test/connect/r/xml_grant.result
+++ b/storage/connect/mysql-test/connect/r/xml_grant.result
@@ -63,7 +63,7 @@ ERROR 28000: Access denied for user 'user'@'localhost' (using password: NO)
 SELECT user();
 user()
 root@localhost
-CREATE VIEW v1 AS SELECT * FROM t1;
+CREATE SQL SECURITY INVOKER VIEW v1 AS SELECT * FROM t1;
 SELECT user();
 user()
 user@localhost
diff --git a/storage/connect/mysql-test/connect/t/grant.inc b/storage/connect/mysql-test/connect/t/grant.inc
index 7bb214d..8f605a7 100644
--- a/storage/connect/mysql-test/connect/t/grant.inc
+++ b/storage/connect/mysql-test/connect/t/grant.inc
@@ -53,7 +53,7 @@ CREATE VIEW v1 AS SELECT * FROM t1;
 --echo # Testing a VIEW created with FILE privileges but accessed with no FILE
 --connection default
 SELECT user();
-CREATE VIEW v1 AS SELECT * FROM t1;
+CREATE SQL SECURITY INVOKER VIEW v1 AS SELECT * FROM t1;
 --connection user
 SELECT user();
 --error ER_ACCESS_DENIED_ERROR
diff --git a/storage/connect/mysql-test/connect/t/grant.test b/storage/connect/mysql-test/connect/t/grant.test
index 909bb41..31a596c 100644
--- a/storage/connect/mysql-test/connect/t/grant.test
+++ b/storage/connect/mysql-test/connect/t/grant.test
@@ -49,7 +49,7 @@ CREATE VIEW v1 AS SELECT * FROM t1;
 --echo # Testing a VIEW created with FILE privileges but accessed with no FILE
 --connection default
 SELECT user();
-CREATE VIEW v1 AS SELECT * FROM t1;
+CREATE SQL SECURITY INVOKER VIEW v1 AS SELECT * FROM t1;
 --connection user
 SELECT user();
 --error ER_ACCESS_DENIED_ERROR
diff --git a/storage/connect/mysql-test/connect/t/grant2.test b/storage/connect/mysql-test/connect/t/grant2.test
new file mode 100644
index 0000000..dbcdfca
--- /dev/null
+++ b/storage/connect/mysql-test/connect/t/grant2.test
@@ -0,0 +1,871 @@
+-- source include/not_embedded.inc
+
+# Tests that involve SQL SECURITY DEFINER (e.g. in VIEWs)
+# TODO: add test with stored routines eventually.
+
+let $MYSQLD_DATADIR= `select @@datadir`;
+
+--echo #
+--echo # MDEV-7574 Security definer views don't work with CONNECT ODBC tables
+--echo #
+
+GRANT ALL PRIVILEGES ON *.* TO user@localhost;
+REVOKE FILE ON *.* FROM user@localhost;
+--connect(user,localhost,user,,)
+
+
+--echo # Testing SQLCOM_SELECT
+--connection default
+CREATE TABLE t1 (a INT) ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t1.fix';
+INSERT INTO t1 VALUES (10);
+CREATE SQL SECURITY INVOKER VIEW v1_invoker AS SELECT * FROM t1;
+CREATE SQL SECURITY DEFINER VIEW v1_definer AS SELECT * FROM t1;
+SELECT * FROM t1;
+SELECT * FROM v1_invoker;
+SELECT * FROM v1_definer;
+--connection user
+--error ER_ACCESS_DENIED_ERROR
+SELECT * FROM t1;
+--error ER_ACCESS_DENIED_ERROR
+SELECT * FROM v1_invoker;
+SELECT * FROM v1_definer;
+--connection default
+DROP VIEW v1_invoker, v1_definer;
+DROP TABLE t1;
+--remove_file $MYSQLD_DATADIR/test/t1.fix
+
+
+--echo # Testing SQLCOM_UPDATE
+--connection default
+CREATE TABLE t1 (a INT) ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t1.fix';
+INSERT INTO t1 VALUES (10);
+CREATE SQL SECURITY INVOKER VIEW v1_invoker AS SELECT * FROM t1;
+CREATE SQL SECURITY DEFINER VIEW v1_definer AS SELECT * FROM t1;
+UPDATE t1 SET a=11;
+UPDATE v1_invoker SET a=12;
+UPDATE v1_definer SET a=13;
+--connection user
+--error ER_ACCESS_DENIED_ERROR
+UPDATE t1 SET a=21;
+--error ER_ACCESS_DENIED_ERROR
+UPDATE v1_invoker SET a=22;
+UPDATE v1_definer SET a=23;
+--connection default
+DROP VIEW v1_invoker, v1_definer;
+DROP TABLE t1;
+--remove_file $MYSQLD_DATADIR/test/t1.fix
+
+
+--echo # Testing SQLCOM_INSERT
+--connection default
+CREATE TABLE t1 (a INT) ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t1.fix';
+INSERT INTO t1 VALUES (10);
+CREATE SQL SECURITY INVOKER VIEW v1_invoker AS SELECT * FROM t1;
+CREATE SQL SECURITY DEFINER VIEW v1_definer AS SELECT * FROM t1;
+INSERT INTO t1 VALUES (11);
+INSERT INTO v1_invoker VALUES (12);
+INSERT INTO v1_definer VALUES (13);
+--connection user
+--error ER_ACCESS_DENIED_ERROR
+INSERT INTO t1 VALUES (21);
+--error ER_ACCESS_DENIED_ERROR
+INSERT INTO v1_invoker VALUES (22);
+INSERT INTO v1_definer VALUES (23);
+--connection default
+DROP VIEW v1_invoker, v1_definer;
+DROP TABLE t1;
+--remove_file $MYSQLD_DATADIR/test/t1.fix
+
+
+--echo # Testing SQLCOM_REPLACE
+# REPLACE is not supported by ConnectSE, so we're testing the difference
+# between ER_ACCESS_DENIED_ERROR vs ER_NOT_ALLOWED_COMMAND
+--connection default
+CREATE TABLE t1 (a INT) ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t1.fix';
+INSERT INTO t1 VALUES (10);
+CREATE SQL SECURITY INVOKER VIEW v1_invoker AS SELECT * FROM t1;
+CREATE SQL SECURITY DEFINER VIEW v1_definer AS SELECT * FROM t1;
+--error ER_NOT_ALLOWED_COMMAND
+REPLACE INTO t1 VALUES (11);
+--error ER_NOT_ALLOWED_COMMAND
+REPLACE INTO v1_invoker VALUES (12);
+--error ER_NOT_ALLOWED_COMMAND
+REPLACE INTO v1_definer VALUES (13);
+--connection user
+--error ER_ACCESS_DENIED_ERROR
+REPLACE INTO t1 VALUES (21);
+--error ER_ACCESS_DENIED_ERROR
+REPLACE INTO v1_invoker VALUES (22);
+--error ER_NOT_ALLOWED_COMMAND
+REPLACE INTO v1_definer VALUES (23);
+--connection default
+DROP VIEW v1_invoker, v1_definer;
+DROP TABLE t1;
+--remove_file $MYSQLD_DATADIR/test/t1.fix
+
+
+--echo # Testing SQLCOM_DELETE
+--connection default
+CREATE TABLE t1 (a INT) ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t1.fix';
+INSERT INTO t1 VALUES (10),(11),(12),(13),(21),(22),(23);
+CREATE SQL SECURITY INVOKER VIEW v1_invoker AS SELECT * FROM t1;
+CREATE SQL SECURITY DEFINER VIEW v1_definer AS SELECT * FROM t1;
+DELETE FROM t1 WHERE a=11;
+DELETE FROM v1_invoker WHERE a=12;
+DELETE FROM v1_definer WHERE a=13;
+--connection user
+--error ER_ACCESS_DENIED_ERROR
+DELETE FROM t1 WHERE a=21;
+--error ER_ACCESS_DENIED_ERROR
+DELETE FROM v1_invoker WHERE a=22;
+DELETE FROM v1_definer WHERE a=23;
+--connection default
+DROP VIEW v1_invoker, v1_definer;
+DROP TABLE t1;
+--remove_file $MYSQLD_DATADIR/test/t1.fix
+
+
+
+--echo # Testing SQLCOM_LOAD
+--connection default
+CREATE TABLE t1 (a VARCHAR(128)) ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t1.fix';
+INSERT INTO t1 VALUES (10);
+CREATE SQL SECURITY INVOKER VIEW v1_invoker AS SELECT * FROM t1;
+CREATE SQL SECURITY DEFINER VIEW v1_definer AS SELECT * FROM t1;
+--replace_result $MTR_SUITE_DIR MTR_SUITE_DIR
+--eval LOAD DATA LOCAL INFILE '$MTR_SUITE_DIR/std_data/boys.txt' INTO TABLE t1
+--replace_result $MTR_SUITE_DIR MTR_SUITE_DIR
+--eval LOAD DATA LOCAL INFILE '$MTR_SUITE_DIR/std_data/boys.txt' INTO TABLE v1_invoker
+--replace_result $MTR_SUITE_DIR MTR_SUITE_DIR
+--eval LOAD DATA LOCAL INFILE '$MTR_SUITE_DIR/std_data/boys.txt' INTO TABLE v1_definer
+--connection user
+--replace_result $MTR_SUITE_DIR MTR_SUITE_DIR
+--error ER_ACCESS_DENIED_ERROR
+--eval LOAD DATA LOCAL INFILE '$MTR_SUITE_DIR/std_data/boys.txt' INTO TABLE t1
+--replace_result $MTR_SUITE_DIR MTR_SUITE_DIR
+--error ER_ACCESS_DENIED_ERROR
+--eval LOAD DATA LOCAL INFILE '$MTR_SUITE_DIR/std_data/boys.txt' INTO TABLE v1_invoker
+--replace_result $MTR_SUITE_DIR MTR_SUITE_DIR
+--eval LOAD DATA LOCAL INFILE '$MTR_SUITE_DIR/std_data/boys.txt' INTO TABLE v1_definer
+--connection default
+DROP VIEW v1_invoker, v1_definer;
+DROP TABLE t1;
+--remove_file $MYSQLD_DATADIR/test/t1.fix
+
+
+--echo # Testing SQLCOM_TRUNCATE
+--connection default
+CREATE TABLE t1 (a INT) ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t1.fix';
+INSERT INTO t1 VALUES (10);
+TRUNCATE TABLE t1;
+INSERT INTO t1 VALUES (11);
+--connection user
+--error ER_ACCESS_DENIED_ERROR
+TRUNCATE TABLE t1;
+--connection default
+DROP TABLE t1;
+--remove_file $MYSQLD_DATADIR/test/t1.fix
+
+
+# TODO: Perhaps FILE_ACL is not needed for DROP TABLE. Discuss with Olivier.
+--echo # Testing SQLCOM_DROP_TABLE
+--connection default
+CREATE TABLE t1 (a INT) ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t1.fix';
+INSERT INTO t1 VALUES (10);
+--connection user
+--error ER_ACCESS_DENIED_ERROR
+DROP TABLE t1;
+--connection default
+DROP TABLE t1;
+--remove_file $MYSQLD_DATADIR/test/t1.fix
+
+
+--echo # Testing SQLCOM_DROP_VIEW
+--echo # DROP VIEW does not need FILE_ACL.
+--connection default
+CREATE TABLE t1 (a INT) ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t1.fix';
+INSERT INTO t1 VALUES (10),(11),(12),(13),(21),(22),(23);
+CREATE SQL SECURITY INVOKER VIEW v1_invoker AS SELECT * FROM t1;
+CREATE SQL SECURITY DEFINER VIEW v1_definer AS SELECT * FROM t1;
+DROP VIEW v1_invoker, v1_definer;
+CREATE SQL SECURITY INVOKER VIEW v1_invoker AS SELECT * FROM t1;
+CREATE SQL SECURITY DEFINER VIEW v1_definer AS SELECT * FROM t1;
+--connection user
+DROP VIEW v1_invoker;
+DROP VIEW v1_definer;
+--connection default
+DROP TABLE t1;
+--remove_file $MYSQLD_DATADIR/test/t1.fix
+
+
+--echo # Testing SQLCOM_CREATE_TABLE
+--connection user
+--error ER_ACCESS_DENIED_ERROR
+CREATE TABLE t1 (a INT) ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t1.fix';
+--connection default
+
+
+--echo # Testing SQLCOM_LOCK_TABLES
+--connection default
+CREATE TABLE t1 (a INT) ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t1.fix';
+INSERT INTO t1 VALUES (10);
+CREATE SQL SECURITY INVOKER VIEW v1_invoker AS SELECT * FROM t1;
+CREATE SQL SECURITY DEFINER VIEW v1_definer AS SELECT * FROM t1;
+LOCK TABLE t1 READ;
+UNLOCK TABLES;
+LOCK TABLE t1 WRITE;
+UNLOCK TABLES;
+LOCK TABLE v1_invoker READ;
+UNLOCK TABLES;
+LOCK TABLE v1_invoker WRITE;
+UNLOCK TABLES;
+LOCK TABLE v1_definer READ;
+UNLOCK TABLES;
+LOCK TABLE v1_definer WRITE;
+UNLOCK TABLES;
+--connection user
+--error ER_ACCESS_DENIED_ERROR
+LOCK TABLE t1 READ;
+--error ER_ACCESS_DENIED_ERROR
+LOCK TABLE t1 WRITE;
+--error ER_ACCESS_DENIED_ERROR
+LOCK TABLE v1_invoker READ;
+--error ER_ACCESS_DENIED_ERROR
+LOCK TABLE v1_invoker WRITE;
+LOCK TABLE v1_definer READ;
+UNLOCK TABLES;
+LOCK TABLE v1_definer WRITE;
+UNLOCK TABLES;
+--connection default
+DROP VIEW v1_invoker, v1_definer;
+DROP TABLE t1;
+--remove_file $MYSQLD_DATADIR/test/t1.fix
+
+
+--echo # Testing SQLCOM_UPDATE_MULTI
+--connection default
+# t1 and t2 require FILE_ACL, t3 does not
+CREATE TABLE t1 (a INT) ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t1.fix';
+CREATE TABLE t2 (a INT) ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t2.fix';
+CREATE TABLE t3 (a INT);
+INSERT INTO t1 VALUES (10);
+INSERT INTO t2 VALUES (20);
+INSERT INTO t3 VALUES (30);
+CREATE SQL SECURITY INVOKER VIEW v1_invoker AS SELECT * FROM t1;
+CREATE SQL SECURITY DEFINER VIEW v1_definer AS SELECT * FROM t1;
+CREATE SQL SECURITY INVOKER VIEW v2_invoker AS SELECT * FROM t2;
+CREATE SQL SECURITY DEFINER VIEW v2_definer AS SELECT * FROM t2;
+UPDATE t1         a1,t1         a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE t1         a1,t2         a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE t1         a1,t3         a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE t1         a1,v1_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE t1         a1,v1_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE t1         a1,v2_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE t1         a1,v2_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE t2         a1,t1         a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE t2         a1,t2         a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE t2         a1,t3         a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE t2         a1,v1_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE t2         a1,v1_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE t2         a1,v2_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE t2         a1,v2_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE t3         a1,t1         a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE t3         a1,t2         a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE t3         a1,t3         a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE t3         a1,v1_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE t3         a1,v1_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE t3         a1,v2_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE t3         a1,v2_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v1_invoker a1,t1         a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v1_invoker a1,t2         a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v1_invoker a1,t3         a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v1_invoker a1,v1_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v1_invoker a1,v1_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v1_invoker a1,v2_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v1_invoker a1,v2_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v1_definer a1,t1         a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v1_definer a1,t2         a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v1_definer a1,t3         a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v1_definer a1,v1_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v1_definer a1,v1_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v1_definer a1,v2_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v1_definer a1,v2_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v2_invoker a1,t1         a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v2_invoker a1,t2         a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v2_invoker a1,t3         a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v2_invoker a1,v1_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v2_invoker a1,v1_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v2_invoker a1,v2_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v2_invoker a1,v2_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v2_definer a1,t1         a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v2_definer a1,t2         a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v2_definer a1,t3         a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v2_definer a1,v1_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v2_definer a1,v1_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v2_definer a1,v2_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v2_definer a1,v2_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
+
+--connection user
+
+# All queries with t1 should fail
+--error ER_ACCESS_DENIED_ERROR
+UPDATE t1         a1,t1         a2 SET a1.a=50 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+UPDATE t1         a1,t2         a2 SET a1.a=50 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+UPDATE t1         a1,t3         a2 SET a1.a=50 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+UPDATE t1         a1,v1_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+UPDATE t1         a1,v1_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+UPDATE t1         a1,v2_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+UPDATE t1         a1,v2_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
+
+# All queries with t2 should fail
+--error ER_ACCESS_DENIED_ERROR
+UPDATE t2         a1,t1         a2 SET a1.a=50 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+UPDATE t2         a1,t2         a2 SET a1.a=50 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+UPDATE t2         a1,t3         a2 SET a1.a=50 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+UPDATE t2         a1,v1_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+UPDATE t2         a1,v1_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+UPDATE t2         a1,v2_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+UPDATE t2         a1,v2_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
+
+# t3 does not need FILE_ALC
+--error ER_ACCESS_DENIED_ERROR
+UPDATE t3         a1,t1         a2 SET a1.a=50 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+UPDATE t3         a1,t2         a2 SET a1.a=50 WHERE a1.a=a2.a;
+# This is OK:
+UPDATE t3         a1,t3         a2 SET a1.a=50 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+UPDATE t3         a1,v1_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
+# This is OK:
+UPDATE t3         a1,v1_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+UPDATE t3         a1,v2_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
+# This is OK:
+UPDATE t3         a1,v2_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
+
+# All queries with v1_invoker should fail
+--error ER_ACCESS_DENIED_ERROR
+UPDATE v1_invoker a1,t1         a2 SET a1.a=50 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+UPDATE v1_invoker a1,t2         a2 SET a1.a=50 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+UPDATE v1_invoker a1,t3         a2 SET a1.a=50 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+UPDATE v1_invoker a1,v1_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+UPDATE v1_invoker a1,v1_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+UPDATE v1_invoker a1,v2_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+UPDATE v1_invoker a1,v2_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
+
+# v1_definer does not need FILE_ACL from the invoker
+--error ER_ACCESS_DENIED_ERROR
+UPDATE v1_definer a1,t1         a2 SET a1.a=50 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+UPDATE v1_definer a1,t2         a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v1_definer a1,t3         a2 SET a1.a=50 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+UPDATE v1_definer a1,v1_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v1_definer a1,v1_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+UPDATE v1_definer a1,v2_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v1_definer a1,v2_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
+
+# All queries with v2_invoker should fail
+--error ER_ACCESS_DENIED_ERROR
+UPDATE v2_invoker a1,t1         a2 SET a1.a=50 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+UPDATE v2_invoker a1,t2         a2 SET a1.a=50 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+UPDATE v2_invoker a1,t3         a2 SET a1.a=50 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+UPDATE v2_invoker a1,v1_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+UPDATE v2_invoker a1,v1_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+UPDATE v2_invoker a1,v2_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+UPDATE v2_invoker a1,v2_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
+
+# v2_definer does not need FILE_ACL from the invoker
+--error ER_ACCESS_DENIED_ERROR
+UPDATE v2_definer a1,t1         a2 SET a1.a=50 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+UPDATE v2_definer a1,t2         a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v2_definer a1,t3         a2 SET a1.a=50 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+UPDATE v2_definer a1,v1_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v2_definer a1,v1_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+UPDATE v2_definer a1,v2_invoker a2 SET a1.a=50 WHERE a1.a=a2.a;
+UPDATE v2_definer a1,v2_definer a2 SET a1.a=50 WHERE a1.a=a2.a;
+
+--connection default
+DROP VIEW v1_invoker, v1_definer, v2_invoker, v2_definer;
+DROP TABLE t1, t2, t3;
+--remove_file $MYSQLD_DATADIR/test/t1.fix
+--remove_file $MYSQLD_DATADIR/test/t2.fix
+
+
+--echo # Testing SQLCOM_DELETE_MULTI
+--connection default
+# t1 and t2 require FILE_ACL, t3 does not
+CREATE TABLE t1 (a INT) ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t1.fix';
+CREATE TABLE t2 (a INT) ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t2.fix';
+CREATE TABLE t3 (a INT);
+INSERT INTO t1 VALUES (10);
+INSERT INTO t2 VALUES (20);
+INSERT INTO t3 VALUES (30);
+CREATE SQL SECURITY INVOKER VIEW v1_invoker AS SELECT * FROM t1;
+CREATE SQL SECURITY DEFINER VIEW v1_definer AS SELECT * FROM t1;
+CREATE SQL SECURITY INVOKER VIEW v2_invoker AS SELECT * FROM t2;
+CREATE SQL SECURITY DEFINER VIEW v2_definer AS SELECT * FROM t2;
+DELETE a1 FROM t1         a1,t1         a2 WHERE a1.a=a2.a;
+DELETE a1 FROM t1         a1,t2         a2 WHERE a1.a=a2.a;
+DELETE a1 FROM t1         a1,t3         a2 WHERE a1.a=a2.a;
+DELETE a1 FROM t1         a1,v1_invoker a2 WHERE a1.a=a2.a;
+DELETE a1 FROM t1         a1,v1_definer a2 WHERE a1.a=a2.a;
+DELETE a1 FROM t1         a1,v2_invoker a2 WHERE a1.a=a2.a;
+DELETE a1 FROM t1         a1,v2_definer a2 WHERE a1.a=a2.a;
+DELETE a1 FROM t2         a1,t1         a2 WHERE a1.a=a2.a;
+DELETE a1 FROM t2         a1,t2         a2 WHERE a1.a=a2.a;
+DELETE a1 FROM t2         a1,t3         a2 WHERE a1.a=a2.a;
+DELETE a1 FROM t2         a1,v1_invoker a2 WHERE a1.a=a2.a;
+DELETE a1 FROM t2         a1,v1_definer a2 WHERE a1.a=a2.a;
+DELETE a1 FROM t2         a1,v2_invoker a2 WHERE a1.a=a2.a;
+DELETE a1 FROM t2         a1,v2_definer a2 WHERE a1.a=a2.a;
+DELETE a1 FROM t3         a1,t1         a2 WHERE a1.a=a2.a;
+DELETE a1 FROM t3         a1,t2         a2 WHERE a1.a=a2.a;
+DELETE a1 FROM t3         a1,t3         a2 WHERE a1.a=a2.a;
+DELETE a1 FROM t3         a1,v1_invoker a2 WHERE a1.a=a2.a;
+DELETE a1 FROM t3         a1,v1_definer a2 WHERE a1.a=a2.a;
+DELETE a1 FROM t3         a1,v2_invoker a2 WHERE a1.a=a2.a;
+DELETE a1 FROM t3         a1,v2_definer a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v1_invoker a1,t1         a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v1_invoker a1,t2         a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v1_invoker a1,t3         a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v1_invoker a1,v1_invoker a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v1_invoker a1,v1_definer a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v1_invoker a1,v2_invoker a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v1_invoker a1,v2_definer a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v1_definer a1,t1         a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v1_definer a1,t2         a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v1_definer a1,t3         a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v1_definer a1,v1_invoker a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v1_definer a1,v1_definer a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v1_definer a1,v2_invoker a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v1_definer a1,v2_definer a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v2_invoker a1,t1         a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v2_invoker a1,t2         a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v2_invoker a1,t3         a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v2_invoker a1,v1_invoker a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v2_invoker a1,v1_definer a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v2_invoker a1,v2_invoker a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v2_invoker a1,v2_definer a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v2_definer a1,t1         a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v2_definer a1,t2         a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v2_definer a1,t3         a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v2_definer a1,v1_invoker a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v2_definer a1,v1_definer a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v2_definer a1,v2_invoker a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v2_definer a1,v2_definer a2 WHERE a1.a=a2.a;
+
+--connection user
+
+# All queries with t1 should fail
+--error ER_ACCESS_DENIED_ERROR
+DELETE a1 FROM t1         a1,t1         a2 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+DELETE a1 FROM t1         a1,t2         a2 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+DELETE a1 FROM t1         a1,t3         a2 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+DELETE a1 FROM t1         a1,v1_invoker a2 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+DELETE a1 FROM t1         a1,v1_definer a2 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+DELETE a1 FROM t1         a1,v2_invoker a2 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+DELETE a1 FROM t1         a1,v2_definer a2 WHERE a1.a=a2.a;
+
+# All queries with t2 should fail
+--error ER_ACCESS_DENIED_ERROR
+DELETE a1 FROM t2         a1,t1         a2 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+DELETE a1 FROM t2         a1,t2         a2 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+DELETE a1 FROM t2         a1,t3         a2 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+DELETE a1 FROM t2         a1,v1_invoker a2 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+DELETE a1 FROM t2         a1,v1_definer a2 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+DELETE a1 FROM t2         a1,v2_invoker a2 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+DELETE a1 FROM t2         a1,v2_definer a2 WHERE a1.a=a2.a;
+
+# t3 does not need FILE_ALC
+--error ER_ACCESS_DENIED_ERROR
+DELETE a1 FROM t3         a1,t1         a2 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+DELETE a1 FROM t3         a1,t2         a2 WHERE a1.a=a2.a;
+# This is OK:
+DELETE a1 FROM t3         a1,t3         a2 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+DELETE a1 FROM t3         a1,v1_invoker a2 WHERE a1.a=a2.a;
+# This is OK:
+DELETE a1 FROM t3         a1,v1_definer a2 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+DELETE a1 FROM t3         a1,v2_invoker a2 WHERE a1.a=a2.a;
+# This is OK:
+DELETE a1 FROM t3         a1,v2_definer a2 WHERE a1.a=a2.a;
+
+# All queries with v1_invoker should fail
+--error ER_ACCESS_DENIED_ERROR
+DELETE a1 FROM v1_invoker a1,t1         a2 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+DELETE a1 FROM v1_invoker a1,t2         a2 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+DELETE a1 FROM v1_invoker a1,t3         a2 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+DELETE a1 FROM v1_invoker a1,v1_invoker a2 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+DELETE a1 FROM v1_invoker a1,v1_definer a2 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+DELETE a1 FROM v1_invoker a1,v2_invoker a2 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+DELETE a1 FROM v1_invoker a1,v2_definer a2 WHERE a1.a=a2.a;
+
+# v1_definer does not need FILE_ACL from the invoker
+--error ER_ACCESS_DENIED_ERROR
+DELETE a1 FROM v1_definer a1,t1         a2 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+DELETE a1 FROM v1_definer a1,t2         a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v1_definer a1,t3         a2 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+DELETE a1 FROM v1_definer a1,v1_invoker a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v1_definer a1,v1_definer a2 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+DELETE a1 FROM v1_definer a1,v2_invoker a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v1_definer a1,v2_definer a2 WHERE a1.a=a2.a;
+
+# All queries with v2_invoker should fail
+--error ER_ACCESS_DENIED_ERROR
+DELETE a1 FROM v2_invoker a1,t1         a2 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+DELETE a1 FROM v2_invoker a1,t2         a2 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+DELETE a1 FROM v2_invoker a1,t3         a2 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+DELETE a1 FROM v2_invoker a1,v1_invoker a2 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+DELETE a1 FROM v2_invoker a1,v1_definer a2 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+DELETE a1 FROM v2_invoker a1,v2_invoker a2 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+DELETE a1 FROM v2_invoker a1,v2_definer a2 WHERE a1.a=a2.a;
+
+# v2_definer does not need FILE_ACL from the invoker
+--error ER_ACCESS_DENIED_ERROR
+DELETE a1 FROM v2_definer a1,t1         a2 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+DELETE a1 FROM v2_definer a1,t2         a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v2_definer a1,t3         a2 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+DELETE a1 FROM v2_definer a1,v1_invoker a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v2_definer a1,v1_definer a2 WHERE a1.a=a2.a;
+--error ER_ACCESS_DENIED_ERROR
+DELETE a1 FROM v2_definer a1,v2_invoker a2 WHERE a1.a=a2.a;
+DELETE a1 FROM v2_definer a1,v2_definer a2 WHERE a1.a=a2.a;
+
+--connection default
+DROP VIEW v1_invoker, v1_definer, v2_invoker, v2_definer;
+DROP TABLE t1, t2, t3;
+--remove_file $MYSQLD_DATADIR/test/t1.fix
+--remove_file $MYSQLD_DATADIR/test/t2.fix
+
+
+--echo # Testing SQLCOM_CREATE_VIEW
+--connection default
+CREATE TABLE t1 (a INT) ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t1.fix';
+INSERT INTO t1 VALUES (10);
+CREATE SQL SECURITY INVOKER VIEW v1_invoker AS SELECT * FROM t1;
+CREATE SQL SECURITY DEFINER VIEW v1_definer AS SELECT * FROM t1;
+CREATE VIEW v2 AS SELECT * FROM v1_invoker;
+DROP VIEW v2;
+CREATE VIEW v2 AS SELECT * FROM v1_definer;
+DROP VIEW v2;
+--connection user
+--error ER_ACCESS_DENIED_ERROR
+CREATE VIEW v2 AS SELECT * FROM t1;
+--error ER_ACCESS_DENIED_ERROR
+CREATE VIEW v2 AS SELECT * FROM v1_invoker;
+CREATE VIEW v2 AS SELECT * FROM v1_definer;
+DROP VIEW v2;
+--connection default
+DROP VIEW v1_invoker, v1_definer;
+DROP TABLE t1;
+--remove_file $MYSQLD_DATADIR/test/t1.fix
+
+
+--echo # Testing SQLCOM_INSERT_SELECT
+--connection default
+CREATE TABLE t1 (a INT) ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t1.fix';
+INSERT INTO t1 VALUES (10);
+CREATE SQL SECURITY INVOKER VIEW v1_invoker AS SELECT * FROM t1;
+CREATE SQL SECURITY DEFINER VIEW v1_definer AS SELECT * FROM t1;
+INSERT INTO t1         SELECT * FROM t1         WHERE a=20;
+INSERT INTO t1         SELECT * FROM v1_invoker WHERE a=20;
+INSERT INTO t1         SELECT * FROM v1_definer WHERE a=20;
+INSERT INTO v1_invoker SELECT * FROM t1         WHERE a=20;
+INSERT INTO v1_invoker SELECT * FROM v1_invoker WHERE a=20;
+INSERT INTO v1_invoker SELECT * FROM v1_definer WHERE a=20;
+INSERT INTO v1_definer SELECT * FROM t1         WHERE a=20;
+INSERT INTO v1_definer SELECT * FROM v1_invoker WHERE a=20;
+INSERT INTO v1_definer SELECT * FROM v1_definer WHERE a=20;
+--connection user
+--error ER_ACCESS_DENIED_ERROR
+INSERT INTO t1         SELECT * FROM t1         WHERE a=20;
+--error ER_ACCESS_DENIED_ERROR
+INSERT INTO t1         SELECT * FROM v1_invoker WHERE a=20;
+--error ER_ACCESS_DENIED_ERROR
+INSERT INTO t1         SELECT * FROM v1_definer WHERE a=20;
+--error ER_ACCESS_DENIED_ERROR
+INSERT INTO v1_invoker SELECT * FROM t1         WHERE a=20;
+--error ER_ACCESS_DENIED_ERROR
+INSERT INTO v1_invoker SELECT * FROM v1_invoker WHERE a=20;
+--error ER_ACCESS_DENIED_ERROR
+INSERT INTO v1_invoker SELECT * FROM v1_definer WHERE a=20;
+--error ER_ACCESS_DENIED_ERROR
+INSERT INTO v1_definer SELECT * FROM t1         WHERE a=20;
+--error ER_ACCESS_DENIED_ERROR
+INSERT INTO v1_definer SELECT * FROM v1_invoker WHERE a=20;
+# This is OK:
+INSERT INTO v1_definer SELECT * FROM v1_definer WHERE a=20;
+--connection default
+DROP VIEW v1_invoker, v1_definer;
+DROP TABLE t1;
+--remove_file $MYSQLD_DATADIR/test/t1.fix
+
+
+--echo # Testing SQLCOM_REPLACE_SELECT
+# REPLACE is not supported by CONNECT
+# so we're testing ER_NOT_ALLOWED_COMMAND vs ER_ACCESS_DENIED_ERROR here
+--connection default
+CREATE TABLE t1 (a INT) ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t1.fix';
+INSERT INTO t1 VALUES (10);
+CREATE SQL SECURITY INVOKER VIEW v1_invoker AS SELECT * FROM t1;
+CREATE SQL SECURITY DEFINER VIEW v1_definer AS SELECT * FROM t1;
+--error ER_NOT_ALLOWED_COMMAND
+REPLACE INTO t1         SELECT * FROM t1         WHERE a=20;
+--error ER_NOT_ALLOWED_COMMAND
+REPLACE INTO t1         SELECT * FROM v1_invoker WHERE a=20;
+--error ER_NOT_ALLOWED_COMMAND
+REPLACE INTO t1         SELECT * FROM v1_definer WHERE a=20;
+--error ER_NOT_ALLOWED_COMMAND
+REPLACE INTO v1_invoker SELECT * FROM t1         WHERE a=20;
+--error ER_NOT_ALLOWED_COMMAND
+REPLACE INTO v1_invoker SELECT * FROM v1_invoker WHERE a=20;
+--error ER_NOT_ALLOWED_COMMAND
+REPLACE INTO v1_invoker SELECT * FROM v1_definer WHERE a=20;
+--error ER_NOT_ALLOWED_COMMAND
+REPLACE INTO v1_definer SELECT * FROM t1         WHERE a=20;
+--error ER_NOT_ALLOWED_COMMAND
+REPLACE INTO v1_definer SELECT * FROM v1_invoker WHERE a=20;
+--error ER_NOT_ALLOWED_COMMAND
+REPLACE INTO v1_definer SELECT * FROM v1_definer WHERE a=20;
+
+--connection user
+--error ER_ACCESS_DENIED_ERROR
+REPLACE INTO t1         SELECT * FROM t1         WHERE a=20;
+--error ER_ACCESS_DENIED_ERROR
+REPLACE INTO t1         SELECT * FROM v1_invoker WHERE a=20;
+--error ER_ACCESS_DENIED_ERROR
+REPLACE INTO t1         SELECT * FROM v1_definer WHERE a=20;
+--error ER_ACCESS_DENIED_ERROR
+REPLACE INTO v1_invoker SELECT * FROM t1         WHERE a=20;
+--error ER_ACCESS_DENIED_ERROR
+REPLACE INTO v1_invoker SELECT * FROM v1_invoker WHERE a=20;
+--error ER_ACCESS_DENIED_ERROR
+REPLACE INTO v1_invoker SELECT * FROM v1_definer WHERE a=20;
+--error ER_NOT_ALLOWED_COMMAND
+REPLACE INTO v1_definer SELECT * FROM t1         WHERE a=20;
+--error ER_NOT_ALLOWED_COMMAND
+REPLACE INTO v1_definer SELECT * FROM v1_invoker WHERE a=20;
+--error ER_NOT_ALLOWED_COMMAND
+REPLACE INTO v1_definer SELECT * FROM v1_definer WHERE a=20;
+--connection default
+DROP VIEW v1_invoker, v1_definer;
+DROP TABLE t1;
+--remove_file $MYSQLD_DATADIR/test/t1.fix
+
+
+--echo # Testing SQLCOM_RENAME_TABLE
+--connection default
+CREATE TABLE t1 (a INT) ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t1.fix';
+INSERT INTO t1 VALUES (10);
+RENAME TABLE t1 TO t2;
+SHOW CREATE TABLE t2;
+RENAME TABLE t2 TO t1;
+--connection user
+# TODO: Perhaps FILE_ACL is needed for RENAME. Discuss with Oliver.
+--error ER_ACCESS_DENIED_ERROR
+RENAME TABLE t1 TO t2;
+--connection default
+DROP TABLE t1;
+--remove_file $MYSQLD_DATADIR/test/t1.fix
+
+
+--echo # Testing SQLCOM_ALTER_TABLE (for ALTER..RENAME)
+--connection default
+CREATE TABLE t1 (a INT) ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t1.fix';
+INSERT INTO t1 VALUES (10);
+ALTER TABLE t1 RENAME TO t2;
+SHOW CREATE TABLE t2;
+ALTER TABLE t2 RENAME TO t1;
+--connection user
+# TODO: Perhaps FILE_ACL is not needed for ALTER..RENAME. Discuss with Olivier.
+--error ER_ACCESS_DENIED_ERROR
+ALTER TABLE t1 RENAME TO t2;
+--connection default
+DROP TABLE t1;
+--remove_file $MYSQLD_DATADIR/test/t1.fix
+
+
+--echo # Testing SQLCOM_ALTER_TABLE (changing ENGINE to non-CONNECT)
+--connection default
+CREATE TABLE t1 (a INT) ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t1.fix';
+INSERT INTO t1 VALUES (10);
+ALTER TABLE t1 ENGINE=MyISAM;
+DROP TABLE t1;
+--remove_file $MYSQLD_DATADIR/test/t1.fix
+CREATE TABLE t1 (a INT) ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t1.fix';
+INSERT INTO t1 VALUES (10);
+--connection user
+--error ER_ACCESS_DENIED_ERROR
+ALTER TABLE t1 ENGINE=MyISAM;
+--connection default
+DROP TABLE t1;
+--remove_file $MYSQLD_DATADIR/test/t1.fix
+
+
+--echo # Testing SQLCOM_ALTER_TABLE (changing ENGINE to CONNECT)
+--connection default
+CREATE TABLE t1 (a INT) ENGINE=MyISAM; 
+INSERT INTO t1 VALUES (10);
+SELECT * FROM t1;
+# This should succeed, as 't1.fix' does not exists.
+ALTER TABLE t1 ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t1.fix';
+DROP TABLE t1;
+CREATE TABLE t1 (a INT) ENGINE=MyISAM;
+INSERT INTO t1 VALUES (10);
+--connection user
+--error ER_ACCESS_DENIED_ERROR
+ALTER TABLE t1 ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t1.fix';
+--connection default
+DROP TABLE t1;
+
+
+--echo # Testing SQLCOM_OPTIMIZE
+--connection default
+CREATE TABLE t1 (a INT NOT NULL, KEY(a)) ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t1.fix';
+INSERT INTO t1 VALUES (10);
+OPTIMIZE TABLE t1;
+--connection user
+# This command succeeds, but reports "Access denied" in the "Msg_text" column.
+OPTIMIZE TABLE t1;
+--connection default
+DROP TABLE t1;
+--remove_file $MYSQLD_DATADIR/test/t1.fix
+
+
+--echo # Testing SQLCOM_ALTER_TABLE (adding columns)
+--connection default
+CREATE TABLE t1 (a INT) ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t1.fix';
+INSERT INTO t1 VALUES (10);
+ALTER TABLE t1 ADD b INT;
+--connection user
+--error ER_ACCESS_DENIED_ERROR
+ALTER TABLE t1 ADD c INT;
+--connection default
+DROP TABLE t1;
+--remove_file $MYSQLD_DATADIR/test/t1.fix
+
+
+--echo # Testing SQLCOM_ALTER_TABLE (removing columns)
+--connection default
+CREATE TABLE t1 (a INT,b INT,c INT) ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t1.fix';
+INSERT INTO t1 VALUES (10,10,10);
+ALTER TABLE t1 DROP b;
+--connection user
+--error ER_ACCESS_DENIED_ERROR
+ALTER TABLE t1 DROP c;
+--connection default
+DROP TABLE t1;
+--remove_file $MYSQLD_DATADIR/test/t1.fix
+
+
+--echo # Testing SQLCOM_ALTER_TABLE (adding keys)
+--connection default
+CREATE TABLE t1 (a INT NOT NULL,b INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t1.fix';
+INSERT INTO t1 VALUES (10,10);
+ALTER TABLE t1 ADD KEY(a);
+--connection user
+--error ER_ACCESS_DENIED_ERROR
+ALTER TABLE t1 ADD KEY(b);
+--connection default
+DROP TABLE t1;
+--remove_file $MYSQLD_DATADIR/test/t1.fix
+--remove_file $MYSQLD_DATADIR/test/t1.fnx
+
+
+--echo # Testing SQLCOM_ALTER_TABLE (removing keys)
+--connection default
+CREATE TABLE t1 (a INT NOT NULL,b INT NOT NULL, KEY a(a), KEY b(b)) ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t1.fix';
+INSERT INTO t1 VALUES (10,10);
+ALTER TABLE t1 DROP KEY a;
+--connection user
+--error ER_ACCESS_DENIED_ERROR
+ALTER TABLE t1 DROP KEY b;
+--connection default
+DROP TABLE t1;
+--remove_file $MYSQLD_DATADIR/test/t1.fix
+--remove_file $MYSQLD_DATADIR/test/t1.fnx
+
+
+--echo # Testing SQLCOM_CREATE_INDEX and SQLCOM_DROP_INDEX
+--connection default
+CREATE TABLE t1 (a INT NOT NULL,b INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=fix FILE_NAME='t1.fix';
+INSERT INTO t1 VALUES (10,10);
+CREATE INDEX a ON t1 (a);
+DROP INDEX a ON t1;
+CREATE INDEX a ON t1 (a);
+--connection user
+--error ER_ACCESS_DENIED_ERROR
+CREATE INDEX b ON t1 (b);
+--error ER_ACCESS_DENIED_ERROR
+DROP INDEX a ON t1;
+--connection default
+DROP TABLE t1;
+--remove_file $MYSQLD_DATADIR/test/t1.fix
+--remove_file $MYSQLD_DATADIR/test/t1.fnx
+
+
+#SQLCOM_ALTER_TABLE (change engine to CONNECT):
+
+
+
+DROP USER user@localhost;
diff --git a/storage/connect/mysql-test/connect/t/ini_grant.test b/storage/connect/mysql-test/connect/t/ini_grant.test
index 3067864..ebc7a80 100644
--- a/storage/connect/mysql-test/connect/t/ini_grant.test
+++ b/storage/connect/mysql-test/connect/t/ini_grant.test
@@ -54,7 +54,7 @@ CREATE VIEW v1 AS SELECT * FROM t1;
 --echo # Testing a VIEW created with FILE privileges but accessed with no FILE
 --connection default
 SELECT user();
-CREATE VIEW v1 AS SELECT * FROM t1;
+CREATE SQL SECURITY INVOKER VIEW v1 AS SELECT * FROM t1;
 --connection user
 SELECT user();
 --error ER_ACCESS_DENIED_ERROR
diff --git a/storage/connect/mysql-test/connect/t/mysql_grant.test b/storage/connect/mysql-test/connect/t/mysql_grant.test
index 7c75103..05337ef 100644
--- a/storage/connect/mysql-test/connect/t/mysql_grant.test
+++ b/storage/connect/mysql-test/connect/t/mysql_grant.test
@@ -54,7 +54,7 @@ CREATE VIEW v1 AS SELECT * FROM t1;
 --echo # Testing a VIEW created with FILE privileges but accessed with no FILE
 --connection default
 SELECT user();
-CREATE VIEW v1 AS SELECT * FROM t1;
+CREATE SQL SECURITY INVOKER VIEW v1 AS SELECT * FROM t1;
 --connection user
 SELECT user();
 --error ER_ACCESS_DENIED_ERROR
diff --git a/storage/connect/mysql-test/connect/t/odbc_sqlite3_grant.test b/storage/connect/mysql-test/connect/t/odbc_sqlite3_grant.test
index 7664a44..887385a 100644
--- a/storage/connect/mysql-test/connect/t/odbc_sqlite3_grant.test
+++ b/storage/connect/mysql-test/connect/t/odbc_sqlite3_grant.test
@@ -56,9 +56,10 @@ ALTER TABLE t1 READONLY=1;
 CREATE VIEW v1 AS SELECT * FROM t1;
 
 --echo # Testing a VIEW created with FILE privileges but accessed with no FILE
+--echo # using SQL SECIRITY INVOKER
 --connection default
 SELECT user();
-CREATE VIEW v1 AS SELECT * FROM t1;
+CREATE SQL SECURITY INVOKER VIEW v1 AS SELECT * FROM t1;
 --connection user
 SELECT user();
 --error ER_ACCESS_DENIED_ERROR
@@ -70,6 +71,17 @@ UPDATE v1 SET a=123;
 --error ER_ACCESS_DENIED_ERROR
 DELETE FROM v1;
 
+--echo # Testing a VIEW created with FILE privileges but accessed with no FILE
+--echo # using SQL SECIRITY DEFINER
+--connection default
+DROP VIEW v1;
+SELECT user();
+CREATE SQL SECURITY DEFINER VIEW v1 AS SELECT * FROM t1;
+--connection user
+SELECT user();
+SELECT * FROM v1 WHERE a='test1';
+
+
 --disconnect user
 --connection default
 SELECT user();
