summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/item.cc2
-rw-r--r--sql/item_func.cc84
-rw-r--r--sql/item_func.h9
-rw-r--r--sql/mysql_priv.h11
-rw-r--r--sql/sp.cc24
-rw-r--r--sql/sp_head.cc77
-rw-r--r--sql/sp_head.h15
-rw-r--r--sql/sql_parse.cc54
-rw-r--r--sql/sql_table.cc314
-rw-r--r--sql/sql_yacc.yy32
-rw-r--r--sql/unireg.cc1
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 &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);
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 &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
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++;