1
0
mirror of https://github.com/MariaDB/server.git synced 2026-10-23 18:49:29 +03:00
Files
mariadb/sql/lex_ident_sys.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

109 lines
3.4 KiB
C++

/* Copyright (c) 2000, 2019, Oracle and/or its affiliates.
Copyright (c) 2010, 2024, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */
#ifndef LEX_IDENT_SYS
#define LEX_IDENT_SYS
#include "lex_ident_cli.h"
#include "sql_alloc.h"
#include "char_buffer.h"
extern "C" MYSQL_PLUGIN_IMPORT CHARSET_INFO *system_charset_info;
struct Lex_ident_sys_st: public LEX_CSTRING, Sql_alloc
{
public:
bool copy_ident_cli(const THD *thd, const Lex_ident_cli_st *str);
bool copy_keyword(const THD *thd, const Lex_ident_cli_st *str);
bool copy_sys(const THD *thd, const LEX_CSTRING *str);
bool convert(const THD *thd, const LEX_CSTRING *str, CHARSET_INFO *cs);
bool copy_or_convert(const THD *thd, const Lex_ident_cli_st *str,
CHARSET_INFO *cs);
bool is_null() const { return str == NULL; }
bool to_size_number(ulonglong *to) const;
void set_valid_utf8(const LEX_CSTRING *name)
{
DBUG_ASSERT(Well_formed_prefix(system_charset_info, name->str,
name->length).length() == name->length);
str= name->str ; length= name->length;
}
};
class Lex_ident_sys: public Lex_ident_sys_st
{
public:
Lex_ident_sys(const THD *thd, const Lex_ident_cli_st *str)
{
if (copy_ident_cli(thd, str))
*this= Lex_ident_sys();
}
Lex_ident_sys()
{
((LEX_CSTRING &) *this)= {nullptr, 0};
}
Lex_ident_sys(const char *name, size_t length)
{
LEX_CSTRING tmp= {name, length};
set_valid_utf8(&tmp);
}
explicit Lex_ident_sys(const LEX_CSTRING &str)
{
set_valid_utf8(&str);
}
Lex_ident_sys & operator=(const Lex_ident_sys_st &name)
{
Lex_ident_sys_st::operator=(name);
return *this;
}
};
/*
A buffer to print a qualified data type.
It does not derive from ErrConv because it does not need lazy calculation yet.
Also it's size is defined according to the error message in errmsg-utf8.txt:
"Unknown data type: '%-.384s'" in errmsg-utf8.txt
*/
#define DATA_TYPE_FORMAT_LENGTH 384
class QTypeErrBuffer: public CharBuffer<DATA_TYPE_FORMAT_LENGTH>
{
public:
QTypeErrBuffer(const Lex_ident_sys_st &db, const Lex_ident_sys_st &package,
const Lex_ident_sys_st &type)
{
DBUG_ASSERT(db.str);
DBUG_ASSERT(package.str);
DBUG_ASSERT(type.str);
my_snprintf(m_buff, sizeof(m_buff), "%.*sQ.%.*sQ.%.*sQ",
(int) db.length, db.str,
(int) package.length, package.str,
(int) type.length, type.str);
}
QTypeErrBuffer(const Lex_ident_sys_st &package, const Lex_ident_sys_st &type)
{
DBUG_ASSERT(package.str);
DBUG_ASSERT(type.str);
my_snprintf(m_buff, sizeof(m_buff), "%.*sQ.%.*sQ",
(int) package.length, package.str,
(int) type.length, type.str);
}
};
#endif // LEX_IDENT_SYS