blob: eb51cea63d0b28ace78601a2717b055b82e0824f [file] [log] [blame]
// **********************************************************************
// @@@ 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 @@@
// **********************************************************************
#include "QRDescriptor.h"
#include "QRSharedPtr.h"
#include "Range.h"
// Element names
const char QRQueryDescriptor::elemName[] = "Query";
const char QRMVDescriptor::elemName[] = "MV";
const char QRResultDescriptor::elemName[] = "Result";
const char QRPublishDescriptor::elemName[] = "Publish";
const char QRQueryMisc::elemName[] = "Misc";
const char QRJBB::elemName[] = "JBB";
const char QRInfo::elemName[] = "Info";
const char QRHub::elemName[] = "Hub";
const char QRJBBCList::elemName[] = "JBBCList";
const char QRTable::elemName[] = "Table";
const char QRForcedMVs::elemName[] = "ForcedMVs";
template<> const char QRList<QRTable>::elemName[] = "TableList";
const char QROperator::elemName[] = "Operator";
const char QRJoinPred::elemName[] = "JoinPred";
template<> const char QRList<QRJoinPred>::elemName[] = "JoinPredList";
const char QRRangePred::elemName[] = "Range";
template<> const char QRList<QRRangePred>::elemName[] = "RangePredList";
template<> const char QRList<QRExpr>::elemName[] = "ResidualPredList";
const char QROpEQ::elemName[] = "OpEQ";
const char QROpLS::elemName[] = "OpLS";
const char QROpLE::elemName[] = "OpLE";
const char QROpGT::elemName[] = "OpGT";
const char QROpGE::elemName[] = "OpGE";
const char QROpBT::elemName[] = "OpBT";
const char QRNumericVal::elemName[] = "NumericVal";
const char QRStringVal::elemName[] = "StringVal";
const char QRWStringVal::elemName[] = "WStringVal";
const char QRFloatVal::elemName[] = "FloatVal";
const char QRNullVal::elemName[] = "NullVal";
const char QRGroupBy::elemName[] = "GroupBy";
const char QROutput::elemName[] = "Output";
template<> const char QRList<QROutput>::elemName[] = "OutputList";
const char QRExtraHub::elemName[] = "ExtraHub";
const char QRColumn::elemName[] = "Column";
const char QRExpr::elemName[] = "Expr";
const char QRExpr::residElemName[] = "Residual"; // 2 elem names map to QRExpr
const char QRBinaryOper::elemName[] = "BinaryOper";
const char QRUnaryOper::elemName[] = "UnaryOper";
const char QRFunction::elemName[] = "Function";
const char QRParameter::elemName[] = "Parameter";
const char QRMVColumn::elemName[] = "MVColumn";
const char QRMVMisc::elemName[] = "Misc";
const char QRJbbResult::elemName[] = "JbbResult";
const char QRJbbSubset::elemName[] = "JbbSubset";
const char QRCandidate::elemName[] = "Candidate";
template<> const char QRList<QRCandidate>::elemName[] = "CandidateList";
const char QRMVName::elemName[] = "MVName";
const char QRVersion::elemName[] = "Version";
const char QRUpdate::elemName[] = "Update";
const char QRInclude::elemName[] = "Include";
const char QRPrimaryGroupBy::elemName[] = "Primary";
const char QRDependentGroupBy::elemName[] = "Dependent";
const char QRMinimalGroupBy::elemName[] = "Minimal";
const char QRKey::elemName[] = "Key";
////////////////////////////////////////////////////
// Member function definitions
////////////////////////////////////////////////////
//
// AggregateFinderVisitor
//
Visitor::VisitResult AggregateFinderVisitor::visit(QRElementPtr caller)
{
if (caller->getElementType() == ET_Function &&
caller->downCastToQRFunction()->isAnAggregate())
{
foundAggregate_ = TRUE;
if (findAll_)
{
aggregatesFound_.insert(caller->getReferencedElement());
return VR_Continue;
}
return VR_Stop;
}
return VR_Continue;
}
Visitor::VisitResult ElementFinderVisitor::visit(QRElementPtr caller)
{
ElementType callerElemType = caller->getElementType();
for (CollIndex i=0; i<targetTypes_.entries(); i++)
{
if (callerElemType == targetTypes_[i])
{
elementsFound_.insert(useRefedElem_ ? caller->getReferencedElement()
: caller);
return VR_Continue;
}
}
return VR_Continue;
}
//
// QRElement
//
const char* const QRElement::ExprResultNames[] = { "Outside", "Provided", "NotProvided" };
QRElement::ExprResult QRElement::encodeResult(const char* resultString)
{
for (Int32 i=FIRST_EXPR_RESULT; i<INVALID_EXPR_RESULT; i++)
{
if (!strcmp(resultString, ExprResultNames[i]))
return (ExprResult)i;
}
throw QRDescriptorException("Invalid value for 'result' attribute -- %s",
resultString);
}
Int32 QRElement::cmpQRElement(const void *p1, const void *p2)
{
QRElementPtr t1 = *((QRElementPtr*)p1);
QRElementPtr t2 = *((QRElementPtr*)p2);
return t1->getReferencedElement()->getSortName().compareTo(t2->getReferencedElement()->getSortName());
}
NAString& QRElement::addEntityRefs(NAString& str, char attrDelim)
{
const char* specialChars;
if (attrDelim == '"')
specialChars = "&<\"";
else if (attrDelim == '\'')
specialChars = "&<'";
else
assertLogAndThrow(CAT_SQL_COMP_QR_DESC_GEN, LL_ERROR,
FALSE, QRDescriptorException,
"addEntityRefs: attribute delimiter must be ' or \"");
const char* data = str.data();
if (!strpbrk(data, specialChars))
return str;
Int32 inx = str.length() - 1;
while (inx >= 0)
{
switch (data[inx])
{
case '&':
str.replace(inx, 1, "&amp;");
break;
case '<':
str.replace(inx, 1, "&lt;");
break;
case '"':
if (attrDelim == '"')
str.replace(inx, 1, "&quot;");
break;
case '\'':
if (attrDelim == '\'')
str.replace(inx, 1, "&apos;");
break;
default:
break;
}
inx--;
}
return str;
}
void QRElement::serializeAttrs(XMLString& xml)
{
if (id_.length() > 0)
xml.append("id='").append(id_).append("' ");
if (ref_.length() > 0)
xml.append("ref='").append(ref_).append("' ");
}
void QRElement::serializeBoolAttr(const char* attrName,
NABoolean attrVal,
XMLString& xml)
{
xml.append(attrName)
.append("='")
.append(attrVal ? '1' : '0')
.append("' ");
}
void QRElement::deserializeBoolAttr(const char* attrName,
const char* attrVal,
NABoolean& attr)
{
if (!strcmp(attrVal, "0"))
attr = FALSE;
else if (!strcmp(attrVal, "1"))
attr = TRUE;
else
throw QRDescriptorException("Value of %s attribute must be either 0 or 1",
attrName);
}
//
// QRElementMapper
//
XMLElementPtr QRElementMapper::operator()(void *parser,
char *elementName,
AttributeList atts)
{
XMLElementPtr elemPtr = NULL;
if (!strcmp(elementName, QRQueryDescriptor::elemName))
elemPtr = new (XMLPARSEHEAP) QRQueryDescriptor(atts, ADD_MEMCHECK_ARGS(XMLPARSEHEAP));
else if (!strcmp(elementName, QRMVDescriptor::elemName))
elemPtr = new (XMLPARSEHEAP) QRMVDescriptor(atts, ADD_MEMCHECK_ARGS(XMLPARSEHEAP));
else if (!strcmp(elementName, QRResultDescriptor::elemName))
elemPtr = new (XMLPARSEHEAP) QRResultDescriptor(atts, ADD_MEMCHECK_ARGS(XMLPARSEHEAP));
else if (!strcmp(elementName, QRPublishDescriptor::elemName))
elemPtr = new (XMLPARSEHEAP) QRPublishDescriptor(atts, ADD_MEMCHECK_ARGS(XMLPARSEHEAP));
return elemPtr;
}
//
// QRElementList
//
QRElementList::QRElementList(ElementType type, XMLElementPtr parent, AttributeList atts,
ADD_MEMCHECK_ARGS_DEF(NAMemory* heap))
: QRElement(type, parent, ADD_MEMCHECK_ARGS_PASS(heap)),
list_(heap)
{
}
QRElementList::~QRElementList()
{
for (CollIndex i = 0; i < list_.entries(); i++)
deletePtr(list_[i]);
}
void QRElementList::serializeBody(XMLString& xml)
{
for (CollIndex i = 0; i < list_.entries(); i++)
list_[i]->toXML(xml);
}
NABoolean QRElementList::treeWalk(VisitorPtr visitor)
{
VISIT_THIS(visitor, this);
for (CollIndex i = 0; i < list_.entries(); i++)
if (list_[i]->treeWalk(visitor))
return TRUE;
return FALSE;
}
void QRElementList::startItemExprElement(void *parser, const char *elementName, const char **atts)
{
QRElementPtr elem = NULL;
if (!strcmp(elementName, QRColumn::elemName))
elem = new (XMLPARSEHEAP) QRColumn(CHILD_ELEM_ARGS(XMLPARSEHEAP));
else if (!strcmp(elementName, QRMVColumn::elemName))
elem = new (XMLPARSEHEAP) QRMVColumn(CHILD_ELEM_ARGS(XMLPARSEHEAP));
else if (!strcmp(elementName, QRExpr::elemName))
elem = new (XMLPARSEHEAP) QRExpr(this, atts, FALSE, ADD_MEMCHECK_ARGS(XMLPARSEHEAP));
else
throw QRDescriptorException("<%s> cannot contain <%s>",
getElementName(), elementName);
addElement(elem);
XMLDocument::setCurrentElement(parser, elem);
}
//
// QRDescriptor
//
NABoolean QRDescriptor::treeWalk(VisitorPtr visitor)
{
VISIT_THIS(visitor, this);
for (CollIndex i=0; i<jbbList_.entries(); i++)
if (jbbList_[i]->treeWalk(visitor))
return TRUE;
return FALSE;
}
//
// QRQueryMisc
//
QRQueryMisc::QRQueryMisc(ADD_MEMCHECK_ARGS_DEF(NAMemory* heap))
: QRElement(ET_QueryMisc, NULL, ADD_MEMCHECK_ARGS_PASS(heap)),
userID_(heap),
mvAge_(heap),
optLevel_(heap),
rewriteLevel_(MRL_OFF),
forcedMVs_(NULL)
{
}
QRQueryMisc::QRQueryMisc(XMLElementPtr parent, AttributeList atts,
ADD_MEMCHECK_ARGS_DEF(NAMemory* heap))
: QRElement(ET_QueryMisc, parent, ADD_MEMCHECK_ARGS_PASS(heap)),
userID_(heap),
mvAge_(heap),
optLevel_(heap),
rewriteLevel_(MRL_OFF),
forcedMVs_(NULL)
{
XMLAttributeIterator iter(atts);
const char *attrName;
const char *attrValue;
while (iter.hasNext())
{
iter.next();
attrName = iter.getName();
attrValue = iter.getValue();
if (!strcmp(attrName, "userID"))
userID_ = attrValue;
else if (!strcmp(attrName, "MVAge"))
mvAge_ = attrValue;
else if (!strcmp(attrName, "optLevel"))
optLevel_ = attrValue;
else if (!strcmp(attrName, "rewriteLevel"))
rewriteLevel_ = (MvqrRewriteLevel)atoi(attrValue);
else
throw QRDescriptorException("Invalid attribute specified for element %s: %s",
elemName, attrName);
}
}
QRQueryMisc::~QRQueryMisc()
{
deletePtr(forcedMVs_);
}
NABoolean QRQueryMisc::treeWalk(VisitorPtr visitor)
{
VISIT_THIS(visitor, this);
if (forcedMVs_ && forcedMVs_->treeWalk(visitor))
return TRUE;
return FALSE;
}
void QRQueryMisc::startElement(void *parser, const char *elementName, const char **atts)
{
if (!strcmp(elementName, QRForcedMVs::elemName))
{
forcedMVs_ = new (XMLPARSEHEAP) QRForcedMVs(CHILD_ELEM_ARGS(XMLPARSEHEAP));
XMLDocument::setCurrentElement(parser, forcedMVs_);
}
else
{
throw QRDescriptorException("Element %s cannot contain element %s",
elemName, elementName);
}
}
void QRQueryMisc::serializeAttrs(XMLString& xml)
{
QRElement::serializeAttrs(xml);
if (userID_.length() > 0)
xml.append("userID='").append(userID_).append("\' ");
if (mvAge_.length() > 0)
xml.append("MVAge='").append(mvAge_).append("\' ");
if (optLevel_.length() > 0)
xml.append("optLevel='").append(optLevel_).append("\' ");
if (rewriteLevel_ != MRL_OFF)
{
char buffer[20];
snprintf(buffer, sizeof(buffer), "rewriteLevel='%d' ", (Int32)rewriteLevel_);
xml.append(buffer);
}
}
void QRQueryMisc::serializeBody(XMLString& xml)
{
if (forcedMVs_)
forcedMVs_->toXML(xml);
}
//
// QRQueryDescriptor
//
QRQueryDescriptor::QRQueryDescriptor(AttributeList atts,
ADD_MEMCHECK_ARGS_DEF(NAMemory* heap))
: QRDescriptor(ET_QueryDescriptor, ADD_MEMCHECK_ARGS_PASS(heap)),
version_(NULL),
misc_(NULL),
options_(heap)
{
// Set parent here so we don't have to use 'this' in initializer.
setParent(this);
XMLAttributeIterator iter(atts);
const char *attrName;
while (iter.hasNext())
{
iter.next();
attrName = iter.getName();
if (!strcmp(attrName, "options"))
options_ = iter.getValue();
else
throw QRDescriptorException("Invalid attribute specified for element %s: %s",
elemName, attrName);
}
}
QRQueryDescriptor::~QRQueryDescriptor()
{
deletePtr(version_);
deletePtr(misc_);
for (CollIndex i = 0; i < jbbList_.entries(); i++)
deletePtr(jbbList_[i]);
}
NABoolean QRQueryDescriptor::treeWalk(VisitorPtr visitor)
{
VISIT_THIS(visitor, this);
if (version_ && version_->treeWalk(visitor))
return TRUE;
if (misc_ && misc_->treeWalk(visitor))
return TRUE;
for (CollIndex i = 0; i < jbbList_.entries(); i++)
if (jbbList_[i]->treeWalk(visitor))
return TRUE;
return FALSE;
}
void QRQueryDescriptor::startElement(void *parser, const char *elementName, const char **atts)
{
if (!strcmp(elementName, QRVersion::elemName))
{
version_ = new (XMLPARSEHEAP) QRVersion(CHILD_ELEM_ARGS(XMLPARSEHEAP));
XMLDocument::setCurrentElement(parser, version_);
}
else if (!strcmp(elementName, QRQueryMisc::elemName))
{
misc_ = new (XMLPARSEHEAP) QRQueryMisc(CHILD_ELEM_ARGS(XMLPARSEHEAP));
XMLDocument::setCurrentElement(parser, misc_);
}
else if (!strcmp(elementName, QRJBB::elemName))
{
QRJBBPtr jbb = new (XMLPARSEHEAP) QRJBB(CHILD_ELEM_ARGS(XMLPARSEHEAP));
addJBB(jbb);
XMLDocument::setCurrentElement(parser, jbb);
}
else
{
throw QRDescriptorException("Element %s cannot contain element %s",
elemName, elementName);
}
}
void QRQueryDescriptor::serializeAttrs(XMLString& xml)
{
QRElement::serializeAttrs(xml);
if (options_.length() > 0)
xml.append("options='").append(options_).append("\' ");
}
void QRQueryDescriptor::serializeBody(XMLString& xml)
{
if (version_)
version_->toXML(xml);
if (misc_)
misc_->toXML(xml);
for (CollIndex i = 0; i < jbbList_.entries(); i++)
jbbList_[i]->toXML(xml);
}
//
// QRJBB
//
QRJBB::QRJBB(NumericID idNum,
JBB* jbb,
ADD_MEMCHECK_ARGS_DEF(NAMemory* heap))
: QRElement(ET_JBB, NULL, ADD_MEMCHECK_ARGS_PASS(heap)),
hub_(new(heap) QRHub(ADD_MEMCHECK_ARGS(heap))),
extraHub_(new(heap) QRExtraHub(ADD_MEMCHECK_ARGS(heap))),
outputList_(new (heap) QRList<QROutput>(ADD_MEMCHECK_ARGS(heap))),
groupBy_(NULL),
caNodeId_(0),
actualJbbPtr_(jbb),
tableArray_(NULL),
tableCount_(0),
maxTableEntries_(0),
gbExpr_(NULL)
{
setID(idNum);
}
QRJBB::QRJBB(NumericID idNum,
CollIndex nodeId,
ADD_MEMCHECK_ARGS_DEF(NAMemory* heap))
: QRElement(ET_JBB, NULL, ADD_MEMCHECK_ARGS_PASS(heap)),
hub_(new(heap) QRHub(ADD_MEMCHECK_ARGS(heap))),
extraHub_(new(heap) QRExtraHub(ADD_MEMCHECK_ARGS(heap))),
outputList_(new (heap) QRList<QROutput>(ADD_MEMCHECK_ARGS(heap))),
groupBy_(NULL),
caNodeId_(nodeId),
actualJbbPtr_(NULL),
tableArray_(NULL),
tableCount_(0),
maxTableEntries_(0),
gbExpr_(NULL)
{
setID(idNum);
}
QRJBB::QRJBB(XMLElementPtr parent, AttributeList atts,
ADD_MEMCHECK_ARGS_DEF(NAMemory* heap))
: QRElement(ET_JBB, parent, ADD_MEMCHECK_ARGS_PASS(heap)),
hub_(NULL),
extraHub_(NULL),
outputList_(NULL),
groupBy_(NULL),
tableArray_(NULL),
tableCount_(0),
maxTableEntries_(0),
gbExpr_(NULL)
{
XMLAttributeIterator iter(atts);
const char *attrName;
while (iter.hasNext())
{
iter.next();
attrName = iter.getName();
if (!strcmp(attrName, "id"))
id_ = iter.getValue();
else if (!strcmp(attrName, "ref"))
ref_ = iter.getValue();
else
throw QRDescriptorException("Invalid attribute specified for element %s: %s",
elemName, attrName);
}
}
QRJBB::~QRJBB()
{
deletePtr(hub_);
deletePtr(extraHub_);
deletePtr(outputList_);
deletePtr(groupBy_);
}
NABoolean QRJBB::treeWalk(VisitorPtr visitor)
{
VISIT_THIS(visitor, this);
if (hub_ && hub_->treeWalk(visitor))
return TRUE;
if (extraHub_ && extraHub_->treeWalk(visitor))
return TRUE;
if (outputList_ && outputList_->treeWalk(visitor))
return TRUE;
if (groupBy_ && groupBy_->treeWalk(visitor))
return TRUE;
return FALSE;
}
void QRJBB::serializeBody(XMLString& xml)
{
// A JBB that is merely a link to another JBB has no body.
if (ref_.length() > 0)
return;
if (hub_)
hub_->toXML(xml);
if (extraHub_)
extraHub_->toXML(xml);
if (outputList_ && !outputList_->isEmpty())
outputList_->toXML(xml);
if (groupBy_)
groupBy_->toXML(xml);
}
void QRJBB::startElement(void *parser, const char *elementName, const char **atts)
{
if (!strcmp(elementName, QRHub::elemName))
{
hub_ = new (XMLPARSEHEAP) QRHub(CHILD_ELEM_ARGS(XMLPARSEHEAP));
XMLDocument::setCurrentElement(parser, hub_);
}
else if (!strcmp(elementName, QRExtraHub::elemName))
{
extraHub_ = new (XMLPARSEHEAP) QRExtraHub(CHILD_ELEM_ARGS(XMLPARSEHEAP));
XMLDocument::setCurrentElement(parser, extraHub_);
}
else if (!strcmp(elementName, QRList<QROutput>::elemName))
{
outputList_ = new (XMLPARSEHEAP) QRList<QROutput>(CHILD_ELEM_ARGS(XMLPARSEHEAP));
XMLDocument::setCurrentElement(parser, outputList_);
}
else if (!strcmp(elementName, QRGroupBy::elemName))
{
groupBy_ = new (XMLPARSEHEAP) QRGroupBy(CHILD_ELEM_ARGS(XMLPARSEHEAP));
XMLDocument::setCurrentElement(parser, groupBy_);
}
else
{
throw QRDescriptorException("Element %s cannot contain element %s",
elemName, elementName);
}
}
void QRJBB::createTableArray(CollIndex maxEntries)
{
assertLogAndThrow1(CAT_SQL_COMP_QR_DESC_GEN, LL_MVQR_FAIL,
!tableArray_, QRDescriptorException,
"tableArray_ already created for jbb %d", getIDNum());
maxTableEntries_ = maxEntries;
tableArray_ = new QRTablePtr[maxEntries];
}
void QRJBB::addTable(QRTablePtr table)
{
assertLogAndThrow1(CAT_SQL_COMP_QR_DESC_GEN, LL_MVQR_FAIL,
tableCount_ < maxTableEntries_, QRDescriptorException,
"Found more tables than in jbbc list for jbb %d", getIDNum());
tableArray_[tableCount_++] = table;
}
//
// QRList
//
template <class T>
void QRList<T>::serializeBody(XMLString& xml)
{
for (CollIndex i = 0; i < list_.entries(); i++)
list_[i]->toXML(xml);
}
template <class T>
NABoolean QRList<T>::treeWalk(VisitorPtr visitor)
{
VISIT_THIS(visitor, this);
for (CollIndex i = 0; i < list_.entries(); i++)
if (list_[i]->treeWalk(visitor))
return TRUE;
return FALSE;
}
template <class T>
void QRList<T>::startElement(void *parser, const char *elementName, const char **atts)
{
if (!strcmp(elementName, T::elemName))
{
PTR_TO_TYPE(T) listElem = new (XMLPARSEHEAP) T(CHILD_ELEM_ARGS(XMLPARSEHEAP));
list_.insert(listElem);
XMLDocument::setCurrentElement(parser, listElem);
}
else
{
throw QRDescriptorException("Element %s cannot contain element %s",
elemName, elementName);
}
}
// This template specialization is necessary because QRExpr is associated with two
// different elements, and when used as a list, is a list of the secondary one
// (<Residual>). So in this specialization, we are looking for residElemName,
// instead of elemName as is the case for all other classes.
template<> void QRList<QRExpr>::startElement(void *parser, const char *elementName, const char **atts)
{
if (!strcmp(elementName, QRExpr::residElemName))
{
PTR_TO_TYPE(QRExpr) listElem =
new (XMLPARSEHEAP) QRExpr(this, atts, TRUE, ADD_MEMCHECK_ARGS(XMLPARSEHEAP));
list_.insert(listElem);
XMLDocument::setCurrentElement(parser, listElem);
}
else
{
throw QRDescriptorException("Element %s cannot contain element %s",
elemName, elementName);
}
}
// For some reason, the generic definition does not work, so I used a specific definition for QRRangePred.
//template<class T>
//void QRList<T>::addItemOrdered(PTR_TO_TYPE(T) item)
template<> void QRList<QRRangePred>::addItemOrdered(PTR_TO_TYPE(QRRangePred) item)
{
CollIndex maxEntries = entries();
if (maxEntries==0)
{
list_.insert(item);
}
else
{
CollIndex pos = 0;
const NAString& newID = item->getID();
while (pos<maxEntries && newID > list_[pos]->getID())
pos++;
list_.insertAt(pos, item);
}
}
//
// QRHub
//
QRHub::QRHub(ADD_MEMCHECK_ARGS_DEF(NAMemory* heap))
: QRElement(ET_Hub, NULL, ADD_MEMCHECK_ARGS_PASS(heap)),
jbbcList_(new(heap) QRJBBCList(ADD_MEMCHECK_ARGS(heap))),
joinPredList_(new(heap) QRList<QRJoinPred>(ADD_MEMCHECK_ARGS(heap))),
rangePredList_(new(heap) QRList<QRRangePred>(ADD_MEMCHECK_ARGS(heap))),
residualPredList_(new(heap) QRList<QRExpr>(ADD_MEMCHECK_ARGS(heap)))
{}
QRHub::QRHub(XMLElementPtr parent, AttributeList atts,
ADD_MEMCHECK_ARGS_DEF(NAMemory* heap))
: QRElement(ET_Hub, parent, ADD_MEMCHECK_ARGS_PASS(heap)),
jbbcList_(NULL),
joinPredList_(NULL),
rangePredList_(NULL),
residualPredList_(NULL)
{
if (*atts)
throw QRDescriptorException("Invalid attribute specified for element %s: %s",
elemName, *atts);
}
QRHub::~QRHub()
{
deletePtr(jbbcList_);
deletePtr(joinPredList_);
deletePtr(rangePredList_);
deletePtr(residualPredList_);
}
void QRHub::serializeBody(XMLString& xml)
{
if (jbbcList_ && !jbbcList_->isEmpty())
jbbcList_->toXML(xml);
if (joinPredList_ && !joinPredList_->isEmpty())
joinPredList_->toXML(xml);
if (rangePredList_ && !rangePredList_->isEmpty())
rangePredList_->toXML(xml);
if (residualPredList_ && !residualPredList_->isEmpty())
residualPredList_->toXML(xml);
}
NABoolean QRHub::treeWalk(VisitorPtr visitor)
{
VISIT_THIS(visitor, this);
if (jbbcList_ && !jbbcList_->isEmpty() && jbbcList_->treeWalk(visitor))
return TRUE;
if (joinPredList_ && !joinPredList_->isEmpty() && joinPredList_->treeWalk(visitor))
return TRUE;
if (rangePredList_ && !rangePredList_->isEmpty() && rangePredList_->treeWalk(visitor))
return TRUE;
if (residualPredList_ && !residualPredList_->isEmpty() && residualPredList_->treeWalk(visitor))
return TRUE;
return FALSE;
}
void QRHub::startElement(void *parser, const char *elementName, const char **atts)
{
if (!strcmp(elementName, QRJBBCList::elemName))
{
jbbcList_ = new (XMLPARSEHEAP) QRJBBCList(CHILD_ELEM_ARGS(XMLPARSEHEAP));
XMLDocument::setCurrentElement(parser, jbbcList_);
}
else if (!strcmp(elementName, QRList<QRJoinPred>::elemName))
{
joinPredList_ = new (XMLPARSEHEAP) QRList<QRJoinPred>(CHILD_ELEM_ARGS(XMLPARSEHEAP));
XMLDocument::setCurrentElement(parser, joinPredList_);
}
else if (!strcmp(elementName, QRList<QRRangePred>::elemName))
{
rangePredList_ = new (XMLPARSEHEAP) QRList<QRRangePred>(CHILD_ELEM_ARGS(XMLPARSEHEAP));
XMLDocument::setCurrentElement(parser, rangePredList_);
}
else if (!strcmp(elementName, QRList<QRExpr>::elemName))
{
residualPredList_ = new (XMLPARSEHEAP) QRList<QRExpr>(CHILD_ELEM_ARGS(XMLPARSEHEAP));
XMLDocument::setCurrentElement(parser, residualPredList_);
}
else
{
throw QRDescriptorException("<%s> cannot contain <%s>",
elemName, elementName);
}
}
//
// QRJBBCList
//
QRJBBCList::QRJBBCList(XMLElementPtr parent, AttributeList atts,
ADD_MEMCHECK_ARGS_DEF(NAMemory* heap))
: QRElementList(ET_JBBCList, parent, NULL, ADD_MEMCHECK_ARGS_PASS(heap))
{
if (*atts)
throw QRDescriptorException("Invalid attribute specified for element %s: %s",
elemName, *atts);
}
void QRJBBCList::startElement(void *parser, const char *elementName, const char **atts)
{
QRElementPtr elem;
if (!strcmp(elementName, QRTable::elemName))
elem = new (XMLPARSEHEAP) QRTable(CHILD_ELEM_ARGS(XMLPARSEHEAP));
else if (!strcmp(elementName, QRJBB::elemName))
elem = new (XMLPARSEHEAP) QRJBB(CHILD_ELEM_ARGS(XMLPARSEHEAP));
else if (!strcmp(elementName, QROperator::elemName))
elem = new (XMLPARSEHEAP) QROperator(CHILD_ELEM_ARGS(XMLPARSEHEAP));
else
throw QRDescriptorException("<%s> cannot contain <%s>",
elemName, elementName);
addElement(elem);
XMLDocument::setCurrentElement(parser, elem);
}
void QRJBBCList::setIsKeyCovered()
{
const ElementPtrList& elemList = getList();
for (CollIndex i=0; i<elemList.entries(); i++)
{
if (elemList[i]->getElementType() == ET_Table)
static_cast<QRTablePtr>(elemList[i])->setIsKeyCovered(TRUE);
}
}
//
// QRTable
//
QRTable::QRTable(ADD_MEMCHECK_ARGS_DEF(NAMemory* heap))
: QRElement(ET_Table, NULL, ADD_MEMCHECK_ARGS_PASS(heap)),
redefTimestamp_(heap),
extraHubReason_(heap),
isAnMV_(FALSE),
tableName_(charData_),
isExtraHub_(FALSE),
isKeyCovered_(FALSE),
numCols_(-1),
rangeBits_(heap),
residualBits_(heap),
hasLOJParent_(FALSE),
key_(NULL),
correlationName_(heap),
joinOrder_(1)
{
}
QRTable::QRTable(XMLElementPtr parent, AttributeList atts,
ADD_MEMCHECK_ARGS_DEF(NAMemory* heap))
: QRElement(ET_Table, parent, ADD_MEMCHECK_ARGS_PASS(heap)),
redefTimestamp_(heap),
extraHubReason_(heap),
isAnMV_(false),
tableName_(charData_),
isExtraHub_(FALSE),
isKeyCovered_(FALSE),
numCols_(-1),
rangeBits_(heap),
residualBits_(heap),
hasLOJParent_(FALSE),
key_(NULL),
correlationName_(heap),
joinOrder_(1)
{
XMLAttributeIterator iter(atts);
const char *attrName;
const char *attrVal;
while (iter.hasNext())
{
iter.next();
attrName = iter.getName();
attrVal = iter.getValue();
if (!strcmp(attrName, "id"))
id_ = attrVal;
else if (!strcmp(attrName, "ref"))
ref_ = attrVal;
else if (!strcmp(attrName, "TS"))
redefTimestamp_ = attrVal; //@ZX -- probably need to convert to INT64
else if (!strcmp(attrName, "reason"))
extraHubReason_ = attrVal;
else if (!strcmp(attrName, "isAnMV"))
deserializeBoolAttr(attrName, attrVal, isAnMV_);
else if (!strcmp(attrName, "isKeyCovered"))
deserializeBoolAttr(attrName, attrVal, isKeyCovered_);
else if (!strcmp(attrName, "numCols"))
setNumCols(atoi(attrVal)); // must call fn, so bitmaps are resized
else if (!strcmp(attrName, "rangeBits"))
rangeBits_.initFromHexString(attrVal, numCols_);
else if (!strcmp(attrName, "residualBits"))
residualBits_.initFromHexString(attrVal, numCols_);
else if (!strcmp(attrName, "hasLOJParent"))
deserializeBoolAttr(attrName, attrVal, hasLOJParent_);
else if (!strcmp(attrName, "corr"))
correlationName_ = attrVal;
else if (!strcmp(attrName, "joinOrder"))
joinOrder_ = atoi(attrVal);
else
throw QRDescriptorException("Invalid attribute specified for element %s: %s",
elemName, attrName);
}
}
void QRTable::serializeAttrs(XMLString& xml)
{
QRElement::serializeAttrs(xml);
if (redefTimestamp_.length() > 0)
xml.append("TS='").append(redefTimestamp_).append("' ");
if (extraHubReason_.length() > 0)
xml.append("reason='").append(extraHubReason_).append("' ");
if (isAnMV_) // 0 is default
xml.append("isAnMV='1' ");
if (isKeyCovered_) // 0 is default
xml.append("isKeyCovered='1' ");
if (numCols_ != -1)
{
char buffer[20];
snprintf(buffer, sizeof(buffer), "numCols='%d' ", numCols_);
xml.append(buffer);
}
if (hasLOJParent_) // 0 is default
xml.append("hasLOJParent='1' ");
if (!rangeBits_.isEmpty())
{
xml.append("rangeBits='");
rangeBits_.toXML(xml);
xml.append("' ");
}
if (!residualBits_.isEmpty())
{
xml.append("residualBits='");
residualBits_.toXML(xml);
xml.append("' ");
}
if (correlationName_ != "")
xml.append("corr='").append(correlationName_).append("' ");
if (joinOrder_ > 1)
{
char buffer[20];
snprintf(buffer, sizeof(buffer), "joinOrder='%d' ", joinOrder_);
xml.append(buffer);
}
}
void QRTable::serializeBody(XMLString& xml)
{
QRElement::serializeBody(xml);
if (key_)
key_->toXML(xml);
}
void QRTable::startElement(void *parser, const char *elementName, const char **atts)
{
QRElementPtr elem;
if (!strcmp(elementName, QRKey::elemName))
{
QRKeyPtr key = new (XMLPARSEHEAP) QRKey(CHILD_ELEM_ARGS(XMLPARSEHEAP));
setKey(key);
elem = key;
}
else
throw QRDescriptorException("<%s> cannot contain <%s>",
elemName, elementName);
XMLDocument::setCurrentElement(parser, elem);
}
NABoolean QRTable::treeWalk(VisitorPtr visitor)
{
VISIT_THIS(visitor, this);
if (key_ && key_->treeWalk(visitor))
return TRUE;
return FALSE;
}
//
// QRKey
//
QRKey::QRKey(XMLElementPtr parent, AttributeList atts,
ADD_MEMCHECK_ARGS_DEF(NAMemory* heap))
: QRElementList(ET_Key, parent, NULL, ADD_MEMCHECK_ARGS_PASS(heap))
{
if (*atts)
throw QRDescriptorException("Invalid attribute specified for element %s: %s",
elemName, *atts);
}
void QRKey::startElement(void *parser, const char *elementName, const char **atts)
{
QRElementPtr elem;
if (!strcmp(elementName, QRColumn::elemName))
elem = new (XMLPARSEHEAP) QRColumn(CHILD_ELEM_ARGS(XMLPARSEHEAP));
else
throw QRDescriptorException("<%s> cannot contain <%s>",
elemName, elementName);
addElement(elem);
XMLDocument::setCurrentElement(parser, elem);
}
//
// QRForcedMVs
//
QRForcedMVs::~QRForcedMVs()
{
CollIndex i;
for (i = 0; i < tableList_.entries(); i++)
deletePtr(tableList_[i]);
}
NABoolean QRForcedMVs::treeWalk(VisitorPtr visitor)
{
VISIT_THIS(visitor, this);
for (CollIndex i = 0; i < tableList_.entries(); i++)
if (tableList_[i]->treeWalk(visitor))
return TRUE;
return FALSE;
}
void QRForcedMVs::startElement(void *parser, const char *elementName, const char **atts)
{
QRTablePtr table;
if (!strcmp(elementName, QRTable::elemName))
{
table = new (XMLPARSEHEAP) QRTable(CHILD_ELEM_ARGS(XMLPARSEHEAP));
XMLDocument::setCurrentElement(parser, table);
addTable(table);
}
else
{
throw QRDescriptorException("Element %s cannot contain element %s",
elemName, elementName);
}
}
void QRForcedMVs::serializeBody(XMLString& xml)
{
CollIndex i;
for (i = 0; i < tableList_.entries(); i++)
tableList_[i]->toXML(xml);
}
//
// QROperator
//
QROperator::QROperator(XMLElementPtr parent, AttributeList atts,
ADD_MEMCHECK_ARGS_DEF(NAMemory* heap))
: QRElement(ET_Operator, parent, ADD_MEMCHECK_ARGS_PASS(heap))
{
// Atts of Operator element have not been defined yet
}
NABoolean QROperator::treeWalk(VisitorPtr visitor)
{
VISIT_THIS(visitor, this);
// Add subelements here...
return FALSE;
}
//
// QRJoinPred
//
QRJoinPred::QRJoinPred(XMLElementPtr parent, AttributeList atts,
ADD_MEMCHECK_ARGS_DEF(NAMemory* heap))
: QRElementList(ET_JoinPred, parent, NULL, ADD_MEMCHECK_ARGS_PASS(heap)),
result_(INVALID_EXPR_RESULT)
{
XMLAttributeIterator iter(atts);
const char *attrName;
while (iter.hasNext())
{
iter.next();
attrName = iter.getName();
if (!strcmp(attrName, "id"))
id_ = iter.getValue();
else if (!strcmp(attrName, "ref"))
ref_ = iter.getValue();
else if (!strcmp(attrName, "result"))
result_ = encodeResult(iter.getValue());
else
throw QRDescriptorException("Invalid attribute specified for element %s: %s",
elemName, attrName);
}
}
void QRJoinPred::serializeAttrs(XMLString& xml)
{
QRElement::serializeAttrs(xml);
if (result_ != INVALID_EXPR_RESULT)
xml.append("result='").append(ExprResultNames[result_]).append( "' ");
}
void QRJoinPred::startElement(void *parser, const char *elementName, const char **atts)
{
QRElementPtr elem;
// A QRJoinPred can also have a QRJoinPred as a child element.
if (!strcmp(elementName, QRJoinPred::elemName))
{
elem = new (XMLPARSEHEAP) QRJoinPred(CHILD_ELEM_ARGS(XMLPARSEHEAP));
addElement(elem);
XMLDocument::setCurrentElement(parser, elem);
}
else
{
QRElementList::startItemExprElement(parser, elementName, atts);
}
}
NABoolean QRJoinPred::isRedundant() const
{
const ElementPtrList& list = getList();
const NAString& joinPredId = getID();
for (CollIndex i=0; i<list.entries(); i++)
{
if (joinPredId != list[i]->getRef())
return FALSE;
}
return TRUE; // all contained eq set members referenced the containing joinpred
}
QRColumnPtr QRJoinPred::getFirstColumn()
{
const ElementPtrList& eqList = getEqualityList();
for (CollIndex i=0; i<eqList.entries(); i++)
{
const QRElementPtr elem = eqList[i]->getReferencedElement();
// Return as soon as we find the first one.
if (elem->getElementType() == ET_Column)
return elem->downCastToQRColumn();
}
// Found no column in equality list, return NULL.
return NULL;
}
//
// QRRangePred
//
QRRangePred::QRRangePred(XMLElementPtr parent, AttributeList atts,
ADD_MEMCHECK_ARGS_DEF(NAMemory* heap))
: QRElement(ET_RangePred, parent, ADD_MEMCHECK_ARGS_PASS(heap)),
result_(INVALID_EXPR_RESULT),
rangeItem_(NULL),
opList_(heap),
mustMatch_(FALSE),
sqlType_(heap),
rangeSpec_(NULL)
{
XMLAttributeIterator iter(atts);
const char *attrName;
while (iter.hasNext())
{
iter.next();
attrName = iter.getName();
if (!strcmp(attrName, "id"))
id_ = iter.getValue();
else if (!strcmp(attrName, "ref"))
ref_ = iter.getValue();
else if (!strcmp(attrName, "sqlType"))
sqlType_ = iter.getValue();
else if (!strcmp(attrName, "result"))
result_ = encodeResult(iter.getValue());
else if (!strcmp(attrName, "mustMatch"))
deserializeBoolAttr(attrName, iter.getValue(), mustMatch_);
else
throw QRDescriptorException("Invalid attribute specified for element %s: %s",
elemName, attrName);
}
}
QRRangePred::~QRRangePred()
{
deletePtr(rangeItem_);
for (CollIndex i = 0; i < opList_.entries(); i++)
deletePtr(opList_[i]);
// RangeSpec is not a SharedPtr derivative.
if (rangeSpec_ != NULL)
delete rangeSpec_;
}
void QRRangePred::serializeAttrs(XMLString& xml)
{
QRElement::serializeAttrs(xml);
if (sqlType_.length() > 0)
xml.append("sqlType='").append(sqlType_).append("' ");
if (result_ != INVALID_EXPR_RESULT)
xml.append("result='").append(ExprResultNames[result_]).append("' ");
if (mustMatch_)
serializeBoolAttr("mustMatch", mustMatch_, xml);
}
void QRRangePred::serializeBody(XMLString& xml)
{
if (rangeItem_)
rangeItem_->toXML(xml);
if (opList_.entries() == 0) // contains no operators
{
// Don't add the comment to result descriptor range preds that reference
// query preds, because they are always empty.
if (result_ == INVALID_EXPR_RESULT || // not in a result descriptor
ref_ == "") // or in a constructed range pred
{
// Add comment to <Range> element explaining that when empty it means
// IS NOT NULL is specified or implied, but no other conditions.
xml.indent();
xml.append("<!-- empty Range element indicates IS NOT NULL -->");
xml.endLine();
}
}
else
for (CollIndex i = 0; i < opList_.entries(); i++)
opList_[i]->toXML(xml);
}
NABoolean QRRangePred::treeWalk(VisitorPtr visitor)
{
VISIT_THIS(visitor, this);
if (rangeItem_ && rangeItem_->treeWalk(visitor))
return TRUE;
for (CollIndex i = 0; i < opList_.entries(); i++)
if (opList_[i]->treeWalk(visitor))
return TRUE;
return FALSE;
}
void QRRangePred::startElement(void *parser, const char *elementName, const char **atts)
{
QRRangeOperatorPtr op;
if (!strcmp(elementName, QRColumn::elemName))
{
setRangeItem(new (XMLPARSEHEAP) QRColumn(CHILD_ELEM_ARGS(XMLPARSEHEAP)));
XMLDocument::setCurrentElement(parser, rangeItem_);
}
else if (!strcmp(elementName, QRMVColumn::elemName))
{
setRangeItem(new (XMLPARSEHEAP) QRMVColumn(CHILD_ELEM_ARGS(XMLPARSEHEAP)));
XMLDocument::setCurrentElement(parser, rangeItem_);
}
else if (!strcmp(elementName, QRExpr::elemName))
{
setRangeItem(new (XMLPARSEHEAP) QRExpr(this, atts, FALSE, ADD_MEMCHECK_ARGS(XMLPARSEHEAP)));
XMLDocument::setCurrentElement(parser, rangeItem_);
}
else if (!strcmp(elementName, QROpEQ::elemName))
{
op = new (XMLPARSEHEAP) QROpEQ(CHILD_ELEM_ARGS(XMLPARSEHEAP));
addOperator(op);
XMLDocument::setCurrentElement(parser, op);
}
else if (!strcmp(elementName, QROpLS::elemName))
{
op = new (XMLPARSEHEAP) QROpLS(CHILD_ELEM_ARGS(XMLPARSEHEAP));
addOperator(op);
XMLDocument::setCurrentElement(parser, op);
}
else if (!strcmp(elementName, QROpLE::elemName))
{
op = new (XMLPARSEHEAP) QROpLE(CHILD_ELEM_ARGS(XMLPARSEHEAP));
addOperator(op);
XMLDocument::setCurrentElement(parser, op);
}
else if (!strcmp(elementName, QROpGT::elemName))
{
op = new (XMLPARSEHEAP) QROpGT(CHILD_ELEM_ARGS(XMLPARSEHEAP));
addOperator(op);
XMLDocument::setCurrentElement(parser, op);
}
else if (!strcmp(elementName, QROpGE::elemName))
{
op = new (XMLPARSEHEAP) QROpGE(CHILD_ELEM_ARGS(XMLPARSEHEAP));
addOperator(op);
XMLDocument::setCurrentElement(parser, op);
}
else if (!strcmp(elementName, QROpBT::elemName))
{
op = new (XMLPARSEHEAP) QROpBT(CHILD_ELEM_ARGS(XMLPARSEHEAP));
addOperator(op);
XMLDocument::setCurrentElement(parser, op);
}
else
throw QRDescriptorException("Element %s cannot contain element %s",
elemName, elementName);
} // QRRangePred::startElement
const RangeSpec* QRRangePred::getRangeSpec(NAMemory* heap)
{
if (rangeSpec_ == NULL)
rangeSpec_ = new (heap) RangeSpec(this, heap);
return rangeSpec_;
}
NABoolean QRRangePred::isSingleValue()
{
if (opList_.entries() != 1)
return FALSE;
QRRangeOperatorPtr op=opList_[0];
if (op->getElementType() != ET_OpEQ)
return FALSE;
QROpEQPtr eqOp = static_cast<QROpEQPtr>(op);
return (eqOp->getValueList().entries() == 1 && !eqOp->includesNull());
}
Int32 QRRangePred::getSize()
{
Int32 result = 0;
CollIndex maxEntries = opList_.entries();
for (CollIndex i=0; i<maxEntries; i++)
result += opList_[i]->getSize();
return result;
}
//
// QROpEQ
//
QROpEQ::~QROpEQ()
{
for (CollIndex i = 0; i < valueList_.entries(); i++)
deletePtr(valueList_[i]);
deletePtr(nullVal_);
}
void QROpEQ::serializeBody(XMLString& xml)
{
if (nullVal_)
{
xml.indent();
xml.append('<').append(nullVal_->getElementName()).append("/>");
xml.endLine();
}
for (CollIndex i = 0; i < valueList_.entries(); i++)
valueList_[i]->toXML(xml);
}
NABoolean QROpEQ::treeWalk(VisitorPtr visitor)
{
VISIT_THIS(visitor, this);
for (CollIndex i = 0; i < valueList_.entries(); i++)
if (valueList_[i]->treeWalk(visitor))
return TRUE;
return FALSE;
}
void QROpEQ::startElement(void *parser, const char *elementName, const char **atts)
{
// Note the early return below when the element is <NullVal>
QRScalarValuePtr valElem = NULL;
if (!strcmp(elementName, QRNumericVal::elemName))
valElem = new (XMLPARSEHEAP) QRNumericVal(CHILD_ELEM_ARGS(XMLPARSEHEAP));
else if (!strcmp(elementName, QRStringVal::elemName))
valElem = new (XMLPARSEHEAP) QRStringVal(CHILD_ELEM_ARGS(XMLPARSEHEAP));
else if (!strcmp(elementName, QRWStringVal::elemName))
valElem = new (XMLPARSEHEAP) QRWStringVal(CHILD_ELEM_ARGS(XMLPARSEHEAP));
else if (!strcmp(elementName, QRFloatVal::elemName))
valElem = new (XMLPARSEHEAP) QRFloatVal(CHILD_ELEM_ARGS(XMLPARSEHEAP));
else if (!strcmp(elementName, QRNullVal::elemName))
{
nullVal_ = new (XMLPARSEHEAP) QRNullVal(CHILD_ELEM_ARGS(XMLPARSEHEAP));
XMLDocument::setCurrentElement(parser, nullVal_);
return;
}
else
throw QRDescriptorException("Element %s cannot contain element %s",
elemName, elementName);
if (valElem)
{
addValue(valElem);
XMLDocument::setCurrentElement(parser, valElem);
}
}
void QROpEQ::unparse(NAString& text, const NAString& rangeItem)
{
CollIndex numValues = valueList_.entries();
if (numValues == 1)
{
// A single value - use the "<range-item> = <literal>" notation.
text.append(rangeItem);
text.append(" = ");
text.append(valueList_[0]->getSql());
}
else if (numValues > 1)
{
// Multiple values - use the "<range-item> IN ( <literal> [, <literal> ] )"
text.append(rangeItem);
text.append(" IN ( ");
for (CollIndex i=0; i<numValues; i++)
{
text.append(valueList_[i]->getSql());
if (i<numValues-1)
text.append(", ");
}
text.append(" ) ");
}
if (nullVal_)
{
// Add an optional "[OR ] <range-item> IS NULL"
if (numValues > 0)
text.append(" OR ");
text.append(rangeItem);
text.append("IS NULL");
}
}
//
// QROpInequality
//
QROpInequality::QROpInequality(ElementType eType, QRElement *parent,
AttributeList atts, const char *elemName,
ADD_MEMCHECK_ARGS_DEF(NAMemory* heap))
: QRRangeOperator(eType, parent, ADD_MEMCHECK_ARGS_PASS(heap)),
value_(NULL),
isNormalized_(FALSE)
{
XMLAttributeIterator iter(atts);
const char *attrName;
const char *attrVal;
while (iter.hasNext())
{
iter.next();
attrName = iter.getName();
attrVal = iter.getValue();
if (!strcmp(attrName, "isNormalized"))
deserializeBoolAttr(attrName, attrVal, isNormalized_);
else
throw QRDescriptorException("Invalid attribute specified for element %s: %s",
elemName, attrName);
}
}
QROpInequality::~QROpInequality()
{
deletePtr(value_);
}
void QROpInequality::serializeAttrs(XMLString& xml)
{
QRElement::serializeAttrs(xml);
if (isNormalized_)
serializeBoolAttr("isNormalized", isNormalized_, xml);
}
void QROpInequality::serializeBody(XMLString& xml)
{
value_->toXML(xml);
}
NABoolean QROpInequality::treeWalk(VisitorPtr visitor)
{
VISIT_THIS(visitor, this);
if (value_->treeWalk(visitor))
return TRUE;
return FALSE;
}
void QROpInequality::startElement(void *parser, const char *elementName, const char **atts)
{
if (!strcmp(elementName, QRNumericVal::elemName))
value_ = new (XMLPARSEHEAP) QRNumericVal(CHILD_ELEM_ARGS(XMLPARSEHEAP));
else if (!strcmp(elementName, QRStringVal::elemName))
value_ = new (XMLPARSEHEAP) QRStringVal(CHILD_ELEM_ARGS(XMLPARSEHEAP));
else if (!strcmp(elementName, QRWStringVal::elemName))
value_ = new (XMLPARSEHEAP) QRWStringVal(CHILD_ELEM_ARGS(XMLPARSEHEAP));
else if (!strcmp(elementName, QRFloatVal::elemName))
value_ = new (XMLPARSEHEAP) QRFloatVal(CHILD_ELEM_ARGS(XMLPARSEHEAP));
else
throw QRDescriptorException("Element %s cannot contain element %s",
getElementName(), elementName);
XMLDocument::setCurrentElement(parser, value_);
}
void QROpInequality::unparse(NAString& text, const NAString& rangeItem)
{
// The text looks like this: "<range-item> <operator-sign> <literal>"
text.append(rangeItem);
text.append(getOperatorSign());
text.append(value_->getSql());
}
//
// QROpBT
//
QROpBT::QROpBT(QRElement *parent, AttributeList atts,
ADD_MEMCHECK_ARGS_DEF(NAMemory* heap))
: QRRangeOperator(ET_OpBT, parent, ADD_MEMCHECK_ARGS_PASS(heap)),
valueCount_(0), startValue_(NULL), endValue_(NULL),
startIsIncluded_(TRUE), endIsIncluded_(TRUE)
{
XMLAttributeIterator iter(atts);
const char *attrName;
const char *attrVal;
while (iter.hasNext())
{
iter.next();
attrName = iter.getName();
attrVal = iter.getValue();
if (!strcmp(attrName, "startIsIncluded"))
deserializeBoolAttr(attrName, attrVal, startIsIncluded_);
else if (!strcmp(attrName, "endIsIncluded"))
deserializeBoolAttr(attrName, attrVal, endIsIncluded_);
else
throw QRDescriptorException("Invalid attribute specified for element %s: %s",
elemName, attrName);
}
}
QROpBT::~QROpBT()
{
deletePtr(startValue_);
deletePtr(endValue_);
}
void QROpBT::serializeAttrs(XMLString& xml)
{
QRElement::serializeAttrs(xml);
serializeBoolAttr("startIsIncluded", startIsIncluded_, xml);
serializeBoolAttr("endIsIncluded", endIsIncluded_, xml);
}
void QROpBT::serializeBody(XMLString& xml)
{
if (startValue_)
startValue_->toXML(xml);
if (endValue_)
endValue_->toXML(xml);
}
NABoolean QROpBT::treeWalk(VisitorPtr visitor)
{
VISIT_THIS(visitor, this);
if (startValue_ && startValue_->treeWalk(visitor))
return TRUE;
if (endValue_ && endValue_->treeWalk(visitor))
return TRUE;
return FALSE;
}
void QROpBT::startElement(void *parser, const char *elementName, const char **atts)
{
valueCount_++;
if (valueCount_ > 2)
throw QRDescriptorException("Only 2 values can be contained in %s", elemName);
//QRElementPtr& val = (valueCount_ == 1 ? startValue_ : endValue_);
QRScalarValuePtr& val = (valueCount_ == 1 ? startValue_ : endValue_);
if (!strcmp(elementName, QRNumericVal::elemName))
val = new (XMLPARSEHEAP) QRNumericVal(CHILD_ELEM_ARGS(XMLPARSEHEAP));
else if (!strcmp(elementName, QRStringVal::elemName))
val = new (XMLPARSEHEAP) QRStringVal(CHILD_ELEM_ARGS(XMLPARSEHEAP));
else if (!strcmp(elementName, QRWStringVal::elemName))
val = new (XMLPARSEHEAP) QRWStringVal(CHILD_ELEM_ARGS(XMLPARSEHEAP));
else if (!strcmp(elementName, QRFloatVal::elemName))
val = new (XMLPARSEHEAP) QRFloatVal(CHILD_ELEM_ARGS(XMLPARSEHEAP));
else
throw QRDescriptorException("Element %s cannot contain element %s",
elemName, elementName);
XMLDocument::setCurrentElement(parser, val);
}
void QROpBT::unparse(NAString& text, const NAString& rangeItem)
{
if (startIsIncluded_ && endIsIncluded_)
{
// If both ends are included, use "<range-item> BETWEEN <literal> AND <literal>"
text.append(rangeItem);
text.append(" BETWEEN ");
text.append(startValue_->getSql());
text.append(" AND ");
text.append(endValue_->getSql());
}
else
{
// Otherwise use: "(<range-item> <operator> <literal> AND <range-item> <operator> <literal>)"
text.append("(");
text.append(rangeItem);
text.append((startIsIncluded_ ? " >= " : " > "));
text.append(startValue_->getSql());
text.append(" AND ");
text.append(rangeItem);
text.append((endIsIncluded_ ? " <= " : " < "));
text.append(endValue_->getSql());
text.append(")");
}
}
//
// QRScalarValue
//
QRScalarValue::QRScalarValue(ElementType eType, QRElement *parent, AttributeList atts,
ADD_MEMCHECK_ARGS_DEF(NAMemory* heap))
: QRExplicitExpr(eType, parent, ADD_MEMCHECK_ARGS_PASS(heap)),
stringRep_(charData_),
sql_(heap)
{
XMLAttributeIterator iter(atts);
const char *attrName;
while (iter.hasNext())
{
iter.next();
attrName = iter.getName();
if (!strcmp(attrName, "id"))
id_ = iter.getValue();
if (!strcmp(attrName, "ref"))
ref_ = iter.getValue();
if (!strcmp(attrName, "sql"))
sql_ = iter.getValue();
}
}
void QRScalarValue::serializeAttrs(XMLString& xml)
{
QRElement::serializeAttrs(xml);
if (sql_ != "")
xml.append("sql=\"").append(addEntityRefs(sql_, '"')).append("\" ");
}
//
// QRNumericVal
//
QRNumericVal::QRNumericVal(QRElement *parent, AttributeList atts,
ADD_MEMCHECK_ARGS_DEF(NAMemory* heap))
: QRScalarValue(ET_NumericVal, parent, atts, ADD_MEMCHECK_ARGS_PASS(heap)),
unscaledNumericVal_(0), numericScale_(0), scale_(heap)
{
XMLAttributeIterator iter(atts);
const char *attrName;
while (iter.hasNext())
{
iter.next();
attrName = iter.getName();
if (!strcmp(attrName, "scale"))
scale_ = iter.getValue();
}
}
void QRNumericVal::setValue(const NAString& value)
{
// synchNumericValue() uses the string representation of the value, so set
// that first.
setStringRep(value);
synchNumericValue();
}
void QRNumericVal::setNumericVal(Int64 unscaledVal, Int32 scale)
{
unscaledNumericVal_ = unscaledVal;
numericScale_ = scale;
// Keep string representations of unscaled value and scale consistent with
// the new value.
snprintf(buf,
sizeof(buf),
"%0*ld",
scale + (unscaledVal < 0), // add one for sign if negative
unscaledVal);
stringRep_ = buf;
if (scale > 0)
stringRep_.insert(stringRep_.length() - scale, ".");
snprintf(buf, sizeof(buf), "%d", scale);
scale_ = buf;
}
void QRNumericVal::synchNumericValue()
{
// Store the scale and the unscaled numeric value.
// @ZX -- This needs sorting out. It uses the scale attribute rather than the
// position of the decimal point in the string representation of the
// constant. The scale attribute is redundant with the scaled
// representation of the value that is the content of QRNumericVal, and
// this needs to be resolved.
if (strlen(scale_.data()) > 0)
sscanf(scale_.data(), "%d", &numericScale_);
Int64 fractionalPart = 0;
sscanf(stringRep_.data(),
PFLL "." PFLL,
&unscaledNumericVal_, &fractionalPart);
unscaledNumericVal_ *= (Int64)pow(10, numericScale_);
unscaledNumericVal_ += fractionalPart;
}
//
// QRStringVal
//
void QRStringVal::toXML(XMLString& xml, NABoolean dummy1, NABoolean dummy2)
{
// Put the content (the string value) directly between the start and end tags
// with no spaces or newlines added. No whitespace will be stripped from
// StringVal's content when deserialized, allowing for leading and trailing
// whitespace that is part of the actual string value.
XMLElement::toXML(xml, TRUE);
}
//
// QRWStringVal
//
void QRWStringVal::toXML(XMLString& xml, NABoolean dummy1, NABoolean dummy2)
{
// Put the content (the string value) directly between the start and end tags
// with no spaces or newlines added.
XMLElement::toXML(xml, TRUE);
}
// Restore the actual code point for a Unicode character encoded as a sequence
// of 4 hex digits. Get the 4-bit value for each hex digit and shift it into
// position, taking endianness into account.
NAWchar QRWStringVal::decode_(const char* buf) const
{
#ifdef NA_LITTLE_ENDIAN
const char* low = buf;
const char* high = buf+2;
#else
const char* low = buf+2;
const char* high = buf;
#endif
NAWchar val = (isdigit(*high) ? *high-48 : *high-55) << 12;
val += (isdigit(*(high+1)) ? *(high+1)-48 : *(high+1)-55) << 8;
val += (isdigit(*low) ? *low-48 : *low-55) << 4;
val += (isdigit(*(low+1)) ? *(low+1)-48 : *(low+1)-55);
return val;
}
// XML parsers have a good deal of latitude in how they break up character data
// into calls to this function. The problem for us is that it takes a sequence
// of 4 characters of input to decode the sequence into a Unicode character. If
// our buffer runs out in the middle of a char's representation, we have to hold
// on to the initial part, and put it together with the remaining hex digits
// for that character in the next call.
void QRWStringVal::charData(void *parser, const char *data, Int32 len)
{
Int32 startOfst = 0;
NAWchar wch;
// if danglingCharCount_ is nonzero, we're holding a partial representation
// from the previous call.
if (danglingCharCount_)
{
// We don't handle the case where the representation of a single char
// spans 3 calls to this function.
assertLogAndThrow(CAT_SQL_COMP_QR_DESC_GEN, LL_MVQR_FAIL,
len >= 4-danglingCharCount_,
QRDescriptorException,
"charData() received buffer that does not complete dangling char");
// Copy the remainder to our local buffer and decode.
memcpy(danglingChars_ + danglingCharCount_,
data,
4 - danglingCharCount_);
wch = decode_(danglingChars_);
wideStringRep_.append(&wch, 1);
startOfst = (4 - danglingCharCount_); // update starting point in passed buffer
}
// Decode each 4-byte sequence in the buffer, and append to the wide char
// string.
for (Int32 i=startOfst; i<len-3; i+=4)
{
wch = decode_(data+i);
wideStringRep_.append(&wch, 1);
}
// If there are chars left over (max 3), save them in separate buffer for when
// we get the rest in the next call.
danglingCharCount_ = (len - startOfst) % 4;
if (danglingCharCount_)
memcpy(danglingChars_, data + len - danglingCharCount_, danglingCharCount_);
}
// This array maps the value of a byte to the hex digit pair that represents the
// same value in hex.
static const char* hexArray[] =
{
"00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0A", "0B", "0C", "0D", "0E", "0F",
"10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1A", "1B", "1C", "1D", "1E", "1F",
"20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2A", "2B", "2C", "2D", "2E", "2F",
"30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "3A", "3B", "3C", "3D", "3E", "3F",
"40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "4A", "4B", "4C", "4D", "4E", "4F",
"50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "5A", "5B", "5C", "5D", "5E", "5F",
"60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6A", "6B", "6C", "6D", "6E", "6F",
"70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7A", "7B", "7C", "7D", "7E", "7F",
"80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8A", "8B", "8C", "8D", "8E", "8F",
"90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9A", "9B", "9C", "9D", "9E", "9F",
"A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9", "AA", "AB", "AC", "AD", "AE", "AF",
"B0", "B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8", "B9", "BA", "BB", "BC", "BD", "BE", "BF",
"C0", "C1", "C2", "C3", "C4", "C5", "C6", "C7", "C8", "C9", "CA", "CB", "CC", "CD", "CE", "CF",
"D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7", "D8", "D9", "DA", "DB", "DC", "DD", "DE", "DF",
"E0", "E1", "E2", "E3", "E4", "E5", "E6", "E7", "E8", "E9", "EA", "EB", "EC", "ED", "EE", "EF",
"F0", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "FA", "FB", "FC", "FD", "FE", "FF",
};
// For each of the double-byte characters that make up the wide string value,
// encode it in 4 hex digits and append them to the XML document.
void QRWStringVal::serializeBody(XMLString& xml)
{
// chPtr MUST be unsigned, or value when used as an index could be negative.
const unsigned char* chPtr = (const unsigned char*)wideStringRep_.data();
size_t wchLen = wideStringRep_.length();
for (size_t i=0; i<wchLen; i++)
{
xml.append(hexArray[*chPtr++]);
xml.append(hexArray[*chPtr++]);
}
}
//
// QRGroupBy
//
QRGroupBy::QRGroupBy(XMLElementPtr parent, AttributeList atts,
ADD_MEMCHECK_ARGS_DEF(NAMemory* heap))
: QRElement(ET_GroupBy, parent, ADD_MEMCHECK_ARGS_PASS(heap)),
result_(INVALID_EXPR_RESULT),
primary_(NULL),
dependent_(NULL),
minimal_(NULL),
tableList_(NULL)
{
XMLAttributeIterator iter(atts);
const char *attrName;
while (iter.hasNext())
{
iter.next();
attrName = iter.getName();
if (!strcmp(attrName, "id"))
id_ = iter.getValue();
else if (!strcmp(attrName, "ref"))
ref_ = iter.getValue();
else if (!strcmp(attrName, "result"))
result_ = encodeResult(iter.getValue());
else
throw QRDescriptorException("Invalid attribute specified for element %s: %s",
elemName, attrName);
}
}
QRGroupBy::~QRGroupBy()
{
deletePtr(primary_);
deletePtr(dependent_);
deletePtr(minimal_);
deletePtr(tableList_);
}
void QRGroupBy::serializeAttrs(XMLString& xml)
{
QRElement::serializeAttrs(xml);
if (result_ != INVALID_EXPR_RESULT)
xml.append("result='").append(ExprResultNames[result_]).append("' ");
}
void QRGroupBy::serializeBody(XMLString& xml)
{
if (primary_ && !primary_->isEmpty())
primary_->toXML(xml);
if (dependent_ && !dependent_->isEmpty())
dependent_->toXML(xml);
if (minimal_ && !minimal_->isEmpty())
minimal_->toXML(xml);
if (tableList_ && !tableList_->isEmpty())
tableList_->toXML(xml);
}
NABoolean QRGroupBy::treeWalk(VisitorPtr visitor)
{
VISIT_THIS(visitor, this);
if (primary_ && primary_->treeWalk(visitor))
return TRUE;
if (dependent_ && dependent_->treeWalk(visitor))
return TRUE;
if (minimal_ && minimal_->treeWalk(visitor))
return TRUE;
if (tableList_ && tableList_->treeWalk(visitor))
return TRUE;
return FALSE;
}
void QRGroupBy::startElement(void *parser, const char *elementName, const char **atts)
{
QRElementPtr elem = NULL;
if (!strcmp(elementName, QRPrimaryGroupBy::elemName))
{
primary_ = new (XMLPARSEHEAP) QRPrimaryGroupBy(CHILD_ELEM_ARGS(XMLPARSEHEAP));
elem = primary_;
}
else if (!strcmp(elementName, QRDependentGroupBy::elemName))
{
dependent_ = new (XMLPARSEHEAP) QRDependentGroupBy(CHILD_ELEM_ARGS(XMLPARSEHEAP));
elem = dependent_;
}
else if (!strcmp(elementName, QRMinimalGroupBy::elemName))
{
minimal_ = new (XMLPARSEHEAP) QRMinimalGroupBy(CHILD_ELEM_ARGS(XMLPARSEHEAP));
elem = minimal_;
}
else if (!strcmp(elementName, QRList<QRTable>::elemName))
{
tableList_ = new (XMLPARSEHEAP) QRList<QRTable>(CHILD_ELEM_ARGS(XMLPARSEHEAP));
elem = tableList_;
}
else
{
throw QRDescriptorException("Element %s cannot contain element %s",
elemName, elementName);
}
XMLDocument::setCurrentElement(parser, elem);
}
//
// QRPrimaryGroupBy
//
QRPrimaryGroupBy::QRPrimaryGroupBy(XMLElementPtr parent, AttributeList atts,
ADD_MEMCHECK_ARGS_DEF(NAMemory* heap))
: QRElementList(ET_PrimaryGroupBy, parent, NULL, ADD_MEMCHECK_ARGS_PASS(heap))
{
if (*atts)
throw QRDescriptorException("Invalid attribute specified for element %s: %s",
elemName, *atts);
}
void QRPrimaryGroupBy::startElement(void *parser, const char *elementName, const char **atts)
{
QRElementList::startItemExprElement(parser, elementName, atts);
}
//
// QRDependentGroupBy
//
QRDependentGroupBy::QRDependentGroupBy(XMLElementPtr parent, AttributeList atts,
ADD_MEMCHECK_ARGS_DEF(NAMemory* heap))
: QRElementList(ET_DependentGroupBy, parent, NULL, ADD_MEMCHECK_ARGS_PASS(heap))
{
if (*atts)
throw QRDescriptorException("Invalid attribute specified for element %s: %s",
elemName, *atts);
}
void QRDependentGroupBy::startElement(void *parser, const char *elementName, const char **atts)
{
QRElementList::startItemExprElement(parser, elementName, atts);
}
//
// QRMinimalGroupBy
//
QRMinimalGroupBy::QRMinimalGroupBy(XMLElementPtr parent, AttributeList atts,
ADD_MEMCHECK_ARGS_DEF(NAMemory* heap))
: QRElementList(ET_MinimalGroupBy, parent, NULL, ADD_MEMCHECK_ARGS_PASS(heap))
{
if (*atts)
throw QRDescriptorException("Invalid attribute specified for element %s: %s",
elemName, *atts);
}
void QRMinimalGroupBy::startElement(void *parser, const char *elementName, const char **atts)
{
QRElementList::startItemExprElement(parser, elementName, atts);
}
//
// QRColumn
//
QRColumn::QRColumn(XMLElementPtr parent, AttributeList atts,
ADD_MEMCHECK_ARGS_DEF(NAMemory* heap))
: QRExplicitExpr(ET_Column, parent, ADD_MEMCHECK_ARGS_PASS(heap)),
tableId_(heap),
fqColumnName_(charData_),
columnName_(heap),
isExtraHub_(FALSE),
colIndex_(-1),
isNullable_(1),
vegrefVid_(0)
{
XMLAttributeIterator iter(atts);
const char *attrName;
const char *attrValue;
while (iter.hasNext())
{
iter.next();
attrName = iter.getName();
attrValue = iter.getValue();
if (!strcmp(attrName, "id"))
id_ = attrValue;
else if (!strcmp(attrName, "ref"))
ref_ = attrValue;
else if (!strcmp(attrName, "tableId"))
tableId_ = attrValue;
else if (!strcmp(attrName, "colIndex"))
colIndex_ = atoi(attrValue);
else if (!strcmp(attrName, "isNullable"))
deserializeBoolAttr(attrName, attrValue, isNullable_);
else
throw QRDescriptorException("Invalid attribute specified for element %s: %s",
elemName, attrName);
}
}
// Redefined to initialize the non-fully qualified column name.
void QRColumn::charData(void *parser, const char *data, Int32 len)
{
// Call the superclass first to initialize the fully qualified column name.
QRElement::charData(parser, data, len);
// Extract the col name from the fully qualified version and set it.
setColumnName_();
}
void QRColumn::serializeAttrs(XMLString& xml)
{
QRElement::serializeAttrs(xml);
if (tableId_.length() > 0)
xml.append("tableId='").append(tableId_).append("' ");
if (colIndex_ != -1)
{
char buffer[20];
snprintf(buffer, sizeof(buffer), "colIndex='%d' ", colIndex_);
xml.append(buffer);
}
if (isNullable_ == FALSE)
xml.append("isNullable='0' ");
}
void QRColumn::setColumnName_()
{
if (fqColumnName_.length() > 0) // QRColumn with ref attr won't include name
{
// Find the position of the column name after the last dot
UInt32 pos = fqColumnName_.last('.')+1;
UInt32 length = fqColumnName_.length();
// Set the column name.
columnName_ = fqColumnName_(pos, length - pos);
}
}
void QRColumn::unparse(NAString& text, NABoolean useColumnName)
{
if (!useColumnName)
text.append("<col>"); //"%s";
else
text.append(getReferencedElement()->getSortName());
}
QRColumnPtr QRColumn::getFirstColumn()
{
if (getReferencedElement() == this)
return this;
else
return getReferencedElement()->getFirstColumn();
}
//
// QRExpr
//
QRExpr::QRExpr(XMLElementPtr parent, AttributeList atts, NABoolean isResidual,
ADD_MEMCHECK_ARGS_DEF(NAMemory* heap))
: QRElement(ET_Expr, parent, ADD_MEMCHECK_ARGS_PASS(heap)),
exprRoot_(NULL),
unparsedTextWithNames_(heap),
unparsedTextNoNames_(heap),
unparsedTextCharSet_(CharInfo::ISO88591),
inputColumns_(heap),
isResidual_(isResidual),
isExtraHub_(FALSE),
result_(INVALID_EXPR_RESULT),
info_(NULL)
{
XMLAttributeIterator iter(atts);
const char *attrName;
while (iter.hasNext())
{
iter.next();
attrName = iter.getName();
if (!strcmp(attrName, "id"))
id_ = iter.getValue();
else if (!strcmp(attrName, "ref"))
ref_ = iter.getValue();
else if (!strcmp(attrName, "result"))
{
assertLogAndThrow(CAT_SQL_COMP_QR_DESC_GEN, LL_MVQR_FAIL,
isResidual_, QRDescriptorException,
"'result' attribute specified for non-residual expr.");
result_ = encodeResult(iter.getValue());
}
else
throw QRDescriptorException("Invalid attribute specified for element %s: %s",
getElementName(), //@ZXresid -- virtual fn in ctor
attrName);
}
}
QRExpr::~QRExpr()
{
deletePtr(exprRoot_);
inputColumns_.clear();
deletePtr(info_);
}
void QRExpr::serializeAttrs(XMLString& xml)
{
QRElement::serializeAttrs(xml);
if (result_ != INVALID_EXPR_RESULT)
xml.append("result='").append(ExprResultNames[result_]).append("' ");
}
void QRExpr::serializeBody(XMLString& xml)
{
if (exprRoot_)
exprRoot_->toXML(xml);
if (info_)
info_->toXML(xml);
}
NABoolean QRExpr::treeWalk(VisitorPtr visitor)
{
VISIT_THIS(visitor, this);
if (exprRoot_ && exprRoot_->treeWalk(visitor))
return TRUE;
return FALSE;
}
void QRExpr::startElement(void *parser, const char *elementName, const char **atts)
{
if (!strcmp(elementName, QRBinaryOper::elemName))
{
exprRoot_ = new (XMLPARSEHEAP) QRBinaryOper(CHILD_ELEM_ARGS(XMLPARSEHEAP));
XMLDocument::setCurrentElement(parser, exprRoot_);
}
else if (!strcmp(elementName, QRFunction::elemName))
{
exprRoot_ = new (XMLPARSEHEAP) QRFunction(CHILD_ELEM_ARGS(XMLPARSEHEAP));
XMLDocument::setCurrentElement(parser, exprRoot_);
}
else if (!strcmp(elementName, QRUnaryOper::elemName))
{
exprRoot_ = new (XMLPARSEHEAP) QRUnaryOper(CHILD_ELEM_ARGS(XMLPARSEHEAP));
XMLDocument::setCurrentElement(parser, exprRoot_);
}
else if (!strcmp(elementName, QRMVColumn::elemName))
{
exprRoot_ = new (XMLPARSEHEAP) QRMVColumn(CHILD_ELEM_ARGS(XMLPARSEHEAP));
XMLDocument::setCurrentElement(parser, exprRoot_);
}
else if (!strcmp(elementName, QRInfo::elemName))
{
info_ = new (XMLPARSEHEAP) QRInfo(CHILD_ELEM_ARGS(XMLPARSEHEAP));
XMLDocument::setCurrentElement(parser, info_);
}
else
{
throw QRDescriptorException("Element %s cannot contain element %s",
getElementName(), elementName);
}
}
const NAString& QRExpr::getExprText(NABoolean useColumnName)
{
NAString& unparsedText = useColumnName ? unparsedTextWithNames_ : unparsedTextNoNames_;
if (unparsedText == "")
{
assertLogAndThrow(CAT_SQL_COMP_QR_COMMON, LL_MVQR_FAIL,
exprRoot_, QRDescriptorException,
"QRExpr has null exprRoot_ and no unparsed text");
exprRoot_->unparse(unparsedText, useColumnName);
}
return unparsedText;
}
const ElementPtrList& QRExpr::getInputColumns(CollHeap* heap,
NABoolean useRefedElem)
{
if (inputColumns_.entries() == 0)
{
assertLogAndThrow(CAT_SQL_COMP_QR_DESC_GEN, LL_MVQR_FAIL,
exprRoot_, QRDescriptorException,
"QRExpr has null exprRoot_ and no input columns");
exprRoot_->getInputColumns(inputColumns_, heap, useRefedElem);
}
return inputColumns_;
}
QRColumnPtr QRExpr::getFirstColumn()
{
const ElementPtrList& eqList = getInputColumns(NULL);
if (eqList.entries() == 0)
return NULL;
else
return eqList[0]->getReferencedElement()->getFirstColumn();
}
//
// QRExplicitExpr
//
NABoolean QRExplicitExpr::containsAnAggregate(CollHeap* heap)
{
// Return cached value if we've done this already.
if (containsAnAggregate_ != AGGREGATE_UNKNOWN)
return (NABoolean)containsAnAggregate_;
AggregateFinderVisitorPtr aggVisitor
= new(heap) AggregateFinderVisitor(ADD_MEMCHECK_ARGS(heap));
treeWalk(aggVisitor);
NABoolean returnValue = aggVisitor->foundAggregate();
containsAnAggregate_ = (enum AggregateStatus)returnValue; // cache the result
deletePtr(aggVisitor);
return returnValue;
}
QRExplicitExprPtr QRExplicitExpr::deepCopyAndSwitch(subExpressionRewriteHash& subExpressions,
CollHeap* heap)
{
const NAString* id = &getID();
if (*id == "")
id = &getRef();
if(subExpressions.contains(id))
{
const QRExplicitExprPtr mvCol = subExpressions.getFirstValue(id);
subExpressions.remove(id);
return mvCol;
}
else
{
QRExplicitExprPtr dup = deepCopy(subExpressions, heap);
dup->setRef(*id);
return dup;
}
}
QRExplicitExprPtr QRExplicitExpr::constructSubElement(void *parser,
const char *elementName,
const char **atts)
{
QRExplicitExprPtr elem;
if (!strcmp(elementName, QRColumn::elemName))
elem = new (XMLPARSEHEAP) QRColumn(CHILD_ELEM_ARGS(XMLPARSEHEAP));
else if (!strcmp(elementName, QRMVColumn::elemName))
elem = new (XMLPARSEHEAP) QRMVColumn(CHILD_ELEM_ARGS(XMLPARSEHEAP));
else if (!strcmp(elementName, QRBinaryOper::elemName))
elem = new (XMLPARSEHEAP) QRBinaryOper(CHILD_ELEM_ARGS(XMLPARSEHEAP));
else if (!strcmp(elementName, QRFunction::elemName))
elem = new (XMLPARSEHEAP) QRFunction(CHILD_ELEM_ARGS(XMLPARSEHEAP));
else if (!strcmp(elementName, QRUnaryOper::elemName))
elem = new (XMLPARSEHEAP) QRUnaryOper(CHILD_ELEM_ARGS(XMLPARSEHEAP));
else if (!strcmp(elementName, QRStringVal::elemName))
elem = new (XMLPARSEHEAP) QRStringVal(CHILD_ELEM_ARGS(XMLPARSEHEAP));
else if (!strcmp(elementName, QRWStringVal::elemName))
elem = new (XMLPARSEHEAP) QRWStringVal(CHILD_ELEM_ARGS(XMLPARSEHEAP));
else if (!strcmp(elementName, QRNumericVal::elemName))
elem = new (XMLPARSEHEAP) QRNumericVal(CHILD_ELEM_ARGS(XMLPARSEHEAP));
else if (!strcmp(elementName, QRFloatVal::elemName))
elem = new (XMLPARSEHEAP) QRFloatVal(CHILD_ELEM_ARGS(XMLPARSEHEAP));
else if (!strcmp(elementName, QRNullVal::elemName))
elem = new (XMLPARSEHEAP) QRNullVal(CHILD_ELEM_ARGS(XMLPARSEHEAP));
else
{
throw QRDescriptorException("Element %s cannot contain element %s",
getElementName(), elementName);
}
return elem;
}
void QRExplicitExpr::getInputColumns(ElementPtrList& inputList, CollHeap* heap,
NABoolean useRefedElem)
{
NAList<ElementType> elemTypes(heap);
elemTypes.insert(ET_Column);
elemTypes.insert(ET_MVColumn);
ElementFinderVisitorPtr visitor =
new(heap) ElementFinderVisitor(elemTypes, useRefedElem,
ADD_MEMCHECK_ARGS(heap));
treeWalk(visitor);
inputList = visitor->getElementsFound();
deletePtr(visitor);
}
//
// QRBinaryOper
//
QRBinaryOper::QRBinaryOper(XMLElementPtr parent, AttributeList atts,
ADD_MEMCHECK_ARGS_DEF(NAMemory* heap))
: QRExplicitExpr(ET_BinaryOper, parent, ADD_MEMCHECK_ARGS_PASS(heap)),
operator_(heap),
firstOperand_(NULL),
secondOperand_(NULL)
{
XMLAttributeIterator iter(atts);
const char *attrName;
while (iter.hasNext())
{
iter.next();
attrName = iter.getName();
if (!strcmp(attrName, "id"))
id_ = iter.getValue();
else if (!strcmp(attrName, "ref"))
ref_ = iter.getValue();
else if (!strcmp(attrName, "op"))
operator_ = iter.getValue();
else
throw QRDescriptorException("Invalid attribute specified for element %s: %s",
elemName, attrName);
}
}
void QRBinaryOper::serializeAttrs(XMLString& xml)
{
QRExplicitExpr::serializeAttrs(xml);
if (operator_.length() > 0)
{
const char* opText = operator_.data();
xml.append("op='");
if (*opText == '<')
{
// Use entity reference in place of '<' to avoid illegal attribute.
xml.append("&lt;");
opText++;
}
xml.append(opText).append("' ");
}
}
void QRBinaryOper::serializeBody(XMLString& xml)
{
if (firstOperand_)
firstOperand_->toXML(xml);
if (secondOperand_)
secondOperand_->toXML(xml);
}
NABoolean QRBinaryOper::treeWalk(VisitorPtr visitor)
{
VISIT_THIS(visitor, this);
if (firstOperand_ && firstOperand_->treeWalk(visitor))
return TRUE;
if (secondOperand_ && secondOperand_->treeWalk(visitor))
return TRUE;
return FALSE;
}
void QRBinaryOper::startElement(void* parser, const char* elementName, const char** atts)
{
QRExplicitExprPtr elem = constructSubElement(parser, elementName, atts);
if (!firstOperand_)
firstOperand_ = elem;
else if (!secondOperand_)
secondOperand_ = elem;
else
throw QRDescriptorException("More than two operands given for binary operator "
"with id=%s", id_.data());
XMLDocument::setCurrentElement(parser, elem);
}
//
// QRUnaryOper
//
QRUnaryOper::QRUnaryOper(XMLElementPtr parent, AttributeList atts,
ADD_MEMCHECK_ARGS_DEF(NAMemory* heap))
: QRExplicitExpr(ET_UnaryOper, parent, ADD_MEMCHECK_ARGS_PASS(heap)),
operator_(heap),
operand_(NULL)
{
XMLAttributeIterator iter(atts);
const char *attrName;
while (iter.hasNext())
{
iter.next();
attrName = iter.getName();
if (!strcmp(attrName, "id"))
id_ = iter.getValue();
else if (!strcmp(attrName, "ref"))
ref_ = iter.getValue();
else if (!strcmp(attrName, "op"))
operator_ = iter.getValue();
else
throw QRDescriptorException("Invalid attribute specified for element %s: %s",
elemName, attrName);
}
}
void QRUnaryOper::serializeAttrs(XMLString& xml)
{
QRExplicitExpr::serializeAttrs(xml);
if (operator_.length() > 0)
xml.append("op='").append(operator_.data()).append("' ");
}
void QRUnaryOper::serializeBody(XMLString& xml)
{
if (operand_)
operand_->toXML(xml);
}
NABoolean QRUnaryOper::treeWalk(VisitorPtr visitor)
{
VISIT_THIS(visitor, this);
if (operand_ && operand_->treeWalk(visitor))
return TRUE;
return FALSE;
}
void QRUnaryOper::startElement(void *parser, const char *elementName, const char **atts)
{
QRExplicitExprPtr elem = constructSubElement(parser, elementName, atts);
if (!operand_)
operand_ = elem;
else
throw QRDescriptorException("More than one operand given for unary operator "
"with id=%s", id_.data());
XMLDocument::setCurrentElement(parser, elem);
}
//
// QRParameter
//
QRParameter::QRParameter(XMLElementPtr parent, AttributeList atts,
ADD_MEMCHECK_ARGS_DEF(NAMemory* heap))
: QRElement(ET_Parameter, parent, ADD_MEMCHECK_ARGS_PASS(heap)),
paramName_(heap), paramValue_(heap)
{
XMLAttributeIterator iter(atts);
const char *attrName;
while (iter.hasNext())
{
iter.next();
attrName = iter.getName();
if (!strcmp(attrName, "name"))
paramName_ = iter.getValue();
else if (!strcmp(attrName, "value"))
paramValue_ = iter.getValue();
else
throw QRDescriptorException("Invalid attribute specified for element %s: %s",
elemName, attrName);
}
}
void QRParameter::serializeAttrs(XMLString& xml)
{
assertLogAndThrow1(CAT_SQL_COMP_QR_DESC_GEN, LL_MVQR_FAIL,
paramName_.length() > 0, QRDescriptorException,
"'name' attribute not specified for %s element.", elemName);
assertLogAndThrow1(CAT_SQL_COMP_QR_DESC_GEN, LL_MVQR_FAIL,
paramValue_.length() > 0, QRDescriptorException,
"'value' attribute not specified for %s element.", elemName);
xml.append("name='").append(paramName_).append("\' ");
xml.append("value='").append(paramValue_).append("\' ");
}
//
// QRFunction
//
QRFunction::QRFunction(XMLElementPtr parent, AttributeList atts,
ADD_MEMCHECK_ARGS_DEF(NAMemory* heap))
: QRExplicitExpr(ET_Function, parent, ADD_MEMCHECK_ARGS_PASS(heap)),
function_(heap),
arguments_(heap),
hiddenParams_(heap),
aggregateFunc_(AFT_NONE)
{
XMLAttributeIterator iter(atts);
const char* attrName;
const char* attrVal;
while (iter.hasNext())
{
iter.next();
attrName = iter.getName();
attrVal = iter.getValue();
if (!strcmp(attrName, "id"))
id_ = attrVal;
else if (!strcmp(attrName, "ref"))
ref_ = iter.getValue();
else if (!strcmp(attrName, "op"))
function_ = attrVal;
else if (!strcmp(attrName, "aggregateFunc"))
aggregateFunc_ = (AggregateFunctionType)atoi(iter.getValue());
else
throw QRDescriptorException("Invalid attribute specified for element %s: %s",
getElementName(), attrName);
}
}
QRFunction::QRFunction(const QRFunction& other,
ADD_MEMCHECK_ARGS_DEF(NAMemory* heap))
: QRExplicitExpr(other, ADD_MEMCHECK_ARGS_PASS(heap)),
function_(other.function_, heap),
arguments_(heap),
hiddenParams_(heap),
aggregateFunc_(other.aggregateFunc_)
{
for (CollIndex i=0; i<other.hiddenParams_.entries(); i++)
addHiddenParam(new(heap) QRParameter(*other.hiddenParams_[i]));
}
QRFunction::~QRFunction()
{
for (CollIndex i = 0; i < arguments_.entries(); i++)
deletePtr(arguments_[i]);
for (CollIndex i = 0; i < hiddenParams_.entries(); i++)
deletePtr(hiddenParams_[i]);
}
void QRFunction::serializeAttrs(XMLString& xml)
{
QRExplicitExpr::serializeAttrs(xml);
if (function_.length() > 0)
xml.append("op='").append(function_.data()).append("' ");
if (aggregateFunc_ != AFT_NONE) // Optional attr, AF_NONE is the default.
{
char buffer[20];
snprintf(buffer, sizeof(buffer), "aggregateFunc='%d' ", (Int32)aggregateFunc_);
xml.append(buffer);
}
}
void QRFunction::serializeBody(XMLString& xml)
{
for (CollIndex i = 0; i < arguments_.entries(); i++)
arguments_[i]->toXML(xml);
for (CollIndex i = 0; i < hiddenParams_.entries(); i++)
hiddenParams_[i]->toXML(xml, FALSE, TRUE);
}
NABoolean QRFunction::treeWalk(VisitorPtr visitor)
{
VISIT_THIS(visitor, this);
for (CollIndex i = 0; i < arguments_.entries(); i++)
if (arguments_[i]->treeWalk(visitor))
return TRUE;
for (CollIndex i = 0; i < hiddenParams_.entries(); i++)
if (hiddenParams_[i]->treeWalk(visitor))
return TRUE;
return FALSE;
}
void QRFunction::startElement(void *parser, const char *elementName, const char **atts)
{
if (!strcmp(elementName, QRParameter::elemName))
{
QRParameterPtr param =
new (XMLPARSEHEAP) QRParameter(CHILD_ELEM_ARGS(XMLPARSEHEAP));
addHiddenParam(param);
XMLDocument::setCurrentElement(parser, param);
}
else
{
QRExplicitExprPtr elem = constructSubElement(parser, elementName, atts);
addArgument(elem);
XMLDocument::setCurrentElement(parser, elem);
}
}
void QRFunction::setAggregateFunc(OperatorTypeEnum itemExprType, NABoolean isDistinct)
{
if (isDistinct)
{
// ItemExpr::getText() for distinct aggregate functions returns a text
// that includes a ValueID. This breaks matching, so we need to override
// the function name.
NAString name;
switch (itemExprType)
{
case ITM_COUNT_NONULL:
aggregateFunc_ = AFT_COUNT_DISTINCT;
name = "count distinct";
break;
case ITM_SUM:
aggregateFunc_ = AFT_SUM_DISTINCT;
name = "sum distinct";
break;
default:
throw QRDescriptorException("Unsupported distinct aggregate function.");
}
setFunctionName(name);
}
else
{
switch (itemExprType)
{
case ITM_COUNT_NONULL:
aggregateFunc_ = AFT_COUNT;
break;
case ITM_COUNT:
aggregateFunc_ = AFT_COUNTSTAR;
break;
case ITM_SUM:
aggregateFunc_ = AFT_SUM;
break;
case ITM_MIN:
aggregateFunc_ = AFT_MIN;
break;
case ITM_MAX:
aggregateFunc_ = AFT_MAX;
break;
case ITM_ONE_ROW:
aggregateFunc_ = AFT_ONE_ROW;
break;
case ITM_ONEROW:
aggregateFunc_ = AFT_ONEROW;
break;
case ITM_ONE_TRUE:
aggregateFunc_ = AFT_ONE_TRUE;
break;
case ITM_ANY_TRUE:
aggregateFunc_ = AFT_ANY_TRUE;
break;
// AVG is not listed here because by now it will get translated to SUM/COUNT.
// STDDEV/VARIANCE get translated to ScalarVariance(SUM*SUM, SUM, COUNT)
default:
throw QRDescriptorException("Unsupported aggregate function.");
}
}
}
NABoolean QRFunction::isCountStarEquivalent(CollHeap* heap)
{
// If its a COUNT(*), than its really easy.
if (aggregateFunc_ == AFT_COUNTSTAR)
return TRUE;
// If its not a COUNT, forget it.
else if (aggregateFunc_ != AFT_COUNT)
return FALSE;
// OK, this is a COUNT.
// Now check that all the input columns are not nullable.
ElementPtrList inputList(heap);
getInputColumns(inputList, heap);
NABoolean allInputsAreNotNullable = TRUE;
for (CollIndex i=0; i<inputList.entries(); i++)
{
QRElementPtr input = inputList[i]->getReferencedElement();
if (input->getElementType() != ET_Column)
{
// This is a join pred. Don't bother for now.
allInputsAreNotNullable = FALSE;
break;
}
QRColumnPtr inputCol = input->downCastToQRColumn();
if (inputCol->isNullable())
{
allInputsAreNotNullable = FALSE;
break;
}
}
return allInputsAreNotNullable;
}
void QRFunction::unparse(NAString& text, NABoolean useColumnName)
{
if (function_ == "cast")
{
// Skip Cast functions.
arguments_[0]->unparse(text, useColumnName);
}
else
{
text.append(function_ + "[");
// Do the parameters inside square brackets.
for (CollIndex j=0; j<hiddenParams_.entries(); j++)
{
QRParameterPtr param = hiddenParams_[j];
text.append(param->getName() + "=" + param->getValue() + " ");
}
// And then the argumants inside parenthesis.
text.append("](");
CollIndex maxEntries = arguments_.entries();
for (CollIndex i=0; i<maxEntries; i++)
{
arguments_[i]->unparse(text, useColumnName);
if (i != maxEntries-1)
text.append(", ");
}
text.append(")");
}
}
//
// QRMVColumn
//
QRMVColumn::QRMVColumn(XMLElementPtr parent, AttributeList atts,
ADD_MEMCHECK_ARGS_DEF(NAMemory* heap))
: QRExplicitExpr(ET_MVColumn, parent, ADD_MEMCHECK_ARGS_PASS(heap)),
mv_(heap),
mvColName_(charData_),
aggForRewrite_(ITM_NOT) // This means not initialized.
{
XMLAttributeIterator iter(atts);
const char *attrName;
while (iter.hasNext())
{
iter.next();
attrName = iter.getName();
if (!strcmp(attrName, "MV"))
mv_ = iter.getValue();
else if (!strcmp(attrName, "ref"))
ref_ = iter.getValue();
else
throw QRDescriptorException("Invalid attribute specified for element %s: %s",
elemName, attrName);
}
}
void QRMVColumn::serializeAttrs(XMLString& xml)
{
QRElement::serializeAttrs(xml);
if (mv_.length() > 0)
xml.append("MV='").append(mv_).append("' ");
}
NABoolean QRMVColumn::hasRefTo(CollIndex vid)
{
NumericID refNum = getRefNum();
char firstChar = getRefFirstChar();
switch (firstChar)
{
case 'C':
return vid == refNum;
case 'J':
{
QRJoinPredPtr joinPred = getReferencedElement()->downCastToQRJoinPred();
const ElementPtrList& eqList = joinPred->getEqualityList();
for (CollIndex i=0; i<eqList.entries(); i++)
{
if (vid == eqList[i]->getReferencedElement()->getIDNum())
return TRUE;
}
return FALSE;
}
// Default includes ' ', returned by getRefFirstChar() when there is no ref.
default:
return FALSE;
}
}
//
// QROutput
//
QROutput::QROutput(XMLElementPtr parent, AttributeList atts,
ADD_MEMCHECK_ARGS_DEF(NAMemory* heap))
: QRElementList(ET_Output, parent, NULL, ADD_MEMCHECK_ARGS_PASS(heap)),
name_(heap),
result_(INVALID_EXPR_RESULT),
colPos_(-1)
{
XMLAttributeIterator iter(atts);
const char *attrName;
while (iter.hasNext())
{
iter.next();
attrName = iter.getName();
if (!strcmp(attrName, "id"))
id_ = iter.getValue();
else if (!strcmp(attrName, "name"))
name_ = iter.getValue();
else if (!strcmp(attrName, "ref"))
ref_ = iter.getValue();
else if (!strcmp(attrName, "result"))
result_ = encodeResult(iter.getValue());
else
throw QRDescriptorException("Invalid attribute specified for element %s: %s",
elemName, attrName);
}
}
void QROutput::serializeAttrs(XMLString& xml)
{
QRElement::serializeAttrs(xml);
if (name_.length() > 0)
xml.append("name='").append(name_).append("' ");
if (result_ != INVALID_EXPR_RESULT)
xml.append("result='").append(ExprResultNames[result_]).append("' ");
}
void QROutput::startElement(void *parser, const char *elementName, const char **atts)
{
QRElementList::startItemExprElement(parser, elementName, atts);
}
//
// QRExtraHub
//
void QRExtraHub::serializeBody(XMLString& xml)
{
if (tableList_ && !tableList_->isEmpty())
tableList_->toXML(xml);
if (joinPredList_ && !joinPredList_->isEmpty())
joinPredList_->toXML(xml);
}
NABoolean QRExtraHub::treeWalk(VisitorPtr visitor)
{
VISIT_THIS(visitor, this);
if (tableList_ && !tableList_->isEmpty() && tableList_->treeWalk(visitor))
return TRUE;
if (joinPredList_ && !joinPredList_->isEmpty() && joinPredList_->treeWalk(visitor))
return TRUE;
return FALSE;
}
void QRExtraHub::startElement(void *parser, const char *elementName, const char **atts)
{
if (!strcmp(elementName, QRList<QRTable>::elemName))
{
tableList_ = new (XMLPARSEHEAP) QRList<QRTable>(CHILD_ELEM_ARGS(XMLPARSEHEAP));
XMLDocument::setCurrentElement(parser, tableList_);
}
else if (!strcmp(elementName, QRList<QRJoinPred>::elemName))
{
joinPredList_ = new (XMLPARSEHEAP) QRList<QRJoinPred>(CHILD_ELEM_ARGS(XMLPARSEHEAP));
XMLDocument::setCurrentElement(parser, joinPredList_);
}
else
{
throw QRDescriptorException("Element %s cannot contain element %s",
elemName, elementName);
}
}
//
// QRMVMisc
//
QRMVMisc::QRMVMisc(XMLElementPtr parent, AttributeList atts,
ADD_MEMCHECK_ARGS_DEF(NAMemory* heap))
: QRElement(ET_MVMisc, parent, ADD_MEMCHECK_ARGS_PASS(heap)),
isolationLevel_(0), // @ZX -- what should default be?
isIncremental_(FALSE),
isImmediate_(FALSE),
isFromQuery_(FALSE),
isUMV_(FALSE)
{
XMLAttributeIterator iter(atts);
const char *attrName;
while (iter.hasNext())
{
iter.next();
attrName = iter.getName();
if (!strcmp(attrName, "isolationLevel"))
isolationLevel_ = atoi(iter.getValue());
else if (!strcmp(attrName, "isIncremental"))
deserializeBoolAttr(attrName, iter.getValue(), isIncremental_);
else if (!strcmp(attrName, "isImmediate"))
deserializeBoolAttr(attrName, iter.getValue(), isImmediate_);
else if (!strcmp(attrName, "isFromQuery"))
deserializeBoolAttr(attrName, iter.getValue(), isFromQuery_);
else if (!strcmp(attrName, "isUMV"))
deserializeBoolAttr(attrName, iter.getValue(), isUMV_);
else
throw QRDescriptorException("Invalid attribute specified for element %s: %s",
elemName, attrName);
}
}
void QRMVMisc::serializeAttrs(XMLString& xml)
{
QRElement::serializeAttrs(xml);
// Isolation level matching not implemented.
//char buffer[20];
//sprintf(buffer, "isolationLevel='%d' ", isolationLevel_);
//xml.append(buffer);
serializeBoolAttr("isIncremental", isIncremental_, xml);
if (isImmediate_)
serializeBoolAttr("isImmediate", isImmediate_, xml);
if (isFromQuery_)
serializeBoolAttr("isFromQuery", isFromQuery_, xml);
if (isUMV_)
serializeBoolAttr("isUMV", isUMV_, xml);
}
//
// QRMVDescriptor
//
QRMVDescriptor::QRMVDescriptor(AttributeList atts,
ADD_MEMCHECK_ARGS_DEF(NAMemory* heap))
: QRDescriptor(ET_MVDescriptor, ADD_MEMCHECK_ARGS_PASS(heap)),
version_(NULL),
table_(NULL),
misc_(NULL) //,
//jbbList_(heap)
{
// Set parent here so we don't have to use 'this' in initializer
setParent(this);
if (*atts)
throw QRDescriptorException("<%s> should have no attributes; attribute %s specified",
getElementName(), *atts);
}
QRMVDescriptor::~QRMVDescriptor()
{
deletePtr(version_);
deletePtr(table_);
deletePtr(misc_);
for (CollIndex i = 0; i < jbbList_.entries(); i++)
deletePtr(jbbList_[i]);
}
void QRMVDescriptor::serializeAttrs(XMLString& xml)
{
QRElement::serializeAttrs(xml);
}
void QRMVDescriptor::serializeBody(XMLString& xml)
{
if (version_)
version_->toXML(xml);
if (table_)
table_->toXML(xml);
if (misc_)
misc_->toXML(xml);
for (CollIndex i = 0; i < jbbList_.entries(); i++)
jbbList_[i]->toXML(xml);
}
NABoolean QRMVDescriptor::treeWalk(VisitorPtr visitor)
{
VISIT_THIS(visitor, this);
if (version_ && version_->treeWalk(visitor))
return TRUE;
if (table_ && table_->treeWalk(visitor))
return TRUE;
if (misc_ && misc_->treeWalk(visitor))
return TRUE;
for (CollIndex i = 0; i < jbbList_.entries(); i++)
if (jbbList_[i]->treeWalk(visitor))
return TRUE;
return FALSE;
}
void QRMVDescriptor::startElement(void *parser, const char *elementName, const char **atts)
{
if (!strcmp(elementName, QRVersion::elemName))
{
version_ = new (XMLPARSEHEAP) QRVersion(CHILD_ELEM_ARGS(XMLPARSEHEAP));
XMLDocument::setCurrentElement(parser, version_);
}
else if (!strcmp(elementName, QRTable::elemName))
{
table_ = new (XMLPARSEHEAP) QRTable(CHILD_ELEM_ARGS(XMLPARSEHEAP));
XMLDocument::setCurrentElement(parser, table_);
}
else if (!strcmp(elementName, QRMVMisc::elemName))
{
misc_ = new (XMLPARSEHEAP) QRMVMisc(CHILD_ELEM_ARGS(XMLPARSEHEAP));
XMLDocument::setCurrentElement(parser, misc_);
}
else if (!strcmp(elementName, QRJBB::elemName))
{
QRJBBPtr jbb = new (XMLPARSEHEAP) QRJBB(CHILD_ELEM_ARGS(XMLPARSEHEAP));
addJBB(jbb);
XMLDocument::setCurrentElement(parser, jbb);
}
else
{
throw QRDescriptorException("Element %s cannot contain element %s",
elemName, elementName);
}
}
//
// QRMVName
//
QRMVName::QRMVName(XMLElementPtr parent, AttributeList atts,
ADD_MEMCHECK_ARGS_DEF(NAMemory* heap))
: QRElement(ET_MVName, parent, ADD_MEMCHECK_ARGS_PASS(heap)),
timestamp_(heap),
fqMVName_(charData_)
{
XMLAttributeIterator iter(atts);
const char *attrName;
while (iter.hasNext())
{
iter.next();
attrName = iter.getName();
if (!strcmp(attrName, "id"))
id_ = iter.getValue();
else if (!strcmp(attrName, "TS"))
timestamp_ = iter.getValue();
else
throw QRDescriptorException("Invalid attribute specified for element %s: %s",
elemName, attrName);
}
}
void QRMVName::serializeAttrs(XMLString& xml)
{
QRElement::serializeAttrs(xml);
if (timestamp_.length() > 0)
xml.append("TS='").append(timestamp_).append("\' ");
}
//
// QRCandidate
//
QRCandidate::QRCandidate(XMLElementPtr parent, AttributeList atts,
ADD_MEMCHECK_ARGS_DEF(NAMemory* heap))
: QRElement(ET_Candidate, parent, ADD_MEMCHECK_ARGS_PASS(heap)),
isPreferredMatch_(FALSE),
isIndirectGroupBy_(FALSE),
statsOnly_(FALSE),
mvName_(NULL),
tableList_(NULL),
joinPredList_(NULL),
rangePredList_(NULL),
residualPredList_(NULL),
groupBy_(NULL),
outputList_(NULL)
{
XMLAttributeIterator iter(atts);
const char *attrName;
const char *attrVal;
while (iter.hasNext())
{
iter.next();
attrName = iter.getName();
attrVal = iter.getValue();
if (!strcmp(attrName, "statsOnly"))
deserializeBoolAttr(attrName, attrVal, statsOnly_);
else if (!strcmp(attrName, "isPreferredMatch"))
deserializeBoolAttr(attrName, attrVal, isPreferredMatch_);
else if (!strcmp(attrName, "isIndirectGroupBy"))
deserializeBoolAttr(attrName, attrVal, isIndirectGroupBy_);
else
throw QRDescriptorException("Invalid attribute specified for element %s: %s",
elemName, attrName);
}
}
QRCandidate::~QRCandidate()
{
deletePtr(mvName_);
deletePtr(tableList_);
deletePtr(joinPredList_);
deletePtr(rangePredList_);
deletePtr(residualPredList_);
deletePtr(groupBy_);
deletePtr(outputList_);
}
void QRCandidate::serializeAttrs(XMLString& xml)
{
QRElement::serializeAttrs(xml);
serializeBoolAttr("isPreferredMatch", isPreferredMatch_, xml);
if (isIndirectGroupBy_)
serializeBoolAttr("isIndirectGroupBy", isIndirectGroupBy_, xml);
serializeBoolAttr("statsOnly", statsOnly_, xml);
}
void QRCandidate::serializeBody(XMLString& xml)
{
if (mvName_)
mvName_->toXML(xml);
if (tableList_ && !tableList_->isEmpty())
tableList_->toXML(xml);
if (joinPredList_ && !joinPredList_->isEmpty())
joinPredList_->toXML(xml);
if (rangePredList_ && !rangePredList_->isEmpty())
rangePredList_->toXML(xml);
if (residualPredList_ && !residualPredList_->isEmpty())
residualPredList_->toXML(xml);
if (groupBy_)
groupBy_->toXML(xml);
if (outputList_ && !outputList_->isEmpty())
outputList_->toXML(xml);
}
NABoolean QRCandidate::treeWalk(VisitorPtr visitor)
{
VISIT_THIS(visitor, this);
if (mvName_ && mvName_->treeWalk(visitor))
return TRUE;
if (tableList_ && !tableList_->isEmpty() && tableList_->treeWalk(visitor))
return TRUE;
if (joinPredList_ && !joinPredList_->isEmpty() && joinPredList_->treeWalk(visitor))
return TRUE;
if (rangePredList_ && !rangePredList_->isEmpty() && rangePredList_->treeWalk(visitor))
return TRUE;
if (residualPredList_ && !residualPredList_->isEmpty() && residualPredList_->treeWalk(visitor))
return TRUE;
if (groupBy_ && groupBy_->treeWalk(visitor))
return TRUE;
if (outputList_ && !outputList_->isEmpty() && outputList_->treeWalk(visitor))
return TRUE;
return FALSE;
}
void QRCandidate::startElement(void *parser, const char *elementName, const char **atts)
{
if (!strcmp(elementName, QRMVName::elemName))
{
mvName_ = new (XMLPARSEHEAP) QRMVName(CHILD_ELEM_ARGS(XMLPARSEHEAP));
XMLDocument::setCurrentElement(parser, mvName_);
}
else if (!strcmp(elementName, QRList<QRTable>::elemName))
{
tableList_ = new (XMLPARSEHEAP) QRList<QRTable>(CHILD_ELEM_ARGS(XMLPARSEHEAP));
XMLDocument::setCurrentElement(parser, tableList_);
}
else if (!strcmp(elementName, QRList<QRJoinPred>::elemName))
{
joinPredList_ = new (XMLPARSEHEAP) QRList<QRJoinPred>(CHILD_ELEM_ARGS(XMLPARSEHEAP));
XMLDocument::setCurrentElement(parser, joinPredList_);
}
else if (!strcmp(elementName, QRList<QRRangePred>::elemName))
{
rangePredList_ = new (XMLPARSEHEAP) QRList<QRRangePred>(CHILD_ELEM_ARGS(XMLPARSEHEAP));
XMLDocument::setCurrentElement(parser, rangePredList_);
}
else if (!strcmp(elementName, QRList<QRExpr>::elemName))
{
residualPredList_ = new (XMLPARSEHEAP) QRList<QRExpr>(CHILD_ELEM_ARGS(XMLPARSEHEAP));
XMLDocument::setCurrentElement(parser, residualPredList_);
}
else if (!strcmp(elementName, QRGroupBy::elemName))
{
groupBy_ = new (XMLPARSEHEAP) QRGroupBy(CHILD_ELEM_ARGS(XMLPARSEHEAP));
XMLDocument::setCurrentElement(parser, groupBy_);
}
else if (!strcmp(elementName, QRList<QROutput>::elemName))
{
outputList_ = new (XMLPARSEHEAP) QRList<QROutput>(CHILD_ELEM_ARGS(XMLPARSEHEAP));
XMLDocument::setCurrentElement(parser, outputList_);
}
else
{
throw QRDescriptorException("Element %s cannot contain element %s",
elemName, elementName);
}
} // QRCandidate::startElement
//
// QRJbbSubset
//
QRJbbSubset::QRJbbSubset(XMLElementPtr parent, AttributeList atts,
ADD_MEMCHECK_ARGS_DEF(NAMemory* heap))
: QRElement(ET_JbbSubset, parent, ADD_MEMCHECK_ARGS_PASS(heap)),
tableList_(NULL),
candidateList_(NULL),
hasGroupBy_(FALSE)
{
XMLAttributeIterator iter(atts);
const char *attrName;
const char *attrVal;
while (iter.hasNext())
{
iter.next();
attrName = iter.getName();
attrVal = iter.getValue();
if (!strcmp(attrName, "hasGroupby"))
deserializeBoolAttr(attrName, attrVal, hasGroupBy_);
else if (!strcmp(attrName, "ref"))
ref_ = iter.getValue();
else
throw QRDescriptorException("Invalid attribute specified for element %s: %s",
elemName, attrName);
}
}
void QRJbbSubset::serializeAttrs(XMLString& xml)
{
QRElement::serializeAttrs(xml);
serializeBoolAttr("hasGroupby", hasGroupBy_, xml);
}
void QRJbbSubset::serializeBody(XMLString& xml)
{
if (tableList_ && !tableList_->isEmpty())
tableList_->toXML(xml);
if (candidateList_ && !candidateList_->isEmpty())
candidateList_->toXML(xml);
}
NABoolean QRJbbSubset::treeWalk(VisitorPtr visitor)
{
VISIT_THIS(visitor, this);
if (tableList_ && !tableList_->isEmpty() && tableList_->treeWalk(visitor))
return TRUE;
if (candidateList_ && !candidateList_->isEmpty() && candidateList_->treeWalk(visitor))
return TRUE;
return FALSE;
}
void QRJbbSubset::startElement(void *parser, const char *elementName, const char **atts)
{
if (!strcmp(elementName, QRList<QRTable>::elemName))
{
tableList_ = new (XMLPARSEHEAP) QRList<QRTable>(CHILD_ELEM_ARGS(XMLPARSEHEAP));
XMLDocument::setCurrentElement(parser, tableList_);
}
else if (!strcmp(elementName, QRList<QRCandidate>::elemName))
{
candidateList_ = new (XMLPARSEHEAP) QRList<QRCandidate>(CHILD_ELEM_ARGS(XMLPARSEHEAP));
XMLDocument::setCurrentElement(parser, candidateList_);
}
else
{
throw QRDescriptorException("Element %s cannot contain element %s",
elemName, elementName);
}
}
//
// QRJbbResult
//
QRJbbResult::QRJbbResult(XMLElementPtr parent, AttributeList atts,
ADD_MEMCHECK_ARGS_DEF(NAMemory* heap))
: QRElement(ET_JbbResult, parent, ADD_MEMCHECK_ARGS_PASS(heap)),
jbbSubsets_(heap),
infoItems_(heap)
{
XMLAttributeIterator iter(atts);
const char *attrName;
while (iter.hasNext())
{
iter.next();
attrName = iter.getName();
if (!strcmp(attrName, "ref"))
ref_ = iter.getValue();
else
throw QRDescriptorException("Invalid attribute specified for element %s: %s",
elemName, attrName);
}
}
QRJbbResult::~QRJbbResult()
{
CollIndex i;
for (i = 0; i < jbbSubsets_.entries(); i++)
deletePtr(jbbSubsets_[i]);
for (i = 0; i < infoItems_.entries(); i++)
deletePtr(infoItems_[i]);
}
void QRJbbResult::serializeBody(XMLString& xml)
{
CollIndex i;
for (i = 0; i < jbbSubsets_.entries(); i++)
jbbSubsets_[i]->toXML(xml);
for (i = 0; i < infoItems_.entries(); i++)
infoItems_[i]->toXML(xml);
}
NABoolean QRJbbResult::treeWalk(VisitorPtr visitor)
{
VISIT_THIS(visitor, this);
CollIndex i;
for (i = 0; i < jbbSubsets_.entries(); i++)
if (jbbSubsets_[i]->treeWalk(visitor))
return TRUE;
for (i = 0; i < infoItems_.entries(); i++)
if (infoItems_[i]->treeWalk(visitor))
return TRUE;
return FALSE;
}
void QRJbbResult::startElement(void *parser, const char *elementName, const char **atts)
{
if (!strcmp(elementName, QRJbbSubset::elemName))
{
QRJbbSubsetPtr jbbSubset = new (XMLPARSEHEAP) QRJbbSubset(CHILD_ELEM_ARGS(XMLPARSEHEAP));
addJbbSubset(jbbSubset);
XMLDocument::setCurrentElement(parser, jbbSubset);
}
else if (!strcmp(elementName, QRInfo::elemName))
{
QRInfoPtr info = new (XMLPARSEHEAP) QRInfo(CHILD_ELEM_ARGS(XMLPARSEHEAP));
addInfoItem(info);
XMLDocument::setCurrentElement(parser, info);
}
else
throw QRDescriptorException("Element %s cannot contain element %s",
elemName, elementName);
}
//
// QRResultDescriptor
//
QRResultDescriptor::~QRResultDescriptor()
{
deletePtr(version_);
for (CollIndex i = 0; i < jbbResults_.entries(); i++)
deletePtr(jbbResults_[i]);
}
void QRResultDescriptor::serializeBody(XMLString& xml)
{
if (version_)
version_->toXML(xml);
for (CollIndex i = 0; i < jbbResults_.entries(); i++)
jbbResults_[i]->toXML(xml);
}
NABoolean QRResultDescriptor::treeWalk(VisitorPtr visitor)
{
VISIT_THIS(visitor, this);
if (version_ && version_->treeWalk(visitor))
return TRUE;
for (CollIndex i = 0; i < jbbResults_.entries(); i++)
if (jbbResults_[i]->treeWalk(visitor))
return TRUE;
return FALSE;
}
void QRResultDescriptor::startElement(void *parser, const char *elementName, const char **atts)
{
if (!strcmp(elementName, QRVersion::elemName))
{
version_ = new (XMLPARSEHEAP) QRVersion(CHILD_ELEM_ARGS(XMLPARSEHEAP));
XMLDocument::setCurrentElement(parser, version_);
}
else if (!strcmp(elementName, QRJbbResult::elemName))
{
QRJbbResultPtr jbbResult = new (XMLPARSEHEAP) QRJbbResult(CHILD_ELEM_ARGS(XMLPARSEHEAP));
addJbbResult(jbbResult);
XMLDocument::setCurrentElement(parser, jbbResult);
}
else
{
throw QRDescriptorException("Element %s cannot contain element %s",
elemName, elementName);
}
}
//
// QRPublishDescriptor
//
QRPublishDescriptor::QRPublishDescriptor(AttributeList atts,
ADD_MEMCHECK_ARGS_DEF(NAMemory* heap))
: QRElement(ET_PublishDescriptor, NULL, ADD_MEMCHECK_ARGS_PASS(heap)),
redefTimestamp_(heap),
name_(NULL),
updateList_(heap),
includeFile_(NULL),
mvDesc_(NULL),
mvDescText_(NULL)
{
// Set parent here so we don't have to use 'this' in initializer.
setParent(this);
XMLAttributeIterator iter(atts);
const char *attrName;
while (iter.hasNext())
{
iter.next();
attrName = iter.getName();
if (!strcmp(attrName, "TS"))
redefTimestamp_ = iter.getValue();
else
throw QRDescriptorException("Invalid attribute specified for element %s: %s",
elemName, attrName);
}
}
QRPublishDescriptor::~QRPublishDescriptor()
{
deletePtr(name_);
deletePtr(includeFile_);
deletePtr(mvDesc_);
if (mvDescText_)
delete mvDescText_;
for (CollIndex i=0; i<updateList_.entries(); i++)
deletePtr(updateList_[i]);
}
NABoolean QRPublishDescriptor::treeWalk(VisitorPtr visitor)
{
VISIT_THIS(visitor, this);
if (name_ && name_->treeWalk(visitor))
return TRUE;
for (CollIndex i=0; i<updateList_.entries(); i++)
if (updateList_[i]->treeWalk(visitor))
return TRUE;
if (includeFile_ && includeFile_->treeWalk(visitor))
return TRUE;
if (mvDesc_ && mvDesc_->treeWalk(visitor))
return TRUE;
return FALSE;
}
void QRPublishDescriptor::startElement(void *parser,
const char *elementName,
const char **atts)
{
if (!strcmp(elementName, QRUpdate::elemName))
{
QRUpdatePtr update = new (XMLPARSEHEAP) QRUpdate(CHILD_ELEM_ARGS(XMLPARSEHEAP));
addUpdate(update);
XMLDocument::setCurrentElement(parser, update);
}
else if (!strcmp(elementName, QRMVName::elemName))
{
name_ = new (XMLPARSEHEAP) QRMVName(CHILD_ELEM_ARGS(XMLPARSEHEAP));
XMLDocument::setCurrentElement(parser, name_);
}
else if (!strcmp(elementName, QRInclude::elemName))
{
includeFile_ = new (XMLPARSEHEAP) QRInclude(CHILD_ELEM_ARGS(XMLPARSEHEAP));
XMLDocument::setCurrentElement(parser, includeFile_);
}
else if (!strcmp(elementName, QRMVDescriptor::elemName))
{
mvDesc_ = new (XMLPARSEHEAP) QRMVDescriptor(CHILD_ELEM_ARGS(XMLPARSEHEAP));
XMLDocument::setCurrentElement(parser, mvDesc_);
}
else
{
throw QRDescriptorException("Element %s cannot contain element %s",
elemName, elementName);
}
}
void QRPublishDescriptor::serializeAttrs(XMLString& xml)
{
QRElement::serializeAttrs(xml);
if (redefTimestamp_.length() > 0)
xml.append("TS='").append(redefTimestamp_).append("\' ");
}
void QRPublishDescriptor::serializeBody(XMLString& xml)
{
if (name_)
name_->toXML(xml);
for (CollIndex i=0; i<updateList_.entries(); i++)
updateList_[i]->toXML(xml);
if (includeFile_)
includeFile_->toXML(xml);
if (mvDesc_)
mvDesc_->toXML(xml);
if (mvDescText_)
{
xml.incrementLevel();
xml.indent();
xml.append(mvDescText_->data());
xml.endLine();
xml.decrementLevel();
}
}
void QRPublishDescriptor::initialize(ComPublishMVOperationType opType,
const NAString* redefTimestamp,
NAString* mvDescText,
const NAString* mvName,
NABoolean hasIgnoreChanges,
const NAString* refreshTimestamp,
const NAString* newName,
NAMemory* heap)
{
setRedefTimestamp(*redefTimestamp);
QRMVNamePtr nameElement = new(heap) QRMVName(ADD_MEMCHECK_ARGS(heap));
nameElement->setMVName(*mvName);
setName(nameElement);
switch(opType)
{
case COM_PUBLISH_MV_CREATE_AND_REFRESH:
addUpdate(createUpdateForRefresh(refreshTimestamp, heap));
// Fall through to CREATE.
case COM_PUBLISH_MV_CREATE:
if (hasIgnoreChanges)
addUpdate(createUpdateForAlter(hasIgnoreChanges, heap));
setMVText(mvDescText, heap);
break;
case COM_PUBLISH_MV_RENAME:
addUpdate(createUpdateForRename(newName, heap));
break;
case COM_PUBLISH_MV_ALTER_IGNORE_CHANGES:
addUpdate(createUpdateForAlter(hasIgnoreChanges, heap));
break;
case COM_PUBLISH_MV_TOUCH:
// Nothing to do here.
break;
case COM_PUBLISH_MV_DROP:
addUpdate(createUpdateForDrop(heap));
break;
case COM_PUBLISH_MV_REPUBLISH:
setMVText(mvDescText, heap);
addUpdate(createUpdateForAlter(hasIgnoreChanges, heap));
addUpdate(createUpdateForRefresh(refreshTimestamp, heap));
break;
case COM_PUBLISH_MV_REFRESH:
addUpdate(createUpdateForRefresh(refreshTimestamp, heap));
break;
case COM_PUBLISH_MV_REFRESH_RECOMPUTE:
addUpdate(createUpdateForRecompute(refreshTimestamp, heap));
break;
case COM_PUBLISH_MV_UNKNOWN:
default:
assertLogAndThrow(CAT_SQL_COMP_QR_DESC_GEN, LL_MVQR_FAIL,
FALSE, QRDescriptorException,
"Unhandled MV operation type");
break;
}
}
QRUpdatePtr QRPublishDescriptor::createUpdateForAlter(NABoolean hasIgnoreChanges, NAMemory* heap)
{
QRUpdatePtr update = new (heap) QRUpdate(QRUpdate::ALTER, ADD_MEMCHECK_ARGS(heap));
update->setIgnoreChanges(hasIgnoreChanges);
return update;
}
QRUpdatePtr QRPublishDescriptor::createUpdateForRefresh(const NAString* refreshTimestamp, NAMemory* heap)
{
QRUpdatePtr update = new (heap) QRUpdate(QRUpdate::REFRESH, ADD_MEMCHECK_ARGS(heap));
update->setRefreshTimestamp(*refreshTimestamp);
return update;
}
QRUpdatePtr QRPublishDescriptor::createUpdateForRecompute(const NAString* refreshTimestamp, NAMemory* heap)
{
QRUpdatePtr update = new (heap) QRUpdate(QRUpdate::RECOMPUTE, ADD_MEMCHECK_ARGS(heap));
update->setRefreshTimestamp(*refreshTimestamp);
return update;
}
QRUpdatePtr QRPublishDescriptor::createUpdateForDrop(NAMemory* heap)
{
QRUpdatePtr update = new (heap) QRUpdate(QRUpdate::DROP, ADD_MEMCHECK_ARGS(heap));
return update;
}
QRUpdatePtr QRPublishDescriptor::createUpdateForRename(const NAString* newName, NAMemory* heap)
{
QRUpdatePtr update = new (heap) QRUpdate(QRUpdate::RENAME, ADD_MEMCHECK_ARGS(heap));
update->setNewName(*newName);
return update;
}
//
// QRUpdate
//
// The order of these names must match that of the UpdateType enum.
const char* const QRUpdate::UpdateTypeNames_[] =
{ "Non-Init", "Alter", "Default", "Drop", "Recompute", "Refresh", "Rename" };
QRUpdate::QRUpdate(XMLElementPtr parent,
AttributeList atts,
ADD_MEMCHECK_ARGS_DEF(NAMemory* heap))
: QRElement(ET_Update, parent, ADD_MEMCHECK_ARGS_PASS(heap)),
type_(NON_INIT),
timestamp_(heap),
hasIgnoreChanges_(FALSE),
newName_(charData_),
defaultName_(heap),
defaultValue_(heap)
{
XMLAttributeIterator iter(atts);
const char *attrName;
const char *attrVal;
while (iter.hasNext())
{
iter.next();
attrName = iter.getName();
attrVal = iter.getValue();
if (!strcmp(attrName, "TS")) // refresh timestamp; only for op=Refresh
timestamp_ = attrVal; //@ZX -- probably need to convert to INT64
else if (!strcmp(attrName, "attr")) // default attribute name for op=Default
defaultName_ = attrVal;
else if (!strcmp(attrName, "value")) // default attribute value for op=Default
defaultValue_ = attrVal;
else if (!strcmp(attrName, "op"))
{
if (!strcmp(attrVal, "Refresh"))
type_ = REFRESH;
else if (!strcmp(attrVal, "Recompute"))
type_ = RECOMPUTE;
else if (!strcmp(attrVal, "Drop"))
type_ = DROP;
else if (!strcmp(attrVal, "Alter"))
type_ = ALTER;
else if (!strcmp(attrVal, "Rename"))
type_ = RENAME;
else if (!strcmp(attrVal, "Default"))
type_ = DEFAULT;
else
throw QRDescriptorException("Invalid Update type: %s", attrVal);
}
else if (!strcmp(attrName, "hasIgnoreChanges"))
deserializeBoolAttr(attrName, attrVal, hasIgnoreChanges_);
else
throw QRDescriptorException("Invalid attribute specified for element %s: %s",
elemName, attrName);
}
}
QRUpdate::QRUpdate(UpdateType updateType,
ADD_MEMCHECK_ARGS_DEF(NAMemory* heap))
: QRElement(ET_Update, NULL, ADD_MEMCHECK_ARGS_PASS(heap)),
type_(updateType),
timestamp_(heap),
hasIgnoreChanges_(FALSE),
newName_(charData_)
{
}
void QRUpdate::serializeAttrs(XMLString& xml)
{
QRElement::serializeAttrs(xml);
assertLogAndThrow(CAT_SQL_COMP_QR_DESC_GEN, LL_MVQR_FAIL,
type_ != NON_INIT, QRDescriptorException,
"Op type has not been set for <Update>");
xml.append("op='").append(UpdateTypeNames_[type_]).append("' ");
switch (type_)
{
case ALTER:
serializeBoolAttr("hasIgnoreChanges", hasIgnoreChanges_, xml);
break;
case REFRESH:
case RECOMPUTE:
xml.append("TS='").append(timestamp_).append("' ");
break;
case DEFAULT:
assertLogAndThrow(CAT_SQL_COMP_QR_DESC_GEN, LL_MVQR_FAIL,
defaultName_.length() > 0, QRDescriptorException,
"Attribute name not available for default operation");
assertLogAndThrow(CAT_SQL_COMP_QR_DESC_GEN, LL_MVQR_FAIL,
defaultValue_.length() > 0, QRDescriptorException,
"Attribute value not available for default operation");
xml.append("attr='").append(defaultName_).append("' ");
xml.append("value='").append(defaultValue_).append( "' ");
break;
case DROP:
// Nothing to do here.
break;
}
}