8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-22 22:03:03 +01:00

Fixed CORE-6358 - Adding NOT NULL column with DEFAULT value may cause default values to update when selecting or have the wrong charset.

This commit is contained in:
Adriano dos Santos Fernandes 2020-07-07 14:44:05 -03:00
parent 9bab7423f8
commit 2e146d8dcf

View File

@ -5897,55 +5897,6 @@ static bool make_version(thread_db* tdbb, SSHORT phase, DeferredWork* work, jrd_
tfb->tfb_next = stack;
stack = tfb;
memset(&tfb->tfb_default, 0, sizeof(tfb->tfb_default));
if (notNull && !defaultValue->isEmpty())
{
Jrd::ContextPoolHolder context(tdbb, attachment->createPool());
JrdStatement* defaultStatement = NULL;
try
{
ValueExprNode* defaultNode = static_cast<ValueExprNode*>(MET_parse_blob(
tdbb, relation, defaultValue, NULL, &defaultStatement, false, false));
jrd_req* const defaultRequest = defaultStatement->findRequest(tdbb);
// Attention: this is scoped to the end of this "try".
AutoSetRestore2<jrd_req*, thread_db> autoRequest(tdbb,
&thread_db::getRequest, &thread_db::setRequest, defaultRequest);
TimeZoneUtil::validateGmtTimeStamp(defaultRequest->req_gmt_timestamp);
TRA_attach_request(transaction, defaultRequest);
dsc* result = EVL_expr(tdbb, defaultRequest, defaultNode);
TRA_detach_request(defaultRequest);
if (result)
{
dsc desc = *result;
MoveBuffer buffer;
if (desc.isText() || desc.isBlob())
{
UCHAR* ptr = NULL;
const int len = MOV_make_string2(tdbb, &desc, CS_NONE, &ptr, buffer, true);
fb_assert(ULONG(len) < ULONG(MAX_USHORT));
desc.makeText(len, ttype_none, ptr);
}
EVL_make_value(tdbb, &desc, &tfb->tfb_default, relation->rel_pool);
}
}
catch (const Exception&)
{
if (defaultStatement)
defaultStatement->release(tdbb);
throw;
}
defaultStatement->release(tdbb);
}
// for text data types, grab the CHARACTER_SET and
// COLLATION to give the type of international text
@ -5985,6 +5936,74 @@ static bool make_version(thread_db* tdbb, SSHORT phase, DeferredWork* work, jrd_
ERR_punt(); // if INTL_texttype_lookup hasn't punt
}
// Store the default value.
memset(&tfb->tfb_default, 0, sizeof(tfb->tfb_default));
if (notNull && !defaultValue->isEmpty())
{
Jrd::ContextPoolHolder context(tdbb, attachment->createPool());
JrdStatement* defaultStatement = NULL;
try
{
ValueExprNode* defaultNode = static_cast<ValueExprNode*>(MET_parse_blob(
tdbb, relation, defaultValue, NULL, &defaultStatement, false, false));
jrd_req* const defaultRequest = defaultStatement->findRequest(tdbb);
// Attention: this is scoped to the end of this "try".
AutoSetRestore2<jrd_req*, thread_db> autoRequest(tdbb,
&thread_db::getRequest, &thread_db::setRequest, defaultRequest);
TimeZoneUtil::validateGmtTimeStamp(defaultRequest->req_gmt_timestamp);
TRA_attach_request(transaction, defaultRequest);
dsc* result = EVL_expr(tdbb, defaultRequest, defaultNode);
TRA_detach_request(defaultRequest);
if (result)
{
dsc desc = *result;
MoveBuffer buffer;
if (desc.isText() || desc.isBlob())
{
UCHAR* ptr = NULL;
const int len = MOV_make_string2(tdbb, &desc, tfb->tfb_desc.getCharSet(),
&ptr, buffer, true);
fb_assert(ULONG(len) < ULONG(MAX_USHORT));
desc.makeText(len, tfb->tfb_desc.getCharSet(), ptr);
}
if (!tfb->tfb_desc.isBlob() && !DSC_EQUIV(result, &tfb->tfb_desc, false))
{
impure_value tempValue;
tempValue.vlu_desc = tfb->tfb_desc;
MoveBuffer buffer2;
if (tfb->tfb_desc.isText())
tempValue.vlu_desc.dsc_address = buffer2.getBuffer(tfb->tfb_desc.dsc_length);
else
tempValue.vlu_desc.dsc_address = (UCHAR*) &tempValue.vlu_misc;
MOV_move(tdbb, &desc, &tempValue.vlu_desc);
EVL_make_value(tdbb, &tempValue.vlu_desc, &tfb->tfb_default, relation->rel_pool);
}
else
EVL_make_value(tdbb, &desc, &tfb->tfb_default, relation->rel_pool);
}
}
catch (const Exception&)
{
if (defaultStatement)
defaultStatement->release(tdbb);
throw;
}
defaultStatement->release(tdbb);
}
// dimitr: view fields shouldn't be marked as computed
if (null_view && !FLD.RDB$COMPUTED_BLR.isEmpty())
tfb->tfb_flags |= TFB_computed;