Commit be816290 authored by unknown's avatar unknown

Merge baker@bk-internal.mysql.com:/home/bk/mysql-5.0

into avenger.(none):/export/brian/mysql/archive-5.0
parents af00baec c6100a3d
# Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Library General Public License for more details.
#
# You should have received a copy of the GNU Library General Public
# License along with this library; if not, write to the Free
# Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
# MA 02111-1307, USA
## Process this file with automake to create Makefile.in
# This is a dummy file to satisfy the hierarchy of Makefiles.
# When a release is built, the true Makefile will be copied
# together with the "real" files in this directory.
EXTRA_DIST =
# Nothing to create in this dummy directory.
all:
:
# Nothing to cleanup in this dummy directory.
clean:
:
# Don't update the files from bitkeeper
%::SCCS/s.%
......@@ -456,3 +456,8 @@ PREPARE stmt FROM 'UPDATE t1 AS P1 INNER JOIN (SELECT N FROM t1 GROUP BY N HAVIN
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
DROP TABLE t1;
create table t1 (a varchar(20));
insert into t1 values ('foo');
prepare stmt FROM 'SELECT char_length (a) FROM t1';
ERROR 42000: FUNCTION test.char_length does not exist
drop table t1;
......@@ -462,3 +462,14 @@ EXECUTE stmt;
DEALLOCATE PREPARE stmt;
DROP TABLE t1;
#
# Bug#6102 "Server crash with prepared statement and blank after
# function name"
# ensure that stored functions are cached when preparing a statement
# before we open tables
#
create table t1 (a varchar(20));
insert into t1 values ('foo');
--error 1305
prepare stmt FROM 'SELECT char_length (a) FROM t1';
drop table t1;
......@@ -72,6 +72,7 @@ Long data handling:
#include "sql_select.h" // for JOIN
#include <m_ctype.h> // for isspace()
#include "sp_head.h"
#include "sp.h"
#ifdef EMBEDDED_LIBRARY
/* include MYSQL_BIND headers */
#include <mysql.h>
......@@ -1409,6 +1410,20 @@ static int send_prepare_results(Prepared_statement *stmt, bool text_protocol)
lex->first_lists_tables_same();
tables= lex->query_tables;
/*
Preopen 'proc' system table and cache all functions used in this
statement. We must do that before we open ordinary tables to avoid
deadlocks. We can't open and lock any table once query tables were
opened.
*/
if (lex->sql_command != SQLCOM_CREATE_PROCEDURE &&
lex->sql_command != SQLCOM_CREATE_SPFUNCTION)
{
/* the error is print inside */
if (sp_cache_functions(thd, lex))
DBUG_RETURN(1);
}
switch (sql_command) {
case SQLCOM_REPLACE:
case SQLCOM_INSERT:
......@@ -1883,7 +1898,7 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length)
{
if (stmt->cursor->is_open())
stmt->cursor->init_from_thd(thd);
thd->set_item_arena(&thd->stmt_backup);
stmt->cursor->state= stmt->state;
}
else
{
......@@ -2029,6 +2044,7 @@ void mysql_stmt_fetch(THD *thd, char *packet, uint packet_length)
DBUG_ENTER("mysql_stmt_fetch");
thd->current_arena= stmt;
if (!(stmt= thd->stmt_map.find(stmt_id)) ||
!stmt->cursor ||
!stmt->cursor->is_open())
......@@ -2038,9 +2054,7 @@ void mysql_stmt_fetch(THD *thd, char *packet, uint packet_length)
DBUG_VOID_RETURN;
}
thd->stmt_backup.set_statement(thd);
thd->stmt_backup.set_item_arena(thd);
thd->set_statement(stmt);
thd->set_n_backup_statement(stmt, &thd->stmt_backup);
stmt->cursor->init_thd(thd);
if (!(specialflag & SPECIAL_NO_PRIOR))
......@@ -2055,11 +2069,8 @@ void mysql_stmt_fetch(THD *thd, char *packet, uint packet_length)
/* Restore THD state */
stmt->cursor->reset_thd(thd);
thd->set_statement(&thd->stmt_backup);
thd->set_item_arena(&thd->stmt_backup);
if (error && error != -4)
send_error(thd, ER_OUT_OF_RESOURCES);
thd->restore_backup_statement(stmt, &thd->stmt_backup);
thd->current_arena= thd;
DBUG_VOID_RETURN;
}
......@@ -2070,7 +2081,7 @@ void mysql_stmt_fetch(THD *thd, char *packet, uint packet_length)
SYNOPSIS
mysql_stmt_reset()
thd Thread handle
packet Packet with stmt id
packet Packet with stmt id
DESCRIPTION
This function resets statement to the state it was right after prepare.
......
......@@ -1683,8 +1683,6 @@ Cursor::init_from_thd(THD *thd)
void
Cursor::init_thd(THD *thd)
{
thd->mem_root= mem_root;
DBUG_ASSERT(thd->derived_tables == 0);
thd->derived_tables= derived_tables;
......@@ -1694,7 +1692,6 @@ Cursor::init_thd(THD *thd)
DBUG_ASSERT(thd->lock== 0);
thd->lock= lock;
thd->query_id= query_id;
thd->free_list= free_list;
}
......@@ -1779,6 +1776,8 @@ Cursor::fetch(ulong num_rows)
int error= 0;
/* save references to memory, allocated during fetch */
thd->set_n_backup_item_arena(this, &thd->stmt_backup);
join->fetch_limit+= num_rows;
/*
......@@ -1842,54 +1841,37 @@ Cursor::fetch(ulong num_rows)
if (thd->net.report_error)
error= -1;
if (error == -3) /* LIMIT clause worked */
error= 0;
switch (error) {
/* Fetch limit worked, possibly more rows are there */
case -4:
#ifdef USING_TRANSACTIONS
if (thd->transaction.all.innobase_tid)
ha_release_temporary_latches(thd);
#endif
thd->restore_backup_item_arena(this, &thd->stmt_backup);
if (error == -4)
{
/* Fetch limit worked, possibly more rows are there */
thd->server_status|= SERVER_STATUS_CURSOR_EXISTS;
::send_eof(thd);
thd->server_status&= ~SERVER_STATUS_CURSOR_EXISTS;
/* save references to memory, allocated during fetch */
mem_root= thd->mem_root;
free_list= thd->free_list;
break;
/* Limit clause worked: this is the same as 'no more rows' */
case -3: /* LIMIT clause worked */
error= 0;
/* fallthrough */
case 0: /* No more rows */
if (thd->transaction.all.innobase_tid)
ha_release_temporary_latches(thd);
close();
thd->server_status|= SERVER_STATUS_LAST_ROW_SENT;
::send_eof(thd);
thd->server_status&= ~SERVER_STATUS_LAST_ROW_SENT;
join= 0;
unit= 0;
free_items(thd->free_list);
thd->free_list= free_list= 0;
/*
Must be last, as some memory might be allocated for free purposes,
like in free_tmp_table() (TODO: fix this issue)
*/
mem_root= thd->mem_root;
free_root(&mem_root, MYF(0));
break;
default:
}
else
{
close();
join= 0;
unit= 0;
free_items(thd->free_list);
thd->free_list= free_list= 0;
/*
Must be last, as some memory might be allocated for free purposes,
like in free_tmp_table() (TODO: fix this issue)
*/
mem_root= thd->mem_root;
if (error == 0)
{
thd->server_status|= SERVER_STATUS_LAST_ROW_SENT;
::send_eof(thd);
thd->server_status&= ~SERVER_STATUS_LAST_ROW_SENT;
}
else
send_error(thd, ER_OUT_OF_RESOURCES);
/* free cursor memory */
free_items(free_list);
free_list= 0;
free_root(&mem_root, MYF(0));
break;
}
return error;
}
......@@ -1927,6 +1909,8 @@ Cursor::close()
thd->derived_tables= tmp_derived_tables;
thd->lock= tmp_lock;
}
join= 0;
unit= 0;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment