diff options
Diffstat (limited to 'sql')
-rw-r--r-- | sql/item.cc | 2 | ||||
-rw-r--r-- | sql/item_func.cc | 84 | ||||
-rw-r--r-- | sql/item_func.h | 9 | ||||
-rw-r--r-- | sql/mysql_priv.h | 11 | ||||
-rw-r--r-- | sql/sp.cc | 24 | ||||
-rw-r--r-- | sql/sp_head.cc | 77 | ||||
-rw-r--r-- | sql/sp_head.h | 15 | ||||
-rw-r--r-- | sql/sql_parse.cc | 54 | ||||
-rw-r--r-- | sql/sql_table.cc | 314 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 32 | ||||
-rw-r--r-- | sql/unireg.cc | 1 |
11 files changed, 412 insertions, 211 deletions
diff --git a/sql/item.cc b/sql/item.cc index ef3cc5105ef..1096114021e 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -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(); diff --git a/sql/item_func.cc b/sql/item_func.cc index cc4d25bc5af..abcdc1d2aab 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -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); +} diff --git a/sql/item_func.h b/sql/item_func.h index b1ccbfeea53..cd7f39e9557 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -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 @@ public: 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() diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index b978ffe175b..7e58f7bf728 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -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 ×tamps, int ×tamps_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); diff --git a/sql/sp.cc b/sql/sp.cc index 3f6d4d0bf1b..0343735f2a3 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -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]-> diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 21ef89aea72..2097e55d4e3 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -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) { diff --git a/sql/sp_head.h b/sql/sp_head.h index 60979a438cb..ee41b1efc83 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -84,6 +84,9 @@ public: 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 @@ public: 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 @@ public: */ 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 @@ public: void init_strings(THD *thd, LEX *lex, sp_name *name); + TYPELIB * + create_typelib(List<String> *src); + int create(THD *thd); @@ -204,10 +208,7 @@ public: 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, diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 81391dc920f..7d3f8899cd5 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -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); } diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 7ab1a0a3777..31a1f51b085 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -432,6 +432,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 ×tamps, int ×tamps_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 SYNOPSIS @@ -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); } /* diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index fae01502a8d..212f004e3bf 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -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 diff --git a/sql/unireg.cc b/sql/unireg.cc index dd94098fbf3..3e85767dc86 100644 --- a/sql/unireg.cc +++ b/sql/unireg.cc @@ -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++; |