Skip to content

Commit

Permalink
Improvement CORE-3085 - Add clause ALTER DOMAIN <name> [NOT] NULL
Browse files Browse the repository at this point in the history
  • Loading branch information
asfernandes committed Jul 28, 2010
1 parent 6ebf286 commit 36f092f
Show file tree
Hide file tree
Showing 7 changed files with 62 additions and 6 deletions.
6 changes: 6 additions & 0 deletions src/dsql/DdlNodes.epp
Expand Up @@ -4136,6 +4136,12 @@ void AlterDomainNode::execute(thread_db* tdbb, jrd_tra* transaction)
dsqlScratch->getBlrData());
}

if (nullFlag.specified)
{
FLD.RDB$NULL_FLAG.NULL = FALSE;
FLD.RDB$NULL_FLAG = nullFlag.value ? 0 : 1;
}

if (type)
{
type->resolve(dsqlScratch);
Expand Down
1 change: 1 addition & 0 deletions src/dsql/DdlNodes.h
Expand Up @@ -791,6 +791,7 @@ class AlterDomainNode : public DdlNode
dsql_nod* setDefault;
Firebird::MetaName renameTo;
Firebird::AutoPtr<TypeClause> type;
TriStateType<bool> nullFlag; // true = NULL / false = NOT NULL
};


Expand Down
14 changes: 14 additions & 0 deletions src/dsql/Parser.h
Expand Up @@ -166,6 +166,20 @@ class Parser : public Firebird::PermanentStorage
clause = value;
}

template <typename T>
void setClause(TriStateType<T>& clause, const char* duplicateMsg, const T& value)
{
using namespace Firebird;
if (clause.specified)
{
status_exception::raise(
Arg::Gds(isc_sqlerr) << Arg::Num(-637) <<
Arg::Gds(isc_dsql_duplicate_spec) << duplicateMsg);
}

clause = value;
}

void setClause(bool& clause, const char* duplicateMsg)
{
setClause(clause, duplicateMsg, true);
Expand Down
4 changes: 4 additions & 0 deletions src/dsql/parse.y
Expand Up @@ -3124,6 +3124,10 @@ alter_domain_op($alterDomainNode)
{ setClause($alterDomainNode->dropDefault, "DOMAIN DROP DEFAULT"); }
| DROP CONSTRAINT
{ setClause($alterDomainNode->dropConstraint, "DOMAIN DROP CONSTRAINT"); }
| KW_NULL
{ setClause($alterDomainNode->nullFlag, "[NOT] NULL", true); }
| NOT KW_NULL
{ setClause($alterDomainNode->nullFlag, "[NOT] NULL", false); }
| TO symbol_column_name
{ setClause($alterDomainNode->renameTo, "DOMAIN NAME", toName($2)); }
| KW_TYPE init_data_type non_array_type
Expand Down
24 changes: 23 additions & 1 deletion src/jrd/dfw.epp
Expand Up @@ -3341,9 +3341,31 @@ static bool modify_field(thread_db* tdbb, SSHORT phase, DeferredWork* work, jrd_
{
const Firebird::MetaName depName(work->dfw_name);
AutoRequest handle;

// If a domain is being changed to NOT NULL, schedule validation for involved relations.
if (work->findArg(dfw_arg_field_null))
{
FOR(REQUEST_HANDLE handle)
RFL IN RDB$RELATION_FIELDS
WITH RFL.RDB$FIELD_SOURCE EQ depName.c_str()
REDUCED TO RFL.RDB$RELATION_NAME, RFL.RDB$FIELD_ID
{
dsc desc;
desc.makeText(strlen(RFL.RDB$RELATION_NAME), CS_METADATA,
(UCHAR*) RFL.RDB$RELATION_NAME);

DeferredWork* work = DFW_post_work(transaction, dfw_check_not_null, &desc, 0);
SortedArray<int>& ids = DFW_get_ids(work);
ids.add(RFL.RDB$FIELD_ID);
}
END_FOR
}

bid validation;
validation.clear();

handle.reset();

FOR(REQUEST_HANDLE handle)
FLD IN RDB$FIELDS WITH
FLD.RDB$FIELD_NAME EQ depName.c_str()
Expand Down Expand Up @@ -5124,7 +5146,7 @@ static bool make_version(thread_db* tdbb, SSHORT phase, DeferredWork* work, jrd_

DeferredWork* work = DFW_post_work(transaction,
dfw_check_not_null, &desc, 0);
Array<int>& ids = DFW_get_ids(work);
SortedArray<int>& ids = DFW_get_ids(work);
ids.add(RFR.RDB$FIELD_ID);
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/jrd/tra.h
Expand Up @@ -455,7 +455,8 @@ enum dfw_t {
dfw_arg_check_blr, // check if BLR is still compilable
dfw_arg_rel_name, // relation name of a trigger
dfw_arg_trg_type, // trigger type
dfw_arg_new_name // new name
dfw_arg_new_name, // new name
dfw_arg_field_null
};

// Verb actions
Expand Down
16 changes: 12 additions & 4 deletions src/jrd/vio.cpp
Expand Up @@ -2344,7 +2344,7 @@ void VIO_modify(thread_db* tdbb, record_param* org_rpb, record_param* new_rpb, j
EVL_field(0, new_rpb->rpb_record, f_rfr_id, &desc2);

DeferredWork* work = DFW_post_work(transaction, dfw_check_not_null, &desc1, 0);
Array<int>& ids = DFW_get_ids(work);
SortedArray<int>& ids = DFW_get_ids(work);
ids.add(MOV_get_long(&desc2, 0));
}
}
Expand All @@ -2359,23 +2359,31 @@ void VIO_modify(thread_db* tdbb, record_param* org_rpb, record_param* new_rpb, j
MET_change_fields(tdbb, transaction, &desc1);
EVL_field(0, new_rpb->rpb_record, f_fld_name, &desc2);
DeferredWork* dw = MET_change_fields(tdbb, transaction, &desc2);
dsc desc3, desc4;
bool rc1, rc2;

if (dw)
{
// Did we convert computed field into physical, stored field?
// If we did, then force the deletion of the dependencies.
// Warning: getting the result of MET_change_fields is the last relation
// that was affected, but for computed fields, it's an implicit domain
// and hence it can be used only by a single field and therefore one relation.
dsc desc3, desc4;
bool rc1 = EVL_field(0, org_rpb->rpb_record, f_fld_computed, &desc3);
bool rc2 = EVL_field(0, new_rpb->rpb_record, f_fld_computed, &desc4);
rc1 = EVL_field(0, org_rpb->rpb_record, f_fld_computed, &desc3);
rc2 = EVL_field(0, new_rpb->rpb_record, f_fld_computed, &desc4);
if (rc1 != rc2 || rc1 && MOV_compare(&desc3, &desc4)) {
DFW_post_work_arg(transaction, dw, &desc1, 0, dfw_arg_force_computed);
}
}

dw = DFW_post_work(transaction, dfw_modify_field, &desc1, 0);
DFW_post_work_arg(transaction, dw, &desc2, 0, dfw_arg_new_name);

rc1 = EVL_field(NULL, org_rpb->rpb_record, f_fld_null_flag, &desc3);
rc2 = EVL_field(NULL, new_rpb->rpb_record, f_fld_null_flag, &desc4);

if ((!rc1 || MOV_get_long(&desc3, 0) == 0) && rc2 && MOV_get_long(&desc4, 0) != 0)
DFW_post_work_arg(transaction, dw, &desc2, 0, dfw_arg_field_null);
}
break;

Expand Down

0 comments on commit 36f092f

Please sign in to comment.