summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorAlexander Barkov <bar@mariadb.com>2022-03-25 07:05:08 +0400
committerAlexander Barkov <bar@mariadb.com>2022-03-25 10:46:59 +0400
commit6437b304048d0b42e6b2b8f59631ea04bd3c2891 (patch)
tree97ddaaaf3c467dc829faa153aab5372e62c24a71 /sql
parentcd88b0831f7bea7e313af7d0bd96b7050f6c9d60 (diff)
downloadmariadb-git-6437b304048d0b42e6b2b8f59631ea04bd3c2891.tar.gz
MDEV-28166 sql_mode=ORACLE: fully qualified package function calls do not work: db.pkg.func()
Also fixes MDEV-19328 sql_mode=ORACLE: Package function in VIEW
Diffstat (limited to 'sql')
-rw-r--r--sql/item.cc20
-rw-r--r--sql/sql_class.h13
-rw-r--r--sql/sql_lex.cc50
-rw-r--r--sql/sql_lex.h5
-rw-r--r--sql/sql_yacc.yy5
-rw-r--r--sql/sql_yacc_ora.yy5
6 files changed, 96 insertions, 2 deletions
diff --git a/sql/item.cc b/sql/item.cc
index 2fe5411f972..f06055f0a08 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -2898,9 +2898,11 @@ Item_sp::func_name(THD *thd) const
/* Calculate length to avoid reallocation of string for sure */
size_t len= (((m_name->m_explicit_name ? m_name->m_db.length : 0) +
m_name->m_name.length)*2 + //characters*quoting
- 2 + // ` and `
+ 2 + // quotes for the function name
+ 2 + // quotes for the package name
(m_name->m_explicit_name ?
3 : 0) + // '`', '`' and '.' for the db
+ 1 + // '.' between package and function
1 + // end of string
ALIGN_SIZE(1)); // to avoid String reallocation
String qname((char *)alloc_root(thd->mem_root, len), len,
@@ -2912,7 +2914,21 @@ Item_sp::func_name(THD *thd) const
append_identifier(thd, &qname, &m_name->m_db);
qname.append('.');
}
- append_identifier(thd, &qname, &m_name->m_name);
+ if (m_sp && m_sp->m_handler == &sp_handler_package_function)
+ {
+ /*
+ In case of a package function split `pkg.func` and print
+ quoted `pkg` and `func` separately, so the entire result looks like:
+ `db`.`pkg`.`func`
+ */
+ Database_qualified_name tmp= Database_qualified_name::split(m_name->m_name);
+ DBUG_ASSERT(tmp.m_db.length);
+ append_identifier(thd, &qname, &tmp.m_db);
+ qname.append('.');
+ append_identifier(thd, &qname, &tmp.m_name);
+ }
+ else
+ append_identifier(thd, &qname, &m_name->m_name);
return qname.c_ptr_safe();
}
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 311b47aea61..637e16c991b 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -6680,6 +6680,19 @@ public:
}
void copy(MEM_ROOT *mem_root, const LEX_CSTRING &db,
const LEX_CSTRING &name);
+
+ static Database_qualified_name split(const LEX_CSTRING &txt)
+ {
+ DBUG_ASSERT(txt.str[txt.length] == '\0'); // Expect 0-terminated input
+ const char *dot= strchr(txt.str, '.');
+ if (!dot)
+ return Database_qualified_name(NULL, 0, txt.str, txt.length);
+ size_t dblen= dot - txt.str;
+ Lex_cstring db(txt.str, dblen);
+ Lex_cstring name(txt.str + dblen + 1, txt.length - dblen - 1);
+ return Database_qualified_name(db, name);
+ }
+
// Export db and name as a qualified name string: 'db.name'
size_t make_qname(char *dst, size_t dstlen) const
{
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index d51b9bd5a26..cffc0eb25dd 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -8148,6 +8148,56 @@ Item *LEX::make_item_func_call_generic(THD *thd, Lex_ident_cli_st *cdb,
}
+/*
+ Create a 3-step qualified function call.
+ Currently it's possible for package routines only, e.g.:
+ SELECT db.pkg.func();
+*/
+Item *LEX::make_item_func_call_generic(THD *thd,
+ Lex_ident_cli_st *cdb,
+ Lex_ident_cli_st *cpkg,
+ Lex_ident_cli_st *cfunc,
+ List<Item> *args)
+{
+ static Lex_cstring dot(".", 1);
+ Lex_ident_sys db(thd, cdb), pkg(thd, cpkg), func(thd, cfunc);
+ Database_qualified_name q_db_pkg(db, pkg);
+ Database_qualified_name q_pkg_func(pkg, func);
+ sp_name *qname;
+
+ if (db.is_null() || pkg.is_null() || func.is_null())
+ return NULL; // EOM
+
+ if (check_db_name((LEX_STRING*) static_cast<LEX_CSTRING*>(&db)))
+ {
+ my_error(ER_WRONG_DB_NAME, MYF(0), db.str);
+ return NULL;
+ }
+ if (check_routine_name(&pkg) ||
+ check_routine_name(&func))
+ return NULL;
+
+ // Concat `pkg` and `name` to `pkg.name`
+ LEX_CSTRING pkg_dot_func;
+ if (q_pkg_func.make_qname(thd->mem_root, &pkg_dot_func) ||
+ check_ident_length(&pkg_dot_func) ||
+ !(qname= new (thd->mem_root) sp_name(&db, &pkg_dot_func, true)))
+ return NULL;
+
+ sp_handler_package_function.add_used_routine(thd->lex, thd, qname);
+ sp_handler_package_body.add_used_routine(thd->lex, thd, &q_db_pkg);
+
+ thd->lex->safe_to_cache_query= 0;
+
+ if (args && args->elements > 0)
+ return new (thd->mem_root) Item_func_sp(thd, thd->lex->current_context(),
+ qname, &sp_handler_package_function,
+ *args);
+ return new (thd->mem_root) Item_func_sp(thd, thd->lex->current_context(),
+ qname, &sp_handler_package_function);
+}
+
+
Item *LEX::create_item_qualified_asterisk(THD *thd,
const Lex_ident_sys_st *name)
{
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index e1f34afa350..a63ec7c9153 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -3697,6 +3697,11 @@ public:
Item *make_item_func_substr(THD *thd, Item *a, Item *b);
Item *make_item_func_call_generic(THD *thd, Lex_ident_cli_st *db,
Lex_ident_cli_st *name, List<Item> *args);
+ Item *make_item_func_call_generic(THD *thd,
+ Lex_ident_cli_st *db,
+ Lex_ident_cli_st *pkg,
+ Lex_ident_cli_st *name,
+ List<Item> *args);
my_var *create_outvar(THD *thd, const LEX_CSTRING *name);
/*
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index e0e4308ef5c..2852d2efc0c 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -11210,6 +11210,11 @@ function_call_generic:
if (unlikely(!($$= Lex->make_item_func_call_generic(thd, &$1, &$3, $5))))
MYSQL_YYABORT;
}
+ | ident_cli '.' ident_cli '.' ident_cli '(' opt_expr_list ')'
+ {
+ if (unlikely(!($$= Lex->make_item_func_call_generic(thd, &$1, &$3, &$5, $7))))
+ MYSQL_YYABORT;
+ }
;
fulltext_options:
diff --git a/sql/sql_yacc_ora.yy b/sql/sql_yacc_ora.yy
index b45cee01502..8b96937c955 100644
--- a/sql/sql_yacc_ora.yy
+++ b/sql/sql_yacc_ora.yy
@@ -11149,6 +11149,11 @@ function_call_generic:
if (unlikely(!($$= Lex->make_item_func_call_generic(thd, &$1, &$3, $5))))
MYSQL_YYABORT;
}
+ | ident_cli '.' ident_cli '.' ident_cli '(' opt_expr_list ')'
+ {
+ if (unlikely(!($$= Lex->make_item_func_call_generic(thd, &$1, &$3, &$5, $7))))
+ MYSQL_YYABORT;
+ }
;
fulltext_options: