Skip to content

Commit

Permalink
[CBRD-25302] Strengthens checks on date_lang_string_literal in functi…
Browse files Browse the repository at this point in the history
…ons such as TO_DATE() (#5632)

http://jira.cubrid.org/browse/CBRD-25302

* Strengthens checks on date_lang_string_literal in functions such as TO_DATE()
* Functions that take 'date_lang_string_literal' as an argument
   - TO_CHAR
   - TO_DATE, TO_DATETIME, TO_DATETIME_TZ
   - TO_TIME, TO_TIMESTAMP, TO_TIMESTAMP_TZ

NOTE: this commit is erased when fixing conflict during merging with develop
  • Loading branch information
ctshim authored and hgryoo committed Dec 11, 2024
1 parent 3b820b7 commit c093381
Show file tree
Hide file tree
Showing 10 changed files with 377 additions and 220 deletions.
1 change: 1 addition & 0 deletions msg/en_US.utf8/cubrid.msg
Original file line number Diff line number Diff line change
Expand Up @@ -1951,6 +1951,7 @@ $set 8 MSGCAT_SET_PARSER_SEMANTIC
322 Table column '%1$s.%2$s' has not been defined
323 Stored procedure/function '%1$s' has OUT or IN OUT arguments
324 '%1$s' is not a record variable.
325 The argument specifying the language must be a string literal.

325 The argument specifying the language must be a string literal.
326 Stored procedure/function "%1$s" does not exist.
Expand Down
1 change: 1 addition & 0 deletions msg/ko_KR.utf8/cubrid.msg
Original file line number Diff line number Diff line change
Expand Up @@ -1950,6 +1950,7 @@ $set 8 MSGCAT_SET_PARSER_SEMANTIC
322 테이블 컬럼 '%1$s.%2$s'이 정의되지 않았습니다
323 저장 프로시저/함수 '%1$s' 이(가) OUT 또는 IN OUT 인수를 가지고 있습니다.
324 '%1$s'은 레코드 변수가 아닙니다.
325 언어를 지정하는 인수는 문자열 리터럴이어야 합니다.

325 언어를 지정하는 인수는 문자열 리터럴이어야 합니다.
326 저장 프로시저/함수 "%1$s"이(가) 존재하지 않습니다.
Expand Down
43 changes: 8 additions & 35 deletions src/base/language_support.c
Original file line number Diff line number Diff line change
Expand Up @@ -2311,36 +2311,6 @@ lang_set_flag_from_lang (const char *lang_str, bool has_user_format, bool has_us
status = lang_get_lang_id_from_name (lang_str, &lang);
}

if (lang_set_flag_from_lang_id (lang, has_user_format, has_user_lang, flag) == 0)
{
return status;
}

assert (lang == INTL_LANG_ENGLISH);

return 1;
}

