Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MDEV-34317 Implement RECORD type #3515

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
773 changes: 773 additions & 0 deletions mysql-test/suite/compat/oracle/r/sp-record.result

Large diffs are not rendered by default.

836 changes: 836 additions & 0 deletions mysql-test/suite/compat/oracle/t/sp-record.test

Large diffs are not rendered by default.

27 changes: 27 additions & 0 deletions plugin/type_uuid/mysql-test/type_uuid/type_uuid_sp_record.result
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#
# MDEV-34317 DECLARE TYPE type_name IS RECORD (..) with scalar members in stored routines
#
#
# Demonstrate UDT field type with RECORD
#
SET sql_mode=ORACLE;
DECLARE
TYPE rec_t IS RECORD (
a INT,
b UUID
);
rec rec_t:= rec_t(1,'6021cf0b-94f8-11ef-b80e-e454e874f5e5');
BEGIN
CREATE TABLE t1 AS SELECT rec.a, rec.b;
SHOW CREATE TABLE t1;
SELECT * FROM t1;
DROP TABLE t1;
END;
$$
Table Create Table
t1 CREATE TABLE "t1" (
"rec.a" int(11) DEFAULT NULL,
"rec.b" uuid DEFAULT NULL
)
rec.a rec.b
1 6021cf0b-94f8-11ef-b80e-e454e874f5e5
24 changes: 24 additions & 0 deletions plugin/type_uuid/mysql-test/type_uuid/type_uuid_sp_record.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
--echo #
--echo # MDEV-34317 DECLARE TYPE type_name IS RECORD (..) with scalar members in stored routines
--echo #


--echo #
--echo # Demonstrate UDT field type with RECORD
--echo #
SET sql_mode=ORACLE;
DELIMITER $$;
DECLARE
TYPE rec_t IS RECORD (
a INT,
b UUID
);
rec rec_t:= rec_t(1,'6021cf0b-94f8-11ef-b80e-e454e874f5e5');
BEGIN
CREATE TABLE t1 AS SELECT rec.a, rec.b;
SHOW CREATE TABLE t1;
SELECT * FROM t1;
DROP TABLE t1;
END;
$$
DELIMITER ;$$
7 changes: 7 additions & 0 deletions sql/item.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1939,6 +1939,13 @@ bool Item_splocal_row_field::fix_fields(THD *thd, Item **ref)
{
DBUG_ASSERT(fixed() == 0);
Item *item= get_variable(thd->spcont)->element_index(m_field_idx);
/*
If a row field was declared using an anchored data type,
then its creation time type handler was type_handler_null.
Let's now copy the real type handler from the item, which
now contains the resolved data type.
*/
set_handler(item->type_handler());
return fix_fields_from_item(thd, ref, item);
}

Expand Down
1 change: 1 addition & 0 deletions sql/lex.h
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,7 @@ SYMBOL symbols[] = {
{ "READS", SYM(READS_SYM)},
{ "REAL", SYM(REAL)},
{ "REBUILD", SYM(REBUILD_SYM)},
{ "RECORD", SYM(RECORD_SYM)},
{ "RECOVER", SYM(RECOVER_SYM)},
{ "RECURSIVE", SYM(RECURSIVE_SYM)},
{ "REDO_BUFFER_SIZE", SYM(REDO_BUFFER_SIZE_SYM)},
Expand Down
5 changes: 2 additions & 3 deletions sql/share/errmsg-utf8.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12148,9 +12148,8 @@ ER_UNKNOWN_OPERATOR
eng "Operator does not exist: '%-.128s'"
spa "El operador no existe: '%-.128s'"
sw "Opereta haipo: '% -.128s'"
ER_UNUSED_29
eng "You should never see it"
sw "Hupaswi kuiona kamwe"
ER_SP_DUP_DECL
eng "Duplicate declaration: '%-.64s'"
ER_PART_STARTS_BEYOND_INTERVAL
eng "%`s: STARTS is later than query time, first history partition may exceed INTERVAL value"
spa "%`s: STARTS es posterior al momento de consulta (query), la primera partición de historia puede exceder el valor INTERVAL"
Expand Down
32 changes: 32 additions & 0 deletions sql/sp_head.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3937,6 +3937,38 @@ bool sp_head::spvar_fill_type_reference(THD *thd,
}


bool sp_head::spvar_def_fill_type_reference(THD *thd, Spvar_definition *def,
const LEX_CSTRING &table,
const LEX_CSTRING &column)
{
Qualified_column_ident *ref;
if (!(ref= new (thd->mem_root) Qualified_column_ident(&table, &column)))
return true;

def->set_column_type_ref(ref);
m_flags|= sp_head::HAS_COLUMN_TYPE_REFS;

return false;
}


bool sp_head::spvar_def_fill_type_reference(THD *thd, Spvar_definition *def,
const LEX_CSTRING &db,
const LEX_CSTRING &table,
const LEX_CSTRING &column)
{
Qualified_column_ident *ref;
if (!(ref= new (thd->mem_root) Qualified_column_ident(thd, &db, &table,
&column)))
return true;

def->set_column_type_ref(ref);
m_flags|= sp_head::HAS_COLUMN_TYPE_REFS;

return false;
}


bool sp_head::spvar_fill_table_rowtype_reference(THD *thd,
sp_variable *spvar,
const LEX_CSTRING &table)
Expand Down
8 changes: 8 additions & 0 deletions sql/sp_head.h
Original file line number Diff line number Diff line change
Expand Up @@ -819,6 +819,14 @@ class sp_head :private Query_arena,
const LEX_CSTRING &db,
const LEX_CSTRING &table);

bool spvar_def_fill_type_reference(THD *thd, Spvar_definition *def,
const LEX_CSTRING &table,
const LEX_CSTRING &column);
bool spvar_def_fill_type_reference(THD *thd, Spvar_definition *def,
const LEX_CSTRING &db,
const LEX_CSTRING &table,
const LEX_CSTRING &column);

void set_c_chistics(const st_sp_chistics &chistics);
void set_info(longlong created, longlong modified,
const st_sp_chistics &chistics, sql_mode_t sql_mode);
Expand Down
42 changes: 38 additions & 4 deletions sql/sp_pcontext.cc
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,8 @@ sp_pcontext::sp_pcontext()
m_parent(NULL), m_pboundary(0),
m_vars(PSI_INSTRUMENT_MEM), m_case_expr_ids(PSI_INSTRUMENT_MEM),
m_conditions(PSI_INSTRUMENT_MEM), m_cursors(PSI_INSTRUMENT_MEM),
m_handlers(PSI_INSTRUMENT_MEM), m_children(PSI_INSTRUMENT_MEM),
m_scope(REGULAR_SCOPE)
m_handlers(PSI_INSTRUMENT_MEM), m_records(PSI_INSTRUMENT_MEM),
m_children(PSI_INSTRUMENT_MEM), m_scope(REGULAR_SCOPE)
{
init(0, 0, 0);
}
Expand All @@ -111,8 +111,8 @@ sp_pcontext::sp_pcontext(sp_pcontext *prev, sp_pcontext::enum_scope scope)
m_parent(prev), m_pboundary(0),
m_vars(PSI_INSTRUMENT_MEM), m_case_expr_ids(PSI_INSTRUMENT_MEM),
m_conditions(PSI_INSTRUMENT_MEM), m_cursors(PSI_INSTRUMENT_MEM),
m_handlers(PSI_INSTRUMENT_MEM), m_children(PSI_INSTRUMENT_MEM),
m_scope(scope)
m_handlers(PSI_INSTRUMENT_MEM), m_records(PSI_INSTRUMENT_MEM),
m_children(PSI_INSTRUMENT_MEM), m_scope(scope)
{
init(prev->m_var_offset + prev->m_max_var_index,
prev->current_cursor_count(),
Expand Down Expand Up @@ -413,6 +413,40 @@ sp_condition_value *sp_pcontext::find_condition(const LEX_CSTRING *name,
NULL;
}


bool sp_pcontext::add_record(THD *thd, const Lex_ident_column &name,
Row_definition_list *field)
{
sp_record *p= new (thd->mem_root) sp_record(name, field);

if (p == NULL)
return true;

return m_records.append(p);
}


sp_record *sp_pcontext::find_record(const LEX_CSTRING *name,
bool current_scope_only) const
{
size_t i= m_records.elements();

while (i--)
{
sp_record *p= m_records.at(i);

if (p->eq_name(name))
{
return p;
}
}

return (!current_scope_only && m_parent) ?
m_parent->find_record(name, false) :
NULL;
}


sp_condition_value *
sp_pcontext::find_declared_or_predefined_condition(THD *thd,
const LEX_CSTRING *name)
Expand Down
51 changes: 51 additions & 0 deletions sql/sp_pcontext.h
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,31 @@ class sp_handler : public Sql_alloc
{ }
};


///////////////////////////////////////////////////////////////////////////

/// This class represents 'DECLARE RECORD' statement.

class sp_record : public Sql_alloc
{
public:
/// Name of the record.
Lex_ident_column name;
Row_definition_list *field;

public:
sp_record(const Lex_ident_column &name_arg, Row_definition_list *prmfield)
:Sql_alloc(),
name(name_arg),
field(prmfield)
{ }
bool eq_name(const LEX_CSTRING *str) const
{
return name.streq(*str);
}
};


///////////////////////////////////////////////////////////////////////////

/// The class represents parse-time context, which keeps track of declared
Expand Down Expand Up @@ -700,6 +725,29 @@ class sp_pcontext : public Sql_alloc
return m_for_loop;
}

