diff --git a/src/parser/parse_tree_cl.c b/src/parser/parse_tree_cl.c index 412d43d2c7..5ce1c73f62 100644 --- a/src/parser/parse_tree_cl.c +++ b/src/parser/parse_tree_cl.c @@ -943,6 +943,13 @@ pt_walk_private (PARSER_CONTEXT * parser, PT_NODE * node, void *void_arg) * calling pt_apply. */ node_type = node->node_type; + assert (node_type >= PT_NODE_NONE); + if (node_type == PT_NODE_NONE) + { + assert (pt_has_error (parser)); + return NULL; + } + if (node_type >= PT_LAST_NODE_NUMBER || !(apply = pt_apply_f[node_type])) { return NULL; diff --git a/src/parser/type_checking.c b/src/parser/type_checking.c index 69f0b9d24a..4112dff288 100644 --- a/src/parser/type_checking.c +++ b/src/parser/type_checking.c @@ -529,12 +529,11 @@ pt_get_expression_definition (const PT_OP_TYPE op, EXPRESSION_DEFINITION * def) num = 0; /* two overloads */ - /* arg1 */ sig.arg1_type.type = pt_arg_type::GENERIC; sig.arg1_type.val.generic_type = PT_GENERIC_TYPE_STRING; - /* return type */ + /* return type */ sig.return_type.type = pt_arg_type::NORMAL; sig.return_type.val.type = PT_TYPE_INTEGER; def->overloads[num++] = sig; @@ -542,10 +541,13 @@ pt_get_expression_definition (const PT_OP_TYPE op, EXPRESSION_DEFINITION * def) /* arg1 */ sig.arg1_type.type = pt_arg_type::GENERIC; sig.arg1_type.val.generic_type = PT_GENERIC_TYPE_BIT; + /* return type */ + def->overloads[num++] = sig; + /* arg1 */ + sig.arg1_type.type = pt_arg_type::NORMAL; + sig.arg1_type.val.type = PT_TYPE_BLOB; /* return type */ - sig.return_type.type = pt_arg_type::NORMAL; - sig.return_type.val.type = PT_TYPE_INTEGER; def->overloads[num++] = sig; def->overloads_count = num; @@ -6128,8 +6130,8 @@ pt_apply_expressions_definition (PARSER_CONTEXT * parser, PT_NODE ** node) return NO_ERROR; } - matches = -1; best_match = 0; + matches = -1; for (i = 0; i < def.overloads_count; i++) { int match_cnt = 0; @@ -15759,6 +15761,24 @@ pt_evaluate_db_value_expr (PARSER_CONTEXT * parser, PT_NODE * expr, PT_OP_TYPE o if (!PT_IS_STRING_TYPE (o1->type_enum)) { + if (o1->type_enum == PT_TYPE_BLOB) + { + DB_VALUE tval; + + db_make_null (&tval); + dom_status = tp_value_cast (arg1, &tval, &tp_VarBit_domain, false); + if (dom_status != DOMAIN_COMPATIBLE) + { + PT_ERRORmf2 (parser, o1, MSGCAT_SET_PARSER_SEMANTIC, MSGCAT_SEMANTIC_CANT_COERCE_TO, + pt_short_print (parser, o1), pt_show_type_enum (rTyp)); + db_value_clear (&tval); + return 0; + } + db_make_int (result, db_get_string_size (&tval)); + db_value_clear (&tval); + return 1; + } + return 0; } @@ -15774,6 +15794,27 @@ pt_evaluate_db_value_expr (PARSER_CONTEXT * parser, PT_NODE * expr, PT_OP_TYPE o if (!PT_IS_STRING_TYPE (o1->type_enum)) { + if (o1->type_enum == PT_TYPE_BLOB) + { + DB_VALUE tval; + int len = 0; + + db_make_null (&tval); + dom_status = tp_value_cast (arg1, &tval, &tp_VarBit_domain, false); + if (dom_status != DOMAIN_COMPATIBLE) + { + PT_ERRORmf2 (parser, o1, MSGCAT_SET_PARSER_SEMANTIC, MSGCAT_SEMANTIC_CANT_COERCE_TO, + pt_short_print (parser, o1), pt_show_type_enum (rTyp)); + db_value_clear (&tval); + return 0; + } + + db_get_bit (&tval, &len); + db_make_int (result, len); + db_value_clear (&tval); + return 1; + } + return 0; } @@ -19203,6 +19244,11 @@ pt_semantic_type (PARSER_CONTEXT * parser, PT_NODE * tree, SEMANTIC_CHK_INFO * s } /* do type checking */ tree = parser_walk_tree (parser, tree, pt_eval_type_pre, sc_info_ptr, pt_eval_type, sc_info_ptr); + if (pt_has_error (parser)) + { + tree = NULL; + return tree; + } /* do constant folding */ tree = parser_walk_tree (parser, tree, pt_fold_constants_pre, NULL, pt_fold_constants_post, sc_info_ptr); if (pt_has_error (parser)) @@ -20377,6 +20423,8 @@ pt_is_op_hv_late_bind (PT_OP_TYPE op) case PT_HOURF: case PT_MINUTEF: case PT_SECONDF: + case PT_BIT_LENGTH: + case PT_OCTET_LENGTH: case PT_TO_DATE: case PT_TO_DATETIME: case PT_TO_DATETIME_TZ: diff --git a/src/query/fetch.c b/src/query/fetch.c index d78d38d411..8b8bc8daa3 100644 --- a/src/query/fetch.c +++ b/src/query/fetch.c @@ -58,7 +58,6 @@ #include "dbtype.h" // XXX: SHOULD BE THE LAST INCLUDE HEADER #include "memory_wrapper.hpp" - static int fetch_peek_arith (THREAD_ENTRY * thread_p, REGU_VARIABLE * regu_var, val_descr * vd, OID * obj_oid, QFILE_TUPLE tpl, DB_VALUE ** peek_dbval); static int fetch_peek_dbval_pos (REGU_VARIABLE * regu_var, QFILE_TUPLE tpl, int pos, DB_VALUE ** peek_dbval, @@ -1210,6 +1209,37 @@ fetch_peek_arith (THREAD_ENTRY * thread_p, REGU_VARIABLE * regu_var, val_descr * { PRIM_SET_NULL (arithptr->value); } + else if (DB_VALUE_DOMAIN_TYPE (peek_right) == DB_TYPE_BLOB) + { + DB_VALUE tval; + + db_make_null (&tval); + dom_status = tp_value_cast (peek_right, &tval, &tp_VarBit_domain, false); + if (dom_status != DOMAIN_COMPATIBLE) + { + (void) tp_domain_status_er_set (dom_status, ARG_FILE_LINE, peek_right, &tp_VarBit_domain); + db_value_clear (&tval); + goto error; + } + + db_make_int (arithptr->value, db_get_string_size (&tval)); + db_value_clear (&tval); + } + else if (!TP_IS_STRING_TYPE (DB_VALUE_TYPE (peek_right))) + { + DB_VALUE tval; + + db_make_null (&tval); + dom_status = tp_value_cast (peek_right, &tval, &tp_Char_domain, false); + if (dom_status != DOMAIN_COMPATIBLE) + { + (void) tp_domain_status_er_set (dom_status, ARG_FILE_LINE, peek_right, &tp_Char_domain); + db_value_clear (&tval); + goto error; + } + db_make_int (arithptr->value, db_get_string_size (&tval)); + db_value_clear (&tval); + } else { db_make_int (arithptr->value, db_get_string_size (peek_right)); @@ -1228,6 +1258,39 @@ fetch_peek_arith (THREAD_ENTRY * thread_p, REGU_VARIABLE * regu_var, val_descr * db_get_bit (peek_right, &len); db_make_int (arithptr->value, len); } + else if (DB_VALUE_DOMAIN_TYPE (peek_right) == DB_TYPE_BLOB) + { + DB_VALUE tval; + int len = 0; + + db_make_null (&tval); + dom_status = tp_value_cast (peek_right, &tval, &tp_VarBit_domain, false); + if (dom_status != DOMAIN_COMPATIBLE) + { + (void) tp_domain_status_er_set (dom_status, ARG_FILE_LINE, peek_right, &tp_VarBit_domain); + db_value_clear (&tval); + goto error; + } + + db_get_bit (&tval, &len); + db_make_int (arithptr->value, len); + db_value_clear (&tval); + } + else if (!TP_IS_CHAR_TYPE (DB_VALUE_TYPE (peek_right))) + { + DB_VALUE tval; + + db_make_null (&tval); + dom_status = tp_value_cast (peek_right, &tval, &tp_Char_domain, false); + if (dom_status != DOMAIN_COMPATIBLE) + { + (void) tp_domain_status_er_set (dom_status, ARG_FILE_LINE, peek_right, &tp_Char_domain); + db_value_clear (&tval); + goto error; + } + db_make_int (arithptr->value, 8 * db_get_string_size (&tval)); + db_value_clear (&tval); + } else { /* must be a char string type */ diff --git a/src/query/string_opfunc.c b/src/query/string_opfunc.c index 2230e1ec23..21a8bbd826 100644 --- a/src/query/string_opfunc.c +++ b/src/query/string_opfunc.c @@ -26659,6 +26659,7 @@ db_hex (const DB_VALUE * param, DB_VALUE * result) const char *str = NULL; char *hexval = NULL; int str_size = 0, hexval_len = 0, i = 0, error_code = NO_ERROR; + DB_VALUE tval, *ptval = NULL; /* check parameters for NULL values */ if (param == NULL || result == NULL) @@ -26676,6 +26677,7 @@ db_hex (const DB_VALUE * param, DB_VALUE * result) /* compute hex representation */ param_type = DB_VALUE_DOMAIN_TYPE (param); +coerce_pos: if (TP_IS_CHAR_TYPE (param_type) || TP_IS_BIT_TYPE (param_type)) { if (TP_IS_CHAR_TYPE (param_type)) @@ -26776,14 +26778,34 @@ db_hex (const DB_VALUE * param, DB_VALUE * result) } else { - error_code = ER_QSTR_INVALID_DATA_TYPE; - goto error; + db_make_null (&tval); + ptval = &tval; + if (tp_value_cast (param, &tval, &tp_Char_domain, false) != DOMAIN_COMPATIBLE) + { + error_code = ER_QSTR_INVALID_DATA_TYPE; + goto error; + } + + param = &tval; + param_type = DB_VALUE_DOMAIN_TYPE (param); + assert (TP_IS_CHAR_TYPE (param_type)); + goto coerce_pos; + } + + if (ptval) + { + db_value_clear (ptval); } /* all ok */ return NO_ERROR; error: + if (ptval) + { + db_value_clear (ptval); + } + if (result) { db_make_null (result);