/*
* lang_set_flag_from_lang - set a flag according to language identifier
*
* return: 0 if language string OK and flag was set, non-zero otherwise
* lang(in): language identier
* has_user_format(in): true if user has given a format, false otherwise
* has_user_lang(in): true if user has given a language, false otherwise
* flag(out): bit flag : bits 0 and 1 are user flags, bits 2 - 31 are for
* language identification
* Bit 0 : if set, the format was given by user
* Bit 1 : if set, the language was given by user
* Bit 2 - 31 : INTL_LANG
* Consider change this flag to store the language as value
* instead of as bit map
*
* Note : function is used in context of some date-string functions.
*/
int
lang_set_flag_from_lang_id (const INTL_LANG lang, bool has_user_format, bool has_user_lang, int *flag)
{
int lang_val = (int) lang;

*flag = 0;
Expand All @@ -2351,13 +2321,15 @@ lang_set_flag_from_lang_id (const INTL_LANG lang, bool has_user_format, bool has
if (lang_val >= lang_Count_locales)
{
lang_val = (int) INTL_LANG_ENGLISH;
*flag |= lang_val << 2;
return 1;
status = 1;
}

*flag |= lang_val << 2;
*flag |= (lang_val << 2);

return 0;
assert (((*flag) & LANG_LOADED_LOCALES_PARITY_MASK) == 0);
*flag |= LANG_LOADED_LOCALES_PARITY;

return status;
}

/*
Expand All @@ -2378,7 +2350,8 @@ lang_get_lang_id_from_flag (const int flag, bool * has_user_format, bool * has_u
*has_user_format = ((flag & 0x1) == 0x1) ? true : false;
*has_user_lang = ((flag & 0x2) == 0x2) ? true : false;

lang_val = flag >> 2;
assert ((flag & LANG_LOADED_LOCALES_PARITY_MASK) == LANG_LOADED_LOCALES_PARITY);
lang_val = (flag & ~LANG_LOADED_LOCALES_PARITY_MASK) >> 2;

if (lang_val >= 0 && lang_val < lang_Count_locales)
{
Expand Down
3 changes: 2 additions & 1 deletion src/base/language_support.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@
#define LANG_MAX_COLLATIONS 256
#define LANG_MAX_BUILTIN_COLLATIONS 32
#define LANG_MAX_LOADED_LOCALES 32
#define LANG_LOADED_LOCALES_PARITY_MASK 0xFFFFF000
#define LANG_LOADED_LOCALES_PARITY 0x75A5C000

#define LANG_COERCIBLE_COLL LANG_SYS_COLLATION
#define LANG_COERCIBLE_CODESET LANG_SYS_CODESET
Expand Down Expand Up @@ -300,7 +302,6 @@ extern "C"
extern int lang_get_lang_id_from_name (const char *lang_name, INTL_LANG * lang_id);
extern const char *lang_get_lang_name_from_id (const INTL_LANG lang_id);
extern int lang_set_flag_from_lang (const char *lang_str, bool has_user_format, bool has_user_lang, int *flag);
extern int lang_set_flag_from_lang_id (const INTL_LANG lang, bool has_user_format, bool has_user_lang, int *flag);
extern INTL_LANG lang_get_lang_id_from_flag (const int flag, bool * has_user_format, bool * has_user_lang);
extern const char *lang_date_format_parse (const INTL_LANG lang_id, const INTL_CODESET codeset, const DB_TYPE type,
INTL_CODESET * format_codeset);
Expand Down
59 changes: 39 additions & 20 deletions src/parser/csql_grammar.y
Original file line number Diff line number Diff line change
Expand Up @@ -26393,32 +26393,51 @@ parser_make_date_lang (int arg_cnt, PT_NODE * arg3)
if (arg3 && arg_cnt == 3)
{
char *lang_str;
if ((arg3->type_enum == PT_TYPE_CHAR || arg3->type_enum == PT_TYPE_NCHAR) && arg3->info.value.data_value.str != NULL)
if (arg3->node_type == PT_VALUE)
{
date_lang = parser_new_node (this_parser, PT_VALUE);
if (!date_lang)
if ((arg3->type_enum == PT_TYPE_CHAR || arg3->type_enum == PT_TYPE_NCHAR)
&& arg3->info.value.data_value.str != NULL)
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, sizeof (PT_NODE));
return NULL;
}
int flag = 0;
lang_str = (char *) arg3->info.value.data_value.str->bytes;
if (lang_set_flag_from_lang (lang_str, 1, 1, &flag))
{
PT_ERROR (this_parser, arg3, "check syntax at 'date_lang'");
date_lang = parser_new_node (this_parser, PT_VALUE);
if (!date_lang)
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, sizeof (PT_NODE));
return NULL;
}
int flag = 0;
lang_str = (char *) arg3->info.value.data_value.str->bytes;
if (lang_set_flag_from_lang (lang_str, 1, 1, &flag))
{
//PT_ERROR (this_parser, arg3, "check syntax at 'date_lang'");
PT_ERRORmf (this_parser, arg3, MSGCAT_SET_ERROR, -(ER_LOCALE_LANG_NOT_AVAILABLE), lang_str);
}
date_lang->info.value.data_value.i = (long) flag;
date_lang->type_enum = PT_TYPE_INTEGER;
parser_free_node (this_parser, arg3);
}
date_lang->info.value.data_value.i = (long) flag;
}

if (date_lang)
else if (arg3->node_type == PT_HOST_VAR)
{
date_lang->type_enum = PT_TYPE_INTEGER;
parser_free_node (this_parser, arg3);
}
else
date_lang = arg3;
}
else if(this_parser->flag.is_parsing_static_sql)
{
date_lang = arg3;
if (arg3->node_type == PT_EXPR && arg3->info.expr.op == PT_CAST)
{
PT_NODE * node = arg3->info.expr.cast_type;
if(node->node_type == PT_DATA_TYPE && PT_IS_SIMPLE_CHAR_STRING_TYPE(node->type_enum))
{
date_lang = arg3;
}
}
}

if (date_lang == NULL)
{
PT_ERRORm (this_parser, arg3, MSGCAT_SET_PARSER_SEMANTIC, MSGCAT_SEMANTIC_NOT_SUPPORT_TYPE_TO_DATE_LANG);

date_lang = arg3;
}
}
else
{
Expand All @@ -26442,7 +26461,7 @@ parser_make_date_lang (int arg_cnt, PT_NODE * arg3)
}

}
return date_lang;
return date_lang;
}

static PT_NODE *
Expand Down
58 changes: 49 additions & 9 deletions src/parser/parse_tree_cl.c
Original file line number Diff line number Diff line change
Expand Up @@ -10573,23 +10573,63 @@ pt_print_expr (PARSER_CONTEXT * parser, PT_NODE * p)
r1 = pt_print_bytes (parser, p->info.expr.arg1);
q = pt_append_varchar (parser, q, r1);

flags = p->info.expr.arg3->info.value.data_value.i;
lang_id = lang_get_lang_id_from_flag (flags, &has_user_format, &has_user_lang);
if (has_user_format)
assert (p->info.expr.arg3);
if (p->info.expr.arg3->node_type == PT_HOST_VAR)
{
const char *lang_name = lang_get_lang_name_from_id (lang_id);

q = pt_append_nulstring (parser, q, ", ");
r1 = pt_print_bytes (parser, p->info.expr.arg2);
q = pt_append_varchar (parser, q, r1);

if (lang_name != NULL && has_user_lang)
q = pt_append_nulstring (parser, q, ", ");
r1 = pt_print_bytes (parser, p->info.expr.arg3);
q = pt_append_varchar (parser, q, r1);
}
else if (p->info.expr.arg3->node_type == PT_VALUE)
{
flags = p->info.expr.arg3->info.value.data_value.i;
lang_id = lang_get_lang_id_from_flag (flags, &has_user_format, &has_user_lang);
if (has_user_format)
{
q = pt_append_nulstring (parser, q, ", '");
q = pt_append_nulstring (parser, q, lang_name);
q = pt_append_nulstring (parser, q, "'");
const char *lang_name = lang_get_lang_name_from_id (lang_id);

q = pt_append_nulstring (parser, q, ", ");
r1 = pt_print_bytes (parser, p->info.expr.arg2);
q = pt_append_varchar (parser, q, r1);

if (lang_name != NULL && has_user_lang)
{
q = pt_append_nulstring (parser, q, ", '");
q = pt_append_nulstring (parser, q, lang_name);
q = pt_append_nulstring (parser, q, "'");
}
}
}
else if (parser->flag.is_parsing_static_sql)
{
assert (p->info.expr.arg3->node_type == PT_EXPR && p->info.expr.arg3->info.expr.op == PT_CAST);
assert (p->info.expr.arg3->info.expr.cast_type->node_type == PT_DATA_TYPE);
assert (PT_IS_SIMPLE_CHAR_STRING_TYPE (p->info.expr.arg3->info.expr.cast_type->type_enum));
q = pt_append_nulstring (parser, q, ", ");
r1 = pt_print_bytes (parser, p->info.expr.arg2);
q = pt_append_varchar (parser, q, r1);

q = pt_append_nulstring (parser, q, ", ");
r1 = pt_print_bytes (parser, p->info.expr.arg3);
q = pt_append_varchar (parser, q, r1);
}
else
{
/*
create table foo(a char(20), b varchar, c nchar(20), d nchar varying, e sequence(int));
insert into foo values('aaa', 'bbb', n'ccc', n'ddd', {1, 2, 3, 4, 5});
select to_char(e) from foo order by 1;

--In a case like "select to_char(e) from foo", it enters the second step.
*/
assert ((pt_has_error (parser) || er_errid () != NO_ERROR)
|| (p->info.expr.arg2 &&
p->info.expr.arg2->node_type == PT_VALUE && p->info.expr.arg2->type_enum == PT_TYPE_NULL));
}
q = pt_append_nulstring (parser, q, ")");
}
break;
Expand Down
1 change: 1 addition & 0 deletions src/parser/parser_message.h
Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,7 @@
#define MSGCAT_SEMANTIC_UNDEFINED_TABLE_COLUMN MSGCAT_SEMANTIC_NO(322)
#define MSGCAT_SEMANTIC_SP_OUT_ARGS_EXISTS_IN_QUERY MSGCAT_SEMANTIC_NO(323)
#define MSGCAT_SEMANTIC_SP_INTO_FIELD_EXPR_IN_NON_STATIC_SQL MSGCAT_SEMANTIC_NO(324)
#define MSGCAT_SEMANTIC_NOT_SUPPORT_TYPE_TO_DATE_LANG MSGCAT_SEMANTIC_NO(325)

#define MSGCAT_SEMANTIC_NOT_SUPPORT_TYPE_TO_DATE_LANG MSGCAT_SEMANTIC_NO(325)
#define MSTCAT_SEMANTIC_SP_NOT_EXIST MSGCAT_SEMANTIC_NO(326)
Expand Down
Loading

0 comments on commit c093381

Please sign in to comment.