Commit f2cff125 authored by Alexander Barkov's avatar Alexander Barkov

MDEV-20924 Unify grammar rules: field_type_string and sp_param_field_type_string

In order to:
- unify sql_yacc.yy and sql_yacc_ora.yy easier
- move more functionality from the parser to Type_handler
  (so plugins can override the behavior)

this patch:
- removes rules sp_param_field_type_string and sp_param_field_type
  from sql_yacc_ora.yy
- adds a new virtial method Type_handler::Column_definition_set_attributes()
parent 0ccfdc8e
......@@ -10073,17 +10073,26 @@ bool Column_definition::prepare_interval_field(MEM_ROOT *mem_root,
}
void Column_definition::set_attributes(const Lex_field_type_st &type,
CHARSET_INFO *cs)
bool Column_definition::set_attributes(THD *thd,
const Lex_field_type_st &def,
CHARSET_INFO *cs,
column_definition_type_t type)
{
DBUG_ASSERT(type_handler() == &type_handler_null);
DBUG_ASSERT(charset == &my_charset_bin || charset == NULL);
DBUG_ASSERT(length == 0);
DBUG_ASSERT(decimals == 0);
set_handler(type.type_handler());
charset= cs;
set_handler(def.type_handler());
return type_handler()->Column_definition_set_attributes(thd, this,
def, cs, type);
}
void
Column_definition_attributes::set_length_and_dec(const Lex_length_and_dec_st
&type)
{
if (type.length())
{
int err;
......
......@@ -4862,6 +4862,7 @@ class Column_definition_attributes
bool frm_unpack_numeric_with_dec(TABLE_SHARE *share, const uchar *buff);
bool frm_unpack_temporal_with_dec(TABLE_SHARE *share, uint intlen,
const uchar *buff);
void set_length_and_dec(const Lex_length_and_dec_st &attr);
};
......@@ -4964,7 +4965,10 @@ class Column_definition: public Sql_alloc,
}
Column_definition(THD *thd, Field *field, Field *orig_field);
void set_attributes(const Lex_field_type_st &type, CHARSET_INFO *cs);
bool set_attributes(THD *thd,
const Lex_field_type_st &attr,
CHARSET_INFO *cs,
column_definition_type_t type);
void create_length_to_internal_length_null()
{
DBUG_ASSERT(length == 0);
......
......@@ -5580,9 +5580,22 @@ sp_variable *LEX::sp_param_init(LEX_CSTRING *name)
}
bool LEX::sp_param_fill_definition(sp_variable *spvar)
bool LEX::sp_param_fill_definition(sp_variable *spvar,
const Lex_field_type_st &def)
{
return sphead->fill_spvar_definition(thd, last_field, &spvar->name);
return
last_field->set_attributes(thd, def, charset,
COLUMN_DEFINITION_ROUTINE_PARAM) ||
sphead->fill_spvar_definition(thd, last_field, &spvar->name);
}
bool LEX::sf_return_fill_definition(const Lex_field_type_st &def)
{
return
last_field->set_attributes(thd, def, charset,
COLUMN_DEFINITION_FUNCTION_RETURN) ||
sphead->fill_field_definition(thd, last_field);
}
......
......@@ -3742,7 +3742,9 @@ struct LEX: public Query_tables_list
bool sp_proc_stmt_statement_finalize(THD *, bool no_lookahead);
sp_variable *sp_param_init(LEX_CSTRING *name);
bool sp_param_fill_definition(sp_variable *spvar);
bool sp_param_fill_definition(sp_variable *spvar,
const Lex_field_type_st &def);
bool sf_return_fill_definition(const Lex_field_type_st &def);
int case_stmt_action_expr(Item* expr);
int case_stmt_action_when(Item *when, bool simple);
......
......@@ -2832,6 +2832,108 @@ bool Type_handler::
}
/*************************************************************************/
bool
Type_handler::Column_definition_set_attributes(THD *thd,
Column_definition *def,
const Lex_field_type_st &attr,
CHARSET_INFO *cs,
column_definition_type_t type)
const
{
def->charset= cs;
def->set_length_and_dec(attr);
return false;
}
/*
In sql_mode=ORACLE, real size of VARCHAR and CHAR with no length
in SP parameters is fixed at runtime with the length of real args.
Let's translate VARCHAR to VARCHAR(4000) for return value.
Since Oracle 9, maximum size for VARCHAR in PL/SQL is 32767.
In MariaDB the limit for VARCHAR is 65535 bytes.
We could translate VARCHAR with no length to VARCHAR(65535), but
it would mean that for multi-byte character sets we'd have to translate
VARCHAR to MEDIUMTEXT, to guarantee 65535 characters.
Also we could translate VARCHAR to VARCHAR(16383), where 16383 is
the maximum possible length in characters in case of mbmaxlen=4
(e.g. utf32, utf16, utf8mb4). However, we'll have character sets with
mbmaxlen=5 soon (e.g. gb18030).
*/
bool
Type_handler_string::Column_definition_set_attributes(
THD *thd,
Column_definition *def,
const Lex_field_type_st &attr,
CHARSET_INFO *cs,
column_definition_type_t type)
const
{
Type_handler::Column_definition_set_attributes(thd, def, attr, cs, type);
if (attr.length())
return false;
switch (type) {
case COLUMN_DEFINITION_ROUTINE_PARAM:
case COLUMN_DEFINITION_FUNCTION_RETURN:
if (thd->variables.sql_mode & MODE_ORACLE)
{
// See Type_handler_varchar::Column_definition_set_attributes()
def->length= def->decimals= 2000;
def->set_handler(&type_handler_varchar);
return false;
}
break;
case COLUMN_DEFINITION_ROUTINE_LOCAL:
case COLUMN_DEFINITION_TABLE_FIELD:
break;
}
def->length= 1;
return false;
}
bool
Type_handler_varchar::Column_definition_set_attributes(
THD *thd,
Column_definition *def,
const Lex_field_type_st &attr,
CHARSET_INFO *cs,
column_definition_type_t type)
const
{
Type_handler::Column_definition_set_attributes(thd, def, attr, cs, type);
if (attr.length())
return false;
switch (type) {
case COLUMN_DEFINITION_ROUTINE_PARAM:
case COLUMN_DEFINITION_FUNCTION_RETURN:
if (thd->variables.sql_mode & MODE_ORACLE)
{
/*
Type_handler_varchar::adjust_spparam_type() tests "decimals"
to detect if the formal parameter length needs to be adjusted to
the actual parameter length. Non-zero decimals means that the length
was set implicitly to the default value and needs to be adjusted.
*/
def->length= def->decimals= 4000;
return false;
}
break;
case COLUMN_DEFINITION_ROUTINE_LOCAL:
case COLUMN_DEFINITION_TABLE_FIELD:
break;
}
thd->parse_error();
return true;
}
/*************************************************************************/
bool Type_handler_null::
Column_definition_fix_attributes(Column_definition *def) const
......
......@@ -127,6 +127,15 @@ enum partition_value_print_mode_t
};
enum column_definition_type_t
{
COLUMN_DEFINITION_TABLE_FIELD,
COLUMN_DEFINITION_ROUTINE_PARAM,
COLUMN_DEFINITION_ROUTINE_LOCAL,
COLUMN_DEFINITION_FUNCTION_RETURN
};
class Data_type_statistics
{
public:
......@@ -3620,6 +3629,13 @@ class Type_handler
virtual bool Column_definition_validate_check_constraint(THD *thd,
Column_definition *c)
const;
// Set attributes in the parser
virtual bool Column_definition_set_attributes(THD *thd,
Column_definition *def,
const Lex_field_type_st &attr,
CHARSET_INFO *cs,
column_definition_type_t type)
const;
// Fix attributes after the parser
virtual bool Column_definition_fix_attributes(Column_definition *c) const= 0;
/*
......@@ -6488,6 +6504,12 @@ class Type_handler_string: public Type_handler_longstr
Field *make_conversion_table_field(MEM_ROOT *root,
TABLE *table, uint metadata,
const Field *target) const override;
bool Column_definition_set_attributes(THD *thd,
Column_definition *def,
const Lex_field_type_st &attr,
CHARSET_INFO *cs,
column_definition_type_t type)
const override;
bool Column_definition_fix_attributes(Column_definition *c) const override;
bool Column_definition_prepare_stage2(Column_definition *c,
handler *file,
......@@ -6581,6 +6603,12 @@ class Type_handler_varchar: public Type_handler_longstr
Field *make_conversion_table_field(MEM_ROOT *root,
TABLE *table, uint metadata,
const Field *target) const override;
bool Column_definition_set_attributes(THD *thd,
Column_definition *def,
const Lex_field_type_st &attr,
CHARSET_INFO *cs,
column_definition_type_t type)
const override;
bool Column_definition_fix_attributes(Column_definition *c) const override;
bool Column_definition_prepare_stage2(Column_definition *c,
handler *file,
......
......@@ -1830,7 +1830,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
wild_and_where
%type <const_simple_string>
field_length opt_field_length opt_field_length_default_1
field_length opt_field_length
opt_compression_method
%type <string>
......@@ -3422,7 +3422,7 @@ sp_param_name:
sp_param_name_and_type:
sp_param_name type_with_opt_collate
{
if (unlikely(Lex->sp_param_fill_definition($$= $1)))
if (unlikely(Lex->sp_param_fill_definition($$= $1, $2)))
MYSQL_YYABORT;
}
| sp_param_name TYPE_SYM OF_SYM ident '.' ident
......@@ -3551,6 +3551,10 @@ row_field_name:
row_field_definition:
row_field_name type_with_opt_collate
{
Lex->last_field->set_attributes(thd, $2, Lex->charset,
COLUMN_DEFINITION_ROUTINE_LOCAL);
}
;
row_field_definition_list:
......@@ -3580,11 +3584,15 @@ sp_decl_idents_init_vars:
sp_decl_variable_list:
sp_decl_idents_init_vars
type_with_opt_collate
{
Lex->last_field->set_attributes(thd, $2, Lex->charset,
COLUMN_DEFINITION_ROUTINE_LOCAL);
}
sp_opt_default
{
if (unlikely(Lex->sp_variable_declarations_finalize(thd, $1,
&Lex->last_field[0],
$3)))
$4)))
MYSQL_YYABORT;
$$.init_using_vars($1);
}
......@@ -6680,7 +6688,11 @@ field_spec:
;
field_type_or_serial:
field_type { Lex->last_field->set_attributes($1, Lex->charset); }
field_type
{
Lex->last_field->set_attributes(thd, $1, Lex->charset,
COLUMN_DEFINITION_TABLE_FIELD);
}
field_def
| SERIAL_SYM
{
......@@ -6898,7 +6910,7 @@ field_type_numeric:
$$.set(&type_handler_float);
}
}
| BIT_SYM opt_field_length_default_1
| BIT_SYM opt_field_length
{
$$.set(&type_handler_bit, $2);
}
......@@ -6934,39 +6946,39 @@ opt_binary_and_compression:
;
field_type_string:
char opt_field_length_default_1 opt_binary
char opt_field_length opt_binary
{
$$.set(&type_handler_string, $2);
}
| nchar opt_field_length_default_1 opt_bin_mod
| nchar opt_field_length opt_bin_mod
{
$$.set(&type_handler_string, $2);
bincmp_collation(national_charset_info, $3);
}
| BINARY opt_field_length_default_1
| BINARY opt_field_length
{
Lex->charset=&my_charset_bin;
$$.set(&type_handler_string, $2);
}
| varchar field_length opt_binary_and_compression
| varchar opt_field_length opt_binary_and_compression
{
$$.set(&type_handler_varchar, $2);
}
| VARCHAR2_ORACLE_SYM field_length opt_binary_and_compression
| VARCHAR2_ORACLE_SYM opt_field_length opt_binary_and_compression
{
$$.set(&type_handler_varchar, $2);
}
| nvarchar field_length opt_compressed opt_bin_mod
| nvarchar opt_field_length opt_compressed opt_bin_mod
{
$$.set(&type_handler_varchar, $2);
bincmp_collation(national_charset_info, $4);
}
| VARBINARY field_length opt_compressed
| VARBINARY opt_field_length opt_compressed
{
Lex->charset=&my_charset_bin;
$$.set(&type_handler_varchar, $2);
}
| RAW_ORACLE_SYM field_length opt_compressed
| RAW_ORACLE_SYM opt_field_length opt_compressed
{
Lex->charset= &my_charset_bin;
$$.set(&type_handler_varchar, $2);
......@@ -7181,11 +7193,6 @@ opt_field_length:
| field_length { $$= $1; }
;
opt_field_length_default_1:
/* empty */ { $$= (char*) "1"; }
| field_length { $$= $1; }
;
opt_precision:
/* empty */ { $$.set(0, 0); }
| precision { $$= $1; }
......@@ -7343,7 +7350,6 @@ type_with_opt_collate:
if (unlikely(!(Lex->charset= merge_charset_and_collation(Lex->charset, $2))))
MYSQL_YYABORT;
}
Lex->last_field->set_attributes($1, Lex->charset);
}
;
......@@ -18299,8 +18305,7 @@ sf_return_type:
}
type_with_opt_collate
{
if (unlikely(Lex->sphead->fill_field_definition(thd,
Lex->last_field)))
if (unlikely(Lex->sf_return_fill_definition($3)))
MYSQL_YYABORT;
}
;
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment