~maria-captains/maria/mysql-6.0-backup

« back to all changes in this revision

Viewing changes to sql/sql_parse.cc

  • Committer: Thava Alagu
  • Date: 2010-03-11 19:18:17 UTC
  • mfrom: (3719.14.62 mysql-6.0-codebase)
  • Revision ID: thavamuni.alagu@sun.com-20100311191817-5nigmq884xo9fuut
Merge from mysql-6.0-codebase

Show diffs side-by-side

added added

removed removed

Lines of Context:
332
332
  sql_command_flags[SQLCOM_PRELOAD_KEYS]=       CF_AUTO_COMMIT_TRANS;
333
333
 
334
334
  sql_command_flags[SQLCOM_FLUSH]=              CF_AUTO_COMMIT_TRANS;
 
335
  sql_command_flags[SQLCOM_RESET]=              CF_AUTO_COMMIT_TRANS;
335
336
  sql_command_flags[SQLCOM_CHECK]=              CF_AUTO_COMMIT_TRANS;
336
337
 
337
338
  sql_command_flags[SQLCOM_BACKUP]=             CF_AUTO_COMMIT_TRANS;
1657
1658
 
1658
1659
 
1659
1660
/**
 
1661
  Implementation of FLUSH TABLES <table_list> WITH READ LOCK.
 
1662
 
 
1663
  In brief: take exclusive locks, expel tables from the table
 
1664
  cache, reopen the tables, enter the 'LOCKED TABLES' mode,
 
1665
  downgrade the locks.
 
1666
 
 
1667
  Required privileges
 
1668
  -------------------
 
1669
  Since the statement implicitly enters LOCK TABLES mode,
 
1670
  it requires LOCK TABLES privilege on every table.
 
1671
  But since the rest of FLUSH commands require
 
1672
  the global RELOAD_ACL, it also requires RELOAD_ACL.
 
1673
 
 
1674
  Compatibility with the global read lock
 
1675
  ---------------------------------------
 
1676
  We don't wait for the GRL, since neither the
 
1677
  5.1 combination that this new statement is intended to
 
1678
  replace (LOCK TABLE <list> WRITE; FLUSH TABLES;),
 
1679
  nor FLUSH TABLES WITH READ LOCK do.
 
1680
  @todo: this is not implemented, Dmitry disagrees.
 
1681
  Currently we wait for GRL in another connection,
 
1682
  but are compatible with a GRL in our own connection.
 
1683
 
 
1684
  Behaviour under LOCK TABLES
 
1685
  ---------------------------
 
1686
  Bail out: i.e. don't perform an implicit UNLOCK TABLES.
 
1687
  This is not consistent with LOCK TABLES statement, but is
 
1688
  in line with behaviour of FLUSH TABLES WITH READ LOCK, and we
 
1689
  try to not introduce any new statements with implicit
 
1690
  semantics.
 
1691
 
 
1692
  Compatibility with parallel updates
 
1693
  -----------------------------------
 
1694
  As a result, we will wait for all open transactions
 
1695
  against the tables to complete. After the lock downgrade,
 
1696
  new transactions will be able to read the tables, but not
 
1697
  write to them.
 
1698
 
 
1699
  Differences from FLUSH TABLES <list>
 
1700
  -------------------------------------
 
1701
  - you can't flush WITH READ LOCK a non-existent table
 
1702
  - you can't flush WITH READ LOCK under LOCK TABLES
 
1703
  - currently incompatible with the GRL (@todo: fix)
 
1704
*/
 
1705
 
 
1706
static bool flush_tables_with_read_lock(THD *thd, TABLE_LIST *all_tables)
 
