blob: b007e8ca94a93de60bc0e95e4dc8cdaabec84e6a [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 "QueryMemoView.h"
#include "ui_QueryMemoView.h"
#include "QueryData.h"
#include "MainWindow.h"
extern MainWindow *mainWindow_;
DirtyGrid::DirtyGrid(Int32 row, Int32 col,const QIcon & pict) :
m_row(row), m_col(col), m_pict(pict) {}
QueryMemoView::QueryMemoView(QWidget * parent):QWidget(parent),
ui(new Ui::QueryMemoView)
{
ui->setupUi(this);
m_currTaskNo = 0;
m_currTask = NULL;
m_currContext = NULL;
m_currGrpNo = 0;
m_currExpNo = 0;
m_memo = NULL;
m_cascadesTask = NULL;
m_hold = TRUE;
m_trackGridCell = FALSE;
m_memoGridHasElem = FALSE;
m_initialGroups = 0;
m_oldGroups = 0;
m_oldTasks = 0;
m_stopTaskNo = -1; // stops at every task until reset
m_stopGroupNo = -1;
m_stopExprNo = -1;
//m_stopExpr = NULL;
//m_stopPlan = NULL;
m_bStopNextTask = FALSE;
m_bStopTaskNo = FALSE;
m_bStopNextGroup = FALSE;
m_bStopExprOfGrp = FALSE;
m_dirtyList.clear();
m_taskList.clear();
m_contextList.clear();
m_groupList.clear();
m_groupSize.clear();
VIEWPORT_MAXROWS = 20;
VIEWPORT_MAXCOLS = 50;
RANGE_LOW = -1;
RANGE_HIGH = 32767;
RANGE_HIGH_TASKS = 2147483647;
ui->memoWidget->setMouseTracking(true);
ui->contextWidget->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
ui->contextWidget->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
ui->taskWidget->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
ui->taskWidget->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
}
QueryMemoView::~QueryMemoView()
{
delete ui;
}
void QueryMemoView::ResetMemoMembers()
{
//------------------------------------------------------------------
// GSH : Here we clear all components of the memo view in
// preparation for displaying the memo for the next query. The
// components include the memo grid, task list, context list, and
// all the spin controls, In this procedure we also reset all the
// the member variables of CSqldbgMView thus preparing for the
// memo display for next query.
//------------------------------------------------------------------
//------------------------------------------------------------------
// GSH : Reset the memo grid.
//------------------------------------------------------------------
if (m_memoGridHasElem)
ClearMemoGrid();
//------------------------------------------------------------------
// GSH : Reset the task list and context list.
//------------------------------------------------------------------
FreeTaskMemory();
FreeContextMemory();
//------------------------------------------------------------------
// GSH : Now reset the Spin Controls.
//------------------------------------------------------------------
ui->group_spin->setValue(RANGE_LOW);
ui->expr_spin->setValue(RANGE_LOW);
ui->task_spin->setValue(RANGE_LOW);
//ui->step_spin->setValue(RANGE_LOW);
//------------------------------------------------------------------
// GSH : Now reset the member variables.
//------------------------------------------------------------------
m_currTaskNo = 0;
m_memo = NULL;
m_cascadesTask = NULL;
m_currTask = NULL;
m_currContext = NULL;
m_hold = TRUE;
m_trackGridCell = FALSE;
m_memoGridHasElem = FALSE;
m_initialGroups = 0;
m_oldGroups = 0;
m_oldTasks = 0;
m_stopTaskNo = -1; // stops at every task until reset
m_stopGroupNo = -1;
m_stopExprNo = -1;
//m_stopExpr = NULL;
//m_stopPlan = NULL;
m_bStopNextTask = FALSE;
m_bStopTaskNo = FALSE;
m_bStopNextGroup = FALSE;
m_bStopExprOfGrp = FALSE;
m_taskList.clear();
m_contextList.clear();
m_groupList.clear();
m_groupSize.clear();
}
void QueryMemoView::SetMemoData(void *memoData)
{
m_memo = (CascadesMemo *) memoData;
}
// make Grp No and Exp No consistent with the plan in the document.
void QueryMemoView::syncToDocument()
{
// make Grp No and Exp No consistent with the plan in the document.
m_memo = (CascadesMemo*)(mainWindow_->m_querydata->GetMemo());
void *plan = NULL;
void *query = NULL;
mainWindow_->m_querydata->GetData(&query, &plan);
if(plan)
syncGrpNoExpNoToPlan((CascadesPlan *)plan);
}
void QueryMemoView::syncGrpNoExpNoToPlan(CascadesPlan *targetPlan)
{
m_currContext = targetPlan->getContext();
RelExpr *pExpr = targetPlan->getPhysicalExpr();
m_currGrpNo = pExpr->getGroupId();
if(m_memo) {
CascadesGroup *group = (*m_memo)[m_currGrpNo];
RelExpr *expr = group->getFirstLogExpr();
Int32 exprNo = 0;
while(expr && expr->isLogical()) {
expr = expr->getNextInGroup();
exprNo++;
}
expr = group->getFirstPhysExpr();
while(expr && expr->isPhysical()) {
expr = expr->getNextInGroup();
exprNo++;
}
for(Int32 planNo=0; planNo < (Int32)group->getCountOfPlans(); planNo++){
CascadesPlan *plan = group->getPlans()[planNo];
if(plan == targetPlan){
m_currExpNo = exprNo;
return;
}
exprNo++;
}
}
}
NABoolean QueryMemoView::NeedToStop(Int32 passNo, Int32 groupNo, Int32 currentTaskNo, CascadesTask *task, ExprNode *expr, CascadesPlan *plan)
{
// this call has the side effect of setting the current task number
m_currTaskNo = currentTaskNo;
m_currTask = task;
m_currPassNo = passNo;
m_currGrpNo = groupNo;
calcCurrExprNo(expr, plan);
if ( m_hold OR
m_bStopNextTask OR
(m_bStopTaskNo AND (m_stopTaskNo == currentTaskNo)) OR
(m_bStopExprOfGrp AND m_stopExprNo != -1 AND (m_stopGroupNo == groupNo) AND (m_stopExprNo == m_currExpNo)) OR
(m_bStopExprOfGrp AND m_stopExprNo == -1 AND (m_stopGroupNo == groupNo)) OR
(m_bStopTask AND (m_stopTask == task))
)
{
logprint("m_stopTask:%p => task:%p\n", m_stopTask, task);
m_hold = TRUE;
m_memo = (CascadesMemo*)(mainWindow_->m_querydata->GetMemo());
m_cascadesTask = (CascadesTaskList*)(mainWindow_->m_querydata->GetTaskList());
//------------------------------------------------------------------
// GSH : First we need to update the memo view with the latest memo
// and task list.
//------------------------------------------------------------------
m_analysis = (QueryAnalysis*)(mainWindow_->m_querydata->GetAnalysis());
UpdateGroupList();
UpdateView();
if (task != NULL AND task->getPlan() != NULL)
setDisplayExpr(NULL, task->getPlan());
else if (task != NULL AND task->getExpr() != NULL)
setDisplayExpr(task->getExpr()->castToRelExpr(), NULL);
}
return m_hold;
}
/*
* Keep m_groupList and exprNo in each group sync with memo
* */
void QueryMemoView::UpdateGroupList()
{
// bring the list of groups up to date
// add new group opointer to m_groupList if a new group added in memo
while ((CollIndex)m_memo->getCountOfUsedGroups() > m_groupList.size())
{
m_groupList.append((*m_memo)[(Int32) m_groupList.size()]);
m_groupSize.append(0);
}
// bring the expression counts up to date
// keep expr num in each group sync
for (Int32 grno = 0; (CollIndex)grno < m_groupSize.size(); grno++)
{
m_groupSize[grno] = NumExprsInGroup(grno);
}
}
void QueryMemoView::UpdateView()
{
calcCurrContext();
updateSelfFully();
}
void QueryMemoView::calcCurrContext()
{
CascadesPlan *plan = calcCurrPlan();
if(plan)
m_currContext = plan->getContext();
}
void QueryMemoView::calcCurrExprNo(ExprNode *expr, CascadesPlan *plan)
{
//calculate m_currExpNo from expr or plan passed to NeedToStop
if(NULL == m_memo)
return;
Int32 exprCount = 0;
if(NULL == expr && NULL != plan)
{
CascadesGroup *_group = (*m_memo)[m_currGrpNo];
exprCount += _group->getCountOfLogicalExpr();
exprCount += _group->getCountOfPhysicalExpr();
for(Int32 planNo=0; planNo < (Int32)_group->getCountOfPlans(); planNo++)
{
CascadesPlan * _plan = _group->getPlans()[planNo];
exprCount++;
if(NULL != _plan && _plan == plan) goto L;
}
}//if(NULL == expr && NULL != plan)
else if(NULL != expr && NULL == plan)
{
CascadesGroup *_group = (*m_memo)[m_currGrpNo];
RelExpr *_expr = _group->getFirstLogExpr();
while(_expr && _expr->isLogical())
{
exprCount++;
if(_expr == expr) goto L;
_expr = _expr->getNextInGroup();
}
_expr = _group->getFirstPhysExpr();
while(_expr && _expr->isPhysical()) {
exprCount++;
if(_expr == expr) goto L;
_expr = _expr->getNextInGroup();
}
}//else if
L:
m_currExpNo = exprCount - 1;
}
void QueryMemoView::updateSelfFully()
{
m_trackGridCell = FALSE;
DrawMemo();
UpdateTaskList();
UpdateSpinControls();
UpdateContextList();
m_trackGridCell = TRUE;
}
void QueryMemoView::clearDirtyGrids()
{
for(UInt32 i = 0; i< m_dirtyList.size(); i++){
struct DirtyGrid *grid = m_dirtyList[i];
Int32 row = grid->m_row;
Int32 col = grid->m_col;
QIcon icon = grid->m_pict;
QTableWidgetItem * cell = ui->memoWidget->item(row, col);
if(cell)
cell->setIcon(icon);
delete grid;
}
m_dirtyList.clear();
}
void QueryMemoView::changeMemo()
{
if(!m_memo || ! m_memoGridHasElem)
return;
clearDirtyGrids();
drawSelectedExpr();
drawCandidatePlanAndSolution(m_currContext);
}
void QueryMemoView::updateSelf()
{
m_trackGridCell = FALSE;
changeMemo();
UpdateTaskList();
UpdateSpinControls();
UpdateContextList();
m_trackGridCell = TRUE;
}
void QueryMemoView::UpdateContextList()
{
//---------------------------------------------------------------------
// GSH : Don't do anything if we aren't optimizing
//---------------------------------------------------------------------
//ui->contextWidget->setColumnCount(5);
if(m_memo != NULL AND m_memo->getCountOfUsedGroups() != 0)
{
//---------------------------------------------------------------------
// GSH : Delete the existing context list and update it with the new
// contexts.
//---------------------------------------------------------------------
m_contextList.clear();
//---------------------------------------------------------------------
// GSH : Make sure that the group list is up to date.
//--------------------------------------------------------------------
if ((CollIndex)m_memo->getCountOfUsedGroups() > m_groupList.size())
UpdateGroupList();
#if 1
Context *currContext;
for (Int32 i=0; i<m_groupList[m_currGrpNo]->getCountOfContexts(); i++)
{
currContext = m_groupList[m_currGrpNo]->getContext(i);
m_contextList.insert(0,currContext);
}
#endif
#if 0
Context *currContext;
for (Int32 i=0; i<(*m_memo)[m_currGrpNo]->getCountOfContexts(); i++)
{
currContext = (*m_memo)[m_currGrpNo]->getContext(i);
m_contextList->insertAt(0,currContext);
}
#endif
//--------------------------------------------------------------------
// GSH : Now m_contextList has all the context that we need to display
// in the m_context list control. So go ahead and display. First you have
// to delete all the existing items in the m_context list control.
//--------------------------------------------------------------------
FreeContextMemory();
displayContextList();
}
// adjust Context table size
QStringList header;
header << "Group" << "Cost Limit" << "Logical Props" << "Status" << "Required Physical Properties";
ui->contextWidget->setHorizontalHeaderLabels(header);
for(int i=0; i<ui->contextWidget->columnCount(); i++){
ui->contextWidget->resizeColumnToContents(i);
int width = ui->contextWidget->columnWidth (i);
ui->contextWidget->setColumnWidth (i,width + 30);
}
}
void QueryMemoView::displayContextList()
{
// clear current context if we are switching groups
if (m_currContext &&
m_currContext->getGroupId() != (CascadesGroupId)m_currGrpNo)
{
m_currContext = NULL;
}
ui->contextWidget->setRowCount(m_contextList.size());
for (Int32 i = 0; (CollIndex)i < m_contextList.size(); i ++)
{
#if 0
CONTEXTDETAILS* pContextDetails;
pContextDetails = new CONTEXTDETAILS;
pContextDetails->thisContext = m_contextList[i];
pContextDetails->costText = QString(m_contextList[i]->getCostString().data());
pContextDetails->ilpText = QString(m_contextList[i]->getILPString().data());
pContextDetails->statText = QString(m_contextList[i]->getStatusString().data());
pContextDetails->rppText = QString(m_contextList[i]->getRPPString().data());
pContextDetails->groupNo = m_currGrpNo;
#endif
//highlight the current context
QIcon contextIcon;
if(m_currContext == m_contextList[i])
contextIcon = QIcon(":/file/Resource/Main/Context_green.bmp");
else
contextIcon = QIcon(":/file/Resource/Main/Context.bmp");
//add one row
//save context pointer to cell
QTableWidgetItem *pItem0 = new QTableWidgetItem(contextIcon,QString::number(m_currGrpNo));
QVariant itemData = qVariantFromValue((void*)(m_contextList[i]));
pItem0->setData(Qt::UserRole, itemData);
QTableWidgetItem *pItem1 = new QTableWidgetItem(QString(m_contextList[i]->getCostString().data()));
QTableWidgetItem *pItem2 = new QTableWidgetItem(QString(m_contextList[i]->getILPString().data()));
QTableWidgetItem *pItem3 = new QTableWidgetItem(QString(m_contextList[i]->getStatusString().data()));
QTableWidgetItem *pItem4 = new QTableWidgetItem(QString(m_contextList[i]->getRPPString().data()));
ui->contextWidget->setItem (i, 0, pItem0);
ui->contextWidget->setItem (i, 1, pItem1);
ui->contextWidget->setItem (i, 2, pItem2);
ui->contextWidget->setItem (i, 3, pItem3);
ui->contextWidget->setItem (i, 4, pItem4);
}//for (Int32 i = 0; (CollIndex)i < m_contextList.size(); i ++)
}
void QueryMemoView::FreeContextMemory()
{
ui->contextWidget->clear();
}
void QueryMemoView::UpdateSpinControls()
{
ui->group_spin->setValue(m_currGrpNo);
ui->expr_spin->setValue(m_currExpNo);
ui->task_spin->setValue(m_currTaskNo);
}
void QueryMemoView::UpdateTaskList()
{
//---------------------------------------------------------------------
// GSH : Get the list of Cascades Task list from the docmument and
// display the text describing each task in the m_task List control of
// the Memo View.
//---------------------------------------------------------------------
m_cascadesTask = (CascadesTaskList*)(mainWindow_->m_querydata->GetTaskList());
//---------------------------------------------------------------------
// GSH : Don't do anything if we aren't optimizing
//---------------------------------------------------------------------
if (m_memo != NULL AND
m_memo->getCountOfUsedGroups() != 0 AND
m_cascadesTask != NULL)
{
//---------------------------------------------------------------------
// GSH : Delete the existing task list and update it with the new tasks.
//---------------------------------------------------------------------
m_taskList.clear();
//--------------------------------------------------------------------
// GSH : Populate m_taskList with tasks in docmument tasklist
//--------------------------------------------------------------------
CascadesTask *currTask = m_cascadesTask->getFirst();
while (currTask != NULL)
{
m_taskList.insert(0,currTask);
currTask = m_cascadesTask->getNext(currTask);
}
//--------------------------------------------------------------------
// GSH : Now m_taskList has all the task that we need to display in
// the m_task list control. So go ahead and display. First you have
// to delete all the existing items in the m_task list control.
//--------------------------------------------------------------------
FreeTaskMemory();
displayTaskList();
}
//adjust task view size
QStringList header;
header << "Tasks"<<" ";
ui->taskWidget->setHorizontalHeaderLabels(header);
for(int i=0;i<ui->taskWidget->columnCount();i++){
ui->taskWidget->resizeColumnToContents(i);
int width = ui->taskWidget->columnWidth (i);
ui->taskWidget->setColumnWidth (i,width + 30);
}
/*
* taskWidget only need one column,
* the column just to make scrollbar appear.
* */
ui->taskWidget->setColumnWidth(1,1);
}
void QueryMemoView::FreeTaskMemory()
{
ui->taskWidget->clear();
}
void QueryMemoView::displayTaskList()
{
ui->taskWidget->setRowCount(m_taskList.size());
for (Int32 i = 0; (CollIndex)i < m_taskList.size(); i ++)
{
QTableWidgetItem *pItem = new QTableWidgetItem();
pItem->setIcon(QIcon(":/file/Resource/Main/Taskdetails.bmp"));
pItem->setText(QString(m_taskList[i]->taskText().data()));
QVariant itemData = qVariantFromValue((void*)(m_taskList[i]));
pItem->setData(Qt::UserRole, itemData);
ui->taskWidget->setItem (m_taskList.size()-1-i, 0, pItem);
}
}
Int32 QueryMemoView::NumExprsInGroup(Int32 grno)
{
Int32 result = 0;
if (m_memo != NULL AND
grno >= 0 AND
(Lng32)grno < m_memo->getCountOfUsedGroups())
{
RelExpr *e = (*m_memo)[grno]->getFirstLogExpr();
while (e != NULL)
{
result++;
e = e->getNextInGroup();
}
e = (*m_memo)[grno]->getFirstPhysExpr();
while (e != NULL)
{
result++;
e = e->getNextInGroup();
}
CollIndex numplans = (*m_memo)[grno]->getCountOfPlans();
if (numplans > 0)
result += ((Int32)numplans);
}
return result;
}
CascadesPlan * QueryMemoView::calcCurrPlan()
{
CascadesPlan *p = NULL;
if (m_memo != NULL && m_currExpNo > 0) {
Int32 grno = m_currGrpNo;
Int32 exprno = m_currExpNo;
// found the group, now walk the list to expression number "exprno"
RelExpr *e = (*m_memo)[grno]->getFirstLogExpr();
while (e != NULL AND exprno > 0)
{
e = e->getNextInGroup();
exprno--;
}
if (e == NULL)
e = (*m_memo)[grno]->getFirstPhysExpr();
while (e != NULL AND exprno > 0)
{
e = e->getNextInGroup();
exprno--;
}
if (e == NULL)
{
Lng32 numPlans = (*m_memo)[grno]->getCountOfPlans();
if (exprno >= 0 AND exprno < numPlans)
p = (*m_memo)[grno]->getPlans()[exprno];
}
}//if(m_memo != NULL && m_currExpNo > 0)
return p;
}
void QueryMemoView::setDisplayExpr(RelExpr* expr, CascadesPlan* plan)
{
// need to update m_currGrpNo & m_currExpNo
mainWindow_->m_querydata->SetData(expr, plan);
//mainWindow_->UpdateAllViews();
mainWindow_->UpdateQueryTreeView();
}
void QueryMemoView::DrawMemo(void)
{
m_memo = (CascadesMemo*)(mainWindow_->m_querydata->GetMemo());
if(!m_memo){
m_currGrpNo = 0;
m_currExpNo = 0;
}
setMemoMaxRowsCols();
InitMemoDisplay(22, 22);
if (m_memoGridHasElem)
ClearMemoGrid();
// now draw them
if (m_memo != NULL)
{
CascadesGroupId maxgroups = m_memo->getCountOfUsedGroups();
if (m_initialGroups == 0)
m_initialGroups = (Int32)maxgroups;
//draw all the expressions and plans in memo
for (CascadesGroupId grno=0; grno<maxgroups; grno++)
{
DrawMemoGroup((Int32) grno);
}
drawSelectedExpr();
drawCandidatePlanAndSolution(m_currContext);
m_memoGridHasElem = TRUE;
m_oldGroups = maxgroups;
}
}
void QueryMemoView::setMemoMaxRowsCols()
{
Int32 maxRows, maxCols;
if(m_memo){
maxRows = m_memo->getCountOfUsedGroups();
maxCols = 0;
for(Int32 grp = 0; grp < maxRows; grp++){
Int32 numExpr = NumExprsInGroup(grp);
if(maxCols < numExpr)
maxCols = numExpr;
}
maxCols++;
}
else{
maxRows = VIEWPORT_MAXROWS;
maxCols = VIEWPORT_MAXCOLS;
}
ui->memoWidget->setRowCount(maxRows);
ui->memoWidget->setColumnCount(maxCols);
}
/*
* set every grid cell width and height
* */
void QueryMemoView::InitMemoDisplay(int width, int height)
{
Int32 row, col;
for (row=0;row<ui->memoWidget->rowCount();row++)
{
ui->memoWidget->setRowHeight(row, width);
}
for (col=0;col<ui->memoWidget->columnCount();col++)
{
ui->memoWidget->setColumnWidth(col, height);
}
}
void QueryMemoView::ClearMemoGrid()
{
ui->memoWidget->clear();
m_memoGridHasElem = FALSE;
}
void QueryMemoView::DrawMemoGroup(Int32 grno)
{
if (m_memo == NULL OR grno < 0)
return;
QTableWidgetItem *pItem = new QTableWidgetItem();
// ---------------------------------------------------------------------
// display the icon (colored rectangle) for the group
// ---------------------------------------------------------------------
if ((*m_memo)[grno]->getGroupId() != (CollIndex)grno)
// this group is merged and no longer exists
pItem->setIcon(QIcon(":/file/Resource/Main/Merggrp.bmp"));
else if (grno < m_initialGroups)
// this group was allocated as part of the original query
pItem->setIcon(QIcon(":/file/Resource/Main/Initgrp.bmp"));
else if (grno < m_oldGroups)
//this group was added during optimization, but before the last step
pItem->setIcon(QIcon(":/file/Resource/Main/Addngrp.bmp"));
else
// this group was added during the last step
pItem->setIcon(QIcon(":/file/Resource/Main/Newgrp.bmp"));
//-------------------------------------------------------------
// GSH : This is one of the places where we do not use the member
// function SetGridCell to set the appropriate Grid row and
// column. This is to draw the icon representing the group.
//-------------------------------------------------------------
ui->memoWidget->setItem (grno, 0, pItem);
DrawExprInMemoGroup(grno);
}
void QueryMemoView::DrawExprInMemoGroup(Int32 grno)
{
Int32 exprno = 0;
DrawLogExpr(grno,exprno);
DrawPhyExpr(grno,exprno);
DrawPlans(grno,exprno);
}
void QueryMemoView::DrawLogExpr(Int32 grno, Int32& exprno)
{
CascadesGroup *group = (*m_memo)[grno];
RelExpr *expr = NULL;
expr = group->getFirstLogExpr();
if (expr == NULL)
return;
while ((expr != NULL) && expr->isLogical())
{
QTableWidgetItem *pItem = new QTableWidgetItem();
pItem->setIcon(QIcon(":/file/Resource/Main/Logexp.bmp"));
pItem->setToolTip (QString("%1,%2").arg(grno).arg(exprno));
ui->memoWidget->setItem (grno, exprno + 1, pItem);
exprno++; // Increment exprno for next expression in group
expr = expr->getNextInGroup(); // get next expression
}
}
void QueryMemoView::DrawPhyExpr(Int32 grno, Int32& exprno)
{
CascadesGroup *group = (*m_memo)[grno];
RelExpr *expr = NULL;
expr = group->getFirstPhysExpr();
if (expr == NULL)
return;
while (expr != NULL && expr->isPhysical())
{
QTableWidgetItem *pItem = new QTableWidgetItem();
pItem->setIcon(QIcon(":/file/Resource/Main/Phyexp.bmp"));
pItem->setToolTip (QString("%1,%2").arg(grno).arg(exprno));
ui->memoWidget->setItem (grno, exprno + 1, pItem);
exprno++; // Increment col for next expression in group
expr = expr->getNextInGroup(); // get next expression
}
}
void QueryMemoView::DrawPlans(Int32 grno, Int32& exprno)
{
CascadesGroup *group = (*m_memo)[grno];
for(Int32 planNo=0; planNo < (Int32)group->getCountOfPlans(); planNo++){
CascadesPlan *plan = group->getPlans()[planNo];
RelExpr *expr = plan->getPhysicalExpr();
if(expr) {
QTableWidgetItem *pItem = new QTableWidgetItem();
pItem->setIcon(QIcon(":/file/Resource/Main/Plan.bmp"));
pItem->setToolTip(QString("%1,%2").arg(grno).arg(exprno));
ui->memoWidget->setItem (grno, exprno + 1, pItem);
exprno++;
}
} //end for
}
/*selected expression is current expression in current group*/
void QueryMemoView::drawSelectedExpr()
{
Int32 grno = m_currGrpNo;
Int32 exprno = m_currExpNo;
//Scroll to current expression
ui->memoWidget->scrollTo(ui->memoWidget->model()->index(m_currGrpNo, m_currExpNo>0?m_currExpNo:0), QAbstractItemView::EnsureVisible);
if(-1 == m_currExpNo) //-1 == m_currExpNo means there is no selected Expr
return;
//find the selected expression via m_currGrpNo and m_currExpNo
RelExpr *e = (*m_memo)[grno]->getFirstLogExpr();
while (e != NULL AND exprno > 0)
{
e = e->getNextInGroup();
exprno--;
}
if(e) { //exprno fall in LogExpr
QTableWidgetItem *pItem = ui->memoWidget->item(m_currGrpNo, m_currExpNo+1);
pItem->setIcon(QIcon(":/file/Resource/Main/SelLogExp.bmp"));
struct DirtyGrid *grid = new DirtyGrid(m_currGrpNo,
m_currExpNo+1,
QIcon(":/file/Resource/Main/Logexp.bmp"));
m_dirtyList.insert(0, grid);
return;
}
//out of range of LogExpr find in PhysExpr
e = (*m_memo)[grno]->getFirstPhysExpr();
while (e != NULL AND exprno > 0)
{
e = e->getNextInGroup();
exprno--;
}
if(e){//exprno fall in PhysExpr
QTableWidgetItem *pItem = ui->memoWidget->item(m_currGrpNo, m_currExpNo+1);
pItem->setIcon(QIcon(":/file/Resource/Main/SelPhyExp.bmp"));
struct DirtyGrid *grid = new DirtyGrid(m_currGrpNo,
m_currExpNo+1,
QIcon(":/file/Resource/Main/Phyexp.bmp"));
m_dirtyList.insert(0, grid);
return;
}
//find expr in Plan range
Lng32 numPlans = (*m_memo)[grno]->getCountOfPlans();
if (exprno >= 0 AND exprno < numPlans){
QTableWidgetItem *pItem = ui->memoWidget->item(m_currGrpNo, m_currExpNo+1);
pItem->setIcon(QIcon(":/file/Resource/Main/SelPlan.bmp"));
struct DirtyGrid *grid = new DirtyGrid(m_currGrpNo,
m_currExpNo+1,
QIcon(":/file/Resource/Main/Plan.bmp"));
m_dirtyList.insert(0, grid);
}
}
/*mark the plan of current group if it is a Solution or Candidate*/
void QueryMemoView::drawCandidatePlanAndSolution(Context* context)
{
if(!context)
return;
Int32 exprno = 0;
Int32 grno = m_currGrpNo;
RelExpr *e = (*m_memo)[grno]->getFirstLogExpr();
while (e)
{
e = e->getNextInGroup();
exprno++;
}
e = (*m_memo)[grno]->getFirstPhysExpr();
while (e)
{
e = e->getNextInGroup();
exprno++;
}
CascadesGroup *group = (*m_memo)[grno];
for(Int32 planNo=0; planNo < (Int32)group->getCountOfPlans(); planNo++){
CascadesPlan *plan = group->getPlans()[planNo];
RelExpr *expr = plan->getPhysicalExpr();
if(expr){
if (context->getSolution() == plan) {
QTableWidgetItem *pItem = ui->memoWidget->item(grno, exprno+1);
pItem->setIcon(QIcon(":/file/Resource/Main/Solution.bmp"));
struct DirtyGrid *grid = new DirtyGrid(grno,
exprno+1,
QIcon(":/file/Resource/Main/Plan.bmp"));
m_dirtyList.insert(0, grid);
}
else if (context->isACandidate(plan)){
QTableWidgetItem *pItem = ui->memoWidget->item(grno, exprno+1);
pItem->setIcon(QIcon(":/file/Resource/Main/CandPlan.bmp"));
struct DirtyGrid *grid = new DirtyGrid(grno,
exprno+1,
QIcon(":/file/Resource/Main/Plan.bmp"));
m_dirtyList.insert(0, grid);
}
exprno++;
}//if(expr)
} //for
}
void QueryMemoView::InitTaskList()
{
ui->taskWidget->setColumnCount(2);
ui->taskWidget->horizontalHeader()->setDefaultAlignment(Qt::AlignLeft);
}
void QueryMemoView::InitContextList()
{
ui->contextWidget->setColumnCount(5);
ui->contextWidget->horizontalHeader()->setDefaultAlignment(Qt::AlignLeft);
}
void QueryMemoView::InitSpinControls()
{
unsigned long max_range = RANGE_HIGH_TASKS > RANGE_HIGH ? RANGE_HIGH_TASKS : RANGE_HIGH;
ui->group_spin->setRange(RANGE_LOW, max_range);
ui->expr_spin->setRange(RANGE_LOW, max_range);
ui->task_spin->setRange(RANGE_LOW, max_range);
}
void QueryMemoView::StopAtExpr(Int32 grno, Int32 exprno, NABoolean enabled)
{
m_bStopExprOfGrp = enabled;
m_stopGroupNo = grno;
m_stopExprNo = exprno;
}
void QueryMemoView::turnOffMemoTrack()
{
m_trackGridCell = FALSE;
}
void QueryMemoView::OnMemoStepOneTask()
{
ResetMemoStops();
StopAtNextTask(TRUE);
mainWindow_->IsBackToSqlCompiler_ = true;
turnOffMemoTrack();
}
void QueryMemoView::OnMemoSteptasknum()
{
//validation check
if(ui->task_spin->value() <= m_currTaskNo)
{
QMessageBox::warning(this, "Warning", "Stop task number should be greater than current task number");
return;
}
ResetMemoStops();
StopAtTaskNo(ui->task_spin->value(), TRUE);
mainWindow_->IsBackToSqlCompiler_ = true;
}
void QueryMemoView::OnMemoStepTask()
{
QList<QTableWidgetItem *> selTaskList = ui->taskWidget->selectedItems();
if(selTaskList.count() >= 1)
{
QVariant v = selTaskList[0]->data(Qt::UserRole);
void * task = v.value < void * >();
if (NULL == task)
return;
ResetMemoStops();
StopAtTask(task, TRUE);
mainWindow_->IsBackToSqlCompiler_ = true;
}
}
void QueryMemoView::OnMemoStepgrp()
{
ResetMemoStops();
StopAtExpr(ui->group_spin->value(), -1, TRUE);
mainWindow_->IsBackToSqlCompiler_ = true;
}
void QueryMemoView::OnMemoStepexpr()
{
ResetMemoStops();
StopAtExpr(ui->group_spin->value(), ui->expr_spin->value(), TRUE);
mainWindow_->IsBackToSqlCompiler_ = true;
}
void QueryMemoView::OnMemoFinish()
{
ResetMemoStops();
mainWindow_->IsBackToSqlCompiler_ = true;
turnOffMemoTrack();
}
void QueryMemoView::OnMemoFinishpass()
{
ResetMemoStops();
mainWindow_->IsBackToSqlCompiler_ = true;
turnOffMemoTrack();
}
void QueryMemoView::memoWidgetCell(int row, int col)
{
// TODO: Add your control notification handler code here
if(!m_trackGridCell||!m_memo)
return;
if(row == m_currGrpNo && col-1 == m_currExpNo)
return;
if(CURRSTMT_OPTGLOBALS->memo) //memo is context global
m_currGrpNo = row < m_memo->getCountOfUsedGroups() ? row : m_memo->getCountOfUsedGroups();
else
m_currGrpNo = row;
m_currExpNo = (col-1) > 0 ? (col-1) : 0;
calcCurrContext();
updateSelf();
displayCurrExpr();
}
void QueryMemoView::on_memoWidget_currentCellChanged( int currentRow, int currentColumn, int previousRow, int previousColumn )
{
memoWidgetCell(currentRow, currentColumn);
}
void QueryMemoView::on_memoWidget_cellClicked(int row, int col)
{
memoWidgetCell(row, col);
}
void QueryMemoView::contextWidgetCell(int row, int col)
{
//retreive previously saved context pointer
QList<QTableWidgetItem *> selContextList = ui->contextWidget->selectedItems();
if(selContextList.count() >= 1)
{
QVariant v = selContextList[0]->data(Qt::UserRole);
Context* context = (Context*) v.value < void * >();
if (NULL == context)
return;
//now, if any, we draw the plan and solution of the context
clearDirtyGrids();
drawCandidatePlanAndSolution(context);
}
}
void QueryMemoView::on_contextWidget_cellClicked (int row, int column)
{
contextWidgetCell(row, column);
}
/*calc & display expr and plan from current grno and ExprNo*/
void QueryMemoView::displayCurrExpr()
{
if (m_memo != NULL) {
Int32 grno = m_currGrpNo;
Int32 exprno = m_currExpNo;
// found the group, now walk the list to expression number "exprno"
RelExpr *e = (*m_memo)[grno]->getFirstLogExpr();
while (e != NULL AND exprno > 0)
{
e = e->getNextInGroup();
exprno--;
}
if (e == NULL)
e = (*m_memo)[grno]->getFirstPhysExpr();
while (e != NULL AND exprno > 0)
{
e = e->getNextInGroup();
exprno--;
}
CascadesPlan *p = NULL;
if (e == NULL)
{
Lng32 numPlans = (*m_memo)[grno]->getCountOfPlans();
if (exprno >= 0 AND exprno < numPlans)
{
p = (*m_memo)[grno]->getPlans()[exprno];
e = NULL;
}
}
//set tree root of query viewer
mainWindow_->m_querydata->SetData(e, p);
mainWindow_->UpdateQueryTreeView();
}
}