diff options
-rw-r--r-- | sql/field.cc | 17 | ||||
-rw-r--r-- | sql/field.h | 6 | ||||
-rw-r--r-- | sql/sql_lex.cc | 17 | ||||
-rw-r--r-- | sql/sql_lex.h | 4 | ||||
-rw-r--r-- | sql/sql_type.cc | 102 | ||||
-rw-r--r-- | sql/sql_type.h | 28 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 47 | ||||
-rw-r--r-- | sql/sql_yacc_ora.yy | 167 |
8 files changed, 222 insertions, 166 deletions
diff --git a/sql/field.cc b/sql/field.cc index ce03694e7aa..baf6748fb14 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -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; diff --git a/sql/field.h b/sql/field.h index 1af55487704..7644003989b 100644 --- a/sql/field.h +++ b/sql/field.h @@ -4862,6 +4862,7 @@ public: 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 @@ public: } 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); diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index c2ca6c41e21..070a2dd8189 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -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); } diff --git a/sql/sql_lex.h b/sql/sql_lex.h index a05264195fb..3aa458d47e5 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -3742,7 +3742,9 @@ public: 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); diff --git a/sql/sql_type.cc b/sql/sql_type.cc index 0fdebb51d8d..d7fd1f24517 100644 --- a/sql/sql_type.cc +++ b/sql/sql_type.cc @@ -2833,6 +2833,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 { diff --git a/sql/sql_type.h b/sql/sql_type.h index 6fcd363e797..4ec6ffbf29c 100644 --- a/sql/sql_type.h +++ b/sql/sql_type.h @@ -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 @@ public: 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 @@ public: 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 @@ public: 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, diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 4254c4b8a34..b1f9131175f 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -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; } ; diff --git a/sql/sql_yacc_ora.yy b/sql/sql_yacc_ora.yy index 5a54b7c6eb1..b64dea9ad74 100644 --- a/sql/sql_yacc_ora.yy +++ b/sql/sql_yacc_ora.yy @@ -1302,7 +1302,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> @@ -1311,9 +1311,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); %type <type_handler> int_type real_type %type <Lex_field_type> type_with_opt_collate field_type - sp_param_type_with_opt_collate - sp_param_field_type - sp_param_field_type_string field_type_numeric field_type_string field_type_lob @@ -1478,8 +1475,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); %type <Lex_cast_type> cast_type cast_type_numeric cast_type_temporal %type <Lex_length_and_dec> precision opt_precision float_options - opt_field_length_default_sp_param_varchar - opt_field_length_default_sp_param_char %type <lex_user> user grant_user grant_role user_or_role current_role admin_option_for_role user_maybe_role @@ -3214,9 +3209,9 @@ sp_param_name: ; sp_param_name_and_type: - sp_param_name sp_param_type_with_opt_collate + 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 sp_decl_ident '.' ident PERCENT_ORACLE_SYM TYPE_SYM @@ -3258,10 +3253,10 @@ sp_pdparams: ; sp_pdparam: - sp_param_name sp_opt_inout sp_param_type_with_opt_collate + sp_param_name sp_opt_inout type_with_opt_collate { $1->mode= $2; - if (unlikely(Lex->sp_param_fill_definition($1))) + if (unlikely(Lex->sp_param_fill_definition($1, $3))) MYSQL_YYABORT; } | sp_param_name sp_opt_inout sp_decl_ident '.' ident PERCENT_ORACLE_SYM TYPE_SYM @@ -3428,6 +3423,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: @@ -3457,11 +3456,15 @@ sp_decl_idents_init_vars: sp_decl_vars: 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); } @@ -6678,7 +6681,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 { @@ -6874,31 +6881,6 @@ field_type: } ; - -sp_param_field_type: - field_type_numeric - | field_type_temporal - | sp_param_field_type_string - | field_type_lob - | field_type_misc - | IDENT_sys float_options srid_option - { - if (Lex->set_field_type_udt(&$$, $1, $2)) - MYSQL_YYABORT; - } - | reserved_keyword_udt float_options srid_option - { - if (Lex->set_field_type_udt(&$$, $1, $2)) - MYSQL_YYABORT; - } - | non_reserved_keyword_udt float_options srid_option - { - if (Lex->set_field_type_udt(&$$, $1, $2)) - MYSQL_YYABORT; - } - ; - - field_type_numeric: int_type opt_field_length last_field_options { @@ -6921,7 +6903,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); } @@ -6957,87 +6939,45 @@ 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); } ; - -sp_param_field_type_string: - char opt_field_length_default_sp_param_char opt_binary - { - $$.set(&type_handler_varchar, $2); - } - | nchar opt_field_length_default_sp_param_char opt_bin_mod - { - $$.set(&type_handler_varchar, $2); - bincmp_collation(national_charset_info, $3); - } - | BINARY opt_field_length_default_sp_param_char - { - Lex->charset=&my_charset_bin; - $$.set(&type_handler_varchar, $2); - } - | varchar opt_field_length_default_sp_param_varchar opt_binary - { - $$.set(&type_handler_varchar, $2); - } - | VARCHAR2_ORACLE_SYM opt_field_length_default_sp_param_varchar opt_binary - { - $$.set(&type_handler_varchar, $2); - } - | nvarchar opt_field_length_default_sp_param_varchar opt_bin_mod - { - $$.set(&type_handler_varchar, $2); - bincmp_collation(national_charset_info, $3); - } - | VARBINARY opt_field_length_default_sp_param_varchar - { - Lex->charset= &my_charset_bin; - $$.set(&type_handler_varchar, $2); - } - | RAW_ORACLE_SYM opt_field_length_default_sp_param_varchar - { - Lex->charset= &my_charset_bin; - $$.set(&type_handler_varchar, $2); - } - ; - - field_type_temporal: YEAR_SYM opt_field_length last_field_options { @@ -7246,38 +7186,6 @@ opt_field_length: | field_length { $$= $1; } ; -opt_field_length_default_1: - /* empty */ { $$= (char*) "1"; } - | field_length { $$= $1; } - ; - -/* - 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). -*/ -opt_field_length_default_sp_param_varchar: - /* empty */ { $$.set("4000", "4000"); } - | field_length { $$.set($1, NULL); } - ; - -opt_field_length_default_sp_param_char: - /* empty */ { $$.set("2000", "2000"); } - | field_length { $$.set($1, NULL); } - ; - opt_precision: /* empty */ { $$.set(0, 0); } | precision { $$= $1; } @@ -7435,20 +7343,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); - } - ; - -sp_param_type_with_opt_collate: - sp_param_field_type opt_collate - { - $$= $1; - if ($2) - { - if (unlikely(!(Lex->charset= merge_charset_and_collation(Lex->charset, $2)))) - MYSQL_YYABORT; - } - Lex->last_field->set_attributes($1, Lex->charset); } ; @@ -18529,10 +18423,9 @@ sf_return_type: &empty_clex_str, thd->variables.collation_database); } - sp_param_type_with_opt_collate + type_with_opt_collate { - if (unlikely(Lex->sphead->fill_field_definition(thd, - Lex->last_field))) + if (unlikely(Lex->sf_return_fill_definition($2))) MYSQL_YYABORT; } ; |