Commit ca336ad1 authored by tomas@poseidon.ndb.mysql.com's avatar tomas@poseidon.ndb.mysql.com

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

into poseidon.ndb.mysql.com:/home/tomas/mysql-5.0
parents b87f4701 8d94824a
...@@ -7,6 +7,7 @@ Greg@greg-laptop. ...@@ -7,6 +7,7 @@ Greg@greg-laptop.
Miguel@light.local Miguel@light.local
Sinisa@sinisa.nasamreza.org Sinisa@sinisa.nasamreza.org
WAX@sergbook.mysql.com WAX@sergbook.mysql.com
acurtis@ltantony.rdg.cyberkinetica.homeunix.net
acurtis@pcgem.rdg.cyberkinetica.com acurtis@pcgem.rdg.cyberkinetica.com
administrador@light.hegel.local administrador@light.hegel.local
ahlentz@co3064164-a.rochd1.qld.optusnet.com.au ahlentz@co3064164-a.rochd1.qld.optusnet.com.au
......
...@@ -3047,7 +3047,10 @@ logs_empty_and_mark_files_at_shutdown(void) ...@@ -3047,7 +3047,10 @@ logs_empty_and_mark_files_at_shutdown(void)
mutex_enter(&kernel_mutex); mutex_enter(&kernel_mutex);
/* Check that there are no longer transactions */ /* Check that there are no longer transactions. We need this wait even
for the 'very fast' shutdown, because the InnoDB layer may have
committed or prepared transactions and we don't want to lose them. */
if (trx_n_mysql_transactions > 0 if (trx_n_mysql_transactions > 0
|| UT_LIST_GET_LEN(trx_sys->trx_list) > 0) { || UT_LIST_GET_LEN(trx_sys->trx_list) > 0) {
...@@ -3056,6 +3059,23 @@ logs_empty_and_mark_files_at_shutdown(void) ...@@ -3056,6 +3059,23 @@ logs_empty_and_mark_files_at_shutdown(void)
goto loop; goto loop;
} }
if (srv_very_fast_shutdown) {
/* In a 'very fast' shutdown we do not flush the buffer pool:
it is essentially a 'crash' of the InnoDB server.
Make sure that the log is all flushed to disk, so that
we can recover all committed transactions in a crash
recovery.
In a 'very fast' shutdown we do not flush the buffer pool:
it is essentially a 'crash' of the InnoDB server. Then we must
not write the lsn stamps to the data files, since at a
startup InnoDB deduces from the stamps if the previous
shutdown was clean. */
log_buffer_flush_to_disk();
return; /* We SKIP ALL THE REST !! */
}
/* Check that the master thread is suspended */ /* Check that the master thread is suspended */
if (srv_n_threads_active[SRV_MASTER] != 0) { if (srv_n_threads_active[SRV_MASTER] != 0) {
...@@ -3092,24 +3112,13 @@ logs_empty_and_mark_files_at_shutdown(void) ...@@ -3092,24 +3112,13 @@ logs_empty_and_mark_files_at_shutdown(void)
log_archive_all(); log_archive_all();
#endif /* UNIV_LOG_ARCHIVE */ #endif /* UNIV_LOG_ARCHIVE */
if (!srv_very_fast_shutdown) {
/* In a 'very fast' shutdown we do not flush the buffer pool:
it is essentially a 'crash' of the InnoDB server. */
log_make_checkpoint_at(ut_dulint_max, TRUE); log_make_checkpoint_at(ut_dulint_max, TRUE);
} else {
/* Make sure that the log is all flushed to disk, so that
we can recover all committed transactions in a crash
recovery */
log_buffer_flush_to_disk();
}
mutex_enter(&(log_sys->mutex)); mutex_enter(&(log_sys->mutex));
lsn = log_sys->lsn; lsn = log_sys->lsn;
if ((ut_dulint_cmp(lsn, log_sys->last_checkpoint_lsn) != 0 if ((ut_dulint_cmp(lsn, log_sys->last_checkpoint_lsn) != 0)
&& !srv_very_fast_shutdown)
#ifdef UNIV_LOG_ARCHIVE #ifdef UNIV_LOG_ARCHIVE
|| (srv_log_archive_on || (srv_log_archive_on
&& ut_dulint_cmp(lsn, && ut_dulint_cmp(lsn,
...@@ -3158,7 +3167,7 @@ logs_empty_and_mark_files_at_shutdown(void) ...@@ -3158,7 +3167,7 @@ logs_empty_and_mark_files_at_shutdown(void)
completely flushed to disk! (We do not call fil_write... if the completely flushed to disk! (We do not call fil_write... if the
'very fast' shutdown is enabled.) */ 'very fast' shutdown is enabled.) */
if (!srv_very_fast_shutdown && !buf_all_freed()) { if (!buf_all_freed()) {
goto loop; goto loop;
} }
...@@ -3181,7 +3190,7 @@ logs_empty_and_mark_files_at_shutdown(void) ...@@ -3181,7 +3190,7 @@ logs_empty_and_mark_files_at_shutdown(void)
/* Make some checks that the server really is quiet */ /* Make some checks that the server really is quiet */
ut_a(srv_n_threads_active[SRV_MASTER] == 0); ut_a(srv_n_threads_active[SRV_MASTER] == 0);
ut_a(srv_very_fast_shutdown || buf_all_freed()); ut_a(buf_all_freed());
ut_a(0 == ut_dulint_cmp(lsn, log_sys->lsn)); ut_a(0 == ut_dulint_cmp(lsn, log_sys->lsn));
if (ut_dulint_cmp(lsn, srv_start_lsn) < 0) { if (ut_dulint_cmp(lsn, srv_start_lsn) < 0) {
...@@ -3196,15 +3205,7 @@ logs_empty_and_mark_files_at_shutdown(void) ...@@ -3196,15 +3205,7 @@ logs_empty_and_mark_files_at_shutdown(void)
srv_shutdown_lsn = lsn; srv_shutdown_lsn = lsn;
if (!srv_very_fast_shutdown) {
/* In a 'very fast' shutdown we do not flush the buffer pool:
it is essentially a 'crash' of the InnoDB server. Then we must
not write the lsn stamps to the data files, since at a
startup InnoDB deduces from the stamps if the previous
shutdown was clean. */
fil_write_flushed_lsn_to_data_files(lsn, arch_log_no); fil_write_flushed_lsn_to_data_files(lsn, arch_log_no);
}
fil_flush_file_spaces(FIL_TABLESPACE); fil_flush_file_spaces(FIL_TABLESPACE);
...@@ -3212,7 +3213,7 @@ logs_empty_and_mark_files_at_shutdown(void) ...@@ -3212,7 +3213,7 @@ logs_empty_and_mark_files_at_shutdown(void)
/* Make some checks that the server really is quiet */ /* Make some checks that the server really is quiet */
ut_a(srv_n_threads_active[SRV_MASTER] == 0); ut_a(srv_n_threads_active[SRV_MASTER] == 0);
ut_a(srv_very_fast_shutdown || buf_all_freed()); ut_a(buf_all_freed());
ut_a(0 == ut_dulint_cmp(lsn, log_sys->lsn)); ut_a(0 == ut_dulint_cmp(lsn, log_sys->lsn));
} }
......
...@@ -1740,6 +1740,13 @@ innobase_shutdown_for_mysql(void) ...@@ -1740,6 +1740,13 @@ innobase_shutdown_for_mysql(void)
srv_shutdown_state = SRV_SHUTDOWN_EXIT_THREADS; srv_shutdown_state = SRV_SHUTDOWN_EXIT_THREADS;
/* In a 'very fast' shutdown, we do not need to wait for these threads
to die; all which counts is that we flushed the log; a 'very fast'
shutdown is essentially a crash. */
if (srv_fast_shutdown)
return((int) DB_SUCCESS);
/* All threads end up waiting for certain events. Put those events /* All threads end up waiting for certain events. Put those events
to the signaled state. Then the threads will exit themselves in to the signaled state. Then the threads will exit themselves in
os_thread_event_wait(). */ os_thread_event_wait(). */
......
...@@ -203,7 +203,7 @@ select parameter_style, sql_data_access, dtd_identifier ...@@ -203,7 +203,7 @@ select parameter_style, sql_data_access, dtd_identifier
from information_schema.routines; from information_schema.routines;
parameter_style sql_data_access dtd_identifier parameter_style sql_data_access dtd_identifier
SQL CONTAINS SQL NULL SQL CONTAINS SQL NULL
SQL CONTAINS SQL int SQL CONTAINS SQL int(11)
show procedure status; show procedure status;
Db Name Type Definer Modified Created Security_type Comment Db Name Type Definer Modified Created Security_type Comment
test sel2 PROCEDURE root@localhost # # DEFINER test sel2 PROCEDURE root@localhost # # DEFINER
...@@ -258,7 +258,7 @@ Function sql_mode Create Function ...@@ -258,7 +258,7 @@ Function sql_mode Create Function
sub1 sub1
show create function sub2; show create function sub2;
Function sql_mode Create Function Function sql_mode Create Function
sub2 CREATE FUNCTION `test`.`sub2`(i int) RETURNS int sub2 CREATE FUNCTION `test`.`sub2`(i int) RETURNS int(11)
return i+1 return i+1
drop function sub2; drop function sub2;
show create procedure sel2; show create procedure sel2;
......
...@@ -962,7 +962,7 @@ comment 'Characteristics procedure test' ...@@ -962,7 +962,7 @@ comment 'Characteristics procedure test'
return 42| return 42|
show create function chistics| show create function chistics|
Function sql_mode Create Function Function sql_mode Create Function
chistics CREATE FUNCTION `test`.`chistics`() RETURNS int chistics CREATE FUNCTION `test`.`chistics`() RETURNS int(11)
DETERMINISTIC DETERMINISTIC
SQL SECURITY INVOKER SQL SECURITY INVOKER
COMMENT 'Characteristics procedure test' COMMENT 'Characteristics procedure test'
...@@ -975,7 +975,7 @@ no sql ...@@ -975,7 +975,7 @@ no sql
comment 'Characteristics function test'| comment 'Characteristics function test'|
show create function chistics| show create function chistics|
Function sql_mode Create Function Function sql_mode Create Function
chistics CREATE FUNCTION `test`.`chistics`() RETURNS int chistics CREATE FUNCTION `test`.`chistics`() RETURNS int(11)
NO SQL NO SQL
DETERMINISTIC DETERMINISTIC
SQL SECURITY INVOKER SQL SECURITY INVOKER
...@@ -2026,11 +2026,11 @@ bug2564_2 ANSI_QUOTES CREATE PROCEDURE "test"."bug2564_2"() ...@@ -2026,11 +2026,11 @@ bug2564_2 ANSI_QUOTES CREATE PROCEDURE "test"."bug2564_2"()
insert into "t1" values ('foo', 1) insert into "t1" values ('foo', 1)
show create function bug2564_3| show create function bug2564_3|
Function sql_mode Create Function Function sql_mode Create Function
bug2564_3 CREATE FUNCTION `test`.`bug2564_3`(x int, y int) RETURNS int bug2564_3 CREATE FUNCTION `test`.`bug2564_3`(x int, y int) RETURNS int(11)
return x || y return x || y
show create function bug2564_4| show create function bug2564_4|
Function sql_mode Create Function Function sql_mode Create Function
bug2564_4 REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ONLY_FULL_GROUP_BY,ANSI CREATE FUNCTION "test"."bug2564_4"(x int, y int) RETURNS int bug2564_4 REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ONLY_FULL_GROUP_BY,ANSI CREATE FUNCTION "test"."bug2564_4"(x int, y int) RETURNS int(11)
return x || y return x || y
drop procedure bug2564_1| drop procedure bug2564_1|
drop procedure bug2564_2| drop procedure bug2564_2|
...@@ -2095,6 +2095,28 @@ drop procedure bug4579_1| ...@@ -2095,6 +2095,28 @@ drop procedure bug4579_1|
drop procedure bug4579_2| drop procedure bug4579_2|
drop table t3| drop table t3|
drop table if exists t3| drop table if exists t3|
drop procedure if exists bug2773|
create function bug2773() returns int return null|
create table t3 as select bug2773()|
show create table t3|
Table Create Table
t3 CREATE TABLE `t3` (
`bug2773()` int(11) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t3|
drop function bug2773|
drop procedure if exists bug3788|
create function bug3788() returns date return cast("2005-03-04" as date)|
select bug3788()|
bug3788()
2005-03-04
drop function bug3788|
create function bug3788() returns binary(5) return 5|
select bug3788()|
bug3788()
5
drop function bug3788|
drop table if exists t3|
create table t3 (f1 int, f2 int, f3 int)| create table t3 (f1 int, f2 int, f3 int)|
insert into t3 values (1,1,1)| insert into t3 values (1,1,1)|
drop procedure if exists bug4726| drop procedure if exists bug4726|
......
...@@ -2546,6 +2546,35 @@ drop procedure bug4579_1| ...@@ -2546,6 +2546,35 @@ drop procedure bug4579_1|
drop procedure bug4579_2| drop procedure bug4579_2|
drop table t3| drop table t3|
#
# BUG#2773: Function's data type ignored in stored procedures
#
--disable_warnings
drop table if exists t3|
drop procedure if exists bug2773|
--enable_warnings
create function bug2773() returns int return null|
create table t3 as select bug2773()|
show create table t3|
drop table t3|
drop function bug2773|
#
# BUG#3788: Stored procedure packet error
#
--disable_warnings
drop procedure if exists bug3788|
--enable_warnings
create function bug3788() returns date return cast("2005-03-04" as date)|
select bug3788()|
drop function bug3788|
create function bug3788() returns binary(5) return 5|
select bug3788()|
drop function bug3788|
# #
# BUG#4726 # BUG#4726
......
...@@ -3521,7 +3521,7 @@ bool Item_ref::fix_fields(THD *thd, TABLE_LIST *tables, Item **reference) ...@@ -3521,7 +3521,7 @@ bool Item_ref::fix_fields(THD *thd, TABLE_LIST *tables, Item **reference)
enum_parsing_place place= NO_MATTER; enum_parsing_place place= NO_MATTER;
SELECT_LEX *current_sel= thd->lex->current_select; SELECT_LEX *current_sel= thd->lex->current_select;
if (!ref) if (!ref || ref == not_found_item)
{ {
SELECT_LEX_UNIT *prev_unit= current_sel->master_unit(); SELECT_LEX_UNIT *prev_unit= current_sel->master_unit();
SELECT_LEX *outer_sel= prev_unit->outer_select(); SELECT_LEX *outer_sel= prev_unit->outer_select();
......
...@@ -4368,13 +4368,33 @@ longlong Item_func_row_count::val_int() ...@@ -4368,13 +4368,33 @@ longlong Item_func_row_count::val_int()
Item_func_sp::Item_func_sp(sp_name *name) Item_func_sp::Item_func_sp(sp_name *name)
:Item_func(), m_name(name), m_sp(NULL) :Item_func(), m_name(name), m_sp(NULL)
{ {
char *empty_name= (char *) "";
maybe_null= 1;
m_name->init_qname(current_thd); m_name->init_qname(current_thd);
bzero(&dummy_table, sizeof(dummy_table));
dummy_table.share.table_cache_key = empty_name;
dummy_table.share.table_name = empty_name;
dummy_table.table.alias = empty_name;
dummy_table.share.table_name = empty_name;
dummy_table.table.maybe_null = maybe_null;
dummy_table.table.in_use= current_thd;
dummy_table.table.s = &dummy_table.share;
} }
Item_func_sp::Item_func_sp(sp_name *name, List<Item> &list) Item_func_sp::Item_func_sp(sp_name *name, List<Item> &list)
:Item_func(list), m_name(name), m_sp(NULL) :Item_func(list), m_name(name), m_sp(NULL)
{ {
char *empty_name= (char *) "";
maybe_null= 1;
m_name->init_qname(current_thd); m_name->init_qname(current_thd);
bzero(&dummy_table, sizeof(dummy_table));
dummy_table.share.table_cache_key = empty_name;
dummy_table.share.table_name = empty_name;
dummy_table.table.alias = empty_name;
dummy_table.share.table_name = empty_name;
dummy_table.table.maybe_null = maybe_null;
dummy_table.table.in_use= current_thd;
dummy_table.table.s = &dummy_table.share;
} }
const char * const char *
...@@ -4399,6 +4419,18 @@ Item_func_sp::func_name() const ...@@ -4399,6 +4419,18 @@ Item_func_sp::func_name() const
} }
Field *
Item_func_sp::sp_result_field(void) const
{
Field *field= 0;
THD *thd= current_thd;
DBUG_ENTER("Item_func_sp::sp_result_field");
if (m_sp)
field= m_sp->make_field(max_length, name, &dummy_table.table);
DBUG_RETURN(field);
}
int int
Item_func_sp::execute(Item **itp) Item_func_sp::execute(Item **itp)
{ {
...@@ -4449,17 +4481,38 @@ Item_func_sp::execute(Item **itp) ...@@ -4449,17 +4481,38 @@ Item_func_sp::execute(Item **itp)
} }
void
Item_func_sp::make_field(Send_field *tmp_field)
{
Field *field;
DBUG_ENTER("Item_func_sp::make_field");
if (! m_sp)
m_sp= sp_find_function(current_thd, m_name, TRUE); // cache only
if ((field= sp_result_field()))
{
field->make_field(tmp_field);
delete field;
DBUG_VOID_RETURN;
}
my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", m_name->m_qname.str);
init_make_field(tmp_field, MYSQL_TYPE_VARCHAR);
DBUG_VOID_RETURN;
}
enum enum_field_types enum enum_field_types
Item_func_sp::field_type() const Item_func_sp::field_type() const
{ {
Field *field= 0;
DBUG_ENTER("Item_func_sp::field_type"); DBUG_ENTER("Item_func_sp::field_type");
if (! m_sp) if (! m_sp)
m_sp= sp_find_function(current_thd, m_name, TRUE); // cache only m_sp= sp_find_function(current_thd, m_name, TRUE); // cache only
if (m_sp) if ((field= sp_result_field()))
{ {
DBUG_PRINT("info", ("m_returns = %d", m_sp->m_returns)); enum_field_types result= field->type();
DBUG_RETURN(m_sp->m_returns); delete field;
DBUG_RETURN(result);
} }
my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", m_name->m_qname.str); my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", m_name->m_qname.str);
DBUG_RETURN(MYSQL_TYPE_VARCHAR); DBUG_RETURN(MYSQL_TYPE_VARCHAR);
...@@ -4469,14 +4522,17 @@ Item_func_sp::field_type() const ...@@ -4469,14 +4522,17 @@ Item_func_sp::field_type() const
Item_result Item_result
Item_func_sp::result_type() const Item_func_sp::result_type() const
{ {
Field *field= 0;
DBUG_ENTER("Item_func_sp::result_type"); DBUG_ENTER("Item_func_sp::result_type");
DBUG_PRINT("info", ("m_sp = %p", m_sp)); DBUG_PRINT("info", ("m_sp = %p", m_sp));
if (! m_sp) if (! m_sp)
m_sp= sp_find_function(current_thd, m_name, TRUE); // cache only m_sp= sp_find_function(current_thd, m_name, TRUE); // cache only
if (m_sp) if ((field= sp_result_field()))
{ {
DBUG_RETURN(m_sp->result()); Item_result result= field->result_type();
delete field;
DBUG_RETURN(result);
} }
my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", m_name->m_qname.str); my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", m_name->m_qname.str);
DBUG_RETURN(STRING_RESULT); DBUG_RETURN(STRING_RESULT);
...@@ -4495,7 +4551,7 @@ Item_func_sp::fix_length_and_dec() ...@@ -4495,7 +4551,7 @@ Item_func_sp::fix_length_and_dec()
} }
else else
{ {
switch (m_sp->result()) { switch (result_type()) {
case STRING_RESULT: case STRING_RESULT:
maybe_null= 1; maybe_null= 1;
max_length= MAX_BLOB_WIDTH; max_length= MAX_BLOB_WIDTH;
...@@ -4530,3 +4586,19 @@ longlong Item_func_found_rows::val_int() ...@@ -4530,3 +4586,19 @@ longlong Item_func_found_rows::val_int()
return thd->found_rows(); return thd->found_rows();
} }
Field *
Item_func_sp::tmp_table_field(TABLE *t_arg)
{
Field *res= 0;
enum_field_types ftype;
DBUG_ENTER("Item_func_sp::tmp_table_field");
if (m_sp)
res= m_sp->make_field(max_length, (const char *)name, t_arg);
if (!res)
res= Item_func::tmp_table_field(t_arg);
DBUG_RETURN(res);
}
...@@ -1252,8 +1252,13 @@ class Item_func_sp :public Item_func ...@@ -1252,8 +1252,13 @@ class Item_func_sp :public Item_func
private: private:
sp_name *m_name; sp_name *m_name;
mutable sp_head *m_sp; mutable sp_head *m_sp;
mutable struct {
TABLE table;
TABLE_SHARE share;
} dummy_table;
int execute(Item **itp); int execute(Item **itp);
Field *sp_result_field(void) const;
public: public:
...@@ -1268,6 +1273,10 @@ class Item_func_sp :public Item_func ...@@ -1268,6 +1273,10 @@ class Item_func_sp :public Item_func
enum enum_field_types field_type() const; enum enum_field_types field_type() const;
Field *tmp_table_field(TABLE *t_arg);
void make_field(Send_field *tmp_field);
Item_result result_type() const; Item_result result_type() const;
longlong val_int() longlong val_int()
......
...@@ -629,6 +629,10 @@ int mysql_derived_filling(THD *thd, LEX *lex, TABLE_LIST *t); ...@@ -629,6 +629,10 @@ int mysql_derived_filling(THD *thd, LEX *lex, TABLE_LIST *t);
Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
Item ***copy_func, Field **from_field, Item ***copy_func, Field **from_field,
bool group, bool modify_item, uint convert_blob_length); bool group, bool modify_item, uint convert_blob_length);
int prepare_create_field(create_field *sql_field,
uint &blob_columns,
int &timestamps, int &timestamps_with_niladic,
uint table_flags);
int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
List<create_field> &fields, List<create_field> &fields,
List<Key> &keys, uint &db_options, List<Key> &keys, uint &db_options,
...@@ -838,6 +842,13 @@ bool add_field_to_list(THD *thd, char *field_name, enum enum_field_types type, ...@@ -838,6 +842,13 @@ bool add_field_to_list(THD *thd, char *field_name, enum enum_field_types type,
char *change, List<String> *interval_list, char *change, List<String> *interval_list,
CHARSET_INFO *cs, CHARSET_INFO *cs,
uint uint_geom_type); uint uint_geom_type);
create_field * new_create_field(THD *thd, char *field_name, enum_field_types type,
char *length, char *decimals,
uint type_modifier,
Item *default_value, Item *on_update_value,
LEX_STRING *comment, char *change,
List<String> *interval_list, CHARSET_INFO *cs,
uint uint_geom_type);
void store_position_for_column(const char *name); void store_position_for_column(const char *name);
bool add_to_list(THD *thd, SQL_LIST &list,Item *group,bool asc=0); bool add_to_list(THD *thd, SQL_LIST &list,Item *group,bool asc=0);
void add_join_on(TABLE_LIST *b,Item *expr); void add_join_on(TABLE_LIST *b,Item *expr);
......
...@@ -334,6 +334,22 @@ db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp) ...@@ -334,6 +334,22 @@ db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp)
} }
static void
sp_returns_type(THD *thd, String &result, sp_head *sp)
{
struct {
TABLE table;
TABLE_SHARE share;
} dummy;
Field *field;
bzero(&dummy, sizeof(dummy));
dummy.table.in_use= thd;
dummy.table.s = &dummy.share;
field= sp->make_field(0, 0, &dummy.table);
field->sql_type(result);
delete field;
}
static int static int
db_create_routine(THD *thd, int type, sp_head *sp) db_create_routine(THD *thd, int type, sp_head *sp)
{ {
...@@ -388,9 +404,13 @@ db_create_routine(THD *thd, int type, sp_head *sp) ...@@ -388,9 +404,13 @@ db_create_routine(THD *thd, int type, sp_head *sp)
store((longlong)sp->m_chistics->suid); store((longlong)sp->m_chistics->suid);
table->field[MYSQL_PROC_FIELD_PARAM_LIST]-> table->field[MYSQL_PROC_FIELD_PARAM_LIST]->
store(sp->m_params.str, sp->m_params.length, system_charset_info); store(sp->m_params.str, sp->m_params.length, system_charset_info);
if (sp->m_retstr.str) if (sp->m_type == TYPE_ENUM_FUNCTION)
{
String retstr(64);
sp_returns_type(thd, retstr, sp);
table->field[MYSQL_PROC_FIELD_RETURNS]-> table->field[MYSQL_PROC_FIELD_RETURNS]->
store(sp->m_retstr.str, sp->m_retstr.length, system_charset_info); store(retstr.ptr(), retstr.length(), system_charset_info);
}
table->field[MYSQL_PROC_FIELD_BODY]-> table->field[MYSQL_PROC_FIELD_BODY]->
store(sp->m_body.str, sp->m_body.length, system_charset_info); store(sp->m_body.str, sp->m_body.length, system_charset_info);
table->field[MYSQL_PROC_FIELD_DEFINER]-> table->field[MYSQL_PROC_FIELD_DEFINER]->
......
...@@ -305,11 +305,11 @@ sp_head::init(LEX *lex) ...@@ -305,11 +305,11 @@ sp_head::init(LEX *lex)
*/ */
lex->trg_table_fields.empty(); lex->trg_table_fields.empty();
my_init_dynamic_array(&m_instr, sizeof(sp_instr *), 16, 8); my_init_dynamic_array(&m_instr, sizeof(sp_instr *), 16, 8);
m_param_begin= m_param_end= m_returns_begin= m_returns_end= m_body_begin= 0; m_param_begin= m_param_end= m_body_begin= 0;
m_qname.str= m_db.str= m_name.str= m_params.str= m_retstr.str= m_qname.str= m_db.str= m_name.str= m_params.str=
m_body.str= m_defstr.str= 0; m_body.str= m_defstr.str= 0;
m_qname.length= m_db.length= m_name.length= m_params.length= m_qname.length= m_db.length= m_name.length= m_params.length=
m_retstr.length= m_body.length= m_defstr.length= 0; m_body.length= m_defstr.length= 0;
m_returns_cs= NULL; m_returns_cs= NULL;
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
...@@ -351,41 +351,6 @@ sp_head::init_strings(THD *thd, LEX *lex, sp_name *name) ...@@ -351,41 +351,6 @@ sp_head::init_strings(THD *thd, LEX *lex, sp_name *name)
(char *)m_param_begin, m_params.length); (char *)m_param_begin, m_params.length);
} }
if (m_returns_begin && m_returns_end)
{
/* QQ KLUDGE: We can't seem to cut out just the type in the parser
(without the RETURNS), so we'll have to do it here. :-(
Furthermore, if there's a character type as well, it's not include
(beyond the m_returns_end pointer), in which case we need
m_returns_cs. */
char *p= (char *)m_returns_begin+strspn((char *)m_returns_begin,"\t\n\r ");
p+= strcspn(p, "\t\n\r ");
p+= strspn(p, "\t\n\r ");
if (p < (char *)m_returns_end)
m_returns_begin= (uchar *)p;
/* While we're at it, trim the end too. */
p= (char *)m_returns_end-1;
while (p > (char *)m_returns_begin &&
(*p == '\t' || *p == '\n' || *p == '\r' || *p == ' '))
p-= 1;
m_returns_end= (uchar *)p+1;
if (m_returns_cs)
{
String s((char *)m_returns_begin, m_returns_end - m_returns_begin,
system_charset_info);
s.append(' ');
s.append(m_returns_cs->csname);
m_retstr.length= s.length();
m_retstr.str= strmake_root(root, s.ptr(), m_retstr.length);
}
else
{
m_retstr.length= m_returns_end - m_returns_begin;
m_retstr.str= strmake_root(root,
(char *)m_returns_begin, m_retstr.length);
}
}
m_body.length= lex->ptr - m_body_begin; m_body.length= lex->ptr - m_body_begin;
/* Trim nuls at the end */ /* Trim nuls at the end */
n= 0; n= 0;
...@@ -401,6 +366,27 @@ sp_head::init_strings(THD *thd, LEX *lex, sp_name *name) ...@@ -401,6 +366,27 @@ sp_head::init_strings(THD *thd, LEX *lex, sp_name *name)
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
TYPELIB *
sp_head::create_typelib(List<String> *src)
{
TYPELIB *result= NULL;
DBUG_ENTER("sp_head::clone_typelib");
if (src->elements)
{
result= (TYPELIB*) alloc_root(mem_root, sizeof(TYPELIB));
result->count= src->elements;
result->name= "";
if (!(result->type_names=(const char **)
alloc_root(mem_root,sizeof(char *)*(result->count+1))))
return 0;
List_iterator<String> it(*src);
for (uint i=0; i<result->count; i++)
result->type_names[i]= strdup_root(mem_root, (it++)->c_ptr());
result->type_names[result->count]= 0;
}
return result;
}
int int
sp_head::create(THD *thd) sp_head::create(THD *thd)
{ {
...@@ -481,6 +467,21 @@ sp_head::destroy() ...@@ -481,6 +467,21 @@ sp_head::destroy()
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
Field *
sp_head::make_field(uint max_length, const char *name, TABLE *dummy)
{
Field *field;
DBUG_ENTER("sp_head::make_field");
field= ::make_field((char *)0,
!m_returns_len ? max_length : m_returns_len,
(uchar *)"", 0, m_returns_pack, m_returns, m_returns_cs,
(enum Field::geometry_type)0, Field::NONE,
m_returns_typelib,
name ? name : (const char *)m_name.str, dummy);
DBUG_RETURN(field);
}
int int
sp_head::execute(THD *thd) sp_head::execute(THD *thd)
{ {
......
...@@ -84,6 +84,9 @@ class sp_head :private Item_arena ...@@ -84,6 +84,9 @@ class sp_head :private Item_arena
int m_type; // TYPE_ENUM_FUNCTION or TYPE_ENUM_PROCEDURE int m_type; // TYPE_ENUM_FUNCTION or TYPE_ENUM_PROCEDURE
enum enum_field_types m_returns; // For FUNCTIONs only enum enum_field_types m_returns; // For FUNCTIONs only
CHARSET_INFO *m_returns_cs; // For FUNCTIONs only CHARSET_INFO *m_returns_cs; // For FUNCTIONs only
TYPELIB *m_returns_typelib; // For FUNCTIONs only
uint m_returns_len; // For FUNCTIONs only
uint m_returns_pack; // For FUNCTIONs only
my_bool m_has_return; // For FUNCTIONs only my_bool m_has_return; // For FUNCTIONs only
my_bool m_simple_case; // TRUE if parsing simple case, FALSE otherwise my_bool m_simple_case; // TRUE if parsing simple case, FALSE otherwise
my_bool m_multi_results; // TRUE if a procedure with SELECT(s) my_bool m_multi_results; // TRUE if a procedure with SELECT(s)
...@@ -96,7 +99,6 @@ class sp_head :private Item_arena ...@@ -96,7 +99,6 @@ class sp_head :private Item_arena
LEX_STRING m_db; LEX_STRING m_db;
LEX_STRING m_name; LEX_STRING m_name;
LEX_STRING m_params; LEX_STRING m_params;
LEX_STRING m_retstr; // For FUNCTIONs only
LEX_STRING m_body; LEX_STRING m_body;
LEX_STRING m_defstr; LEX_STRING m_defstr;
LEX_STRING m_definer_user; LEX_STRING m_definer_user;
...@@ -112,8 +114,7 @@ class sp_head :private Item_arena ...@@ -112,8 +114,7 @@ class sp_head :private Item_arena
*/ */
HASH m_spfuns, m_spprocs; HASH m_spfuns, m_spprocs;
// Pointers set during parsing // Pointers set during parsing
uchar *m_param_begin, *m_param_end, *m_returns_begin, *m_returns_end, uchar *m_param_begin, *m_param_end, *m_body_begin;
*m_body_begin;
static void * static void *
operator new(size_t size); operator new(size_t size);
...@@ -131,6 +132,9 @@ class sp_head :private Item_arena ...@@ -131,6 +132,9 @@ class sp_head :private Item_arena
void void
init_strings(THD *thd, LEX *lex, sp_name *name); init_strings(THD *thd, LEX *lex, sp_name *name);
TYPELIB *
create_typelib(List<String> *src);
int int
create(THD *thd); create(THD *thd);
...@@ -204,10 +208,7 @@ class sp_head :private Item_arena ...@@ -204,10 +208,7 @@ class sp_head :private Item_arena
char *create_string(THD *thd, ulong *lenp); char *create_string(THD *thd, ulong *lenp);
inline Item_result result() Field *make_field(uint max_length, const char *name, TABLE *dummy);
{
return sp_map_result_type(m_returns);
}
void set_info(char *definer, uint definerlen, void set_info(char *definer, uint definerlen,
longlong created, longlong modified, longlong created, longlong modified,
......
...@@ -5207,9 +5207,6 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type, ...@@ -5207,9 +5207,6 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
{ {
register create_field *new_field; register create_field *new_field;
LEX *lex= thd->lex; LEX *lex= thd->lex;
uint allowed_type_modifier=0;
uint sign_len;
ulong max_field_charlength= MAX_FIELD_CHARLENGTH;
DBUG_ENTER("add_field_to_list"); DBUG_ENTER("add_field_to_list");
if (strlen(field_name) > NAME_LEN) if (strlen(field_name) > NAME_LEN)
...@@ -5270,9 +5267,38 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type, ...@@ -5270,9 +5267,38 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
my_error(ER_INVALID_ON_UPDATE, MYF(0), field_name); my_error(ER_INVALID_ON_UPDATE, MYF(0), field_name);
DBUG_RETURN(1); DBUG_RETURN(1);
} }
if (!(new_field=new create_field())) if (!(new_field= new_create_field(thd, field_name, type, length, decimals,
type_modifier, default_value, on_update_value,
comment, change, interval_list, cs, uint_geom_type)))
DBUG_RETURN(1); DBUG_RETURN(1);
lex->create_list.push_back(new_field);
lex->last_field=new_field;
DBUG_RETURN(0);
}
/*****************************************************************************
** Create field definition for create
** Return 0 on failure, otherwise return create_field instance
******************************************************************************/
create_field *
new_create_field(THD *thd, char *field_name, enum_field_types type,
char *length, char *decimals,
uint type_modifier,
Item *default_value, Item *on_update_value,
LEX_STRING *comment,
char *change, List<String> *interval_list, CHARSET_INFO *cs,
uint uint_geom_type)
{
register create_field *new_field;
uint sign_len, allowed_type_modifier=0;
ulong max_field_charlength= MAX_FIELD_CHARLENGTH;
DBUG_ENTER("new_create_field");
if (!(new_field=new create_field()))
DBUG_RETURN(NULL);
new_field->field=0; new_field->field=0;
new_field->field_name=field_name; new_field->field_name=field_name;
new_field->def= default_value; new_field->def= default_value;
...@@ -5344,7 +5370,7 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type, ...@@ -5344,7 +5370,7 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
new_field->length >= new_field->decimals) new_field->length >= new_field->decimals)
break; break;
my_error(ER_WRONG_FIELD_SPEC, MYF(0), field_name); my_error(ER_WRONG_FIELD_SPEC, MYF(0), field_name);
DBUG_RETURN(1); DBUG_RETURN(NULL);
case MYSQL_TYPE_VARCHAR: case MYSQL_TYPE_VARCHAR:
/* /*
Long VARCHAR's are automaticly converted to blobs in mysql_prepare_table Long VARCHAR's are automaticly converted to blobs in mysql_prepare_table
...@@ -5367,7 +5393,7 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type, ...@@ -5367,7 +5393,7 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
{ {
my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0), my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0),
field_name); /* purecov: inspected */ field_name); /* purecov: inspected */
DBUG_RETURN(1); /* purecov: inspected */ DBUG_RETURN(NULL);
} }
new_field->def=0; new_field->def=0;
} }
...@@ -5387,7 +5413,7 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type, ...@@ -5387,7 +5413,7 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
if (tmp_length > PRECISION_FOR_DOUBLE) if (tmp_length > PRECISION_FOR_DOUBLE)
{ {
my_error(ER_WRONG_FIELD_SPEC, MYF(0), field_name); my_error(ER_WRONG_FIELD_SPEC, MYF(0), field_name);
DBUG_RETURN(1); DBUG_RETURN(NULL);
} }
else if (tmp_length > PRECISION_FOR_FLOAT) else if (tmp_length > PRECISION_FOR_FLOAT)
{ {
...@@ -5484,7 +5510,7 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type, ...@@ -5484,7 +5510,7 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
if (interval_list->elements > sizeof(longlong)*8) if (interval_list->elements > sizeof(longlong)*8)
{ {
my_error(ER_TOO_BIG_SET, MYF(0), field_name); /* purecov: inspected */ my_error(ER_TOO_BIG_SET, MYF(0), field_name); /* purecov: inspected */
DBUG_RETURN(1); /* purecov: inspected */ DBUG_RETURN(NULL);
} }
new_field->pack_length= (interval_list->elements + 7) / 8; new_field->pack_length= (interval_list->elements + 7) / 8;
if (new_field->pack_length > 4) if (new_field->pack_length > 4)
...@@ -5525,7 +5551,7 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type, ...@@ -5525,7 +5551,7 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
{ {
my_error(ER_TOO_BIG_FIELDLENGTH, MYF(0), field_name, my_error(ER_TOO_BIG_FIELDLENGTH, MYF(0), field_name,
MAX_BIT_FIELD_LENGTH); MAX_BIT_FIELD_LENGTH);
DBUG_RETURN(1); DBUG_RETURN(NULL);
} }
new_field->pack_length= (new_field->length + 7) / 8; new_field->pack_length= (new_field->length + 7) / 8;
break; break;
...@@ -5544,17 +5570,15 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type, ...@@ -5544,17 +5570,15 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
{ {
my_error(ER_TOO_BIG_FIELDLENGTH, MYF(0), my_error(ER_TOO_BIG_FIELDLENGTH, MYF(0),
field_name, max_field_charlength); /* purecov: inspected */ field_name, max_field_charlength); /* purecov: inspected */
DBUG_RETURN(1); /* purecov: inspected */ DBUG_RETURN(NULL);
} }
type_modifier&= AUTO_INCREMENT_FLAG; type_modifier&= AUTO_INCREMENT_FLAG;
if ((~allowed_type_modifier) & type_modifier) if ((~allowed_type_modifier) & type_modifier)
{ {
my_error(ER_WRONG_FIELD_SPEC, MYF(0), field_name); my_error(ER_WRONG_FIELD_SPEC, MYF(0), field_name);
DBUG_RETURN(1); DBUG_RETURN(NULL);
} }
lex->create_list.push_back(new_field); DBUG_RETURN(new_field);
lex->last_field=new_field;
DBUG_RETURN(0);
} }
......
This diff is collapsed.
...@@ -1372,19 +1372,37 @@ create_function_tail: ...@@ -1372,19 +1372,37 @@ create_function_tail:
RETURNS_SYM RETURNS_SYM
{ {
LEX *lex= Lex; LEX *lex= Lex;
sp_head *sp= lex->sphead; lex->charset= NULL;
lex->length= lex->dec= NULL;
sp->m_returns_begin= lex->tok_start; lex->interval_list.empty();
sp->m_returns_cs= lex->charset= NULL; lex->type= 0;
} }
type type
{ {
LEX *lex= Lex; LEX *lex= Lex;
sp_head *sp= lex->sphead; sp_head *sp= lex->sphead;
LEX_STRING cmt = { 0, 0 };
create_field *new_field;
uint unused1= 0;
int unused2= 0;
if (!(new_field= new_create_field(YYTHD, "", (enum enum_field_types)$8,
lex->length, lex->dec, lex->type,
(Item *)0, (Item *) 0, &cmt, 0, &lex->interval_list,
(lex->charset ? lex->charset : default_charset_info),
lex->uint_geom_type)))
YYABORT;
if (prepare_create_field(new_field, unused1, unused2, unused2, 0))
YYABORT;
sp->m_returns= new_field->sql_type;
sp->m_returns_cs= new_field->charset;
sp->m_returns_len= new_field->length;
sp->m_returns_pack= new_field->pack_flag;
sp->m_returns_typelib=
sp->create_typelib(&new_field->interval_list);
sp->m_returns_end= lex->tok_start;
sp->m_returns= (enum enum_field_types)$8;
sp->m_returns_cs= lex->charset;
bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics)); bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
} }
sp_c_chistics sp_c_chistics
......
...@@ -695,6 +695,7 @@ static bool make_empty_rec(File file,enum db_type table_type, ...@@ -695,6 +695,7 @@ static bool make_empty_rec(File file,enum db_type table_type,
field->interval, field->interval,
field->field_name, field->field_name,
&table); &table);
DBUG_ASSERT(regfield);
if (!(field->flags & NOT_NULL_FLAG)) if (!(field->flags & NOT_NULL_FLAG))
null_count++; null_count++;
......
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