blob: 161c2c78a8c449529eb5114b06337545a142b92c [file] [log] [blame]
/* -*-C++-*-
// @@@ START COPYRIGHT @@@
//
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// @@@ END COPYRIGHT @@@
*****************************************************************************
*
* File: ElemDDLConstraint.C
* Description: methods for classes representing constraints.
*
* Created: 9/21/95
* Language: C++
*
*
*
*
*****************************************************************************
*/
#include "AllElemDDLConstraint.h"
#include "AllElemDDLConstraintAttr.h"
#include "BaseTypes.h"
#include "ComASSERT.h"
#include "ComDiags.h"
#include "ComOperators.h"
#include "ElemDDLColName.h"
#include "ElemDDLRefTrigActions.h"
#include "ElemDDLReferences.h"
#include "ItemExpr.h"
#include "NADefaults.h"
#include "SchemaDB.h"
// -----------------------------------------------------------------------
// methods for class ElemDDLConstraint
// -----------------------------------------------------------------------
// virtual destructor
ElemDDLConstraint::~ElemDDLConstraint()
{
// delete all children
for (Int32 index = 0; index < getArity(); index++)
{
delete getChild(index);
}
}
// cast
ElemDDLConstraint *
ElemDDLConstraint::castToElemDDLConstraint()
{
return this;
}
//
// accessors
//
Int32
ElemDDLConstraint::getArity() const
{
return MAX_ELEM_DDL_CONSTRAINT_ARITY;
}
ExprNode *
ElemDDLConstraint::getChild(Lng32 index)
{
ComASSERT(index EQU INDEX_CONSTRAINT_ATTRIBUTES);
return pConstraintAttributes_;
}
//
// mutators
//
void
ElemDDLConstraint::setChild(Lng32 index, ExprNode * pChildNode)
{
ComASSERT(index EQU INDEX_CONSTRAINT_ATTRIBUTES);
if (NOT pChildNode)
{
pConstraintAttributes_ = NULL;
}
else
{
ComASSERT(pChildNode->castToElemDDLNode());
pConstraintAttributes_ = pChildNode->castToElemDDLNode();
}
}
void
ElemDDLConstraint::setConstraintAttributes(
ElemDDLNode * pConstraintAttributes)
{
setChild(INDEX_CONSTRAINT_ATTRIBUTES, pConstraintAttributes);
NABoolean hasDroppableConstrSpecified = FALSE;
if (pConstraintAttributes)
{
CollIndex num = pConstraintAttributes->entries();
for (CollIndex index = 0; ((index < num) && NOT hasDroppableConstrSpecified); index++)
{
ElemDDLNode *pCnstrntAttr = (*pConstraintAttributes)[index];
if (pCnstrntAttr->castToElemDDLConstraintAttrDroppable())
hasDroppableConstrSpecified = TRUE;
}
}
if (NOT hasDroppableConstrSpecified ) // no constraint attributes specified
{
//
// Currently, there are only two kinds of constraint attributes
// available:
// droppable (or not droppable), and only not null
// and primary key constraints can have the not-droppable
// attribute.
// enforced ( or not enforced), and only RI constraints
// can have the not enforced attribute
//
// [not] droppable attribute was not specified, use the
// default settings.
//
// Note that the primary key constraint created by the ALTER
// TABLE <table-name> ADD CONSTRAINT statement specified by
// the user will always have the DROPPABLE attribute, but
// there is not enough information available at this point
// so we still use the default settings if the user does not
// specify the [ not ] droppable attribute. This information
// will be overwritten later when we process the root node
// of the ALTER TABLE <table-name> ADD CONSTRAINT statement.
//
if (isConstraintNotNull())
{
setDroppableFlag(
CmpCommon::getDefault(NOT_NULL_CONSTRAINT_DROPPABLE_OPTION)
== DF_ON);
}
else if (castToElemDDLConstraintPK())
{
setDroppableFlag(
CmpCommon::getDefault(PRIMARY_KEY_CONSTRAINT_DROPPABLE_OPTION)
== DF_ON);
}
else
{
// Does nothing. isDroppable_ was already set to TRUE.
}
if (NOT pConstraintAttributes)
return;
}
CollIndex entries = pConstraintAttributes->entries();
NABoolean droppableClauseSpec = FALSE;
NABoolean enforcedClauseSpec = FALSE;
for (CollIndex index = 0; index < entries; index++)
{
//
// Currently, there is only twos kind of constraint attributes
// available: (a) droppable (or not droppable), and only not null
// and primary key constraints can have the not-droppable
// attribute.
//(b) enforced (or not enforced), and only RI constraints can have
// the not enforced attribute
ElemDDLNode *pCnstrntAttr = (*pConstraintAttributes)[index];
if (pCnstrntAttr->castToElemDDLConstraintAttrDroppable())
{
//
// The user specified the [ NOT ] DROPPABLE clause explicitly.
//
if (droppableClauseSpec)
{
// Duplicate [ NOT ] DROPPABLE clauses.
*SqlParser_Diags << DgSqlCode(-3167);
return;
}
droppableClauseSpec = TRUE;
if (NOT isConstraintNotNull() AND
NOT castToElemDDLConstraintPK() AND
NOT pCnstrntAttr->
castToElemDDLConstraintAttrDroppable()->isDroppable())
{
// NOT DROPPABLE clause can only appear in NOT NULL and PRIMARY KEY
// constraint definitions.
*SqlParser_Diags << DgSqlCode(-3054);
return;
}
setDroppableFlag(pCnstrntAttr->
castToElemDDLConstraintAttrDroppable()->isDroppable());
if (isDroppable()) // DROPPABLE clause specified explicitly
{
droppableClauseInfo_ = DROPPABLE_SPECIFIED_EXPLICITLY;
}
else
{
droppableClauseInfo_ = NOT_DROPPABLE_SPECIFIED_EXPLICITLY;
}
}
else if (pCnstrntAttr->castToElemDDLConstraintAttrEnforced())
{
//
// The user specified the [ NOT ] ENFORCED clause explicitly.
//
if (enforcedClauseSpec)
{
// Duplicate [ NOT ] ENFORCED clauses.
*SqlParser_Diags << DgSqlCode(-3243);
return;
}
enforcedClauseSpec = TRUE;
if (NOT castToElemDDLConstraintRI() AND
NOT pCnstrntAttr->
castToElemDDLConstraintAttrEnforced()->isEnforced())
{
// NOT ENFORCED clause can only appear in RI constraints
// constraint definitions.
*SqlParser_Diags << DgSqlCode(-3244);
return;
}
setEnforcedFlag(pCnstrntAttr->
castToElemDDLConstraintAttrEnforced()->isEnforced());
}
else
{
ABORT("internal logic error");
}
} // for
} // ElemDDLConstraint::setConstraintAttributes()
void
ElemDDLConstraint::setDroppableFlag(const NABoolean setting)
{
isDroppable_ = setting;
}
void
ElemDDLConstraint::setEnforcedFlag(const NABoolean setting)
{
isEnforced_ = setting;
}
//
// methods for tracing
//
const NAString
ElemDDLConstraint::displayLabel1() const
{
if (getConstraintName().length() NEQ 0)
return NAString("Constraint name: ") + getConstraintName();
else
return NAString("Constraint name not specified.");
}
NATraceList
ElemDDLConstraint::getDetailInfo() const
{
NAString detailText;
NATraceList detailTextList;
detailTextList.append(displayLabel1()); // constraint name
detailTextList.append(displayLabel2()); // constraint type (e.g., Not Null)
detailText = "Constraint kind: ";
if (getConstraintKind() EQU ElemDDLConstraint::COLUMN_CONSTRAINT_DEF)
{
detailText += "Column";
}
else
{
detailText += "Table";
}
detailTextList.append(detailText);
detailText = "is deferrable? ";
detailText += YesNo(isDeferrable());
detailTextList.append(detailText);
detailText = "is droppable? ";
detailText += YesNo(isDroppable());
detailTextList.append(detailText);
detailText = "is enforced? ";
detailText += YesNo(isEnforced());
detailTextList.append(detailText);
return detailTextList;
} // ElemDDLConstraint::getDetailInfo()
const NAString
ElemDDLConstraint::getText() const
{
return "ElemDDLConstraint";
}
// -----------------------------------------------------------------------
// methods for class ElemDDLConstraintArray
// -----------------------------------------------------------------------
// virtual destructor
ElemDDLConstraintArray::~ElemDDLConstraintArray()
{}
// -----------------------------------------------------------------------
// methods for class ElemDDLConstraintCheck
// -----------------------------------------------------------------------
// initialize constructor
ElemDDLConstraintCheck::ElemDDLConstraintCheck(ItemExpr *pSearchCondition,
const ParNameLocList &nameLocs,
CollHeap *heap)
: ElemDDLConstraint(heap, ELM_CONSTRAINT_CHECK_ELEM),
searchCondition_(pSearchCondition),
nameLocList_(nameLocs, heap),
startPos_(nameLocs.getTextStartPosition()),
endPos_(0) // to be set later
{
}
// virtual destructor
ElemDDLConstraintCheck::~ElemDDLConstraintCheck()
{
}
// cast
ElemDDLConstraintCheck *
ElemDDLConstraintCheck::castToElemDDLConstraintCheck()
{
return this;
}
// This method should be: ####
// ElemDDLConstraintNotNull *
// ElemDDLConstraintCheck::castToElemDDLConstraintNotNull()
// and
// class ElemDDLConstraintNotNull shd be derived from ElemDDLConstraintCheck
//
NABoolean
ElemDDLConstraintCheck::isConstraintNotNull() const
{
return getSearchCondition()->isISNOTNULL();
}
NABoolean
ElemDDLConstraintCheck::getColumnsNotNull(ItemExprList &il)
{
return getSearchCondition()->getColumnsIfThisIsISNOTNULL(il);
}
//
// accessors
//
Int32
ElemDDLConstraintCheck::getArity() const
{
return MAX_ELEM_DDL_CONSTRAINT_CHECK_ARITY;
}
ExprNode *
ElemDDLConstraintCheck::getChild(Lng32 index)
{
ComASSERT(index >= 0 AND index < getArity());
if (index < ElemDDLConstraint::getArity())
{
return ElemDDLConstraint::getChild(index);
}
else
{
ComASSERT(index EQU INDEX_SEARCH_CONDITION);
return searchCondition_;
}
}
//
// mutator
//
void
ElemDDLConstraintCheck::setChild(Lng32 index, ExprNode * pChildNode)
{
ComASSERT(index >= 0 AND index < getArity());
if (index < ElemDDLConstraint::getArity())
{
ElemDDLConstraint::setChild(index, pChildNode);
}
else
{
ComASSERT(index EQU INDEX_SEARCH_CONDITION);
if (NOT pChildNode)
{
searchCondition_ = NULL;
}
else
{
ComASSERT(pChildNode->castToItemExpr());
searchCondition_ = pChildNode->castToItemExpr();
}
}
}
//
// methods for tracing
//
const NAString
ElemDDLConstraintCheck::displayLabel2() const
{
return "Constraint type: Check constraint";
}
const NAString
ElemDDLConstraintCheck::getText() const
{
return "ElemDDLConstraintCheck";
}
// -----------------------------------------------------------------------
// methods for class ElemDDLConstraintName
// -----------------------------------------------------------------------
// virtual destructor
ElemDDLConstraintName::~ElemDDLConstraintName()
{
}
// cast virtual function
ElemDDLConstraintName *
ElemDDLConstraintName::castToElemDDLConstraintName()
{
return this;
}
//
// methods for tracing
//
const NAString
ElemDDLConstraintName::getText() const
{
return "ElemDDLConstraintName";
}
const NAString
ElemDDLConstraintName::displayLabel1() const
{
return NAString("Constraint name: ") + getConstraintName();
}
// -----------------------------------------------------------------------
// methods for class ElemDDLConstraintNotNull
// -----------------------------------------------------------------------
// virtual destructor
ElemDDLConstraintNotNull::~ElemDDLConstraintNotNull()
{
}
// cast
ElemDDLConstraintNotNull *
ElemDDLConstraintNotNull::castToElemDDLConstraintNotNull()
{
return this;
}
// methods for tracing
const NAString
ElemDDLConstraintNotNull::displayLabel2() const
{
return "Constraint type: Not Null constraint";
}
const NAString
ElemDDLConstraintNotNull::getText() const
{
return "ElemDDLConstraintNotNull";
}
// -----------------------------------------------------------------------
// methods for class ElemDDLConstraintPK
// -----------------------------------------------------------------------
// virtual destructor
ElemDDLConstraintPK::~ElemDDLConstraintPK()
{
}
// cast
ElemDDLConstraintPK *
ElemDDLConstraintPK::castToElemDDLConstraintPK()
{
return this;
}
//
// methods for tracing
//
const NAString
ElemDDLConstraintPK::displayLabel2() const
{
return "Constraint type: Primary Key constraint";
}
const NAString
ElemDDLConstraintPK::getText() const
{
return "ElemDDLConstraintPK";
}
// -----------------------------------------------------------------------
// methods for class ElemDDLConstraintPKColumn
// -----------------------------------------------------------------------
// virtual destructor
ElemDDLConstraintPKColumn::~ElemDDLConstraintPKColumn()
{
}
// cast
ElemDDLConstraintPKColumn *
ElemDDLConstraintPKColumn::castToElemDDLConstraintPKColumn()
{
return this;
}
// methods for tracing
const NAString
ElemDDLConstraintPKColumn::getText() const
{
return "ElemDDLConstraintPKColumn";
}
// -----------------------------------------------------------------------
// methods for class ElemDDLConstraintRI
// -----------------------------------------------------------------------
// constructor
ElemDDLConstraintRI::ElemDDLConstraintRI(
ElemDDLNode * pReferencedTableAndColumns,
ComRCMatchOption matchType,
ElemDDLNode * pReferentialTriggeredActions,
CollHeap * heap)
: ElemDDLConstraint(heap, ELM_CONSTRAINT_REFERENTIAL_INTEGRITY_ELEM),
matchType_(matchType),
isDeleteRuleSpec_(FALSE),
deleteRule_(COM_NO_ACTION_DELETE_RULE),
isUpdateRuleSpec_(FALSE),
updateRule_(COM_NO_ACTION_UPDATE_RULE),
referencingColumnNameArray_(heap),
referencedColumnNameArray_(heap)
{
setChild(INDEX_REFERENCING_COLUMN_NAME_LIST, NULL);
setChild(INDEX_REFERENCED_TABLE_AND_COLUMNS, pReferencedTableAndColumns);
setChild(INDEX_REFERENTIAL_TRIGGERED_ACTIONS, pReferentialTriggeredActions);
//
// Note that at the point this parse node is contructed, the information
// regarding the referencing column name list (in the FOREIGN KEY phrase)
// has not been collected yet.
//
//
// referenced table name
//
ComASSERT(pReferencedTableAndColumns);
ElemDDLReferences * pReferences = pReferencedTableAndColumns
->castToElemDDLReferences();
ComASSERT(pReferences);
//
// referenced column name list (if any)
//
ElemDDLNode * pReferencedColumns = pReferences->getReferencedColumns();
if (pReferencedColumns)
{
for (CollIndex index = 0; index < pReferencedColumns->entries(); index++)
{
referencedColumnNameArray_.insert((*pReferencedColumns)[index]
->castToElemDDLColName());
}
}
//
// referential triggered actions
//
if (pReferentialTriggeredActions)
{
for (CollIndex i = 0; i < pReferentialTriggeredActions->entries(); i++)
{
ComASSERT((*pReferentialTriggeredActions)[i]);
setReferentialTriggeredAction((*pReferentialTriggeredActions)[i]
->castToElemDDLRefTrigAct());
}
}
} // ElemDDLConstraintRI::ElemDDLConstraintRI()
// virtual destructor
ElemDDLConstraintRI::~ElemDDLConstraintRI()
{
//
// delete all child parse nodes added to this class
//
// Note that class ElemDDLConstraintRI is derived from class
// ElemDDLConstraint. ~ElemDDLConstraint() deletes all child parse
// nodes belong to class ElemDDLConstraint. So the destructor
// ~ElemDDLConstraintRI() only needs to delete the additional child
// parse nodes that only belong to class ElemDDLConstraintRI.
//
for (Int32 index = ElemDDLConstraint::getArity(); index < getArity(); index++)
{
delete getChild(index);
}
}
// cast
ElemDDLConstraintRI *
ElemDDLConstraintRI::castToElemDDLConstraintRI()
{
return this;
}
//
// accessors
//
Int32
ElemDDLConstraintRI::getArity() const
{
return MAX_ELEM_DDL_CONSTRAINT_RI_ARITY;
}
ExprNode *
ElemDDLConstraintRI::getChild(Lng32 index)
{
ComASSERT(index >= 0 AND index < getArity());
if (index < ElemDDLConstraint::getArity())
{
return ElemDDLConstraint::getChild(index);
}
else
{
return children_[index];
}
}
NAString
ElemDDLConstraintRI::getMatchTypeAsNAString() const
{
switch (getMatchType())
{
case COM_NONE_MATCH_OPTION :
return NAString("Match phrase not specified");
case COM_FULL_MATCH_OPTION :
return NAString("MATCH FULL");
case COM_PARTIAL_MATCH_OPTION :
return NAString("MATCH PARTIAL");
default :
ABORT("internal logic error");
return NAString();
}
}
NAString
ElemDDLConstraintRI::getReferencedTableName() const
{
return getReferencesNode()->
getReferencedNameAsQualifiedName().getQualifiedNameAsAnsiString();
}
ElemDDLReferences *
ElemDDLConstraintRI::getReferencesNode() const
{
return ((ElemDDLReferences *)this)->
getChild(INDEX_REFERENCED_TABLE_AND_COLUMNS)->
castToElemDDLNode()->castToElemDDLReferences();
}
//
// mutators
//
void
ElemDDLConstraintRI::setChild(Lng32 index, ExprNode * pChildNode)
{
ComASSERT(index >= 0 AND index < getArity());
if (index < ElemDDLConstraint::getArity())
{
ElemDDLConstraint::setChild(index, pChildNode);
}
else
{
if (NOT pChildNode)
{
children_[index] = NULL;
}
else
{
ComASSERT(pChildNode->castToElemDDLNode());
children_[index] = pChildNode->castToElemDDLNode();
}
}
}
void
ElemDDLConstraintRI::setReferencingColumnNameList(
ElemDDLNode * pReferencingColumnNameList)
{
setChild(INDEX_REFERENCING_COLUMN_NAME_LIST,
pReferencingColumnNameList);
//
// copies the information to referencingColumnNameArray_
// so the user can access the information easier. This
// method should not be called more than once.
//
if (pReferencingColumnNameList)
{
for (CollIndex i = 0; i < pReferencingColumnNameList->entries(); i++)
{
ComASSERT((*pReferencingColumnNameList)[i] AND
(*pReferencingColumnNameList)[i]
->castToElemDDLColName());
referencingColumnNameArray_.insert((*pReferencingColumnNameList)[i]
->castToElemDDLColName());
}
}
} // ElemDDLConstraintRI::setReferencingColumnNameList()
void
ElemDDLConstraintRI::setReferentialTriggeredAction(
ElemDDLRefTrigAct * pRefTrigAct)
{
ComASSERT(pRefTrigAct);
if (pRefTrigAct->castToElemDDLRefTrigActDeleteRule())
{
if (isDeleteRuleSpec_)
{
// Duplicate DELETE rules specified.
*SqlParser_Diags << DgSqlCode(-3055);
}
isDeleteRuleSpec_ = TRUE;
deleteRule_ = pRefTrigAct->castToElemDDLRefTrigActDeleteRule()
->getDeleteRule();
}
else if (pRefTrigAct->castToElemDDLRefTrigActUpdateRule())
{
if (isUpdateRuleSpec_)
{
// Duplicate UPDATE rules specified.
*SqlParser_Diags << DgSqlCode(-3056);
}
isUpdateRuleSpec_ = TRUE;
updateRule_ = pRefTrigAct->castToElemDDLRefTrigActUpdateRule()
->getUpdateRule();
}
else
{
ABORT("internal logic error");
}
}
//
// methods for tracing
//
const NAString
ElemDDLConstraintRI::displayLabel2() const
{
return "Constraint type: Referential Integrity constraint";
}
NATraceList
ElemDDLConstraintRI::getDetailInfo() const
{
//
// constraint name and related information
//
NAString detailText;
NATraceList detailTextList = ElemDDLConstraint::getDetailInfo();
//
// match type
//
if (getMatchType() EQU COM_NONE_MATCH_OPTION)
{
detailTextList.append("Match type not specified.");
}
else
{
detailText = "Match type: ";
detailText += getMatchTypeAsNAString();
detailTextList.append(detailText);
}
//
// delete rule
//
switch (getDeleteRule())
{
case COM_UNKNOWN_DELETE_RULE :
if (isDeleteRuleSpecified())
{
ABORT("internal logic error");
}
detailTextList.append("Delete Rule not specified.");
break;
case COM_CASCADE_DELETE_RULE :
detailTextList.append("Delete rule: Cascade");
break;
case COM_NO_ACTION_DELETE_RULE :
detailTextList.append("Delete rule: No Action");
break;
case COM_SET_DEFAULT_DELETE_RULE :
detailTextList.append("Delete rule: Set Default");
break;
case COM_SET_NULL_DELETE_RULE :
detailTextList.append("Delete rule: Set Null");
break;
default :
ABORT("internal logic error");
break;
}
//
// update rule
//
switch (getUpdateRule())
{
case COM_UNKNOWN_UPDATE_RULE :
if (isUpdateRuleSpecified())
{
ABORT("internal logic error");
}
detailTextList.append("Update Rule not specified.");
break;
case COM_CASCADE_UPDATE_RULE :
detailTextList.append("Update rule: Cascade");
break;
case COM_NO_ACTION_UPDATE_RULE :
detailTextList.append("Update rule: No Action");
break;
case COM_SET_DEFAULT_UPDATE_RULE :
detailTextList.append("Update rule: Set Default");
break;
case COM_SET_NULL_UPDATE_RULE :
detailTextList.append("Update rule: Set Null");
break;
default :
ABORT("internal logic error");
break;
}
//
// referencing information
//
CollIndex nbrRefCols;
const ElemDDLColNameArray & cols = getReferencingColumns();
nbrRefCols = cols.entries();
if (nbrRefCols EQU 0)
{
detailTextList.append("Referencing column list is empty.");
}
else
{
detailText = "Referencing column list [";
detailText += LongToNAString((Lng32)nbrRefCols);
detailText += " element(s)]:";
detailTextList.append(detailText);
for (CollIndex i = 0; i < nbrRefCols; i++)
{
detailText = "[referencing column ";
detailText += LongToNAString((Lng32)i);
detailText += "]";
detailTextList.append(detailText);
detailTextList.append(" ", cols[i]->getDetailInfo());
}
}
//
// referenced information
//
ElemDDLReferences * pRefd = children_[INDEX_REFERENCED_TABLE_AND_COLUMNS]
->castToElemDDLReferences();
detailTextList.append(pRefd->getDetailInfo());
return detailTextList;
}
const NAString
ElemDDLConstraintRI::getText() const
{
return "ElemDDLConstraintRI";
}
// -----------------------------------------------------------------------
// methods for class ElemDDLConstraintUnique
// -----------------------------------------------------------------------
//
// constructors
//
ElemDDLConstraintUnique::ElemDDLConstraintUnique(ElemDDLNode * pColRefList,
CollHeap * heap)
: ElemDDLConstraint(heap, ELM_CONSTRAINT_UNIQUE_ELEM),
columnRefList_(pColRefList),
keyColumnArray_(heap)
{
}
ElemDDLConstraintUnique::ElemDDLConstraintUnique(OperatorTypeEnum operType,
ElemDDLNode * pColRefList,
CollHeap * heap)
: ElemDDLConstraint(heap, operType),
columnRefList_(pColRefList),
keyColumnArray_(heap)
{
}
//
// virtual destructor
//
ElemDDLConstraintUnique::~ElemDDLConstraintUnique()
{
//
// delete all child parse nodes added to this class
//
// Note that class ElemDDLConstraintUnique is derived from class
// ElemDDLConstraint. ~ElemDDLConstraint() deletes all child parse
// nodes belong to class ElemDDLConstraint. So the destructor
// ~ElemDDLConstraintUnique() only needs to delete the additional
// child parse nodes that only belong to class ElemDDLConstraintUnique.
//
for (Int32 index = ElemDDLConstraint::getArity(); index < getArity(); index++)
{
delete getChild(index);
}
}
// cast
ElemDDLConstraintUnique *
ElemDDLConstraintUnique::castToElemDDLConstraintUnique()
{
return this;
}
//
// accessors
//
Int32
ElemDDLConstraintUnique::getArity() const
{
return MAX_ELEM_DDL_CONSTRAINT_UNIQUE_ARITY;
}
ExprNode *
ElemDDLConstraintUnique::getChild(Lng32 index)
{
ComASSERT(index >= 0 AND index < getArity());
if (index < ElemDDLConstraint::getArity())
{
return ElemDDLConstraint::getChild(index);
}
else
{
ComASSERT(index EQU INDEX_COLUMN_NAME_LIST);
return columnRefList_;
}
}
//
// mutators
//
void
ElemDDLConstraintUnique::setChild(Lng32 index, ExprNode * pChildNode)
{
ComASSERT(index >= 0 AND index < getArity());
if (index < ElemDDLConstraint::getArity())
{
ElemDDLConstraint::setChild(index, pChildNode);
}
else
{
ComASSERT(index EQU INDEX_COLUMN_NAME_LIST);
if (NOT pChildNode)
{
columnRefList_ = NULL;
}
else
{
ComASSERT(pChildNode->castToElemDDLNode());
columnRefList_ = pChildNode->castToElemDDLNode();
}
}
}
void
ElemDDLConstraintUnique::setColumnRefList(ElemDDLNode * pColumnRefList)
{
setChild(INDEX_COLUMN_NAME_LIST, pColumnRefList);
if (getColumnRefList())
{
//
// Copies information about the key column list to keyColumnArray_
// so the user can access the information easier. (Assumes that
// keyColumnArray_ is still empty.)
//
for (CollIndex i = 0; i < getColumnRefList()->entries(); i++)
{
ComASSERT((*getColumnRefList())[i] AND
(*getColumnRefList())[i]->castToElemDDLColRef());
keyColumnArray_.insert((*getColumnRefList())[i]->castToElemDDLColRef());
}
}
} // ElemDDLConstraintUnique::setColumnRefList()
//
// methods for tracing
//
const NAString
ElemDDLConstraintUnique::displayLabel2() const
{
return "Constraint type: Unique constraint";
}
NATraceList
ElemDDLConstraintUnique::getDetailInfo() const
{
NATraceList detailTextList = ElemDDLConstraint::getDetailInfo();
if (getKeyColumnArray().entries() EQU 0)
{
detailTextList.append("No key column list.");
}
else
{
NAString detailText;
detailText = "Key Column List [";
detailText += LongToNAString((Lng32)getKeyColumnArray().entries());
detailText += " element(s)]:";
detailTextList.append(detailText);
for (CollIndex i = 0; i < getKeyColumnArray().entries(); i++)
{
detailText = "[column ";
detailText += LongToNAString((Lng32)i);
detailText += "]";
detailTextList.append(detailText);
detailTextList.append(" ", getKeyColumnArray()[i]->getDetailInfo());
}
}
return detailTextList;
} // ElemDDLConstraintUnique::getDetailInfo()
const NAString
ElemDDLConstraintUnique::getText() const
{
return "ElemDDLConstraintUnique";
}
//
// End of File
//