• unknown's avatar
    A fix and a test case for · 2783fc82
    unknown authored
     Bug#19022 "Memory bug when switching db during trigger execution"
     Bug#17199 "Problem when view calls function from another database."
     Bug#18444 "Fully qualified stored function names don't work correctly in
                SELECT statements"
    
     Documentation note: this patch introduces a change in behaviour of prepared
     statements.
    
     This patch adds a few new invariants with regard to how THD::db should
     be used. These invariants should be preserved in future:
    
      - one should never refer to THD::db by pointer and always make a deep copy
        (strmake, strdup)
      - one should never compare two databases by pointer, but use strncmp or
        my_strncasecmp
      - TABLE_LIST object table->db should be always initialized in the parser or
        by creator of the object.
    
        For prepared statements it means that if the current database is changed
        after a statement is prepared, the database that was current at prepare
        remains active. This also means that you can not prepare a statement that
        implicitly refers to the current database if the latter is not set.
        This is not documented, and therefore needs documentation. This is NOT a
        change in behavior for almost all SQL statements except:
         - ALTER TABLE t1 RENAME t2 
         - OPTIMIZE TABLE t1
         - ANALYZE TABLE t1
         - TRUNCATE TABLE t1 --
         until this patch t1 or t2 could be evaluated at the first execution of
         prepared statement. 
    
         CURRENT_DATABASE() still works OK and is evaluated at every execution
         of prepared statement.
    
         Note, that in stored routines this is not an issue as the default
         database is the database of the stored procedure and "use" statement
         is prohibited in stored routines.
    
      This patch makes obsolete the use of check_db_used (it was never used in the
      old code too) and all other places that check for table->db and assign it
      from THD::db if it's NULL, except the parser.
    
     How this patch was created: THD::{db,db_length} were replaced with a
     LEX_STRING, THD::db. All the places that refer to THD::{db,db_length} were
     manually checked and:
      - if the place uses thd->db by pointer, it was fixed to make a deep copy
      - if a place compared two db pointers, it was fixed to compare them by value
        (via strcmp/my_strcasecmp, whatever was approproate)
     Then this intermediate patch was used to write a smaller patch that does the
     same thing but without a rename.
    
     TODO in 5.1:
       - remove check_db_used
       - deploy THD::set_db in mysql_change_db
    
     See also comments to individual files.
    
    
    mysql-test/r/create.result:
      Modify the result file: a database can never be NULL.
    mysql-test/r/ps.result:
      Update test results (Bug#17199 et al)
    mysql-test/r/sp.result:
      Update test results (Bug#17199 et al)
    mysql-test/t/create.test:
      Update the id of the returned error.
    mysql-test/t/ps.test:
      Add test coverage for prepared statements and current database. In scope of
      work on Bug#17199 "Problem when view calls function from another database."
    mysql-test/t/sp.test:
      Add a test case for Bug#17199 "Problem when view calls function from another
      database." and Bug#18444 "Fully qualified stored function names don't work
      correctly in SELECT statements". Test a complementary problem.
    sql/item_strfunc.cc:
      Touch the code that reads thd->db (cleanup).
    sql/log_event.cc:
      While we are at it, replace direct access to thd->db with a method.
      Should simplify future conversion of THD::db to LEX_STRING.
    sql/slave.cc:
      While we are at it, replace direct access to thd->db with a method.
      Should simplify future conversion of THD::db to LEX_STRING.
    sql/slave.h:
      Remove a declaration for a method that is used only in one module.
    sql/sp.cc:
      Rewrite sp_use_new_db: this is a cleanup that I needed in order to understand
      this function and ensure that it has no bugs.
    sql/sp.h:
      Add a new declaration for sp_use_new_db (uses LEX_STRINGs) and a comment.
    sql/sp_head.cc:
      - drop sp_name_current_db_new - a creator of sp_name class that was used
      when sp_name was created for an identifier without an explicitly initialized
      database. Now we pass thd->db to constructor of sp_name right in the 
      parser.
      - rewrite sp_head::init_strings: name->m_db is always set now
      - use the new variant of sp_use_new_db
      - we don't need to update thd->db with SP MEM_ROOT pointer anymore when
      parsing a stored procedure, as noone will refer to it (yes!)
    sql/sp_head.h:
      - remove unneded methods and members
    sql/sql_class.h:
      - introduce 3 THD  methods to work with THD::db:
        .set_db to assign the current database
        .reset_db to reset the current database (temporarily) or set it to NULL
        .opt_copy_db_to - to deep-copy thd->db to a pointer if it's not NULL
    sql/sql_db.cc:
      While we are at it, replace direct access to thd->db with a method.
      Should simplify future conversion of THD::db to LEX_STRING.
    sql/sql_insert.cc:
      - replace checks with asserts: table_list->db must be always set in the parser.
    sql/sql_lex.h:
      - add a comment
    sql/sql_parse.cc:
      - implement the invariant described in the changeset comment.
      - remove juggling with lex->sphead in SQLCOM_CREATE_PROCEDURE:
        now db_load_routine uses its own LEX object and doesn't damage the main
        LEX.
      - add DBUG_ASSERT(0) to unused "check_db_used"
    sql/sql_table.cc:
      - replace a check with an assert (table_ident->db)
    sql/sql_trigger.cc:
      While we are at it, replace direct access to thd->db with a method.
      Should simplify future conversion of THD::db to LEX_STRING.
    sql/sql_udf.cc:
      - use thd->set_db instead of direct modification of to thd->db
    sql/sql_view.cc:
      - replace a check with an assert (view->db)
    sql/sql_yacc.yy:
      - make sure that we always copy table->db or name->db or ident->db or
        select_lex->db from thd->db if the former is not set. If thd->db
        is not set but is accessed, return an error.
    sql/tztime.cc:
      - be nice, never copy thd->db by pointer.
    2783fc82
slave.h 21.5 KB