1707
{
 
1708
  Lock_tables_prelocking_strategy lock_tables_prelocking_strategy;
 
1709
  TABLE_LIST *table_list;
 
1710
 
 
1711
  /*
 
1712
    This is called from SQLCOM_FLUSH, the transaction has
 
1713
    been committed implicitly.
 
1714
  */
 
1715
 
 
1716
  /* RELOAD_ACL is checked by the caller. Check table-level privileges. */
 
1717
  if (check_table_access(thd, LOCK_TABLES_ACL | SELECT_ACL, all_tables,
 
1718
                         FALSE, FALSE, UINT_MAX))
 
1719
    goto error;
 
1720
 
 
1721
  if (thd->locked_tables_mode)
 
1722
  {
 
1723
    my_error(ER_LOCK_OR_ACTIVE_TRANSACTION, MYF(0));
 
1724
    goto error;
 
1725
  }
 
1726
 
 
1727
  /*
 
1728
    @todo: Since lock_table_names() acquires a global IX
 
1729
    lock, this actually waits for a GRL in another connection.
 
1730
    We are thus introducing an incompatibility.
 
1731
    Do nothing for now, since not taking a global IX violates
 
1732
    current internal MDL asserts, fix after discussing with
 
1733
    Dmitry.
 
1734
  */
 
1735
  if (lock_table_names(thd, all_tables))
 
1736
    goto error;
 
1737
 
 
1738
  if  (open_and_lock_tables(thd, all_tables, FALSE,
 
1739
                            MYSQL_OPEN_HAS_MDL_LOCK,
 
1740
                            &lock_tables_prelocking_strategy) ||
 
1741
       thd->locked_tables_list.init_locked_tables(thd))
 
1742
  {
 
1743
    close_thread_tables(thd);
 
1744
    goto error;
 
1745
  }
 
1746
 
 
1747
  /*
 
1748
    Downgrade the exclusive locks.
 
1749
    Use MDL_SHARED_NO_WRITE as the intended
 
1750
    post effect of this call is identical
 
1751
    to LOCK TABLES <...> READ, and we didn't use
 
1752
    thd->in_lock_talbes and thd->sql_command= SQLCOM_LOCK_TABLES
 
1753
    hacks to enter the LTM.
 
1754
    @todo: release the global IX lock here!!!
 
1755
  */
 
1756
  for (table_list= all_tables; table_list;
 
1757
       table_list= table_list->next_global)
 
1758
    table_list->mdl_request.ticket->downgrade_exclusive_lock(MDL_SHARED_NO_WRITE);
 
1759
 
 
1760
  return FALSE;
 
1761
 
 
1762
error:
 
1763
  return TRUE;
 
1764
}
 
1765
 
 
1766
 
 
1767
/**
1660
1768
  Read query from packet and store in thd->query.
1661
1769
  Used in COM_QUERY and COM_STMT_PREPARE.
1662
1770
 
2181
2289
  }
2182
2290
  case SQLCOM_DO:
2183
2291
    if (check_table_access(thd, SELECT_ACL, all_tables, FALSE, FALSE, UINT_MAX) ||
2184
 
        open_and_lock_tables(thd, all_tables))
 
2292
        open_and_lock_tables(thd, all_tables, TRUE, 0))
2185
2293
      goto error;
2186
2294
 
2187
2295
    res= mysql_do(thd, *lex->insert_list);
2692
2800
        create_table->open_type= OT_BASE_ONLY;
2693
2801
      }
2694
2802
 
2695
 
      if (!(res= open_and_lock_tables_derived(thd, lex->query_tables, TRUE, 0)))
 
2803
      if (!(res= open_and_lock_tables(thd, lex->query_tables, TRUE, 0)))
2696
2804
      {
2697
2805
        /*
2698
2806
          Is table which we are changing used somewhere in other parts
3288
3396
 
3289
3397
    unit->set_limit(select_lex);
3290
3398
 
3291
 
    if (!(res= open_and_lock_tables(thd, all_tables)))
 
3399
    if (!(res= open_and_lock_tables(thd, all_tables, TRUE, 0)))
3292
3400
    {
3293
3401
      /* Skip first table, which is the table we are inserting in */
3294
3402
      TABLE_LIST *second_table= first_table->next_local;
3393
3501
 
3394
3502
    thd_proc_info(thd, "init");
3395
3503
    MYSQL_MULTI_DELETE_START(thd->query());
3396
 
    if ((res= open_and_lock_tables(thd, all_tables)))
 
3504
    if ((res= open_and_lock_tables(thd, all_tables, TRUE, 0)))
3397
3505
      break;
3398
3506
 
3399
3507
    MYSQL_MULTI_DELETE_START(thd->query());
3521
3629
    List<set_var_base> *lex_var_list= &lex->var_list;
3522
3630
 
