You've already forked mariadb-columnstore-engine
							
							
				mirror of
				https://github.com/mariadb-corporation/mariadb-columnstore-engine.git
				synced 2025-10-30 07:25:34 +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
 |