mirror of
https://github.com/MariaDB/server.git
synced 2026-10-23 18:49:29 +03:00
Definition
==========
Implement the SET PATH statement.
```
SET PATH 'schema1, schema2, schema3';
```
Function
--------
In MariaDB, the SQL-path will also be used to lookup packages in
package routine invocations, so the following script:
SET PATH 'sys';
SELECT UTL_ENCODE.BASE64_DECODE('data');
invokes SYS.UTL_ENCODE.BASE64_DECODE('data'), i.e. the function
BASE64_DECODE() in the packge UTL_ENCODE in the database SYS
(if such package and package routine exist).
MariaDB implementation details
------------------------------
The ticket's requirement stated the grammar should support delimited
identifiers with backticks or double quotes within the string quote,
ie: the single tick. A simple parser was implemented to handle this
requirement in Sql_path::from_text.
Only 16 schemas are supported per session - we do not want too many
schemas in the path anyway since it will impact performance. This also
means that the path cache is a simple static array for easier memory
management.
187 lines
4.7 KiB
C++
187 lines
4.7 KiB
C++
#ifndef SQL_PATH_INCLUDED
|
|
#define SQL_PATH_INCLUDED
|
|
|
|
#include "sql_array.h"
|
|
#include "sql_list.h"
|
|
|
|
|
|
/* forward declarations */
|
|
class Database_qualified_name;
|
|
class sp_head;
|
|
class sp_name;
|
|
class Sp_handler;
|
|
struct MDL_key;
|
|
class Lex_ident_db_normalized;
|
|
|
|
struct Sql_path
|
|
{
|
|
private:
|
|
LEX_CSTRING m_schemas[16];
|
|
uint m_count;
|
|
|
|
public:
|
|
Sql_path();
|
|
Sql_path& operator=(const Sql_path &rhs);
|
|
Sql_path& operator=(Sql_path &&rhs)
|
|
{
|
|
set(std::move(rhs));
|
|
return *this;
|
|
}
|
|
Sql_path(const Sql_path&) = delete;
|
|
|
|
bool resolve(THD *thd, sp_head *caller, sp_name *name,
|
|
const Sp_handler **sph, Database_qualified_name *pkgname) const;
|
|
/*
|
|
Initialize the path variable with default values
|
|
*/
|
|
bool init();
|
|
/*
|
|
Free the memory allocated by the path variable
|
|
*/
|
|
void free();
|
|
/*
|
|
Set the variable to the value of rhs, making a copy of the buffer
|
|
|
|
@param thd The thread handle
|
|
@param rhs The path variable to copy from
|
|
*/
|
|
void set(THD *thd, const Sql_path &rhs);
|
|
/*
|
|
Set the variable to the value of rhs, moving the buffer
|
|
|
|
@param rhs The path variable to move from
|
|
*/
|
|
void set(Sql_path &&rhs);
|
|
|
|
/*
|
|
Parse a string and set the path variable to the parsed value
|
|
|
|
@param thd The thread handle
|
|
@param cs The character set of the string
|
|
@param str The string to parse
|
|
*/
|
|
bool from_text(THD *thd, CHARSET_INFO *cs, const LEX_CSTRING &str);
|
|
/*
|
|
Get the number of bytes needed to print the path variable
|
|
|
|
@param thd The thread handle
|
|
@param resolve If true, resolve current schema to
|
|
the current database name
|
|
|
|
@return The number of bytes needed
|
|
*/
|
|
size_t text_format_nbytes_needed(THD *thd, bool resolve) const;
|
|
/*
|
|
Print the path variable to a string
|
|
|
|
@param thd The thread handle
|
|
@param resolve If true, resolve current schema to
|
|
the current database name
|
|
@param dst The destination buffer
|
|
@param nbytes_available The number of bytes available in the buffer
|
|
|
|
@return The number of bytes written
|
|
*/
|
|
size_t print(THD *thd, bool resolve,
|
|
char *dst, size_t nbytes_available) const;
|
|
|
|
LEX_CSTRING lex_cstring(THD *thd, MEM_ROOT *mem_root) const;
|
|
|
|
protected:
|
|
/*
|
|
Helper function to resolve recursive routine calls
|
|
*/
|
|
bool resolve_recursive_routine(sp_head *caller, sp_name *name) const;
|
|
/*
|
|
Helper function to resolve CURRENT_SCHEMA to actual database name.
|
|
Returns the resolved schema, or {nullptr, 0} if resolution fails.
|
|
*/
|
|
LEX_CSTRING resolve_current_schema(THD *thd, sp_head *caller,
|
|
const LEX_CSTRING &schema) const;
|
|
/*
|
|
Helper function to try resolving a routine in a specific schema.
|
|
Returns true if error occured.
|
|
*/
|
|
bool try_resolve_in_schema(THD *thd, const Lex_ident_db_normalized &schema,
|
|
sp_name *name, const Sp_handler **sph,
|
|
Database_qualified_name *pkgname,
|
|
bool *resolved) const;
|
|
|
|
private:
|
|
/*
|
|
Add a schema to the path variable
|
|
|
|
@param thd The thread handle
|
|
@param schema_str The schema name
|
|
@param schema_len The length of the schema name
|
|
|
|
@return true if the schema could not be added
|
|
*/
|
|
bool add_schema(THD *thd, const char *schema_str, size_t schema_len);
|
|
|
|
bool add_schema_direct(const char *schema_str, size_t schema_len);
|
|
|
|
bool is_cur_schema(const LEX_CSTRING &schema) const;
|
|
};
|
|
|
|
|
|
class Sql_path_stack
|
|
{
|
|
List<Sql_path> m_path_stack;
|
|
THD *m_thd;
|
|
public:
|
|
bool m_is_resolving;
|
|
public:
|
|
Sql_path_stack(THD *thd) : m_thd(thd), m_is_resolving(false) {}
|
|
bool push_path(CHARSET_INFO *cs, const LEX_CSTRING &path_str,
|
|
bool *was_pushed);
|
|
bool pop_path();
|
|
};
|
|
|
|
|
|
class Sql_path_push
|
|
{
|
|
bool m_pushed;
|
|
bool m_error;
|
|
Sql_path_stack *m_stack;
|
|
public:
|
|
Sql_path_push(Sql_path_stack *stack, CHARSET_INFO *cs,
|
|
const LEX_CSTRING &path_str)
|
|
: m_pushed(false), m_error(false), m_stack(stack)
|
|
{
|
|
push(stack, cs, path_str);
|
|
}
|
|
Sql_path_push()
|
|
: m_pushed(false), m_error(false), m_stack(nullptr)
|
|
{
|
|
}
|
|
~Sql_path_push()
|
|
{
|
|
pop();
|
|
}
|
|
|
|
bool error() const
|
|
{
|
|
return m_error;
|
|
}
|
|
|
|
void push(Sql_path_stack *stack, CHARSET_INFO *cs, const LEX_CSTRING &path_str)
|
|
{
|
|
m_stack= stack;
|
|
if (m_stack && path_str.length)
|
|
m_error= m_stack->push_path(cs, path_str, &m_pushed);
|
|
}
|
|
|
|
void pop()
|
|
{
|
|
if (m_pushed && m_stack)
|
|
{
|
|
m_stack->pop_path();
|
|
m_pushed= false;
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
#endif /* SQL_PATH_INCLUDED */
|