Bug#14364558 ASSERT `TABLE_LIST->PRELOCKING_PLACEHOLDER==FALSE'              FAILED IN CHECK_LOCK_AND_ST
Bug#14364558 ASSERT `TABLE_LIST->PRELOCKING_PLACEHOLDER==FALSE'
             FAILED IN CHECK_LOCK_AND_ST

Problem:
--------
lock_tables() is supposed to invoke check_lock_and_start_stmt()
for TABLE_LIST which are directly used by top level statement.
TABLE_LIST->prelocking_placeholder is set only for TABLE_LIST
which are used indirectly by stored programs invoked by top
level statement. Hence check_lock_and_start_stmt() should have
TABLE_LIST->prelocking_placeholder==false always, but it is
observed that this assert fails.

The failure is found during RQG test rqg_signal_resignal.

Analysis:
---------
open_tables() invokes open_and_process_routines() where it
finds all the TABLE_LIST that belong to the routine and
adds it to thd->lex->query_tables. During this process if
the open_and_process_routines() fail for some reason,
we are supposed to chop-off all the TABLE_LIST found during
calls to open_and_process_routines(). But, in practice this
is not happening.

thd->lex->query_tables_own_last is supposed to point to a
node in thd->lex->query_tables, which would be a first
TABLE_LIST used indirectly by stored programs invoked by
top level statement. This is found to be not-set correctly
when we plan to chop-off TABLE_LIST's, when
open_and_process_routines() failed.

close_tables_for_reopen() does chop-off all the TABLE_LIST
added after thd->lex->query_table_own_last. This is invoked
upon error in open_and_process_routines(). This call would
not work as expected as thd->lex->query_tables_own_last
is not set, or is not set to correctly.

Further, when open_tables() restarts the process of finding
TABLE_LIST belonging to stored programs, and as the
thd->lex->query_tables_own_last points to in-correct node,
there is possibility of new iteration setting the
thd->lex->query_tables_own_last past some old nodes that
belong to stored programs, added earlier and not removed.
Later when open_tables() completes, lock_tables() ends up
invoking check_lock_and_start_stmt() for TABLE_LIST which
belong to stored programs, which is not expected behavior
and hence we hit the assert
TABLE_LIST->prelocking_placeholder==false.

Due to above behavior, if a user application tries to
execute a SQL statement which invokes some stored function
and if the lock grant on stored function fails due to a
deadlock, then mysqld crashes.

Fix:
----
open_tables() remembers save_query_tables_last which points
to thd-lex->query_tables_last before calls to
open_and_process_routines(). If there is no known
thd->lex->query_tables_own_last set, we are now setting
thd->lex->query_tables_own_last to save_query_tables_last.
This will make sure that the call to close_tables_for_reopen()
will chop-off the list correctly, in other words we now
remove all the nodes added to thd->lex->query_tables, by
previous calls to open_and_process_routines().

Further, it is found that the problem exists starting
from 5.5, due to a code refactoring effort related to
open_tables(). Hence, the fix will be pushed in 5.5, 5.6
and trunk.


slanterns/server,ollie314/server,davidl-zend/zenddbi,natsys/mariadb_10.2,flynn1973/mariadb-aix,ollie314/server,davidl-zend/zenddbi,natsys/mariadb_10.2,natsys/mariadb_10.2,natsys/mariadb_10.2,ollie314/server,davidl-zend/zenddbi,flynn1973/mariadb-aix,davidl-zend/zenddbi,flynn1973/mariadb-aix,davidl-zend/zenddbi,flynn1973/mariadb-aix,flynn1973/mariadb-aix,davidl-zend/zenddbi,natsys/mariadb_10.2,davidl-zend/zenddbi,ollie314/server,ollie314/server,natsys/mariadb_10.2,ollie314/server,flynn1973/mariadb-aix,flynn1973/mariadb-aix,davidl-zend/zenddbi,flynn1973/mariadb-aix,ollie314/server,flynn1973/mariadb-aix,natsys/mariadb_10.2,ollie314/server,natsys/mariadb_10.2,davidl-zend/zenddbi,davidl-zend/zenddbi,natsys/mariadb_10.2,natsys/mariadb_10.2,ollie314/server,natsys/mariadb_10.2,flynn1973/mariadb-aix,davidl-zend/zenddbi,ollie314/server,ollie314/server,flynn1973/mariadb-aix