blob: 23ed465cda946071ba346ae301b8e802420d531b [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 @@@
//
**********************************************************************/
/* -*-C++-*-
******************************************************************************
*
* File: RuSQLRefreshComposer.cpp
* Description: Implementation of class RuSQLRefreshComposer
*
*
* Created: 08/13/2000
* Language: C++
*
*
*
******************************************************************************
*/
#include "RuRefreshSQLComposer.h"
#include "RuGlobals.h"
#include "RuOptions.h"
#include "RuSQLDynamicStatementContainer.h"
//--------------------------------------------------------------------------//
// Constructor
//--------------------------------------------------------------------------//
CRURefreshSQLComposer::CRURefreshSQLComposer(CRURefreshTask *pTask) :
inherited(),
pTask_(pTask),
pRootMV_(&(pTask->GetRootMV()))
{}
//--------------------------------------------------------------------------//
// CRURefreshSQLComposer::StartInternalRefresh()
//
// Start a new INTERNAL REFRESH statement composition
//--------------------------------------------------------------------------//
void CRURefreshSQLComposer::StartInternalRefresh()
{
if (NULL == CRUGlobals::GetInstance()->GetOptions().
FindDebugOption(CRUGlobals::DISPLAY_REFRESH,"") )
{
sql_ = "INTERNAL REFRESH ";
}
else
{
// LCOV_EXCL_START :dpm
sql_ = "DISPLAY INTERNAL REFRESH ";
// LCOV_EXCL_STOP
}
sql_ += GetRootMV().GetFullName();
}
//--------------------------------------------------------------------------//
// CRURefreshSQLComposer::AddDeltaDefClause()
//
// Generate the DeltaDef clause
//
//--------------------------------------------------------------------------//
void CRURefreshSQLComposer::AddDeltaDefClause(const CRUDeltaDef *pDdef,
CDSString &fromEpoch,
CDSString &toEpoch)
{
// <table-name> BETWEEN <begin-epoch> AND <end-epoch>
sql_ += "\n\t" + pDdef->tblName_;
sql_ += " BETWEEN " + fromEpoch + " AND " + toEpoch;
sql_ += " DE LEVEL " + TInt32ToStr(pDdef->deLevel_);
// The delta statistics clauses (based on the emptiness check
// and the duplicate elimimation results)
AddRngDeltaStatisticsClause(pDdef);
AddIUDDeltaStatisticsClause(pDdef);
}
//--------------------------------------------------------------------------//
// CRURefreshSQLComposer::AddRngDeltaStatisticsClause()
//
// AddDeltaDefClause() callee
//
//--------------------------------------------------------------------------//
void CRURefreshSQLComposer::
AddRngDeltaStatisticsClause(const CRUDeltaDef *pDdef)
{
sql_ += "\n\t";
if (FALSE == pDdef->isRangeLogNonEmpty_)
{
sql_ += " USE NO RANGELOG";
return;
}
CRUDeltaStatistics *pStat = pDdef->pStat_;
RUASSERT(CRUDeltaDef::NO_DE != pDdef->deLevel_ && NULL != pStat);
// USE RANGELOG <number> NUM_OF_RANGES <number> ROWS_COVERED
TInt32 nRanges = pStat->nRanges_;
RUASSERT(nRanges > 0);
sql_ += "USE RANGELOG " + TInt32ToStr(nRanges) + " NUM_OF_RANGES ";
TInt32 nCoveredRows = pStat->nRangeCoveredRows_;
if (CRUDeltaStatistics::RANGE_SIZE_UNKNOWN != nCoveredRows)
{
sql_ += TInt32ToStr(nCoveredRows) + " ROWS_COVERED";
}
}
//--------------------------------------------------------------------------//
// CRURefreshSQLComposer::AddIUDDeltaStatisticsClause()
//
// AddDeltaDefClause() callee
//
//--------------------------------------------------------------------------//
void CRURefreshSQLComposer::
AddIUDDeltaStatisticsClause(const CRUDeltaDef *pDdef)
{
sql_ += "\n\t";
if (FALSE == pDdef->isIUDLogNonEmpty_)
{
sql_ += " USE NO IUDLOG";
return;
}
sql_ += "USE IUDLOG ";
if (CRUDeltaDef::SINGLE_2_SINGLE != pDdef->deLevel_)
{
// We can only tell whether the delta is insert-only or not
if (TRUE == pDdef->isIUDLogInsertOnly_)
{
// USE IUDLOG INSERT ONLY
sql_ += "INSERT ONLY";
}
return;
}
// Single-row resolution was enforced. We have complete statistics.
CRUDeltaStatistics *pStat = pDdef->pStat_;
if (NULL == pStat)
{
// DE came up with empty stats.
// Just write zeroes, and INTERNAL REFRESH will handle it.
pStat = new CRUDeltaStatistics();
}
// USE IUDLOG
// <number> ROWS_INSERTED
// <number> ROWS_DELETED
// <number> ROWS_UPDATED [COLUMNS <col>,<col>,<col>...]
sql_ += "\n\t" + TInt32ToStr(pStat->nInsertedRows_) + " ROWS_INSERTED ";
sql_ += "\n\t" + TInt32ToStr(pStat->nDeletedRows_) + " ROWS_DELETED ";
sql_ += "\n\t" + TInt32ToStr(pStat->nUpdatedRows_) + " ROWS_UPDATED ";
if (0 != pStat->nUpdatedRows_)
{
CRUUpdateBitmap *pUpdateBitmap = pStat->pUpdateBitmap_;
RUASSERT(NULL != pUpdateBitmap);
AddUpdatedColumnsClause(pUpdateBitmap);
}
}
//--------------------------------------------------------------------------//
// CRURefreshSQLComposer::AddUpdatedColumnsClause()
//
// COLUMNS <col>,<col>,<col>...
//--------------------------------------------------------------------------//
void CRURefreshSQLComposer::
AddUpdatedColumnsClause(const CRUUpdateBitmap *pUpdateBitmap)
{
sql_ += "COLUMNS (";
BOOL isFirst = TRUE;
Int32 numOfColumns = pUpdateBitmap->GetSize() * 8;
for (Int32 index=0;index < numOfColumns;index++)
{
if (FALSE == pUpdateBitmap->IsColumnUpdated(index))
{
continue;
}
if (TRUE == isFirst)
{
isFirst = FALSE;
}
else
{
sql_ += ",";
}
sql_ += TInt32ToStr(index);
}
sql_ += ") ";
}
//--------------------------------------------------------------------------//
// CRURefreshSQLComposer::AddPhaseParam()
//
// Add keyword PHASE with a placeholder for the phase number comple-time
// parameter. This parameter will be replaced through the SQL Container
// before compiling the statement.
//
//--------------------------------------------------------------------------//
void CRURefreshSQLComposer::AddPhaseParam()
{
sql_+= " \n\tPHASE ";
sql_+= CDSString(CRUSQLDynamicStatementContainer::COMPILED_PARAM_TOKEN);
sql_+= " ";
}
//--------------------------------------------------------------------------//
// CRURefreshSQLComposer::AddPipeLineClause()
//
// Generate the PIPELINE clause for each MV that the delta is pipelined to.
//
//--------------------------------------------------------------------------//
void CRURefreshSQLComposer::AddPipeLineClause()
{
CRUMVList &mvList = GetRefreshTask().GetMVList();
RUASSERT(mvList.GetCount() > 1);
DSListPosition pos = mvList.GetHeadPosition();
mvList.GetNext(pos); // Skip the root MV
// Generate root clause
CRUMV *pTopMV = mvList.GetNext(pos);
sql_ += " PIPELINE " ;
sql_ += "(" + pTopMV->GetFullName() + ")";
// Continue with the upper mv's
while (NULL != pos)
{
sql_ += pTopMV->GetFullName();
// Retrieve the next MV from the list
pTopMV = mvList.GetNext(pos);
sql_ += " PIPELINE " ;
sql_ += "(" + pTopMV->GetFullName() + ")";
if (NULL != pos)
{
sql_ += ",";
}
else
{
return;
}
}
}
//--------------------------------------------------------------------------//
// CRURefreshSQLComposer::ComposeCntrlTableMDAMText()
//
// If the name pointer is null then the table_name will be star.
//
// CONTROL TABLE table_name MDAM mdam_option
//
//
//--------------------------------------------------------------------------//
// LCOV_EXCL_START :rfi
void CRURefreshSQLComposer::ComposeCntrlTableMDAMText(
CRUForceOptions::MdamOptions mdamOption,
const CDSString* pName)
{
sql_ = "CONTROL TABLE ";
if (NULL == pName)
{
sql_ += " * ";
}
else
{
sql_ += *pName;
}
sql_ += " MDAM ";
switch (mdamOption)
{
case CRUForceOptions::MDAM_ENABLE:
sql_ += " 'ENABLE'; ";
break;
case CRUForceOptions::MDAM_ON:
sql_ += " 'ON'; ";
break;
case CRUForceOptions::MDAM_OFF:
sql_ += " 'OFF'; ";
break;
default:
ASSERT(FALSE);
}
}
// LCOV_EXCL_STOP
//--------------------------------------------------------------------------//
// CRURefreshSQLComposer::ComposeResetCntrlTableText()
//
// If the name pointer is null then the table_name will be star.
//
// CONTROL TABLE table_name RESET
//
//
//--------------------------------------------------------------------------//
// LCOV_EXCL_START :rfi
void CRURefreshSQLComposer::ComposeResetCntrlTableMDAMText(const CDSString* pName)
{
sql_ = "CONTROL TABLE ";
if (NULL == pName)
{
sql_ += " * ";
}
else
{
sql_ += *pName;
}
sql_ += " RESET; ";
}
// LCOV_EXCL_STOP
//--------------------------------------------------------------------------//
// CRURefreshSQLComposer::GetContextLogName()
//--------------------------------------------------------------------------//
CDSString CRURefreshSQLComposer::GetContextLogName() const
{
return " (RANGE_LOG_TABLE " + GetRootMV().GetFullName() + " ) ";
}
//--------------------------------------------------------------------------//
// CRURefreshSQLComposer::ComposeDeleteContextLogTable()
//--------------------------------------------------------------------------//
void CRURefreshSQLComposer::ComposeDeleteContextLogTable()
{
sql_ = " DELETE FROM TABLE " + GetContextLogName();
}
//--------------------------------------------------------------------------//
// CRURefreshSQLComposer::ComposeControlQueryShape()
//
//
//--------------------------------------------------------------------------//
// LCOV_EXCL_START :rfi
void CRURefreshSQLComposer::ComposeControlQueryShape()
{
RUASSERT(NULL != GetRootMV().GetMVForceOption());
sql_ = "CONTROL QUERY SHAPE ";
ComposeQueryShape();
sql_ += ";";
}
// LCOV_EXCL_STOP
//--------------------------------------------------------------------------//
// CRURefreshSQLComposer::ComposeQueryShape()
//
// The IR tree for internal refresh is as follows :
//
// JOIN
// / \
// JOIN UPDATE MV(sub-tree)
// / \
// GRBY SCAN
// | MV
// DELTA CALC
// (sub-tree)
//
// We allow the user to force the join between the MV and the GROUP BY
// block and the GROUP BY node above the DELTA CALCULATION sub-tree
//--------------------------------------------------------------------------//
// LCOV_EXCL_START :rfi
void CRURefreshSQLComposer::ComposeQueryShape()
{
CDSString grbyStr,joinStr;
const CRUMVForceOptions& forceOption =
*GetRootMV().GetMVForceOption();
switch(forceOption.GetGroupByoption())
{
case CRUForceOptions::GB_HASH:
grbyStr = " HASH_GROUPBY(CUT) ";
break;
case CRUForceOptions::GB_SORT:
grbyStr = " SORT_GROUPBY(CUT) ";
break;
case CRUForceOptions::GB_NO_FORCE:
grbyStr = " GROUPBY(CUT) ";
break;
default:
RUASSERT(FALSE);
}
switch(forceOption.GetJoinoption())
{
case CRUForceOptions::JOIN_MERGE:
joinStr = " MERGE_JOIN( ";
break;
case CRUForceOptions::JOIN_HASH:
joinStr = " HYBRID_HASH_JOIN( ";
break;
case CRUForceOptions::JOIN_NESTED:
joinStr = " NESTED_JOIN( ";
break;
case CRUForceOptions::JOIN_NO_FORCE:
joinStr = " JOIN(";
break;
default:
RUASSERT(FALSE);
}
sql_ += " JOIN( " + joinStr + grbyStr + ",CUT),CUT)";
}
// LCOV_EXCL_STOP
//--------------------------------------------------------------------------//
// CRURefreshSQLComposer::ComposeControlQueryShapeCut()
//--------------------------------------------------------------------------//
// LCOV_EXCL_START :rfi
void CRURefreshSQLComposer::ComposeControlQueryShapeCut()
{
sql_ = "CONTROL QUERY SHAPE CUT;";
}
// LCOV_EXCL_STOP
//--------------------------------------------------------------------------//
// CRURefreshSQLComposer::ComposeControlQueryShapeCut()
//
//--------------------------------------------------------------------------//
// LCOV_EXCL_START :rfi
void CRURefreshSQLComposer::ComposeShowExplain()
{
sql_ = "INSERT INTO ";
sql_ += GetRootMV().GetCatName() + "." + GetRootMV().GetSchName() + ".MV_REFRESH_PLANS ";
sql_ += "SELECT '";
sql_ += GetRootMV().GetName() +"',";
sql_ += "PLAN_ID,";
sql_ += "SEQ_NUM,";
sql_ += "SUBSTRING(OPERATOR,1,30),";
sql_ += "LEFT_CHILD_SEQ_NUM,";
sql_ += "RIGHT_CHILD_SEQ_NUM,";
sql_ += "SUBSTRING(TNAME,1,60),";
sql_ += "CARDINALITY,";
sql_ += "OPERATOR_COST,";
sql_ += "TOTAL_COST,";
sql_ += "SUBSTRING(DETAIL_COST,1,1024),";
sql_ += "SUBSTRING(DESCRIPTION,1,2024)";
sql_ += " FROM TABLE(EXPLAIN(NULL,'DESCRIPTOR_FOR_SQLSTMT'));";
}
// LCOV_EXCL_STOP
/*
// This is the definition of the table in which the explain data is inserted
create table MV_REFRESH_PLANS
(
MV_NAME char(200) NOT NULL NOT DROPPABLE,
PLAN_ID LARGEINT,
SEQ_NUM INT,
OPERATOR CHAR(30),
LEFT_CHILD_SEQ_NUM INT,
RIGHT_CHILD_SEQ_NUM INT,
TNAME CHAR(60),
CARDINALITY REAL,
OPERATOR_COST REAL,
TOTAL_COST REAL,
DETAIL_COST VARCHAR(1024),
DESCRIPTION VARCHAR(2024)
) store by (MV_NAME);
*/