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.
Miguel@light.local
Sinisa@sinisa.nasamreza.org
WAX@sergbook.mysql.com
acurtis@ltantony.rdg.cyberkinetica.homeunix.net
acurtis@pcgem.rdg.cyberkinetica.com
administrador@light.hegel.local
ahlentz@co3064164-a.rochd1.qld.optusnet.com.au
......
......@@ -3047,7 +3047,10 @@ logs_empty_and_mark_files_at_shutdown(void)
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
|| UT_LIST_GET_LEN(trx_sys->trx_list) > 0) {
......@@ -3056,6 +3059,23 @@ logs_empty_and_mark_files_at_shutdown(void)
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 */
if (srv_n_threads_active[SRV_MASTER] != 0) {
......@@ -3092,24 +3112,13 @@ logs_empty_and_mark_files_at_shutdown(void)
log_archive_all();
#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);
} 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));
lsn = log_sys->lsn;
if ((ut_dulint_cmp(lsn, log_sys->last_checkpoint_lsn) != 0
&& !srv_very_fast_shutdown)
if ((ut_dulint_cmp(lsn, log_sys->last_checkpoint_lsn) != 0)
#ifdef UNIV_LOG_ARCHIVE
|| (srv_log_archive_on
&& ut_dulint_cmp(lsn,
......@@ -3158,7 +3167,7 @@ logs_empty_and_mark_files_at_shutdown(void)
completely flushed to disk! (We do not call fil_write... if the
'very fast' shutdown is enabled.) */
if (!srv_very_fast_shutdown && !buf_all_freed()) {
if (!buf_all_freed()) {
goto loop;
}
......@@ -3181,7 +3190,7 @@ logs_empty_and_mark_files_at_shutdown(void)
/* Make some checks that the server really is quiet */
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));
if (ut_dulint_cmp(lsn, srv_start_lsn) < 0) {
......@@ -3196,15 +3205,7 @@ logs_empty_and_mark_files_at_shutdown(void)
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_flush_file_spaces(FIL_TABLESPACE);
......@@ -3212,7 +3213,7 @@ logs_empty_and_mark_files_at_shutdown(void)
/* Make some checks that the server really is quiet */
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));
}
......
......@@ -1740,6 +1740,13 @@ innobase_shutdown_for_mysql(void)
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
to the signaled state. Then the threads will exit themselves in
os_thread_event_wait(). */
......
......@@ -203,7 +203,7 @@ select parameter_style, sql_data_access, dtd_identifier
from information_schema.routines;
parameter_style sql_data_access dtd_identifier
SQL CONTAINS SQL NULL
SQL CONTAINS SQL int
SQL CONTAINS SQL int(11)
show procedure status;
Db Name Type Definer Modified Created Security_type Comment
test sel2 PROCEDURE root@localhost # # DEFINER
......@@ -258,7 +258,7 @@ Function sql_mode Create Function
sub1
show create function sub2;
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
drop function sub2;
show create procedure sel2;
......
......@@ -962,7 +962,7 @@ comment 'Characteristics procedure test'
return 42|
show create function chistics|
Function sql_mode Create Function
chistics CREATE FUNCTION `test`.`chistics`() RETURNS int
chistics CREATE FUNCTION `test`.`chistics`() RETURNS int(11)
DETERMINISTIC
SQL SECURITY INVOKER
COMMENT 'Characteristics procedure test'
......@@ -975,7 +975,7 @@ no sql
comment 'Characteristics function test'|
show create function chistics|
Function sql_mode Create Function
chistics CREATE FUNCTION `test`.`chistics`() RETURNS int
chistics CREATE FUNCTION `test`.`chistics`() RETURNS int(11)
NO SQL
DETERMINISTIC
SQL SECURITY INVOKER
......@@ -2026,11 +2026,11 @@ bug2564_2 ANSI_QUOTES CREATE PROCEDURE "test"."bug2564_2"()
insert into "t1" values ('foo', 1)
show create function bug2564_3|
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
show create function bug2564_4|
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
drop procedure bug2564_1|
drop procedure bug2564_2|
......@@ -2095,6 +2095,28 @@ drop procedure bug4579_1|
drop procedure bug4579_2|
drop table 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)|
insert into t3 values (1,1,1)|
drop procedure if exists bug4726|
......
......@@ -2546,6 +2546,35 @@ drop procedure bug4579_1|
drop procedure bug4579_2|
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
......
......@@ -3521,7 +3521,7 @@ bool Item_ref::fix_fields(THD *thd, TABLE_LIST *tables, Item **reference)
enum_parsing_place place= NO_MATTER;
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 *outer_sel= prev_unit->outer_select();
......
......@@ -4368,13 +4368,33 @@ longlong Item_func_row_count::val_int()
Item_func_sp::Item_func_sp(sp_name *name)
:Item_func(), m_name(name), m_sp(NULL)
{
char *empty_name= (char *) "";
maybe_null= 1;
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(list), m_name(name), m_sp(NULL)
{
char *empty_name= (char *) "";
maybe_null= 1;
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 *
......@@ -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
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
Item_func_sp::field_type() const
{
Field *field= 0;
DBUG_ENTER("Item_func_sp::field_type");
if (! m_sp)
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));
DBUG_RETURN(m_sp->m_returns);
enum_field_types result= field->type();
delete field;
DBUG_RETURN(result);
}
my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", m_name->m_qname.str);
DBUG_RETURN(MYSQL_TYPE_VARCHAR);
......@@ -4469,14 +4522,17 @@ Item_func_sp::field_type() const
Item_result
Item_func_sp::result_type() const
{
Field *field= 0;
DBUG_ENTER("Item_func_sp::result_type");
DBUG_PRINT("info", ("m_sp = %p", m_sp));
if (! m_sp)
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);
DBUG_RETURN(STRING_RESULT);
......@@ -4495,7 +4551,7 @@ Item_func_sp::fix_length_and_dec()
}
else
{
switch (m_sp->result()) {
switch (result_type()) {
case STRING_RESULT:
maybe_null= 1;
max_length= MAX_BLOB_WIDTH;
......@@ -4530,3 +4586,19 @@ longlong Item_func_found_rows::val_int()
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
private:
sp_name *m_name;
mutable sp_head *m_sp;
mutable struct {
TABLE table;
TABLE_SHARE share;
} dummy_table;
int execute(Item **itp);
Field *sp_result_field(void) const;
public:
......@@ -1268,6 +1273,10 @@ class Item_func_sp :public Item_func
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;
longlong val_int()
......
......@@ -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,
Item ***copy_func, Field **from_field,
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,
List<create_field> &fields,
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,
char *change, List<String> *interval_list,
CHARSET_INFO *cs,
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);
bool add_to_list(THD *thd, SQL_LIST &list,Item *group,bool asc=0);
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)
}
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
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);
table->field[MYSQL_PROC_FIELD_PARAM_LIST]->
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]->
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]->
store(sp->m_body.str, sp->m_body.length, system_charset_info);
table->field[MYSQL_PROC_FIELD_DEFINER]->
......
......@@ -305,11 +305,11 @@ sp_head::init(LEX *lex)
*/
lex->trg_table_fields.empty();
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_qname.str= m_db.str= m_name.str= m_params.str= m_retstr.str=
m_param_begin= m_param_end= m_body_begin= 0;
m_qname.str= m_db.str= m_name.str= m_params.str=
m_body.str= m_defstr.str= 0;
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;
DBUG_VOID_RETURN;
}
......@@ -351,41 +351,6 @@ sp_head::init_strings(THD *thd, LEX *lex, sp_name *name)
(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;
/* Trim nuls at the end */
n= 0;
......@@ -401,6 +366,27 @@ sp_head::init_strings(THD *thd, LEX *lex, sp_name *name)
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
sp_head::create(THD *thd)
{
......@@ -481,6 +467,21 @@ sp_head::destroy()
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
sp_head::execute(THD *thd)
{
......
......@@ -84,6 +84,9 @@ class sp_head :private Item_arena
int m_type; // TYPE_ENUM_FUNCTION or TYPE_ENUM_PROCEDURE
enum enum_field_types m_returns; // 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_simple_case; // TRUE if parsing simple case, FALSE otherwise
my_bool m_multi_results; // TRUE if a procedure with SELECT(s)
......@@ -96,7 +99,6 @@ class sp_head :private Item_arena
LEX_STRING m_db;
LEX_STRING m_name;
LEX_STRING m_params;
LEX_STRING m_retstr; // For FUNCTIONs only
LEX_STRING m_body;
LEX_STRING m_defstr;
LEX_STRING m_definer_user;
......@@ -112,8 +114,7 @@ class sp_head :private Item_arena
*/
HASH m_spfuns, m_spprocs;
// Pointers set during parsing
uchar *m_param_begin, *m_param_end, *m_returns_begin, *m_returns_end,
*m_body_begin;
uchar *m_param_begin, *m_param_end, *m_body_begin;
static void *
operator new(size_t size);
......@@ -131,6 +132,9 @@ class sp_head :private Item_arena
void
init_strings(THD *thd, LEX *lex, sp_name *name);
TYPELIB *
create_typelib(List<String> *src);
int
create(THD *thd);
......@@ -204,10 +208,7 @@ class sp_head :private Item_arena
char *create_string(THD *thd, ulong *lenp);
inline Item_result result()
{
return sp_map_result_type(m_returns);
}
Field *make_field(uint max_length, const char *name, TABLE *dummy);
void set_info(char *definer, uint definerlen,
longlong created, longlong modified,
......
......@@ -5207,9 +5207,6 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
{
register create_field *new_field;
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");
if (strlen(field_name) > NAME_LEN)
......@@ -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);
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);
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_name=field_name;
new_field->def= default_value;
......@@ -5344,7 +5370,7 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
new_field->length >= new_field->decimals)
break;
my_error(ER_WRONG_FIELD_SPEC, MYF(0), field_name);
DBUG_RETURN(1);
DBUG_RETURN(NULL);
case MYSQL_TYPE_VARCHAR:
/*
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,
{
my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0),
field_name); /* purecov: inspected */
DBUG_RETURN(1); /* purecov: inspected */
DBUG_RETURN(NULL);
}
new_field->def=0;
}
......@@ -5387,7 +5413,7 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
if (tmp_length > PRECISION_FOR_DOUBLE)
{
my_error(ER_WRONG_FIELD_SPEC, MYF(0), field_name);
DBUG_RETURN(1);
DBUG_RETURN(NULL);
}
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,
if (interval_list->elements > sizeof(longlong)*8)
{
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;
if (new_field->pack_length > 4)
......@@ -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,
MAX_BIT_FIELD_LENGTH);
DBUG_RETURN(1);
DBUG_RETURN(NULL);
}
new_field->pack_length= (new_field->length + 7) / 8;
break;
......@@ -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),
field_name, max_field_charlength); /* purecov: inspected */
DBUG_RETURN(1); /* purecov: inspected */
DBUG_RETURN(NULL);
}
type_modifier&= AUTO_INCREMENT_FLAG;
if ((~allowed_type_modifier) & type_modifier)
{
my_error(ER_WRONG_FIELD_SPEC, MYF(0), field_name);
DBUG_RETURN(1);
DBUG_RETURN(NULL);
}
lex->create_list.push_back(new_field);
lex->last_field=new_field;
DBUG_RETURN(0);
DBUG_RETURN(new_field);
}
......
......@@ -431,6 +431,173 @@ void calculate_interval_lengths(CHARSET_INFO *cs, TYPELIB *interval,
}
/*
Prepare a create_table instance for packing
SYNOPSIS
prepare_create_field()
sql_field field to prepare for packing
blob_columns count for BLOBs
timestamps count for timestamps
table_flags table flags
DESCRIPTION
This function prepares a create_field instance.
Fields such as pack_flag are valid after this call.
RETURN VALUES
0 ok
1 Error
*/
int prepare_create_field(create_field *sql_field,
uint &blob_columns,
int &timestamps, int &timestamps_with_niladic,
uint table_flags)
{
DBUG_ENTER("prepare_field");
{
/* This code came from mysql_prepare_table.
Indent preserved to make patching easier */
DBUG_ASSERT(sql_field->charset);
switch (sql_field->sql_type) {
case FIELD_TYPE_BLOB:
case FIELD_TYPE_MEDIUM_BLOB:
case FIELD_TYPE_TINY_BLOB:
case FIELD_TYPE_LONG_BLOB:
sql_field->pack_flag=FIELDFLAG_BLOB |
pack_length_to_packflag(sql_field->pack_length -
portable_sizeof_char_ptr);
if (sql_field->charset->state & MY_CS_BINSORT)
sql_field->pack_flag|=FIELDFLAG_BINARY;
sql_field->length=8; // Unireg field length
sql_field->unireg_check=Field::BLOB_FIELD;
blob_columns++;
break;
case FIELD_TYPE_GEOMETRY:
#ifdef HAVE_SPATIAL
if (!(table_flags & HA_CAN_GEOMETRY))
{
my_printf_error(ER_CHECK_NOT_IMPLEMENTED, ER(ER_CHECK_NOT_IMPLEMENTED),
MYF(0), "GEOMETRY");
DBUG_RETURN(1);
}
sql_field->pack_flag=FIELDFLAG_GEOM |
pack_length_to_packflag(sql_field->pack_length -
portable_sizeof_char_ptr);
if (sql_field->charset->state & MY_CS_BINSORT)
sql_field->pack_flag|=FIELDFLAG_BINARY;
sql_field->length=8; // Unireg field length
sql_field->unireg_check=Field::BLOB_FIELD;
blob_columns++;
break;
#else
my_printf_error(ER_FEATURE_DISABLED,ER(ER_FEATURE_DISABLED), MYF(0),
sym_group_geom.name, sym_group_geom.needed_define);
DBUG_RETURN(1);
#endif /*HAVE_SPATIAL*/
case MYSQL_TYPE_VARCHAR:
#ifndef QQ_ALL_HANDLERS_SUPPORT_VARCHAR
if (table_flags & HA_NO_VARCHAR)
{
/* convert VARCHAR to CHAR because handler is not yet up to date */
sql_field->sql_type= MYSQL_TYPE_VAR_STRING;
sql_field->pack_length= calc_pack_length(sql_field->sql_type,
(uint) sql_field->length);
if ((sql_field->length / sql_field->charset->mbmaxlen) >
MAX_FIELD_CHARLENGTH)
{
my_printf_error(ER_TOO_BIG_FIELDLENGTH, ER(ER_TOO_BIG_FIELDLENGTH),
MYF(0), sql_field->field_name, MAX_FIELD_CHARLENGTH);
DBUG_RETURN(1);
}
}
#endif
/* fall through */
case FIELD_TYPE_STRING:
sql_field->pack_flag=0;
if (sql_field->charset->state & MY_CS_BINSORT)
sql_field->pack_flag|=FIELDFLAG_BINARY;
break;
case FIELD_TYPE_ENUM:
sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) |
FIELDFLAG_INTERVAL;
if (sql_field->charset->state & MY_CS_BINSORT)
sql_field->pack_flag|=FIELDFLAG_BINARY;
sql_field->unireg_check=Field::INTERVAL_FIELD;
check_duplicates_in_interval("ENUM",sql_field->field_name,
sql_field->interval,
sql_field->charset);
break;
case FIELD_TYPE_SET:
sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) |
FIELDFLAG_BITFIELD;
if (sql_field->charset->state & MY_CS_BINSORT)
sql_field->pack_flag|=FIELDFLAG_BINARY;
sql_field->unireg_check=Field::BIT_FIELD;
check_duplicates_in_interval("SET",sql_field->field_name,
sql_field->interval,
sql_field->charset);
break;
case FIELD_TYPE_DATE: // Rest of string types
case FIELD_TYPE_NEWDATE:
case FIELD_TYPE_TIME:
case FIELD_TYPE_DATETIME:
case FIELD_TYPE_NULL:
sql_field->pack_flag=f_settype((uint) sql_field->sql_type);
break;
case FIELD_TYPE_BIT:
if (!(table_flags & HA_CAN_BIT_FIELD))
{
my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "BIT FIELD");
DBUG_RETURN(1);
}
sql_field->pack_flag= FIELDFLAG_NUMBER;
break;
case FIELD_TYPE_NEWDECIMAL:
sql_field->pack_flag=(FIELDFLAG_NUMBER |
(sql_field->flags & UNSIGNED_FLAG ? 0 :
FIELDFLAG_DECIMAL) |
(sql_field->flags & ZEROFILL_FLAG ?
FIELDFLAG_ZEROFILL : 0) |
(sql_field->decimals << FIELDFLAG_DEC_SHIFT));
break;
case FIELD_TYPE_TIMESTAMP:
/* We should replace old TIMESTAMP fields with their newer analogs */
if (sql_field->unireg_check == Field::TIMESTAMP_OLD_FIELD)
{
if (!timestamps)
{
sql_field->unireg_check= Field::TIMESTAMP_DNUN_FIELD;
timestamps_with_niladic++;
}
else
sql_field->unireg_check= Field::NONE;
}
else if (sql_field->unireg_check != Field::NONE)
timestamps_with_niladic++;
timestamps++;
/* fall-through */
default:
sql_field->pack_flag=(FIELDFLAG_NUMBER |
(sql_field->flags & UNSIGNED_FLAG ? 0 :
FIELDFLAG_DECIMAL) |
(sql_field->flags & ZEROFILL_FLAG ?
FIELDFLAG_ZEROFILL : 0) |
f_settype((uint) sql_field->sql_type) |
(sql_field->decimals << FIELDFLAG_DEC_SHIFT));
break;
}
if (!(sql_field->flags & NOT_NULL_FLAG))
sql_field->pack_flag|= FIELDFLAG_MAYBE_NULL;
if (sql_field->flags & NO_DEFAULT_VALUE_FLAG)
sql_field->pack_flag|= FIELDFLAG_NO_DEFAULT;
}
DBUG_RETURN(0);
}
/*
Preparation for table creation
......@@ -690,142 +857,17 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
{
DBUG_ASSERT(sql_field->charset != 0);
switch (sql_field->sql_type) {
case FIELD_TYPE_BLOB:
case FIELD_TYPE_MEDIUM_BLOB:
case FIELD_TYPE_TINY_BLOB:
case FIELD_TYPE_LONG_BLOB:
sql_field->pack_flag=FIELDFLAG_BLOB |
pack_length_to_packflag(sql_field->pack_length -
portable_sizeof_char_ptr);
if (sql_field->charset->state & MY_CS_BINSORT)
sql_field->pack_flag|=FIELDFLAG_BINARY;
sql_field->length=8; // Unireg field length
sql_field->unireg_check=Field::BLOB_FIELD;
blob_columns++;
create_info->varchar= 1;
break;
case FIELD_TYPE_GEOMETRY:
#ifdef HAVE_SPATIAL
if (!(file->table_flags() & HA_CAN_GEOMETRY))
{
my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "GEOMETRY");
DBUG_RETURN(-1);
}
sql_field->pack_flag=FIELDFLAG_GEOM |
pack_length_to_packflag(sql_field->pack_length -
portable_sizeof_char_ptr);
if (sql_field->charset->state & MY_CS_BINSORT)
sql_field->pack_flag|=FIELDFLAG_BINARY;
sql_field->length=8; // Unireg field length
sql_field->unireg_check=Field::BLOB_FIELD;
blob_columns++;
create_info->varchar= 1;
break;
#else
my_error(ER_FEATURE_DISABLED, MYF(0),
sym_group_geom.name, sym_group_geom.needed_define);
if (prepare_create_field(sql_field, blob_columns,
timestamps, timestamps_with_niladic,
file->table_flags()))
DBUG_RETURN(-1);
#endif /*HAVE_SPATIAL*/
case MYSQL_TYPE_VARCHAR:
#ifndef QQ_ALL_HANDLERS_SUPPORT_VARCHAR
if (file->table_flags() & HA_NO_VARCHAR)
{
/* convert VARCHAR to CHAR because handler is not yet up to date */
sql_field->sql_type= MYSQL_TYPE_VAR_STRING;
sql_field->pack_length= calc_pack_length(sql_field->sql_type,
(uint) sql_field->length);
if ((sql_field->length / sql_field->charset->mbmaxlen) >
MAX_FIELD_CHARLENGTH)
{
my_printf_error(ER_TOO_BIG_FIELDLENGTH, ER(ER_TOO_BIG_FIELDLENGTH),
MYF(0), sql_field->field_name, MAX_FIELD_CHARLENGTH);
DBUG_RETURN(-1);
}
}
else
#endif
create_info->varchar= 1;
/* fall through */
case MYSQL_TYPE_STRING:
sql_field->pack_flag=0;
if (sql_field->charset->state & MY_CS_BINSORT)
sql_field->pack_flag|= FIELDFLAG_BINARY;
break;
case FIELD_TYPE_ENUM:
sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) |
FIELDFLAG_INTERVAL;
if (sql_field->charset->state & MY_CS_BINSORT)
sql_field->pack_flag|=FIELDFLAG_BINARY;
sql_field->unireg_check=Field::INTERVAL_FIELD;
check_duplicates_in_interval("ENUM",sql_field->field_name,
sql_field->interval,
sql_field->charset);
break;
case FIELD_TYPE_SET:
sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) |
FIELDFLAG_BITFIELD;
if (sql_field->charset->state & MY_CS_BINSORT)
sql_field->pack_flag|=FIELDFLAG_BINARY;
sql_field->unireg_check=Field::BIT_FIELD;
check_duplicates_in_interval("SET",sql_field->field_name,
sql_field->interval,
sql_field->charset);
break;
case FIELD_TYPE_DATE: // Rest of string types
case FIELD_TYPE_NEWDATE:
case FIELD_TYPE_TIME:
case FIELD_TYPE_DATETIME:
case FIELD_TYPE_NULL:
sql_field->pack_flag=f_settype((uint) sql_field->sql_type);
break;
case FIELD_TYPE_BIT:
if (!(file->table_flags() & HA_CAN_BIT_FIELD))
{
my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "BIT FIELD");
DBUG_RETURN(-1);
}
sql_field->pack_flag= FIELDFLAG_NUMBER;
break;
case FIELD_TYPE_NEWDECIMAL:
sql_field->pack_flag=(FIELDFLAG_NUMBER |
(sql_field->flags & UNSIGNED_FLAG ? 0 :
FIELDFLAG_DECIMAL) |
(sql_field->flags & ZEROFILL_FLAG ?
FIELDFLAG_ZEROFILL : 0) |
(sql_field->decimals << FIELDFLAG_DEC_SHIFT));
break;
case FIELD_TYPE_TIMESTAMP:
/* We should replace old TIMESTAMP fields with their newer analogs */
if (sql_field->unireg_check == Field::TIMESTAMP_OLD_FIELD)
{
if (!timestamps)
{
sql_field->unireg_check= Field::TIMESTAMP_DNUN_FIELD;
timestamps_with_niladic++;
}
else
sql_field->unireg_check= Field::NONE;
}
else if (sql_field->unireg_check != Field::NONE)
timestamps_with_niladic++;
timestamps++;
/* fall-through */
default:
sql_field->pack_flag=(FIELDFLAG_NUMBER |
(sql_field->flags & UNSIGNED_FLAG ? 0 :
FIELDFLAG_DECIMAL) |
(sql_field->flags & ZEROFILL_FLAG ?
FIELDFLAG_ZEROFILL : 0) |
f_settype((uint) sql_field->sql_type) |
(sql_field->decimals << FIELDFLAG_DEC_SHIFT));
break;
}
if (!(sql_field->flags & NOT_NULL_FLAG))
sql_field->pack_flag|= FIELDFLAG_MAYBE_NULL;
if (sql_field->flags & NO_DEFAULT_VALUE_FLAG)
sql_field->pack_flag|= FIELDFLAG_NO_DEFAULT;
if (sql_field->sql_type == FIELD_TYPE_BLOB ||
sql_field->sql_type == FIELD_TYPE_MEDIUM_BLOB ||
sql_field->sql_type == FIELD_TYPE_TINY_BLOB ||
sql_field->sql_type == FIELD_TYPE_LONG_BLOB ||
sql_field->sql_type == FIELD_TYPE_GEOMETRY ||
sql_field->sql_type == MYSQL_TYPE_VARCHAR)
create_info->varchar= 1;
sql_field->offset= pos;
if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
auto_increment++;
......@@ -1592,6 +1634,8 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
((Item_field *)item)->field :
(Field*) 0))))
DBUG_RETURN(0);
if (item->maybe_null)
cr_field->flags &= ~NOT_NULL_FLAG;
extra_fields->push_back(cr_field);
}
/*
......
......@@ -1372,19 +1372,37 @@ create_function_tail:
RETURNS_SYM
{
LEX *lex= Lex;
sp_head *sp= lex->sphead;
sp->m_returns_begin= lex->tok_start;
sp->m_returns_cs= lex->charset= NULL;
lex->charset= NULL;
lex->length= lex->dec= NULL;
lex->interval_list.empty();
lex->type= 0;
}
type
{
LEX *lex= Lex;
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));
}
sp_c_chistics
......
......@@ -695,6 +695,7 @@ static bool make_empty_rec(File file,enum db_type table_type,
field->interval,
field->field_name,
&table);
DBUG_ASSERT(regfield);
if (!(field->flags & NOT_NULL_FLAG))
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