Skip to content

Commit

Permalink
Addressing Monty's review suggestions for MDEV-11952 Oracle-style pac…
Browse files Browse the repository at this point in the history
…kages (partial)

- Using array_elements() instead of a constant to iterate through an array
- Adding some comments
- Adding new-line function comments
- Using STRING_WITH_LEN instead of C_STRING_WITH_LEN
  • Loading branch information
abarkov authored and vaintroub committed May 21, 2018
1 parent 7d91d98 commit 1e69d3f
Show file tree
Hide file tree
Showing 8 changed files with 99 additions and 30 deletions.
4 changes: 2 additions & 2 deletions client/mysqldump.c
Expand Up @@ -2514,7 +2514,7 @@ static uint dump_routines_for_db(char *db)
"Create Package Body"};
char db_name_buff[NAME_LEN*2+3], name_buff[NAME_LEN*2+3];
char *routine_name;
int i;
uint i;
FILE *sql_file= md_result_file;
MYSQL_ROW row, routine_list_row;

Expand Down Expand Up @@ -2550,7 +2550,7 @@ static uint dump_routines_for_db(char *db)
fputs("\t<routines>\n", sql_file);

/* 0, retrieve and dump functions, 1, procedures, etc. */
for (i= 0; i < 4; i++)
for (i= 0; i < array_elements(routine_type); i++)
{
my_snprintf(query_buff, sizeof(query_buff),
"SHOW %s STATUS WHERE Db = '%s'",
Expand Down
26 changes: 26 additions & 0 deletions sql/item.h
Expand Up @@ -368,11 +368,37 @@ typedef enum monotonicity_info

class sp_rcontext;

/**
A helper class to collect different behavior of various kinds of SP variables:
- local SP variables and SP parameters
- PACKAGE BODY routine variables
- (there will be more kinds in the future)
*/

class Sp_rcontext_handler
{
public:
virtual ~Sp_rcontext_handler() {}
/**
A prefix used for SP variable names in queries:
- EXPLAIN EXTENDED
- SHOW PROCEDURE CODE
Local variables and SP parameters have empty prefixes.
Package body variables are marked with a special prefix.
This improves readability of the output of these queries,
especially when a local variable or a parameter has the same
name with a package body variable.
*/
virtual const LEX_CSTRING *get_name_prefix() const= 0;
/**
At execution time THD->spcont points to the run-time context (sp_rcontext)
of the currently executed routine.
Local variables store their data in the sp_rcontext pointed by thd->spcont.
Package body variables store data in separate sp_rcontext that belongs
to the package.
This method provides access to the proper sp_rcontext structure,
depending on the SP variable kind.
*/
virtual sp_rcontext *get_rcontext(sp_rcontext *ctx) const= 0;
};

Expand Down
4 changes: 4 additions & 0 deletions sql/item_xmlfunc.cc
Expand Up @@ -2632,6 +2632,10 @@ my_xpath_parse_VariableReference(MY_XPATH *xpath)
sp_variable *spv;
const Sp_rcontext_handler *rh;
LEX *lex;
/*
We call lex->find_variable() rather than thd->lex->spcont->find_variable()
to make sure package body variables are properly supported.
*/
if ((lex= thd->lex) &&
(spv= lex->find_variable(&name, &rh)))
{
Expand Down
60 changes: 44 additions & 16 deletions sql/sp.cc
Expand Up @@ -780,6 +780,7 @@ Sp_handler::db_find_and_cache_routine(THD *thd,
Silence DEPRECATED SYNTAX warnings when loading a stored procedure
into the cache.
*/

struct Silence_deprecated_warning : public Internal_error_handler
{
public:
Expand Down Expand Up @@ -1002,7 +1003,7 @@ Sp_handler::db_load_routine(THD *thd, const Database_qualified_name *name,

if (type() == TYPE_ENUM_PACKAGE_BODY)
{
sp_package *package= sphp[0]->get_package();
sp_package *package= (*sphp)->get_package();
List_iterator<LEX> it(package->m_routine_implementations);
for (LEX *lex; (lex= it++); )
{
Expand Down Expand Up @@ -1078,6 +1079,7 @@ sp_returns_type(THD *thd, String &result, const sp_head *sp)
@return SP_OK on success, or SP_DELETE_ROW_FAILED on error.
used to indicate about errors.
*/

int
Sp_handler::sp_drop_routine_internal(THD *thd,
const Database_qualified_name *name,
Expand Down Expand Up @@ -1111,7 +1113,7 @@ Sp_handler::sp_find_and_drop_routine(THD *thd, TABLE *table,
const Database_qualified_name *name) const
{
int ret;
if (SP_OK != (ret= db_find_routine_aux(thd, name, table)))
if ((ret= db_find_routine_aux(thd, name, table)) != SP_OK)
return ret;
return sp_drop_routine_internal(thd, name, table);
}
Expand All @@ -1123,11 +1125,23 @@ Sp_handler_package_spec::
const Database_qualified_name *name) const
{
int ret;
if (SP_OK != (ret= db_find_routine_aux(thd, name, table)))
if ((ret= db_find_routine_aux(thd, name, table)) != SP_OK)
return ret;
/*
When we do "DROP PACKAGE pkg", we should also perform
"DROP PACKAGE BODY pkg" automatically.
*/
ret= sp_handler_package_body.sp_find_and_drop_routine(thd, table, name);
if (ret != SP_KEY_NOT_FOUND && ret != SP_OK)
return ret;
{
/*
- SP_KEY_NOT_FOUND means that "CREATE PACKAGE pkg" did not
have a correspoinding "CREATE PACKAGE BODY pkg" yet.
- SP_OK means that "CREATE PACKAGE pkg" had a correspoinding
"CREATE PACKAGE BODY pkg", which was successfully dropped.
*/
return ret; // Other codes mean an unexpecte error
}
return Sp_handler::sp_find_and_drop_routine(thd, table, name);
}

Expand Down Expand Up @@ -1231,7 +1245,7 @@ Sp_handler::sp_create_routine(THD *thd, const sp_head *sp) const
DBUG_ASSERT(0);
ret= SP_OK;
}
if (ret)
if (ret != SP_OK)
goto done;
}
else if (lex->create_info.if_not_exists())
Expand Down Expand Up @@ -1565,7 +1579,7 @@ Sp_handler::sp_drop_routine(THD *thd,
if (!(table= open_proc_table_for_update(thd)))
DBUG_RETURN(SP_OPEN_TABLE_FAILED);

if (SP_OK == (ret= sp_find_and_drop_routine(thd, table, name)) &&
if ((ret= sp_find_and_drop_routine(thd, table, name)) == SP_OK &&
write_bin_log(thd, TRUE, thd->query(), thd->query_length()))
ret= SP_INTERNAL_ERROR;
/*
Expand Down Expand Up @@ -1916,6 +1930,7 @@ Sp_handler::sp_show_create_routine(THD *thd,
and return it as a 0-terminated string
'pkg.name' -> 'pkg\0'
*/

class Prefix_name_buf: public LEX_CSTRING
{
char m_buf[SAFE_NAME_LEN + 1];
Expand Down Expand Up @@ -1948,6 +1963,7 @@ class Prefix_name_buf: public LEX_CSTRING
- either returns the original SP,
- or makes and returns a new clone of SP
*/

sp_head *
Sp_handler::sp_clone_and_link_routine(THD *thd,
const Database_qualified_name *name,
Expand Down Expand Up @@ -2015,7 +2031,7 @@ Sp_handler::sp_clone_and_link_routine(THD *thd,
1. Cut the package name prefix from the routine name: 'pkg1.p1' -> 'p1',
to have db_load_routine() generate and parse a query like this:
CREATE PROCEDURE p1 ...;
rether than:
rather than:
CREATE PROCEDURE pkg1.p1 ...;
The latter would be misinterpreted by the parser as a standalone
routine 'p1' in the database 'pkg1', which is not what we need.
Expand Down Expand Up @@ -2126,6 +2142,7 @@ Sp_handler::sp_find_routine(THD *thd, const Database_qualified_name *name,
@retval non-NULL - a pointer to an sp_head object
@retval NULL - an error happened.
*/

sp_head *
Sp_handler::sp_find_package_routine(THD *thd,
const LEX_CSTRING pkgname_str,
Expand Down Expand Up @@ -2168,6 +2185,7 @@ Sp_handler::sp_find_package_routine(THD *thd,
@retval non-NULL - a pointer to an sp_head object
@retval NULL - an error happened
*/

sp_head *
Sp_handler::sp_find_package_routine(THD *thd,
const Database_qualified_name *name,
Expand Down Expand Up @@ -2301,6 +2319,7 @@ bool sp_add_used_routine(Query_tables_list *prelocking_ctx, Query_arena *arena,
It's used during parsing of CREATE PACKAGE BODY,
to load the corresponding CREATE PACKAGE.
*/

int
Sp_handler::sp_cache_routine_reentrant(THD *thd,
const Database_qualified_name *name,
Expand All @@ -2315,7 +2334,7 @@ Sp_handler::sp_cache_routine_reentrant(THD *thd,
}


/*
/**
Check if a routine has a declaration in the CREATE PACKAGE statement,
by looking up in thd->sp_package_spec_cache, and by loading from mysql.proc
if needed.
Expand All @@ -2340,6 +2359,7 @@ Sp_handler::sp_cache_routine_reentrant(THD *thd,
After the call of this function, the package specification is always cached,
unless a fatal error happens.
*/

static bool
is_package_public_routine(THD *thd,
const LEX_CSTRING &db,
Expand All @@ -2356,7 +2376,7 @@ is_package_public_routine(THD *thd,
}


/*
/**
Check if a routine has a declaration in the CREATE PACKAGE statement
by looking up in sp_package_spec_cache.
Expand All @@ -2373,6 +2393,7 @@ is_package_public_routine(THD *thd,
The package specification (i.e. the CREATE PACKAGE statement) for
the current package body must already be loaded and cached at this point.
*/

static bool
is_package_public_routine_quick(THD *thd,
const LEX_CSTRING &db,
Expand All @@ -2388,10 +2409,11 @@ is_package_public_routine_quick(THD *thd,
}


/*
/**
Check if a qualified name, e.g. "CALL name1.name2",
refers to a known routine in the package body "pkg".
*/

static bool
is_package_body_routine(THD *thd, sp_package *pkg,
const LEX_CSTRING &name1,
Expand All @@ -2404,11 +2426,12 @@ is_package_body_routine(THD *thd, sp_package *pkg,
}


/*
/**
Resolve a qualified routine reference xxx.yyy(), between:
- A standalone routine: xxx.yyy
- A package routine: current_database.xxx.yyy
*/

bool Sp_handler::
sp_resolve_package_routine_explicit(THD *thd,
sp_head *caller,
Expand Down Expand Up @@ -2444,11 +2467,12 @@ bool Sp_handler::
}


/*
/**
Resolve a non-qualified routine reference yyy(), between:
- A standalone routine: current_database.yyy
- A package routine: current_database.current_package.yyy
*/

bool Sp_handler::
sp_resolve_package_routine_implicit(THD *thd,
sp_head *caller,
Expand Down Expand Up @@ -2534,6 +2558,7 @@ bool Sp_handler::
@retval false on success
@retval true on error (e.g. EOM, could not read CREATE PACKAGE)
*/

bool
Sp_handler::sp_resolve_package_routine(THD *thd,
sp_head *caller,
Expand Down Expand Up @@ -2813,6 +2838,7 @@ int Sp_handler::sp_cache_routine(THD *thd,
@retval false - loaded or does not exists
@retval true - error while loading mysql.proc
*/

int
Sp_handler::sp_cache_package_routine(THD *thd,
const LEX_CSTRING &pkgname_cstr,
Expand Down Expand Up @@ -2856,6 +2882,7 @@ Sp_handler::sp_cache_package_routine(THD *thd,
@retval false - loaded or does not exists
@retval true - error while loading mysql.proc
*/

int Sp_handler::sp_cache_package_routine(THD *thd,
const Database_qualified_name *name,
bool lookup_only, sp_head **sp) const
Expand All @@ -2873,6 +2900,7 @@ int Sp_handler::sp_cache_package_routine(THD *thd,
@return
Returns false on success, true on (alloc) failure.
*/

bool
Sp_handler::show_create_sp(THD *thd, String *buf,
const LEX_CSTRING &db,
Expand Down Expand Up @@ -3015,15 +3043,15 @@ Sp_handler::sp_load_for_information_schema(THD *thd, TABLE *proc_table,

LEX_CSTRING Sp_handler_procedure::empty_body_lex_cstring(sql_mode_t mode) const
{
static LEX_CSTRING m_empty_body_std= {C_STRING_WITH_LEN("BEGIN END")};
static LEX_CSTRING m_empty_body_ora= {C_STRING_WITH_LEN("AS BEGIN NULL; END")};
static LEX_CSTRING m_empty_body_std= {STRING_WITH_LEN("BEGIN END")};
static LEX_CSTRING m_empty_body_ora= {STRING_WITH_LEN("AS BEGIN NULL; END")};
return mode & MODE_ORACLE ? m_empty_body_ora : m_empty_body_std;
}


LEX_CSTRING Sp_handler_function::empty_body_lex_cstring(sql_mode_t mode) const
{
static LEX_CSTRING m_empty_body_std= {C_STRING_WITH_LEN("RETURN NULL")};
static LEX_CSTRING m_empty_body_ora= {C_STRING_WITH_LEN("AS BEGIN RETURN NULL; END")};
static LEX_CSTRING m_empty_body_std= {STRING_WITH_LEN("RETURN NULL")};
static LEX_CSTRING m_empty_body_ora= {STRING_WITH_LEN("AS BEGIN RETURN NULL; END")};
return mode & MODE_ORACLE ? m_empty_body_ora : m_empty_body_std;
}
8 changes: 4 additions & 4 deletions sql/sp.h
Expand Up @@ -371,12 +371,12 @@ class Sp_handler_package_spec: public Sp_handler_package
stored_procedure_type type() const { return TYPE_ENUM_PACKAGE; }
LEX_CSTRING type_lex_cstring() const
{
static LEX_CSTRING m_type_str= {C_STRING_WITH_LEN("PACKAGE")};
static LEX_CSTRING m_type_str= {STRING_WITH_LEN("PACKAGE")};
return m_type_str;
}
LEX_CSTRING empty_body_lex_cstring(sql_mode_t mode) const
{
static LEX_CSTRING m_empty_body= {C_STRING_WITH_LEN("BEGIN END")};
static LEX_CSTRING m_empty_body= {STRING_WITH_LEN("BEGIN END")};
return m_empty_body;
}
const char *show_create_routine_col1_caption() const
Expand Down Expand Up @@ -404,12 +404,12 @@ class Sp_handler_package_body: public Sp_handler_package
stored_procedure_type type() const { return TYPE_ENUM_PACKAGE_BODY; }
LEX_CSTRING type_lex_cstring() const
{
static LEX_CSTRING m_type_str= {C_STRING_WITH_LEN("PACKAGE BODY")};
static LEX_CSTRING m_type_str= {STRING_WITH_LEN("PACKAGE BODY")};
return m_type_str;
}
LEX_CSTRING empty_body_lex_cstring(sql_mode_t mode) const
{
static LEX_CSTRING m_empty_body= {C_STRING_WITH_LEN("BEGIN END")};
static LEX_CSTRING m_empty_body= {STRING_WITH_LEN("BEGIN END")};
return m_empty_body;
}
const char *show_create_routine_col1_caption() const
Expand Down

0 comments on commit 1e69d3f

Please sign in to comment.