/////////////////////////////////////////////////////////////////////////
// Record.
/////////////////////////////////////////////////////////////////////////

bool add_record(THD *thd,
const Lex_ident_column &name,
Row_definition_list *field);

sp_record *find_record(const LEX_CSTRING *name,
bool current_scope_only) const;

bool declare_record(THD *thd,
const Lex_ident_column &name,
Row_definition_list *field)
{
if (find_record(&name, true))
{
my_error(ER_SP_DUP_DECL, MYF(0), name.str);
return true;
}
return add_record(thd, name, field);
}

private:
/// Constructor for a tree node.
/// @param prev the parent parsing context
Expand Down Expand Up @@ -764,6 +812,9 @@ class sp_pcontext : public Sql_alloc
/// Stack of SQL-handlers.
Dynamic_array<sp_handler *> m_handlers;

/// Stack of records.
Dynamic_array<sp_record *> m_records;

/*
In the below example the label <<lab>> has two meanings:
- GOTO lab : must go before the beginning of the loop
Expand Down
7 changes: 6 additions & 1 deletion sql/sp_rcontext.cc
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,12 @@ bool Row_definition_list::resolve_type_refs(THD *thd)
Spvar_definition *def;
while ((def= it++))
{
if (def->is_column_type_ref() &&
if (def->is_row())
{
if (def->row_field_definitions()->resolve_type_refs(thd))
return true;
}
else if (def->is_column_type_ref() &&
def->column_type_ref()->resolve_type_ref(thd, def))
return true;
}
Expand Down
39 changes: 39 additions & 0 deletions sql/sql_lex.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6756,6 +6756,17 @@ bool LEX::sp_variable_declarations_finalize(THD *thd, int nvars,
const LEX_CSTRING &expr_str)
{
DBUG_ASSERT(cdef);

if (cdef->type_handler() == &type_handler_row)
{
if (sp_record *sprec=
(sp_record *)cdef->get_attr_const_void_ptr(0)) {
return sp_variable_declarations_rec_finalize(thd, nvars,
sprec->field,
dflt_value_item, expr_str);
}
}

Column_definition tmp(*cdef);
if (sphead->fill_spvar_definition(thd, &tmp))
return true;
Expand All @@ -6764,6 +6775,34 @@ bool LEX::sp_variable_declarations_finalize(THD *thd, int nvars,
}


bool LEX::sp_variable_declarations_rec_finalize(THD *thd, int nvars,
Row_definition_list *src_row,
Item *dflt_value_item,
const LEX_CSTRING &expr_str)
{
DBUG_ASSERT(src_row);

// Create a copy of the row definition list to fill
// definitions
Row_definition_list *row= new (thd->mem_root) Row_definition_list();
if (unlikely(row == NULL))
return true;

// Create a deep copy of the elements
List_iterator<Spvar_definition> it(*src_row);
for (Spvar_definition *def= it++; def; def= it++)
{
Spvar_definition *new_def= new (thd->mem_root) Spvar_definition(*def);
if (unlikely(new_def == NULL))
return true;

row->push_back(new_def, thd->mem_root);
}

return sp_variable_declarations_row_finalize(thd, nvars, row,
dflt_value_item, expr_str);
}

bool LEX::sp_variable_declarations_row_finalize(THD *thd, int nvars,
Row_definition_list *row,
Item *dflt_value_item,
Expand Down
4 changes: 4 additions & 0 deletions sql/sql_lex.h
Original file line number Diff line number Diff line change
Expand Up @@ -3869,6 +3869,10 @@ struct LEX: public Query_tables_list
const LEX_CSTRING &expr_str);
bool sp_variable_declarations_set_default(THD *thd, int nvars, Item *def,
const LEX_CSTRING &expr_str);
bool sp_variable_declarations_rec_finalize(THD *thd, int nvars,
Row_definition_list *src_row,
Item *def,
const LEX_CSTRING &expr_str);
bool sp_variable_declarations_row_finalize(THD *thd, int nvars,
Row_definition_list *row,
Item *def,
Expand Down
Loading