Skip to content

Commit

Permalink
MDEV-34317: Implement RECORD type
Browse files Browse the repository at this point in the history
Implement `DECLARE TYPE type_name IS RECORD (..)` with scalar members in
 stored routines and anonymous blocks
  • Loading branch information
iqbal-hasprime authored and abarkov committed Jan 28, 2025
1 parent 4c956fa commit 9f5adf0
Show file tree
Hide file tree
Showing 15 changed files with 1,964 additions and 11 deletions.
775 changes: 775 additions & 0 deletions mysql-test/suite/compat/oracle/r/sp-record.result

Large diffs are not rendered by default.

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

Large diffs are not rendered by default.

29 changes: 29 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,29 @@
# Start of 11.8 tests
#
# 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
# End of 11.8 tests
28 changes: 28 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,28 @@
--echo # Start of 11.8 tests

--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 ;$$

--echo # End of 11.8 tests
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 @@ -515,6 +515,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 @@ -12145,9 +12145,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 @@ -3933,6 +3933,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 @@ -815,6 +815,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 @@ -94,8 +94,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 @@ -107,8 +107,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 @@ -409,6 +409,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 @@ -320,6 +320,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 @@ -696,6 +721,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 @@ -760,6 +808,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 @@ -336,7 +336,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 @@ -6755,6 +6755,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 @@ -6763,6 +6774,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 @@ -3874,6 +3874,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

0 comments on commit 9f5adf0

Please sign in to comment.