Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[CBRD-25054] Numeric type column inserted by using rownum does not show error even it's outranged. #4766

Merged
merged 14 commits into from
Nov 24, 2023
Merged
71 changes: 71 additions & 0 deletions src/object/object_domain.c
Original file line number Diff line number Diff line change
Expand Up @@ -11475,6 +11475,77 @@ tp_domain_references_objects (const TP_DOMAIN * dom)
}
}

/*
* tp_value_auto_cast_with_precsion_check
* Cast a value into one of another domain like tp_value_auto_cast.
* It checks the precision in case of casting discrete number type to numeric type
* return: TP_DOMAIN_STATUS
* src(in): src DB_VALUE
* dest(out): dest DB_VALUE
* desired_domain(in): destion domain
*/
TP_DOMAIN_STATUS
tp_value_auto_cast_with_precision_check (const DB_VALUE * src, DB_VALUE * dest, const TP_DOMAIN * desired_domain)
{
TP_DOMAIN_STATUS dom_status = DOMAIN_COMPATIBLE;

static INT64 max_value[19]; /* max precision of a big integer is 19 */
static bool init_bigint_value = false;

if (!init_bigint_value)
{
int i;

max_value[0] = 1;
for (i = 1; i < 19; i++)
{
max_value[i] = max_value[i - 1] * 10;
}

init_bigint_value = true;
}

if (TP_IS_DISCRETE_NUMBER_TYPE (src->domain.general_info.type))
{
/* if the numeric's precision is 19 or more, then it can get the bigint enough */
if (desired_domain->type->id == DB_TYPE_NUMERIC && desired_domain->precision < 19)
{
INT64 bigint;

assert (desired_domain->precision >= 0);

switch (src->domain.general_info.type)
{
case DB_TYPE_BIGINT:
bigint = db_get_bigint (src);
break;
case DB_TYPE_INTEGER:
bigint = db_get_int (src);
break;
case DB_TYPE_SHORT:
bigint = db_get_short (src);
default:
/* never here */
break;
}

if ((bigint > 0 && (bigint >= max_value[desired_domain->precision]))
|| ((bigint < 0) && ((-bigint) >= max_value[desired_domain->precision])))
{
/* can not coerce for overflow */
dom_status = DOMAIN_OVERFLOW;
}
}
}

if (dom_status != DOMAIN_OVERFLOW)
{
dom_status = tp_value_auto_cast (src, dest, desired_domain);
}

return dom_status;
}

/*
* tp_value_auto_cast - Cast a value into one of another domain, returning an
* error only
Expand Down
2 changes: 2 additions & 0 deletions src/object/object_domain.h
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,8 @@ extern "C"
#endif
extern int tp_domain_attach (TP_DOMAIN ** dlist, TP_DOMAIN * domain);

extern TP_DOMAIN_STATUS tp_value_auto_cast_with_precision_check (const DB_VALUE * src, DB_VALUE * dest,
const TP_DOMAIN * desired_domain);
extern TP_DOMAIN_STATUS tp_value_auto_cast (const DB_VALUE * src, DB_VALUE * dest, const TP_DOMAIN * desired_domain);
extern int tp_value_str_auto_cast_to_number (DB_VALUE * src, DB_VALUE * dest, DB_TYPE * val_type);
extern TP_DOMAIN *tp_infer_common_domain (TP_DOMAIN * arg1, TP_DOMAIN * arg2);
Expand Down
3 changes: 2 additions & 1 deletion src/storage/heap_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -11284,7 +11284,8 @@ heap_attrinfo_set (const OID * inst_oid, ATTR_ID attrid, DB_VALUE * attr_val, HE
else
{
/* the domains don't match, must attempt coercion */
dom_status = tp_value_auto_cast (attr_val, &value->dbvalue, value->last_attrepr->domain);
dom_status = tp_value_auto_cast_with_precision_check (attr_val, &value->dbvalue, value->last_attrepr->domain);

if (dom_status != DOMAIN_COMPATIBLE)
{
ret = tp_domain_status_er_set (dom_status, ARG_FILE_LINE, attr_val, value->last_attrepr->domain);
Expand Down