mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-23 10:43:03 +01:00
Fixed CORE-4566: Incorrect size of the output parameter/argument when execute block, procedure or function use system field in metadata charset
This commit is contained in:
parent
75955fa3a9
commit
e8930f4408
@ -10576,7 +10576,13 @@ void UdfCallNode::make(DsqlCompilerScratch* /*dsqlScratch*/, dsc* desc)
|
||||
desc->setNullable(true);
|
||||
|
||||
if (desc->dsc_dtype <= dtype_any_text)
|
||||
{
|
||||
desc->dsc_ttype() = dsqlFunction->udf_character_set_id;
|
||||
|
||||
// Fix UNICODE_FSS wrong length used in system tables.
|
||||
if ((dsqlFunction->udf_flags & UDF_sys_based) && (desc->dsc_ttype() == CS_UNICODE_FSS))
|
||||
desc->dsc_length *= 3;
|
||||
}
|
||||
else
|
||||
desc->dsc_ttype() = dsqlFunction->udf_sub_type;
|
||||
}
|
||||
|
@ -354,7 +354,8 @@ public:
|
||||
enum udf_flags_vals {
|
||||
UDF_new_udf = 1, // udf is newly declared, not committed yet
|
||||
UDF_dropped = 2, // udf has been dropped
|
||||
UDF_subfunc = 4 // sub function
|
||||
UDF_subfunc = 4, // sub function
|
||||
UDF_sys_based = 8 // return value based on column from system table
|
||||
};
|
||||
|
||||
// Variables - input, output & local
|
||||
|
@ -63,6 +63,21 @@ using namespace Jrd;
|
||||
using namespace Firebird;
|
||||
|
||||
|
||||
static void adjustLength(dsc* desc)
|
||||
{
|
||||
USHORT adjust = 0;
|
||||
|
||||
if (desc->dsc_dtype == dtype_varying)
|
||||
adjust = sizeof(USHORT);
|
||||
else if (desc->dsc_dtype == dtype_cstring)
|
||||
adjust = 1;
|
||||
|
||||
desc->dsc_length -= adjust;
|
||||
desc->dsc_length *= 3;
|
||||
desc->dsc_length += adjust;
|
||||
}
|
||||
|
||||
|
||||
LiteralNode* MAKE_const_slong(SLONG value)
|
||||
{
|
||||
thread_db* tdbb = JRD_get_thread_data();
|
||||
@ -257,10 +272,12 @@ void MAKE_desc_from_field(dsc* desc, const dsql_fld* field)
|
||||
desc->dsc_flags = (field->flags & FLD_nullable) ? DSC_nullable : 0;
|
||||
|
||||
if (desc->isText() || desc->isBlob())
|
||||
{
|
||||
desc->setTextType(INTL_CS_COLL_TO_TTYPE(
|
||||
field->charSetId, field->collationId));
|
||||
}
|
||||
desc->setTextType(INTL_CS_COLL_TO_TTYPE(field->charSetId, field->collationId));
|
||||
|
||||
// UNICODE_FSS_HACK
|
||||
// check if the field is a system domain and CHARACTER SET is UNICODE_FSS
|
||||
if (desc->isText() && (INTL_GET_CHARSET(desc) == CS_UNICODE_FSS) && (field->flags & FLD_system))
|
||||
adjustLength(desc);
|
||||
}
|
||||
|
||||
|
||||
@ -327,6 +344,14 @@ FieldNode* MAKE_field(dsql_ctx* context, dsql_fld* field, ValueListNode* indices
|
||||
|
||||
// node->nodDesc.dsc_scale = field->scale;
|
||||
// node->nodDesc.dsc_sub_type = field->subType;
|
||||
|
||||
// UNICODE_FSS_HACK
|
||||
// check if the field is a system domain and the type is CHAR/VARCHAR CHARACTER SET UNICODE_FSS
|
||||
if ((field->flags & FLD_system) && node->nodDesc.dsc_dtype <= dtype_varying &&
|
||||
INTL_GET_CHARSET(&node->nodDesc) == CS_METADATA)
|
||||
{
|
||||
adjustLength(&node->nodDesc);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -350,23 +375,6 @@ FieldNode* MAKE_field(dsql_ctx* context, dsql_fld* field, ValueListNode* indices
|
||||
if ((field->flags & FLD_nullable) || (context->ctx_flags & CTX_outer_join))
|
||||
node->nodDesc.dsc_flags |= DSC_nullable;
|
||||
|
||||
// UNICODE_FSS_HACK
|
||||
// check if the field is a system domain and the type is CHAR/VARCHAR CHARACTER SET UNICODE_FSS
|
||||
if ((field->flags & FLD_system) && node->nodDesc.dsc_dtype <= dtype_varying &&
|
||||
INTL_GET_CHARSET(&node->nodDesc) == CS_METADATA)
|
||||
{
|
||||
USHORT adjust = 0;
|
||||
|
||||
if (node->nodDesc.dsc_dtype == dtype_varying)
|
||||
adjust = sizeof(USHORT);
|
||||
else if (node->nodDesc.dsc_dtype == dtype_cstring)
|
||||
adjust = 1;
|
||||
|
||||
node->nodDesc.dsc_length -= adjust;
|
||||
node->nodDesc.dsc_length *= 3;
|
||||
node->nodDesc.dsc_length += adjust;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
|
@ -82,6 +82,40 @@ namespace
|
||||
ERR_post(Arg::Gds(isc_bad_trans_handle));
|
||||
}
|
||||
}
|
||||
|
||||
bool isSystemRelation(thread_db* tdbb, jrd_tra* transaction, const char* relName)
|
||||
{
|
||||
bool rc = false;
|
||||
|
||||
AutoCacheRequest handle(tdbb, irq_system_relation, IRQ_REQUESTS);
|
||||
FOR(REQUEST_HANDLE handle TRANSACTION_HANDLE transaction)
|
||||
R IN RDB$RELATIONS WITH
|
||||
R.RDB$RELATION_NAME EQ relName AND
|
||||
R.RDB$SYSTEM_FLAG EQUIV 1
|
||||
{
|
||||
rc = true;
|
||||
}
|
||||
END_FOR
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
bool isSystemDomain(thread_db* tdbb, jrd_tra* transaction, const char* fldName)
|
||||
{
|
||||
bool rc = false;
|
||||
|
||||
AutoCacheRequest handle(tdbb, irq_system_domain, IRQ_REQUESTS);
|
||||
FOR(REQUEST_HANDLE handle TRANSACTION_HANDLE transaction)
|
||||
R IN RDB$FIELDS WITH
|
||||
R.RDB$FIELD_NAME EQ fldName AND
|
||||
R.RDB$SYSTEM_FLAG EQUIV 1
|
||||
{
|
||||
rc = true;
|
||||
}
|
||||
END_FOR
|
||||
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -884,6 +918,21 @@ dsql_udf* METD_get_function(jrd_tra* transaction, DsqlCompilerScratch* dsqlScrat
|
||||
if (!F.RDB$CHARACTER_SET_ID.NULL) {
|
||||
userFunc->udf_character_set_id = F.RDB$CHARACTER_SET_ID;
|
||||
}
|
||||
|
||||
if ((!X.RDB$ARGUMENT_MECHANISM.NULL) && X.RDB$ARGUMENT_MECHANISM == prm_mech_type_of &&
|
||||
(!X.RDB$FIELD_NAME.NULL) && X.RDB$FIELD_NAME[0] &&
|
||||
(!X.RDB$RELATION_NAME.NULL) && X.RDB$RELATION_NAME[0])
|
||||
{
|
||||
// type of column used in declaration
|
||||
if (isSystemRelation(tdbb, transaction, X.RDB$RELATION_NAME))
|
||||
userFunc->udf_flags |= UDF_sys_based;
|
||||
}
|
||||
else if ((!X.RDB$FIELD_SOURCE.NULL) && X.RDB$FIELD_SOURCE[0])
|
||||
{
|
||||
// domain used in declaration
|
||||
if (isSystemDomain(tdbb, transaction, X.RDB$FIELD_SOURCE))
|
||||
userFunc->udf_flags |= UDF_sys_based;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1258,6 +1307,22 @@ dsql_prc* METD_get_procedure(jrd_tra* transaction, DsqlCompilerScratch* dsqlScra
|
||||
parameter->typeOfTable = PR.RDB$RELATION_NAME;
|
||||
}
|
||||
|
||||
if (parameter->typeOfTable.hasData())
|
||||
{
|
||||
if (isSystemRelation(tdbb, transaction, parameter->typeOfTable.c_str()))
|
||||
parameter->flags |= FLD_system;
|
||||
}
|
||||
else if (parameter->typeOfName.hasData())
|
||||
{
|
||||
if (isSystemDomain(tdbb, transaction, parameter->typeOfName.c_str()))
|
||||
parameter->flags |= FLD_system;
|
||||
}
|
||||
else if (parameter->fieldSource.hasData())
|
||||
{
|
||||
if (isSystemDomain(tdbb, transaction, parameter->fieldSource.c_str()))
|
||||
parameter->flags |= FLD_system;
|
||||
}
|
||||
|
||||
if (type == 0 &&
|
||||
(!pr_default_value_null ||
|
||||
(fb_utils::implicit_domain(FLD.RDB$FIELD_NAME) && !FLD.RDB$DEFAULT_VALUE.NULL)))
|
||||
|
@ -156,6 +156,8 @@ enum irq_type_t
|
||||
irq_func_ret_fld, // lookup argument's domain
|
||||
irq_fun_validate, // function blr validate
|
||||
irq_c_fun_dpd, // get function dependencies
|
||||
irq_system_relation, // check is relation system or not
|
||||
irq_system_domain, // check is field system or not
|
||||
irq_grant11, // process grant option (functions)
|
||||
irq_cs_security, // verify security for character set
|
||||
irq_coll_security, // verify security for collation
|
||||
|
Loading…
Reference in New Issue
Block a user