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);
|
desc->setNullable(true);
|
||||||
|
|
||||||
if (desc->dsc_dtype <= dtype_any_text)
|
if (desc->dsc_dtype <= dtype_any_text)
|
||||||
|
{
|
||||||
desc->dsc_ttype() = dsqlFunction->udf_character_set_id;
|
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
|
else
|
||||||
desc->dsc_ttype() = dsqlFunction->udf_sub_type;
|
desc->dsc_ttype() = dsqlFunction->udf_sub_type;
|
||||||
}
|
}
|
||||||
|
@ -354,7 +354,8 @@ public:
|
|||||||
enum udf_flags_vals {
|
enum udf_flags_vals {
|
||||||
UDF_new_udf = 1, // udf is newly declared, not committed yet
|
UDF_new_udf = 1, // udf is newly declared, not committed yet
|
||||||
UDF_dropped = 2, // udf has been dropped
|
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
|
// Variables - input, output & local
|
||||||
|
@ -63,6 +63,21 @@ using namespace Jrd;
|
|||||||
using namespace Firebird;
|
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)
|
LiteralNode* MAKE_const_slong(SLONG value)
|
||||||
{
|
{
|
||||||
thread_db* tdbb = JRD_get_thread_data();
|
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;
|
desc->dsc_flags = (field->flags & FLD_nullable) ? DSC_nullable : 0;
|
||||||
|
|
||||||
if (desc->isText() || desc->isBlob())
|
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_scale = field->scale;
|
||||||
// node->nodDesc.dsc_sub_type = field->subType;
|
// 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
|
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))
|
if ((field->flags & FLD_nullable) || (context->ctx_flags & CTX_outer_join))
|
||||||
node->nodDesc.dsc_flags |= DSC_nullable;
|
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;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,6 +82,40 @@ namespace
|
|||||||
ERR_post(Arg::Gds(isc_bad_trans_handle));
|
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) {
|
if (!F.RDB$CHARACTER_SET_ID.NULL) {
|
||||||
userFunc->udf_character_set_id = F.RDB$CHARACTER_SET_ID;
|
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
|
else
|
||||||
{
|
{
|
||||||
@ -1258,6 +1307,22 @@ dsql_prc* METD_get_procedure(jrd_tra* transaction, DsqlCompilerScratch* dsqlScra
|
|||||||
parameter->typeOfTable = PR.RDB$RELATION_NAME;
|
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 &&
|
if (type == 0 &&
|
||||||
(!pr_default_value_null ||
|
(!pr_default_value_null ||
|
||||||
(fb_utils::implicit_domain(FLD.RDB$FIELD_NAME) && !FLD.RDB$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_func_ret_fld, // lookup argument's domain
|
||||||
irq_fun_validate, // function blr validate
|
irq_fun_validate, // function blr validate
|
||||||
irq_c_fun_dpd, // get function dependencies
|
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_grant11, // process grant option (functions)
|
||||||
irq_cs_security, // verify security for character set
|
irq_cs_security, // verify security for character set
|
||||||
irq_coll_security, // verify security for collation
|
irq_coll_security, // verify security for collation
|
||||||
|
Loading…
Reference in New Issue
Block a user