mirror of
https://github.com/mariadb-corporation/mariadb-columnstore-engine.git
synced 2025-04-18 21:44:02 +03:00
409 lines
12 KiB
C++
409 lines
12 KiB
C++
/* Copyright (C) 2014 InfiniDB, Inc.
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License
|
|
as published by the Free Software Foundation; version 2 of
|
|
the License.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
MA 02110-1301, USA. */
|
|
|
|
//
|
|
// $Id: columncommand-jl.cpp 9655 2013-06-25 23:08:13Z xlou $
|
|
// C++ Implementation: columncommand
|
|
//
|
|
// Description:
|
|
//
|
|
//
|
|
// Author: Patrick LeBlanc <pleblanc@calpont.com>, (C) 2008
|
|
//
|
|
// Copyright: See COPYING file that comes with this distribution
|
|
//
|
|
//
|
|
|
|
#include <string>
|
|
#include <cstdlib>
|
|
#include <sstream>
|
|
using namespace std;
|
|
|
|
#include "primitivestep.h"
|
|
#include "tablecolumn.h"
|
|
#include "bpp-jl.h"
|
|
#include "columncommand-jl.h"
|
|
#include "dbrm.h"
|
|
|
|
using namespace messageqcpp;
|
|
|
|
namespace joblist
|
|
{
|
|
ColumnCommandJL::ColumnCommandJL(const pColScanStep& scan, vector<BRM::LBID_t> lastLBID,
|
|
bool hasAuxCol_, const std::vector<BRM::EMEntry>& extentsAux_,
|
|
execplan::CalpontSystemCatalog::OID oidAux) :
|
|
extentsAux(extentsAux_), hasAuxCol(hasAuxCol_),
|
|
fOidAux(oidAux)
|
|
{
|
|
BRM::DBRM dbrm;
|
|
isScan = true;
|
|
|
|
/* grab necessary vars from scan */
|
|
traceFlags = scan.fTraceFlags;
|
|
filterString = scan.fFilterString;
|
|
filterCount = scan.fFilterCount;
|
|
colType = scan.fColType;
|
|
BOP = scan.fBOP;
|
|
extents = scan.extents;
|
|
OID = scan.fOid;
|
|
colName = scan.fName;
|
|
rpbShift = scan.rpbShift;
|
|
fIsDict = scan.fIsDict;
|
|
fLastLbid = lastLBID;
|
|
|
|
// cout << "CCJL inherited lastlbids: ";
|
|
// for (uint32_t i = 0; i < lastLBID.size(); i++)
|
|
// cout << lastLBID[i] << " ";
|
|
// cout << endl;
|
|
|
|
// cout << "Init columncommand from scan with OID " << OID << endl;
|
|
/* I think modmask isn't necessary for scans */
|
|
divShift = scan.divShift;
|
|
modMask = (1 << divShift) - 1;
|
|
|
|
// @Bug 2889. Drop partition enhancement. Read FilesPerColumnPartition and ExtentsPerSegmentFile for use
|
|
// in RID calculation.
|
|
fFilesPerColumnPartition = DEFAULT_FILES_PER_COLUMN_PARTITION;
|
|
// MCOL-4685 remove the option to set more than 2 extents per file (ExtentsPreSegmentFile).
|
|
fExtentsPerSegmentFile = DEFAULT_EXTENTS_PER_SEGMENT_FILE;
|
|
config::Config* cf = config::Config::makeConfig();
|
|
string fpc = cf->getConfig("ExtentMap", "FilesPerColumnPartition");
|
|
|
|
if (fpc.length() != 0)
|
|
fFilesPerColumnPartition = cf->uFromText(fpc);
|
|
}
|
|
|
|
ColumnCommandJL::ColumnCommandJL(const pColStep& step)
|
|
{
|
|
BRM::DBRM dbrm;
|
|
|
|
isScan = false;
|
|
hasAuxCol = false;
|
|
|
|
/* grab necessary vars from step */
|
|
traceFlags = step.fTraceFlags;
|
|
filterString = step.fFilterString;
|
|
filterCount = step.fFilterCount;
|
|
colType = step.fColType;
|
|
BOP = step.fBOP;
|
|
extents = step.extents;
|
|
divShift = step.divShift;
|
|
modMask = step.modMask;
|
|
rpbShift = step.rpbShift;
|
|
OID = step.fOid;
|
|
colName = step.fName;
|
|
fIsDict = step.fIsDict;
|
|
ResourceManager* rm = ResourceManager::instance();
|
|
numDBRoots = rm->getDBRootCount();
|
|
|
|
// grab the last LBID for this column. It's a _minor_ optimization for the block loader.
|
|
// dbrm.getLastLocalHWM((BRM::OID_t)OID, dbroot, partNum, segNum, lastHWM);
|
|
// dbrm.lookupLocal((BRM::OID_t)OID, partNum, segNum, lastHWM, fLastLbid);
|
|
/*
|
|
fLastLbid.resize(numDBRoots);
|
|
for (uint32_t i = 0; i < numDBRoots; i++) {
|
|
dbrm.getLastLocalHWM2((BRM::OID_t)OID, i+1, partNum, segNum, lastHWM);
|
|
dbrm.lookupLocal((BRM::OID_t)OID, partNum, segNum, lastHWM, fLastLbid[i]);
|
|
}
|
|
*/
|
|
|
|
// cout << "Init columncommand from step with OID " << OID << " and width " << colType.colWidth << endl;
|
|
|
|
// @Bug 2889. Drop partition enhancement. Read FilesPerColumnPartition and ExtentsPerSegmentFile for use
|
|
// in RID calculation.
|
|
fFilesPerColumnPartition = DEFAULT_FILES_PER_COLUMN_PARTITION;
|
|
// MCOL-4685 remove the option to set more than 2 extents per file (ExtentsPreSegmentFile).
|
|
fExtentsPerSegmentFile = DEFAULT_EXTENTS_PER_SEGMENT_FILE;
|
|
config::Config* cf = config::Config::makeConfig();
|
|
string fpc = cf->getConfig("ExtentMap", "FilesPerColumnPartition");
|
|
|
|
if (fpc.length() != 0)
|
|
fFilesPerColumnPartition = cf->uFromText(fpc);
|
|
}
|
|
|
|
ColumnCommandJL::ColumnCommandJL(const ColumnCommandJL& prevCmd, const DictStepJL& dictWithFilters)
|
|
{
|
|
BRM::DBRM dbrm;
|
|
|
|
/* grab necessary vars from scan */
|
|
traceFlags = prevCmd.traceFlags;
|
|
// we should call this constructor only when paired with dictionary
|
|
// and in that case previous command should not have any filters and
|
|
// should be "dict" (tokens) column command.
|
|
idbassert(dictWithFilters.getFilterCount() == 0 || prevCmd.filterCount == 0);
|
|
idbassert(prevCmd.fIsDict);
|
|
|
|
// need to reencode filters.
|
|
filterString = dictWithFilters.reencodedFilterString();
|
|
// we have a limitation here.
|
|
// consider this: textcol IS NULL AND textcol IN ('a', 'b')
|
|
// XXX: should check.
|
|
if (filterString.length() > 0 && (BOP = dictWithFilters.getBop() || prevCmd.filterString.length() < 1))
|
|
{
|
|
filterCount = dictWithFilters.getFilterCount();
|
|
BOP = dictWithFilters.getBop();
|
|
fContainsRanges = true;
|
|
}
|
|
else
|
|
{
|
|
filterCount = prevCmd.filterCount;
|
|
filterString = prevCmd.filterString;
|
|
BOP = prevCmd.BOP;
|
|
}
|
|
isScan = prevCmd.isScan;
|
|
hasAuxCol = prevCmd.hasAuxCol;
|
|
extentsAux = prevCmd.extentsAux;
|
|
colType = prevCmd.colType;
|
|
extents = prevCmd.extents;
|
|
OID = prevCmd.OID;
|
|
colName = prevCmd.colName;
|
|
rpbShift = prevCmd.rpbShift;
|
|
fIsDict = prevCmd.fIsDict;
|
|
fLastLbid = prevCmd.fLastLbid;
|
|
lbid = prevCmd.lbid;
|
|
traceFlags = prevCmd.traceFlags;
|
|
dbroot = prevCmd.dbroot;
|
|
numDBRoots = prevCmd.numDBRoots;
|
|
|
|
/* I think modmask isn't necessary for scans */
|
|
divShift = prevCmd.divShift;
|
|
modMask = (1 << divShift) - 1;
|
|
|
|
// @Bug 2889. Drop partition enhancement. Read FilesPerColumnPartition and ExtentsPerSegmentFile for use
|
|
// in RID calculation.
|
|
fFilesPerColumnPartition = prevCmd.fFilesPerColumnPartition;
|
|
// MCOL-4685 remove the option to set more than 2 extents per file (ExtentsPreSegmentFile).
|
|
fExtentsPerSegmentFile = prevCmd.fExtentsPerSegmentFile;
|
|
}
|
|
|
|
ColumnCommandJL::~ColumnCommandJL()
|
|
{
|
|
}
|
|
|
|
// The other leg is in PP, its name is ColumnCommand::makeCommand.
|
|
void ColumnCommandJL::createCommand(ByteStream& bs) const
|
|
{
|
|
bs << (uint8_t)COLUMN_COMMAND;
|
|
colType.serialize(bs);
|
|
bs << (uint8_t)isScan;
|
|
bs << traceFlags;
|
|
if (isDict() && fContainsRanges)
|
|
{
|
|
// XXX: we should discern here between IS (NOT) NULL and other filters.
|
|
ByteStream empty;
|
|
auto zeroFC = filterCount;
|
|
bs << empty;
|
|
bs << BOP;
|
|
zeroFC = 0;
|
|
bs << zeroFC;
|
|
}
|
|
else
|
|
{
|
|
bs << filterString;
|
|
bs << BOP;
|
|
bs << filterCount;
|
|
}
|
|
if (hasAuxCol)
|
|
bs << (uint8_t)1;
|
|
else
|
|
bs << (uint8_t)0;
|
|
serializeInlineVector(bs, fLastLbid);
|
|
|
|
CommandJL::createCommand(bs);
|
|
}
|
|
|
|
void ColumnCommandJL::runCommand(ByteStream& bs) const
|
|
{
|
|
bs << lbid;
|
|
|
|
if (hasAuxCol)
|
|
bs << lbidAux;
|
|
}
|
|
|
|
void ColumnCommandJL::setLBID(uint64_t rid, uint32_t dbRoot)
|
|
{
|
|
uint32_t partNum;
|
|
uint16_t segNum;
|
|
uint8_t extentNum;
|
|
uint16_t blockNum;
|
|
uint32_t colWidth;
|
|
uint32_t i;
|
|
|
|
idbassert(extents.size() > 0);
|
|
colWidth = extents[0].colWid;
|
|
rowgroup::getLocationFromRid(rid, &partNum, &segNum, &extentNum, &blockNum);
|
|
|
|
for (i = 0; i < extents.size(); i++)
|
|
{
|
|
if (extents[i].dbRoot == dbRoot && extents[i].partitionNum == partNum &&
|
|
extents[i].segmentNum == segNum && extents[i].blockOffset == (extentNum * colWidth * 1024))
|
|
{
|
|
lbid = extents[i].range.start + (blockNum * colWidth);
|
|
currentExtentIndex = i;
|
|
/*
|
|
ostringstream os;
|
|
os << "CCJL: rid=" << rid << "; dbroot=" << dbRoot << "; partitionNum=" << partNum
|
|
<< "; segmentNum=" << segNum << "; extentNum = " << (int) extentNum <<
|
|
"; blockNum = " << blockNum << "; OID=" << OID << " LBID=" << lbid;
|
|
cout << os.str() << endl;
|
|
*/
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (i == extents.size())
|
|
{
|
|
throw logic_error("ColumnCommandJL: setLBID didn't find the extent for the rid.");
|
|
}
|
|
|
|
uint32_t j;
|
|
|
|
for (j = 0; j < extentsAux.size(); j++)
|
|
{
|
|
if (extentsAux[j].dbRoot == dbRoot && extentsAux[j].partitionNum == partNum &&
|
|
extentsAux[j].segmentNum == segNum && extentsAux[j].blockOffset == (extentNum * 1 * 1024))
|
|
{
|
|
lbidAux = extentsAux[j].range.start + (blockNum * 1);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (hasAuxCol && j == extentsAux.size())
|
|
{
|
|
throw logic_error("ColumnCommandJL: setLBID didn't find the extent for the rid.");
|
|
}
|
|
|
|
// ostringstream os;
|
|
// os << "CCJL: rid=" << rid << "; dbroot=" << dbRoot << "; partitionNum=" << partitionNum << ";
|
|
//segmentNum=" << segmentNum << "; stripeWithinPartition=" << stripeWithinPartition << "; OID=" << OID << "
|
|
//LBID=" << lbid; BRM::log(os.str());
|
|
}
|
|
|
|
inline uint32_t ColumnCommandJL::getFBO(uint64_t lbid)
|
|
{
|
|
uint32_t i;
|
|
uint64_t lastLBID;
|
|
|
|
for (i = 0; i < extents.size(); i++)
|
|
{
|
|
lastLBID = extents[i].range.start + (extents[i].range.size << 10) - 1;
|
|
|
|
if (lbid >= (uint64_t)extents[i].range.start && lbid <= lastLBID)
|
|
{
|
|
// @Bug 2889. Change for drop partition. Treat the FBO as if all of the partitions are
|
|
// still there as one or more partitions may have been dropped. Get the original index
|
|
// for this partition (i.e. what the index would be if all of the partitions were still
|
|
// there). The RIDs wind up being calculated off of this FBO for use in DML and DML
|
|
// needs calculates the partition number, segment number, etc. off of the RID and needs
|
|
// to remain the same when partitions are dropped.
|
|
//
|
|
// originalIndex = extents in partitions above +
|
|
// extents in this partition in stripes above +
|
|
// file offset in this stripe
|
|
uint32_t originalIndex =
|
|
(extents[i].partitionNum * fExtentsPerSegmentFile * fFilesPerColumnPartition) +
|
|
((extents[i].blockOffset / extents[i].colWid / 1024) * fFilesPerColumnPartition) +
|
|
extents[i].segmentNum;
|
|
|
|
return (lbid - extents[i].range.start) + (originalIndex << divShift);
|
|
}
|
|
}
|
|
|
|
throw logic_error("ColumnCommandJL: didn't find the FBO?");
|
|
}
|
|
|
|
uint8_t ColumnCommandJL::getTableColumnType()
|
|
{
|
|
switch (colType.colWidth)
|
|
{
|
|
case 8: return TableColumn::UINT64;
|
|
|
|
case 4: return TableColumn::UINT32;
|
|
|
|
case 2: return TableColumn::UINT16;
|
|
|
|
case 1: return TableColumn::UINT8;
|
|
|
|
// TODO MCOL-641
|
|
case 16:
|
|
// fallthrough
|
|
|
|
default: throw logic_error("ColumnCommandJL: bad column width");
|
|
}
|
|
}
|
|
|
|
string ColumnCommandJL::toString()
|
|
{
|
|
ostringstream ret;
|
|
|
|
ret << "ColumnCommandJL: " << filterCount << " filters, BOP=" << ((int)BOP) << ", colwidth=" << colType.colWidth << " oid=" << OID
|
|
<< " name=" << colName;
|
|
|
|
if (isScan)
|
|
ret << " (scan)";
|
|
|
|
if (isDict())
|
|
ret << " (tokens)";
|
|
else if (datatypes::isCharType(colType.colDataType))
|
|
ret << " (is char)";
|
|
|
|
return ret.str();
|
|
}
|
|
|
|
uint16_t ColumnCommandJL::getWidth()
|
|
{
|
|
return colType.colWidth;
|
|
}
|
|
|
|
void ColumnCommandJL::reloadExtents()
|
|
{
|
|
int err;
|
|
BRM::DBRM dbrm;
|
|
|
|
err = dbrm.getExtents(OID, extents);
|
|
|
|
if (err)
|
|
{
|
|
ostringstream os;
|
|
os << "pColStep: BRM lookup error. Could not get extents for OID " << OID;
|
|
throw runtime_error(os.str());
|
|
}
|
|
|
|
sort(extents.begin(), extents.end(), BRM::ExtentSorter());
|
|
|
|
if (hasAuxCol)
|
|
{
|
|
err = dbrm.getExtents(fOidAux, extentsAux);
|
|
|
|
if (err)
|
|
{
|
|
ostringstream os;
|
|
os << "BRM lookup error. Could not get extents for Aux OID " << fOidAux;
|
|
throw runtime_error(os.str());
|
|
}
|
|
|
|
sort(extentsAux.begin(), extentsAux.end(), BRM::ExtentSorter());
|
|
}
|
|
}
|
|
|
|
bool ColumnCommandJL::getIsDict()
|
|
{
|
|
return fIsDict;
|
|
}
|
|
|
|
}; // namespace joblist
|