1
0
mirror of https://github.com/MariaDB/server.git synced 2026-10-23 18:49:29 +03:00
Files
mariadb/sql/sql_path.h
Alexander Barkov 0ee34e07bd MDEV-39587 Package-wide TYPE for variable declarations
SET sql_mode=ORACLE;
DELIMITER $$
CREATE OR REPLACE PACKAGE pkg AS
  -- Declare a package public data type
  TYPE varchar_array IS TABLE OF VARCHAR(2000) INDEX BY INTEGER;
END;
$$
DELIMITER ;
DELIMITER $$

CREATE OR REPLACE PROCEDURE p1 AS
  v pkg.varchar_array; -- Use the package public data type
BEGIN
  v(0):='test';
  SELECT v(0);
END;
$$
DELIMITER ;

Note, the change is done only for sql_mode=ORACLE, because the TYPE
declaration is not available for the default mode.

Where package-wide types are available
--------------------------------------
- Variabe list type:
    DECLARE var pkg1.type1;

- RETURN type for a package routine:
    CREATE FUNCTION .. RETURN pkg1.type1 ...

- Parameter type for a package routine:
    PROCEDURE p1(param1 pkg1.type1);

- Assoc array element type:
    TYPE assoc1_t IS TABLE OF pkg1.type1 ...

- REF CURSOR RETURN type:
    TYPE cur1_t IS REF CURSOR RETURN pkg1.type1;

Change details
--------------

- Adding a member Lex_length_and_dec_st::m_foreign_module_type
  It's set to true when the data type was initialized from a TYPE
  in foreign routine (e.g. in PACKAGE spec).
  It's needed to prevent use of qualified identifiers in public contexts,
  i.e. in schema public routine parameter types and schema publuc function
  RETURN types.
  Adding a helper method sp_head::check_applicability() which prevents
  use of qualified types in public context.

- Adding a helper method sp_head::raise_unknown_data_type().

- Adding methods LEX::set_field_type_typedef_package_spec() for
  2-step and 3-step qualified indentifiers.
  It's used in field_type_all_with_typedefs which covers cases:
  - Variabe list type        : DECLARE var pkg1.type1;
  - RETURN type              : CREATE FUNCTION .. RETURN pkg1.type1 ...
  - Parameter type           : PROCEDURE p1(param1 pkg1.type1);
  - Assoc array element type : TYPE assoc1_t IS TABLE OF pkg1.type1 ...

- Adding a method LEX::declare_type_ref_cursor_return_typedef().
  It handles cases when a new TYPE REF CURSOR RETURN is declared,
  for both for qualified RETURN types and non-qualified RETURN types:
  - TYPE cur0_t IS REF CURSOR RETURN rec1_t;
  - TYPE cur0_t IS REF CURSOR RETURN pkg1.rec1_t;
  - TYPE cur0_t IS REF CURSOR RETURN db1.pkg1.rec1_t;

  The code was moved from LEX::declare_type_ref_cursor() into
  LEX::declare_type_ref_cursor_return_typedef() and extended
  to cover qualified RETURN types.

- Adding a method Sql_path::find_package_spec_type().
  It iterates through all schemas specified in @@path and searches
  for the given type in the given package.

- Adding a helper method sp_pcontext::type_defs_add_ref_cursor()
  to reuse the code.

- Adding a new method sp_package::get_typedef() to search
  for TYPE definitions in PACKAGE specifications.

- Adding a new method sp_head::get_typedef_package_spec()
  to search for TYPE definitions used by a PROCEDURE or FUNCTION.

- Adding a helper method
    Sp_handler::sp_cache_routine_reentrant_suppress_errors
  Adding a method Sp_handler::find_package_spec().
2026-08-13 23:15:53 +04:00

127 lines
3.2 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_ident_db 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;
Sql_path(Sql_path &&rhs)
{
m_count= 0;
set(std::move(rhs));
}
~Sql_path() { free(); }
bool resolve(THD *thd, sp_head *caller, sp_name *name,
const Sp_handler **sph, Database_qualified_name *pkgname) const;
bool find_package_spec_type(THD *thd, Lex_ident_db_normalized *db,
const Lex_ident_sys_st &package,
const Lex_ident_sys_st &type);
/*
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 rhs The path variable to copy from
*/
void set(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
The string is in my_charset_utf8mb3_general_ci.
@param sv system_variables, local or global
@param str The string to parse
*/
bool from_text(const system_variables &sv, String *str);
/*
Get the number of bytes needed to print the path variable
@return The number of bytes needed
*/
size_t text_format_nbytes_needed() const;
/*
Print the path variable to a string
@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(char *dst, size_t nbytes_available) const;
LEX_CSTRING lex_cstring(MEM_ROOT *mem_root) const;
private:
/*
Helper function to resolve CURRENT_SCHEMA to actual database name.
Returns the resolved schema, or {nullptr, 0} if resolution fails.
*/
Lex_ident_db resolve_current_schema(THD *thd, sp_head *caller, size_t i) const;
/*
Helper function to try resolving a routine in a specific schema.
Returns true if error occurred.
*/
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;
LEX_CSTRING get_schema_for_print(size_t num) const;
bool add_schema(char **to, bool is_quoted);
bool is_cur_schema(size_t i) const;
};
class Sql_path_instant_set
{
THD *m_thd;
Sql_path m_path;
public:
Sql_path_instant_set(THD *thd, const LEX_CSTRING &str);
Sql_path_instant_set(THD *thd, const Sql_path &new_path);
~Sql_path_instant_set();
bool error() const { return m_thd; }
};
#endif /* SQL_PATH_INCLUDED */