3523
3631
    if ((check_table_access(thd, SELECT_ACL, all_tables, FALSE, FALSE, UINT_MAX) ||
3524
 
         open_and_lock_tables(thd, all_tables)))
 
3632
         open_and_lock_tables(thd, all_tables, TRUE, 0)))
3525
3633
      goto error;
3526
3634
    if (!(res= sql_set_variables(thd, lex_var_list)))
3527
3635
    {
3628
3736
    {
3629
3737
      Lock_tables_prelocking_strategy lock_tables_prelocking_strategy;
3630
3738
 
3631
 
      res= (open_and_lock_tables_derived(thd, all_tables, FALSE,
3632
 
                                         MYSQL_OPEN_TAKE_UPGRADABLE_MDL,
3633
 
                                         &lock_tables_prelocking_strategy) ||
 
3739
      res= (open_and_lock_tables(thd, all_tables, FALSE,
 
3740
                                 MYSQL_OPEN_TAKE_UPGRADABLE_MDL,
 
3741
                                 &lock_tables_prelocking_strategy) ||
3634
3742
            thd->locked_tables_list.init_locked_tables(thd));
3635
3743
    }
3636
3744
 
4053
4161
  case SQLCOM_FLUSH:
4054
4162
  {
4055
4163
    bool write_to_binlog;
 
4164
 
4056
4165
    if (check_global_access(thd,RELOAD_ACL))
4057
4166
      goto error;
4058
4167
 
 
4168
    if (first_table && lex->type & REFRESH_READ_LOCK)
 
4169
    {
 
4170
      if (flush_tables_with_read_lock(thd, all_tables))
 
4171
        goto error;
 
4172
      my_ok(thd);
 
4173
      break;
 
4174
    }
 
4175
 
4059
4176
    /*
4060
4177
      reload_acl_and_cache() will tell us if we are allowed to write to the
4061
4178
      binlog or not.
4335
4452
        required for execution.
4336
4453
      */
4337
4454
      if (check_table_access(thd, SELECT_ACL, all_tables, FALSE, FALSE, UINT_MAX) ||
4338
 
          open_and_lock_tables(thd, all_tables))
 
4455
          open_and_lock_tables(thd, all_tables, TRUE, 0))
4339
4456
       goto error;
4340
4457
 
4341
4458
      /*
4530
4647
        close_thread_tables(thd);
4531
4648
        thd->mdl_context.release_transactional_locks();
4532
4649
 
4533
 
        if (sp_automatic_privileges && !opt_noacl &&
4534
 
            sp_revoke_privileges(thd, db, name,
 
4650
        if (sp_automatic_privileges && !opt_noacl &&
 
4651
            sp_revoke_privileges(thd, db, name,
4535
4652
                                 lex->sql_command == SQLCOM_DROP_PROCEDURE))
4536
 
        {
4537
 
          push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
4538
 
                       ER_PROC_AUTO_REVOKE_FAIL,
4539
 
                       ER(ER_PROC_AUTO_REVOKE_FAIL));
4540
 
        }
 
4653
        {
 
4654
          push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
 
4655
                       ER_PROC_AUTO_REVOKE_FAIL,
 
4656
                       ER(ER_PROC_AUTO_REVOKE_FAIL));
 
4657
          /* If this happens, an error should have been reported. */
 
4658
          goto error;
 
4659
        }
4541
4660
#endif
4542
4661
      }
4543
4662
      res= sp_result;
4852
4971
        new Item_int((ulonglong) thd->variables.select_limit);
4853
4972
  }
4854
4973
  thd->thd_marker.emb_on_expr_nest= NULL;
4855
 
  if (!(res= open_and_lock_tables(thd, all_tables)))
 
4974
  if (!(res= open_and_lock_tables(thd, all_tables, TRUE, 0)))
4856
4975
  {
4857
4976
    if (lex->describe)
4858
4977
    {
5737
5856
    unit->include_down(lex->current_select);
5738
5857
    unit->link_next= 0;
5739
5858
    unit->link_prev= 0;
5740
 
    unit->return_to= lex->current_select;
5741
5859
    select_lex->include_down(unit);
5742
5860
    /*
5743
5861
      By default we assume that it is usual subselect and we have outer name