void ItemDocument::select(const QCanvasItemList &list) {
	const QCanvasItemList::const_iterator end = list.end();

	for (QCanvasItemList::const_iterator it = list.begin(); it != end; ++it)
		selectList()->addQCanvasItem(*it);

	selectList()->setSelected(true);
}
void ItemDocument::fillContextMenu(const QPoint & pos) {
	Q_UNUSED(pos);

	ItemView *activeItemView = dynamic_cast<ItemView*>(activeView());

	if (!KTechlab::self() || !activeItemView)
		return;

	KAction * align_actions[] = {
		activeItemView->action("align_horizontally"),
		activeItemView->action("align_vertically"),
		activeItemView->action("distribute_horizontally"),
		activeItemView->action("distribute_vertically")
	};

	bool enableAlignment = selectList()->itemCount() > 1;

	if (!enableAlignment) return;

	for (unsigned i = 0; i < 4; ++i) {
		align_actions[i]->setEnabled(true);
		m_pAlignmentAction->remove(align_actions[i]);
		m_pAlignmentAction->insert(align_actions[i]);
	}

	QPtrList<KAction> alignment_actions;

	alignment_actions.append(m_pAlignmentAction);
	KTechlab::self()->plugActionList("alignment_actionlist", alignment_actions);
}
GlobalDataTypeRegistry::RegistResult GlobalDataTypeRegistry::remove(Entry* dtd)
{
    if (!dtd)
    {
        UAVCAN_ASSERT(0);
        return RegistResultInvalidParams;
    }
    if (isFrozen())
    {
        return RegistResultFrozen;
    }

    List* list = selectList(dtd->descriptor.getKind());
    if (!list)
    {
        return RegistResultInvalidParams;
    }

    list->remove(dtd);       // If this call came from regist<>(), that would be enough
    Entry* p = list->get();  // But anyway
    while (p)
    {
        Entry* const next = p->getNextListNode();
        if (p->descriptor.match(dtd->descriptor.getKind(), dtd->descriptor.getFullName()))
        {
            list->remove(p);
        }
        p = next;
    }
    return RegistResultOk;
}
void ListEditor::removeListClicked()
{
	QString lname=listName->currentText();
	if(lists->contains(lname)) lists->erase(lname);
	listName->removeItem(listName->currentItem());
	selectList(0);
}
DataTypeSignature GlobalDataTypeRegistry::computeAggregateSignature(DataTypeKind kind,
                                                                    DataTypeIDMask& inout_id_mask) const
{
    UAVCAN_ASSERT(isFrozen());  // Computing the signature if the registry is not frozen is pointless

    const List* list = selectList(kind);
    if (!list)
    {
        UAVCAN_ASSERT(0);
        return DataTypeSignature();
    }

    int prev_dtid = -1;
    DataTypeSignature signature;
    bool signature_initialized = false;
    Entry* p = list->get();
    while (p)
    {
        const DataTypeDescriptor& desc = p->descriptor;
        const int dtid = desc.getID().get();

        if (inout_id_mask[unsigned(dtid)])
        {
            if (signature_initialized)
            {
                signature.extend(desc.getSignature());
            }
            else
            {
                signature = DataTypeSignature(desc.getSignature());
            }
            signature_initialized = true;
        }

        UAVCAN_ASSERT(prev_dtid < dtid);  // Making sure that list is ordered properly
        prev_dtid++;
        while (prev_dtid < dtid)
        {
            inout_id_mask[unsigned(prev_dtid++)] = false; // Erasing bits for missing types
        }
        UAVCAN_ASSERT(prev_dtid == dtid);

        p = p->getNextListNode();
    }
    prev_dtid++;
    while (prev_dtid <= DataTypeID::Max)
    {
        inout_id_mask[unsigned(prev_dtid++)] = false;
    }

    return signature;
}
Exemple #6
0
void StoreSqdb::insert (SourceDesc& desc)
{
    sqdb::transaction tr (m_session);

    bool const found (select (desc));

    if (found)
    {
        selectList (desc);
    }
    else
    {
        Error error;

        String const sourceID (desc.source->uniqueID().toStdString());
        String const createParam (desc.source->createParam().toStdString());
        String const lastFetchTime (Utilities::timeToString (desc.lastFetchTime));
        String const expirationTime (Utilities::timeToString (desc.expirationTime));

        sqdb::statement st = (m_session.prepare <<
            "INSERT INTO Validators_Source ( "
            "  sourceID, "
            "  createParam, "
            "  lastFetchTime, "
            "  expirationTime "
            ") VALUES ( "
            "  ?, ?, ?, ? "
            "); "
            ,sqdb::use (sourceID)
            ,sqdb::use (createParam)
            ,sqdb::use (lastFetchTime)
            ,sqdb::use (expirationTime)
            );

        st.execute_and_fetch (error);

        if (! error)
        {
            error = tr.commit ();
        }

        if (error)
        {
            tr.rollback ();
            report (error, __FILE__, __LINE__);
        }
    }
}
void GlobalDataTypeRegistry::getDataTypeIDMask(DataTypeKind kind, DataTypeIDMask& mask) const
{
    (void)mask.reset();
    const List* list = selectList(kind);
    if (!list)
    {
        UAVCAN_ASSERT(0);
        return;
    }
    Entry* p = list->get();
    while (p)
    {
        UAVCAN_ASSERT(p->descriptor.getKind() == kind);
        mask[p->descriptor.getID().get()] = true;
        p = p->getNextListNode();
    }
}
void ListEditor::addListClicked()
{
 	bool ok;
	int t=listType->currentItem();
    QString name=QInputDialog::getText(tr("New "+listTypeName[t]), tr("Enter list name:"), QLineEdit::Normal,QString::null, &ok, this);
	if(name!="" && ok)
	{
                if( listName->findText(name) != -1 )
		{
			QMessageBox::critical(this,tr("Error"),tr("List \"")+name+tr("\" already exists. Enter another name"));
			return;
		}
		listName->insertItem(name);
		lists->insert(name,VtlList::create(listTypeName[t]));
		selectList(listName->count()-1);
	}
}
int ListEditor::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
{
    _id = QWidget::qt_metacall(_c, _id, _a);
    if (_id < 0)
        return _id;
    if (_c == QMetaObject::InvokeMetaMethod) {
        switch (_id) {
        case 0: shown((*reinterpret_cast< bool(*)>(_a[1]))); break;
        case 1: addListClicked(); break;
        case 2: removeListClicked(); break;
        case 3: load(); break;
        case 4: selectList((*reinterpret_cast< int(*)>(_a[1]))); break;
        default: ;
        }
        _id -= 5;
    }
    return _id;
}
Exemple #10
0
void ItemDocument::slotInitItemActions() {
	ItemView * activeItemView = dynamic_cast<ItemView*>(activeView());

	if (!KTechlab::self() || !activeItemView)
		return;

	KAction * align_actions[] = {
		activeItemView->action("align_horizontally"),
		activeItemView->action("align_vertically"),
		activeItemView->action("distribute_horizontally"),
		activeItemView->action("distribute_vertically")
	};

	bool enableAlignment = selectList()->itemCount() > 1;

	for (unsigned i = 0; i < 4; ++i)
		align_actions[i]->setEnabled(enableAlignment);
}
const DataTypeDescriptor* GlobalDataTypeRegistry::find(DataTypeKind kind, DataTypeID dtid) const
{
    const List* list = selectList(kind);
    if (!list)
    {
        UAVCAN_ASSERT(0);
        return NULL;
    }
    Entry* p = list->get();
    while (p)
    {
        if (p->descriptor.match(kind, dtid))
        {
            return &p->descriptor;
        }
        p = p->getNextListNode();
    }
    return NULL;
}
//----------------------------------------------------------------------------
// The select list here is: (<fixed-count-cols>, <sum-col-refs>)
// The count cols become:
// Case( If <count-col> IS NULL THEN 0 ELSE <count-col>)
// Since the count cols were transformed from COUNT to SUM(@OP), They will 
// now evaluate to NULL instead of 0 when no data is returned, for MAVs 
// without a GROUP BY clause. This is what is fixed here.
//----------------------------------------------------------------------------
RelRoot *MavRelRootBuilder::buildRootForNoGroupBy(RelExpr *topNode)
{
  ItemExprList selectList(heap_);

  for (CollIndex i=0; i<countCols_.entries(); i++)
  {
    const MVColumnInfo *currentMavColumn = countCols_[i];
    const NAString& colName = currentMavColumn->getColName();

    // Build a col reference to the SYS_DELTA column.
    ItemExpr *sysDeltaColExpr = new(heap_)
      ColReference(new(heap_) ColRefName(colName, deltaCorrName_));

    ItemExpr *condExpr = new(heap_)
      Case(NULL, new(heap_)
	IfThenElse(new(heap_) UnLogic(ITM_IS_NULL, sysDeltaColExpr),
		   new(heap_) SystemLiteral(0),
		   sysDeltaColExpr->copyTree(heap_)));

    ItemExpr *renamedColExpr = new(heap_) 
      RenameCol(condExpr, new(heap_) ColRefName(colName, deltaCorrName_));

    selectList.insert(renamedColExpr);
  }

  // Add the SUM cols.
  addColsToSelectList(sumCols_, selectList, deltaCorrName_);

  // Add the extra Min/Max columns.
  selectList.insert(extraMinMaxColRefs_);

  // The select list is ready. Create the root over topNode.
  RelRoot *newRoot = new(heap_) 
    RelRoot(topNode, REL_ROOT, selectList.convertToItemExpr());
  newRoot->setDontOpenNewScope();

  selectList.clear();
  return newRoot;
}  // MavRelRootBuilder::buildRootForNoGroupBy()
//----------------------------------------------------------------------------
// First, do the COUNT columns.
// The select list of this root is (*, <count cols>).
// For COUNT, the SYS_CALC.col expr is:
//   SYS_MAV.col + SYS_DELTA.col
// For MAVs without a GROUP BY clause, this is later fixed by 
// buildRootForNoGroupBy().
//----------------------------------------------------------------------------
RelRoot *MavRelRootBuilder::buildRootForCount(RelExpr *topNode)
{
  // Start the select list with *
  ItemExprList selectList(heap_);
  addStarToSelectList(selectList);

  addColsToSelectList(groupByCols_, selectList, deltaCorrName_, &calcCorrName_);

  // For each column in the COUNT list
  for (CollIndex i=0; i<countCols_.entries(); i++)
  {
    MVColumnInfo *currentCol = countCols_[i];
    const NAString& colName = currentCol->getColName();

    // Find the column in the SYS_DELTA and SYS_MAV lists.
    ItemExpr *sysDeltaColExpr = new(heap_)
      ColReference(new(heap_) ColRefName(colName, deltaCorrName_));

    ItemExpr *sysMavColExpr = new(heap_)
      ColReference(new(heap_) ColRefName(colName, mavCorrName_));
      
    ItemExpr *newCalcExpr = new(heap_) 
      BiArith(ITM_PLUS, sysDeltaColExpr, sysMavColExpr);

    // Add the col expression as SYS_CALC.col
    ColRefName *calcColName = new(heap_) ColRefName(colName, calcCorrName_);
    ItemExpr *newCalcCol = new(heap_) RenameCol(newCalcExpr, calcColName);

    selectList.insert(newCalcCol);
  }

  // The select list is ready. Create the root over topNode.
  RelRoot *newRoot = new(heap_) 
    RelRoot(topNode, REL_ROOT, selectList.convertToItemExpr());
  newRoot->setDontOpenNewScope();

  selectList.clear();
  return newRoot;
}  // MavRelRootBuilder::buildRootForCount()
ListEditor::ListEditor(Lists *ll,QWidget *p) :
        QWidget(p,"ListEditor",Qt::Dialog),
	lists(ll),editor(new TableEditor * [3])
{
    //setModal (false);
    
    setupUi(this);
    for(int i=0;i<nListType;i++) listType->insertItem(tr(listTypeName[i]));
        vboxLayout->add(editor[0] = new StringListEditor(this));
	editor[0]->hide();
        vboxLayout->add(editor[1] = new PictureListEditor(this));
	editor[1]->hide();
        vboxLayout->add(editor[2] = new CommandListEditor(this));
	//selectListType(listType->currentItem());
	connect(listName,SIGNAL(activated(int)),this,SLOT(selectList(int)));
	
	connect(addList,SIGNAL(clicked()),this,SLOT(addListClicked()));
	connect(removeList,SIGNAL(clicked()),this,SLOT(removeListClicked()));
	//ListEditorFormLayout->add(editor[2] = new CommandListEditor(this));
	//lists=new Lists;
	load();
	selectList(0);
}
Exemple #15
0
void ItemDocument::lowerZ() {
	lowerZ(selectList()->items(true));
}
Exemple #16
0
void ItemDocument::raiseZ() {
	raiseZ(selectList()->items(true));
}
//----------------------------------------------------------------------------
// Next, do the SUM, MIN and MAX columns, using the already calculated 
// and bound COUNT columns (SYS_CALC.dep1).
// For col=SUM(a), the new expr is:
//   CASE
// 1)  	WHEN (SYS_CALC.dep1 = 0)     THEN NULL
// 2)  	WHEN (SYS_MAV.col IS NULL)   THEN SYS_DELTA.col
// 3)  	WHEN (SYS_DELTA.col IS NULL) THEN SYS_MAV.col
//   	ELSE SYS_MAV.col + SYS_DELTA.col
//   END
// For col=MIN(a), the else clause is replaced by (no MIN ItemExpr):
//      WHEN (SYS_MAV.col < SYS_DELTA.col) THEN SYS_MAV.col
//      ELSE SYS_DELTA.col
// For col=MAX(a), the else clause is:
//      WHEN (SYS_MAV.col > SYS_DELTA.col) THEN SYS_MAV.col
//      ELSE SYS_DELTA.col
//----------------------------------------------------------------------------
RelRoot *MavRelRootBuilder::buildRootForSum(RelExpr *topNode)
{
  // Start the select list with *
  ItemExprList selectList(heap_);
  addStarToSelectList(selectList);

  // For each column in the COUNT list
  for (CollIndex i=0; i<sumCols_.entries(); i++)
  {
    MVColumnInfo *currentCol = sumCols_[i];
    const NAString& colName = currentCol->getColName();

    // Find the column in the SYS_DELTA and SYS_MAV lists.
    ItemExpr *sysDeltaColExpr = new(heap_)
      ColReference(new(heap_) ColRefName(colName, deltaCorrName_));

    ItemExpr *sysMavColExpr = new(heap_)
      ColReference(new(heap_) ColRefName(colName, mavCorrName_));
      
    // Find the dependent SYS_CALC COUNT column.
    ItemExpr *calcDep1 = 
      buildDepColExpr(calcCorrName_, currentCol->getDepCol1());

    // Build the condition bottom-up - do the ELSE clause first.
    ItemExpr *elseClause = NULL;
    if (currentCol->getOperatorType() == ITM_SUM)
    {
      // The ELSE clause for SUM is (SYS_MAV.col + SYS_DELTA.col).
      elseClause = new(heap_) 
        BiArith(ITM_PLUS, sysDeltaColExpr, sysMavColExpr);
    }
    else
    {
      // The ELSE clause for MIN is:
      //    WHEN (SYS_MAV.col < SYS_DELTA.col) THEN SYS_MAV.col
      //    ELSE SYS_DELTA.col
      // For MAX the < operator is replaced by >.
      OperatorTypeEnum sign = 
        (currentCol->getOperatorType()==ITM_MIN ? ITM_LESS : ITM_GREATER);
      elseClause = new(heap_) 
        IfThenElse(new(heap_) BiRelat(sign, sysMavColExpr, sysDeltaColExpr),
  		   sysMavColExpr,
		   sysDeltaColExpr);
    }

    // The 3rd WHEN clause: WHEN (SYS_DELTA.col IS NULL) THEN SYS_MAV.col
    ItemExpr *when3Clause = new(heap_)
      IfThenElse(new(heap_) UnLogic(ITM_IS_NULL, sysDeltaColExpr),
		 sysMavColExpr,
		 elseClause);

    // The 2nd WHEN clause: WHEN (SYS_MAV.col IS NULL) THEN SYS_DELTA.col
    ItemExpr *when2Clause = new(heap_)
      IfThenElse(new(heap_) UnLogic(ITM_IS_NULL, sysMavColExpr),
		 sysDeltaColExpr,
		 when3Clause);

    // The 1st WHEN clause: WHEN (SYS_CALC.dep1 = 0) THEN NULL
    ItemExpr *when1Clause = new(heap_)
      IfThenElse(new(heap_) BiRelat(ITM_EQUAL, 
    				    calcDep1,
				    new(heap_) SystemLiteral(0)),
		 new(heap_) SystemLiteral(), // NULL constant
		 when2Clause);

    // Build the CASE on top.
    ItemExpr *newCalcExpr = new(heap_) Case(NULL, when1Clause);

    // Add the col expression as SYS_CALC.col
    ColRefName *calcColName = new(heap_) ColRefName(colName, calcCorrName_);
    ItemExpr *newCalcCol = new(heap_) RenameCol(newCalcExpr, calcColName);

    selectList.insert(newCalcCol);
  }

  // The select list is ready. Create the root over topNode.
  RelRoot *newRoot = new(heap_) 
    RelRoot(topNode, REL_ROOT, selectList.convertToItemExpr());
  newRoot->setDontOpenNewScope();

  selectList.clear();
  return newRoot;
}  // MavRelRootBuilder::buildRootForSum()
Exemple #18
0
void ItemDocument::distributeVertically() {
	selectList()->slotDistributeVertically();

	if (ICNDocument *icnd = dynamic_cast<ICNDocument*>(this))
		icnd->requestRerouteInvalidatedConnectors();
}
Exemple #19
0
// these look dangerous., see todo in header file.
void ItemDocument::alignHorizontally() {
	selectList()->slotAlignHorizontally();

	if (ICNDocument *icnd = dynamic_cast<ICNDocument*>(this))
		icnd->requestRerouteInvalidatedConnectors();
}
Exemple #20
0
void ItemDocument::unselect(QCanvasItem *qcanvasItem) {
	selectList()->removeQCanvasItem(qcanvasItem);
	qcanvasItem->setSelected(false);
}
//----------------------------------------------------------------------------
// Next, do the other columns (AVG, STDDEV, VARIANCE), using the already
// calculated and bound COUNT and SUM columns.
// There are 3 dependent columns here (found using MVInfo):
//   dep1 is COUNT(a),
//   dep2 is SUM(a),
//   dep3 is SUM(a*a) (only for STDDEV and VARIANCE)
//   depCount is COUNT(a)
// In the case of STDDEV with a weight parameter - STDDEV(a,b), then
//   dep1 is SUM(b),
//   dep2 is SUM(a*b),
//   dep3 is SUM(a*a*b)
//   depCount is COUNT(a*b) and is the dependent column of dep2.
//
// For col=AVG(a), the new expr is:
//   CASE
//      WHEN (SYS_CALC.depCount = 0)  THEN NULL
//      ELSE SYS_CALC.dep2 / SYS_CALC.dep1
//   END
//
// For STDDEV and VARIANCE its:
//   CASE
//      WHEN (SYS_CALC.depCount = 0)  THEN NULL
//      ELSE ScalarVariance(SYS_CALC.dep3, SYS_CALC.dep2, SYS_CALC.dep1)
//   END
// depCount is the COUNT dependent column of dep2. This works also in the
// case of STDDEV with a weight parameter
//----------------------------------------------------------------------------
RelRoot *MavRelRootBuilder::buildRootForOthers(RelExpr *topNode)
{
  // Start the select list with *
  ItemExprList selectList(heap_);
  addStarToSelectList(selectList);

  // For each column in the COUNT list
  for (CollIndex i=0; i<otherCols_.entries(); i++)
  {
    MVColumnInfo *currentCol = otherCols_[i];
    const NAString& colName = currentCol->getColName();

    const NAType *desiredType = new(heap_) SQLDoublePrecision(TRUE);

    // Find the dependent SYS_CALC COUNT and SUM columns.
    ItemExpr *calcDep1 = 
      buildDepColExpr(calcCorrName_, currentCol->getDepCol1());
    ItemExpr *calcDep2 = 
      buildDepColExpr(calcCorrName_, currentCol->getDepCol2());
    ItemExpr *calcDep3 = NULL;
    ItemExpr *calcDepCount = NULL;
    if (currentCol->getOperatorType() == ITM_AVG)
    {
      calcDepCount = calcDep1;
    }
    else
    {
      // dep3 and depCount are needed only for STDDEV and VARIANCE.
      calcDep3 = buildDepColExpr(calcCorrName_, currentCol->getDepCol3());

      // depCount is the dereferenced dep1 column of dep2.
      MVColumnInfo *dep2ColInfo =
	mavCols_.getMvColInfoByIndex(currentCol->getDepCol2());
      calcDepCount = 
	buildDepColExpr(calcCorrName_, dep2ColInfo->getDepCol1());
    }

    // Build the condition bottom-up - do the ELSE clause first.
    ItemExpr *elseClause = NULL;
    if (currentCol->getOperatorType() == ITM_AVG)
    {
      // For AVG, the ELSE clause is (SYS_CALC.dep2 / SYS_CALC.dep1).
      elseClause = new(heap_)
        BiArith(ITM_DIVIDE, calcDep2, calcDep1);
    }
    else
    {
      // For STDDEV and VARIANCE, the ELSE clause is
      // ScalarVariance(SYS_CALC.dep3, SYS_CALC.dep2, SYS_CALC.dep1)
      elseClause = new(heap_)
        ScalarVariance(currentCol->getOperatorType(), 
		       new(heap_) Cast(calcDep3, desiredType), 
		       new(heap_) Cast(calcDep2, desiredType), 
		       new(heap_) Cast(calcDep1, desiredType));
    }

    // The WHEN clause is the same for AVG, STDDEV and VARIANCE:
    // WHEN (SYS_CALC.depCount = 0)  THEN NULL
    ItemExpr *whenClause = new(heap_)
      IfThenElse(new(heap_) BiRelat(ITM_EQUAL, 
				    calcDepCount,
				    new(heap_) SystemLiteral(0)),
		 new(heap_) SystemLiteral(), // NULL constant
		 elseClause);

    // Put the CASE on top.
    ItemExpr *newCalcExpr = new(heap_) Case(NULL, whenClause);

    // Add the col expression as SYS_CALC.col
    ColRefName *calcColName = new(heap_) ColRefName(colName, calcCorrName_);
    ItemExpr *newCalcCol = new(heap_) RenameCol(newCalcExpr, calcColName);

    selectList.insert(newCalcCol);
  }

  // The select list is ready. Create the root over topNode.
  RelRoot *newRoot = new(heap_) 
    RelRoot(topNode, REL_ROOT, selectList.convertToItemExpr());
  newRoot->setDontOpenNewScope();

  selectList.clear();
  return newRoot;
}  // MavRelRootBuilder::buildRootForOthers()
Exemple #22
0
void ItemDocument::select(QCanvasItem *item) {
	if (!item) return;

	item->setSelected(selectList()->contains(item) || selectList()->addQCanvasItem(item));
}
Exemple #23
0
void ItemDocument::unselectAll() {
	selectList()->removeAllItems();
}
//----------------------------------------------------------------------------
// Finally, Add the @GOP (Group Op) column- The select list is (*, <GOP expr>)
// This column is either 1, 2, 3 or 4 (see enum GroupOpNumbers).
// This is later used as the condition that routes the request down to the
// MAV Insert, MAV Delete or MAV Update nodes.
// @GOP is defined as (cnts represents the column name for COUNT(*)):
// CASE 
//   WHEN (SYS_MAV.cnts IS NULL)	                THEN GOP_INSERT
//   WHEN (SYS_MAV.cnts = (0 - SYS_DELTA.cnts))         THEN GOP_DELETE
//   WHEN <minMaxRecomputeCondition_>                   THEN GOP_MINMAX_RECOMPUTE
//   ELSE                                                    GOP_UPDATE
// END
// The minMaxRecomputeCondition_ condition is built during the 
// buildRootForDelta() phase, and checks if any of the current Min/Max values
// were deleted, so that recalculation is needed.
//
// A predicate is added to the RelRoot node to filter self-cancelling delta
// rows. The condition for a self-cancelling row is:
//   (SYS_MAV.cnts IS NULL AND SYS_DELTA.cnts = 0)
//----------------------------------------------------------------------------
RelRoot *MavRelRootBuilder::buildRootForGop(RelExpr *topNode)
{
  // Find the MAV column name for COUNT(*).
  const NAString& countStarColName =
    mavCols_[posOfCountStar_]->getColName();

  // The condition for Insert to MAV
  ItemExpr *insCondition = new(heap_) // (MAV.cnts IS NULL)
    UnLogic(ITM_IS_NULL, 
	    new(heap_) ColReference(new(heap_) 
	      ColRefName(countStarColName, mavCorrName_)));

  // The condition for Delete from MAV
  // (MAV.cnts = (0 - SYS_DELTA.cnts))
  ItemExpr *delCondition = new(heap_)
    BiRelat(ITM_EQUAL, 
  	    new(heap_) ColReference(new(heap_) 
	      ColRefName(countStarColName, mavCorrName_)),
	    new(heap_) BiArith(ITM_MINUS, 
    			       new(heap_) SystemLiteral(0),
			       new(heap_) ColReference(new(heap_) 
			         ColRefName(countStarColName, deltaCorrName_))));

  // These are the constants for all possible GOP column values.
  ItemExpr *constInsert = new(heap_) SystemLiteral(MavBuilder::GOP_INSERT);
  ItemExpr *constDelete = new(heap_) SystemLiteral(MavBuilder::GOP_DELETE);
  ItemExpr *constUpdate = new(heap_) SystemLiteral(MavBuilder::GOP_UPDATE);
  ItemExpr *constRecompFromUpdate = new(heap_) SystemLiteral(MavBuilder::GOP_MINMAX_RECOMPUTE_FROM_UPDATE);
  ItemExpr *constRecompFromInsert = new(heap_) SystemLiteral(MavBuilder::GOP_MINMAX_RECOMPUTE_FROM_INSERT);

  // The condition for recompute when a min/max value was deleted was created
  // during the buildRootForDelta() phase. If there are no Min/Max columns,
  // it is NULL, and therefore redundant.
  ItemExpr *lastClause;
  if (minMaxRecomputeOnUpdateCondition_ == NULL)
    lastClause = constUpdate;
  else
    lastClause = new(heap_) 
      IfThenElse(minMaxRecomputeOnUpdateCondition_, 
                 constRecompFromUpdate, 
		 constUpdate);

  ItemExpr *insertClause;
  if (minMaxRecomputeOnInsertCondition_ == NULL)
    insertClause = constInsert;
  else
    insertClause = new(heap_) 
      Case(NULL, new(heap_) IfThenElse(minMaxRecomputeOnInsertCondition_, 
                 constRecompFromInsert, 
		 constInsert));

  // Build the CASE and IF operators
  ItemExpr *gopExpression = new(heap_) 
    Case(NULL, 
	 new(heap_) IfThenElse(insCondition, insertClause,
	 new(heap_) IfThenElse(delCondition, constDelete, lastClause)));

  // Add the GOP expression as SYS_CALC.@GOP.
  ColRefName *gopColName = new(heap_)
    ColRefName(MavBuilder::getVirtualGopColumnName(), calcCorrName_);
  ItemExpr *gopColumn = new(heap_) RenameCol(gopExpression, gopColName);

  // Start the select list with *
  ItemExprList selectList(heap_);
  addStarToSelectList(selectList);

  selectList.insert(gopColumn);

  // The select list is ready. Create the root over topNode.
  RelRoot *newRoot = new(heap_) 
    RelRoot(topNode, REL_ROOT, selectList.convertToItemExpr());
  newRoot->setDontOpenNewScope();

  selectList.clear();
  return newRoot;
}  // MavRelRootBuilder::buildRootForGop()
GlobalDataTypeRegistry::RegistResult GlobalDataTypeRegistry::registImpl(Entry* dtd)
{
    if (!dtd || (dtd->descriptor.getID() > DataTypeID::Max))
    {
        UAVCAN_ASSERT(0);
        return RegistResultInvalidParams;
    }
    if (isFrozen())
    {
        return RegistResultFrozen;
    }

    List* list = selectList(dtd->descriptor.getKind());
    if (!list)
    {
        return RegistResultInvalidParams;
    }

    {   // Collision check
        Entry* p = list->get();
        while (p)
        {
            if (p->descriptor.getID() == dtd->descriptor.getID()) // ID collision
            {
                return RegistResultCollision;
            }
            if (!std::strncmp(p->descriptor.getFullName(), dtd->descriptor.getFullName(),
                              DataTypeDescriptor::MaxFullNameLen))                        // Name collision
            {
                return RegistResultCollision;
            }
            p = p->getNextListNode();
        }
    }
#if UAVCAN_DEBUG
    const unsigned len_before = list->getLength();
#endif
    list->insertBefore(dtd, EntryInsertionComparator(dtd));

#if UAVCAN_DEBUG
    {   // List integrity check
        const unsigned len_after = list->getLength();
        if ((len_before + 1) != len_after)
        {
            UAVCAN_ASSERT(0);
            std::abort();
        }
    }
    {   // Order check
        Entry* p = list->get();
        int id = -1;
        while (p)
        {
            if (id >= p->descriptor.getID().get())
            {
                UAVCAN_ASSERT(0);
                std::abort();
            }
            id = p->descriptor.getID().get();
            p = p->getNextListNode();
        }
    }
#endif
    return RegistResultOk;
}