summaryrefslogtreecommitdiff
path: root/sql/item_func.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/item_func.cc')
-rw-r--r--sql/item_func.cc273
1 files changed, 57 insertions, 216 deletions
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 659ec29e452..a8b4a64856e 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -362,7 +362,7 @@ Item_func::fix_fields(THD *thd, Item **ref)
with_window_func= with_window_func || item->with_window_func;
with_field= with_field || item->with_field;
used_tables_and_const_cache_join(item);
- with_subselect|= item->has_subquery();
+ m_with_subquery|= item->with_subquery();
}
}
if (check_arguments())
@@ -3249,7 +3249,7 @@ udf_handler::fix_fields(THD *thd, Item_func_or_sum *func,
func->maybe_null=1;
func->with_sum_func= func->with_sum_func || item->with_sum_func;
func->with_field= func->with_field || item->with_field;
- func->with_subselect|= item->with_subselect;
+ func->With_subquery_cache::join(item);
func->used_tables_and_const_cache_join(item);
f_args.arg_type[i]=item->result_type();
}
@@ -6238,35 +6238,24 @@ longlong Item_func_row_count::val_int()
Item_func_sp::Item_func_sp(THD *thd, Name_resolution_context *context_arg,
sp_name *name):
- Item_func(thd), context(context_arg), m_name(name), m_sp(NULL), sp_result_field(NULL)
+ Item_func(thd), Item_sp(thd, context_arg, name)
{
maybe_null= 1;
- dummy_table= (TABLE*) thd->calloc(sizeof(TABLE)+ sizeof(TABLE_SHARE));
- dummy_table->s= (TABLE_SHARE*) (dummy_table+1);
}
Item_func_sp::Item_func_sp(THD *thd, Name_resolution_context *context_arg,
sp_name *name_arg, List<Item> &list):
- Item_func(thd, list), context(context_arg), m_name(name_arg), m_sp(NULL),
- sp_result_field(NULL)
+ Item_func(thd, list), Item_sp(thd, context_arg, name_arg)
{
maybe_null= 1;
- dummy_table= (TABLE*) thd->calloc(sizeof(TABLE)+ sizeof(TABLE_SHARE));
- dummy_table->s= (TABLE_SHARE*) (dummy_table+1);
}
void
Item_func_sp::cleanup()
{
- if (sp_result_field)
- {
- delete sp_result_field;
- sp_result_field= NULL;
- }
- m_sp= NULL;
- dummy_table->alias.free();
+ Item_sp::cleanup();
Item_func::cleanup();
}
@@ -6274,25 +6263,7 @@ const char *
Item_func_sp::func_name() const
{
THD *thd= current_thd;
- /* Calculate length to avoid reallocation of string for sure */
- uint len= (((m_name->m_explicit_name ? m_name->m_db.length : 0) +
- m_name->m_name.length)*2 + //characters*quoting
- 2 + // ` and `
- (m_name->m_explicit_name ?
- 3 : 0) + // '`', '`' and '.' for the db
- 1 + // end of string
- ALIGN_SIZE(1)); // to avoid String reallocation
- String qname((char *)alloc_root(thd->mem_root, len), len,
- system_charset_info);
-
- qname.length(0);
- if (m_name->m_explicit_name)
- {
- append_identifier(thd, &qname, m_name->m_db.str, m_name->m_db.length);
- qname.append('.');
- }
- append_identifier(thd, &qname, m_name->m_name.str, m_name->m_name.length);
- return qname.c_ptr_safe();
+ return Item_sp::func_name(thd);
}
@@ -6306,75 +6277,6 @@ void my_missing_function_error(const LEX_CSTRING &token, const char *func_name)
/**
- @brief Initialize the result field by creating a temporary dummy table
- and assign it to a newly created field object. Meta data used to
- create the field is fetched from the sp_head belonging to the stored
- proceedure found in the stored procedure functon cache.
-
- @note This function should be called from fix_fields to init the result
- field. It is some what related to Item_field.
-
- @see Item_field
-
- @param thd A pointer to the session and thread context.
-
- @return Function return error status.
- @retval TRUE is returned on an error
- @retval FALSE is returned on success.
-*/
-
-bool
-Item_func_sp::init_result_field(THD *thd, sp_head *sp)
-{
- TABLE_SHARE *share;
- DBUG_ENTER("Item_func_sp::init_result_field");
-
- DBUG_ASSERT(m_sp == NULL);
- DBUG_ASSERT(sp_result_field == NULL);
-
- if (!(m_sp= sp))
- {
- my_missing_function_error (m_name->m_name, ErrConvDQName(m_name).ptr());
- context->process_error(thd);
- DBUG_RETURN(TRUE);
- }
-
- /*
- A Field need to be attached to a Table.
- Below we "create" a dummy table by initializing
- the needed pointers.
- */
-
- share= dummy_table->s;
- dummy_table->alias.set("", 0, table_alias_charset);
- dummy_table->maybe_null = maybe_null;
- dummy_table->in_use= thd;
- dummy_table->copy_blobs= TRUE;
- share->table_cache_key= empty_clex_str;
- share->table_name= empty_clex_str;
-
- if (!(sp_result_field= m_sp->create_result_field(max_length, &name, dummy_table)))
- {
- DBUG_RETURN(TRUE);
- }
-
- if (sp_result_field->pack_length() > sizeof(result_buf))
- {
- void *tmp;
- if (!(tmp= thd->alloc(sp_result_field->pack_length())))
- DBUG_RETURN(TRUE);
- sp_result_field->move_field((uchar*) tmp);
- }
- else
- sp_result_field->move_field(result_buf);
-
- sp_result_field->null_ptr= (uchar *) &null_value;
- sp_result_field->null_bit= 1;
- DBUG_RETURN(FALSE);
-}
-
-
-/**
@note
Deterministic stored procedures are considered inexpensive.
Consequently such procedures may be evaluated during optimization,
@@ -6408,95 +6310,11 @@ void Item_func_sp::fix_length_and_dec()
}
-/**
- @brief Execute function & store value in field.
-
- @return Function returns error status.
- @retval FALSE on success.
- @retval TRUE if an error occurred.
-*/
-
bool
Item_func_sp::execute()
{
- THD *thd= current_thd;
-
/* Execute function and store the return value in the field. */
-
- if (execute_impl(thd))
- {
- null_value= 1;
- context->process_error(thd);
- if (thd->killed)
- thd->send_kill_message();
- return TRUE;
- }
-
- /* Check that the field (the value) is not NULL. */
-
- null_value= sp_result_field->is_null();
-
- return null_value;
-}
-
-
-/**
- @brief Execute function and store the return value in the field.
-
- @note This function was intended to be the concrete implementation of
- the interface function execute. This was never realized.
-
- @return The error state.
- @retval FALSE on success
- @retval TRUE if an error occurred.
-*/
-bool
-Item_func_sp::execute_impl(THD *thd)
-{
- bool err_status= TRUE;
- Sub_statement_state statement_state;
- Security_context *save_security_ctx= thd->security_ctx;
- enum enum_sp_data_access access=
- (m_sp->daccess() == SP_DEFAULT_ACCESS) ?
- SP_DEFAULT_ACCESS_MAPPING : m_sp->daccess();
-
- DBUG_ENTER("Item_func_sp::execute_impl");
-
- if (context->security_ctx)
- {
- /* Set view definer security context */
- thd->security_ctx= context->security_ctx;
- }
- if (sp_check_access(thd))
- goto error;
-
- /*
- Throw an error if a non-deterministic function is called while
- statement-based replication (SBR) is active.
- */
-
- if (!m_sp->detistic() && !trust_function_creators &&
- (access == SP_CONTAINS_SQL || access == SP_MODIFIES_SQL_DATA) &&
- (mysql_bin_log.is_open() &&
- thd->variables.binlog_format == BINLOG_FORMAT_STMT))
- {
- my_error(ER_BINLOG_UNSAFE_ROUTINE, MYF(0));
- goto error;
- }
-
- /*
- Disable the binlogging if this is not a SELECT statement. If this is a
- SELECT, leave binlogging on, so execute_function() code writes the
- function call into binlog.
- */
- thd->reset_sub_statement_state(&statement_state, SUB_STMT_FUNCTION);
- err_status= m_sp->execute_function(thd, args, arg_count, sp_result_field);
- thd->restore_sub_statement_state(&statement_state);
-
-error:
- thd->security_ctx= save_security_ctx;
-
- DBUG_RETURN(err_status);
+ return Item_sp::execute(current_thd, &null_value, args, arg_count);
}
@@ -6561,29 +6379,6 @@ longlong Item_func_sqlcode::val_int()
}
-/**
- @brief Checks if requested access to function can be granted to user.
- If function isn't found yet, it searches function first.
- If function can't be found or user don't have requested access
- error is raised.
-
- @param thd thread handler
-
- @return Indication if the access was granted or not.
- @retval FALSE Access is granted.
- @retval TRUE Requested access can't be granted or function doesn't exists.
-
-*/
-
-bool
-Item_func_sp::sp_check_access(THD *thd)
-{
- DBUG_ENTER("Item_func_sp::sp_check_access");
- DBUG_ASSERT(m_sp);
- DBUG_RETURN(m_sp->check_execute_access(thd));
-}
-
-
bool
Item_func_sp::fix_fields(THD *thd, Item **ref)
{
@@ -6620,20 +6415,66 @@ Item_func_sp::fix_fields(THD *thd, Item **ref)
}
}
+
+ /* Custom aggregates are transformed into an Item_sum_sp. We can not do this
+ earlier as we have no way of knowing what kind of Item we should create
+ when parsing the query.
+
+ TODO(cvicentiu): See if this limitation can be lifted.
+ */
+
+ DBUG_ASSERT(m_sp == NULL);
+ if (!(m_sp= sp))
+ {
+ my_missing_function_error(m_name->m_name, ErrConvDQName(m_name).ptr());
+ context->process_error(thd);
+ DBUG_RETURN(TRUE);
+ }
+
/*
- We must call init_result_field before Item_func::fix_fields()
+ We must call init_result_field before Item_func::fix_fields()
to make m_sp and result_field members available to fix_length_and_dec(),
which is called from Item_func::fix_fields().
*/
- res= init_result_field(thd, sp);
+ res= init_result_field(thd, max_length, maybe_null, &null_value, &name);
if (res)
- DBUG_RETURN(res);
+ DBUG_RETURN(TRUE);
+
+ if (m_sp->agg_type() == GROUP_AGGREGATE)
+ {
+ List<Item> list;
+ list.empty();
+ for (uint i=0; i < arg_count; i++)
+ list.push_back(*(args+i));
+
+ Item_sum_sp *item_sp;
+ Query_arena *arena, backup;
+ arena= thd->activate_stmt_arena_if_needed(&backup);
+
+ if (arg_count)
+ item_sp= new (thd->mem_root) Item_sum_sp(thd, context, m_name, sp, list);
+ else
+ item_sp= new (thd->mem_root) Item_sum_sp(thd, context, m_name, sp);
+
+ if (arena)
+ thd->restore_active_arena(arena, &backup);
+ if (!item_sp)
+ DBUG_RETURN(TRUE);
+ *ref= item_sp;
+ item_sp->name= name;
+ bool err= item_sp->fix_fields(thd, ref);
+ if (err)
+ DBUG_RETURN(TRUE);
+
+ list.empty();
+ DBUG_RETURN(FALSE);
+ }
res= Item_func::fix_fields(thd, ref);
if (res)
- DBUG_RETURN(res);
+ DBUG_RETURN(TRUE);
if (thd->lex->is_view_context_analysis())
{