• Aleksey Midenkov's avatar
    MDEV-29155 CREATE OR REPLACE with self-referencing CHECK hangs · 179fbeb2
    Aleksey Midenkov authored
    	   forever, cannot be killed
    
    Virtual_column_info::fix_and_check_expr() first does fix_expr() which
    finds all fields in query tables and then check_vcol_func_processor()
    which prohibits SELECT expression. So before we get the error
    prohibiting SELECT in vcol expression we must satisfy fix_expr() with
    all the opened tables. The patch achieves this by iterating
    query_tables from parsed vcol expression and by assigning opened
    tables from the main parser context (as they are already preopened if
    the parser sees some SELECT expressions).
    
    But the problem is, we cannot use these TABLE objects fully for vcol
    expression, at least the comment about MERGE tables states so:
    
      /* MERGE tables need to access parent and child TABLE_LISTs. */
      DBUG_ASSERT(tables->table->pos_in_table_list == tables);
    
    Therefore after we have done vcol check we should revert back
    TABLE_LISTs to the original TABLE-less state.
    
    As CREATE OR REPLACE first drops the original table (at least prior to
    MDEV-25292) we can use the above hack from the currently opening
    table. And that is possible only after bitmaps initialized, so we move
    their execution to a little earlier stage, before vcol parsing. But
    partitioning depends on uninitialized bitmaps, so we temporarily
    revert some to make partitioning initialization happy.
    
    Note that plain CREATE TABLE just fails this case in parser with
    NO_SUCH_TABLE, CREATE OR REPLACE doesn't fail in parser as the old
    table still exists.
    
    Now to the hang, mysql_rm_table_no_locks() does TDC_RT_REMOVE_ALL
    which waits while share is closed. The table normally is open only as
    OPEN_STUB, this is what parser does for CREATE TABLE. But for SELECT
    the table is opened not as a stub. If it is the same table name we
    anyway have two TABLE_LIST objects: stub and not stub. So for "not
    stub" TDC_RT_REMOVE_ALL sees open count and decides to wait until it
    is closed. And of course it hangs, because that was opened in the same
    thread. Now we force close such TABLE objects before
    mysql_rm_table_no_locks().
    
    And the third, condition for sequences was wrong: we have to check
    TABLE_LIST::sequence property to make sure we processing sequence.
    179fbeb2
not_supported.result 3.58 KB