// This returns the position in contentLine of the first non-whitespace
 // character after the substring of contentLine which matches the indices
 // in indicesVector. If the indices are not matched, std::string::npos is
 // returned. (Also, if the line is nothing but the indices,
 // std::string::npos will be returned in this case as well.)
 inline size_t
 ParsingUtilities::StartOfMatchedContent( std::string const& contentLine,
                                     std::vector< int > const& indicesVector )
 {
   size_t contentStart( contentLine.find_first_not_of( WhitespaceChars() ) );
   for( std::vector< int >::const_iterator
        indexValue( indicesVector.begin() );
        indexValue != indicesVector.end();
        ++indexValue )
   {
     contentStart = MatchesIndex( contentLine,
                                  contentStart,
                                  *indexValue );
     if( contentStart == std::string::npos )
     {
       return std::string::npos;
     }
   }
   return contentStart;
 }
short
PhysUnPackRows::codeGen(Generator *generator)
{
    // Get handles on expression generator, map table, and heap allocator
    //
    ExpGenerator *expGen = generator->getExpGenerator();
    Space *space = generator->getSpace();

    // Allocate a new map table for this operation
    //
    MapTable *localMapTable = generator->appendAtEnd();

    // Generate the child and capture the task definition block and a description
    // of the reply composite row layout and the explain information.
    //
    child(0)->codeGen(generator);

    ComTdb *childTdb = (ComTdb*)(generator->getGenObj());

    ex_cri_desc *childCriDesc = generator->getCriDesc(Generator::UP);

    ExplainTuple *childExplainTuple = generator->getExplainTuple();

    // Make all of my child's outputs map to ATP 1. Since they are
    // not needed above, they will not be in the work ATP (0).
    // (Later, they will be removed from the map table)
    //
    localMapTable->setAllAtp(1);

    // Generate the given and returned composite row descriptors.
    // unPackRows adds a tupp (for the generated outputs) to the
    // row given by the parent. The workAtp will have the 2 more
    // tupps (1 for the generated outputs and another for the
    // indexValue) than the given.
    //
    ex_cri_desc *givenCriDesc = generator->getCriDesc(Generator::DOWN);

    ex_cri_desc *returnedCriDesc =
#pragma nowarn(1506)   // warning elimination 
        new(space) ex_cri_desc(givenCriDesc->noTuples() + 1, space);
#pragma warn(1506)  // warning elimination 

    ex_cri_desc *workCriDesc =
#pragma nowarn(1506)   // warning elimination 
        new(space) ex_cri_desc(givenCriDesc->noTuples() + 2, space);
#pragma warn(1506)  // warning elimination 


    // unPackCols is the next to the last Tp in Atp 0, the work ATP.
    // and the last Tp in the returned ATP.
    //
    const Int32 unPackColsAtpIndex = workCriDesc->noTuples() - 2;
    const Int32 unPackColsAtp = 0;

    // The length of the new tuple which will contain the columns
    // generated by unPackRows
    //
    ULng32 unPackColsTupleLen;

    // The Tuple Desc describing the tuple containing the new unPacked columns
    // It is generated when the expression is generated.
    //
    ExpTupleDesc *unPackColsTupleDesc = 0;

    // indexValue is the last Tp in Atp 0, the work ATP.
    //
    const Int32 indexValueAtpIndex = workCriDesc->noTuples() - 1;
    const Int32 indexValueAtp = 0;

    // The length of the work tuple which will contain the value
    // of the index.  This should always be sizeof(int).
    //
    ULng32 indexValueTupleLen = 0;

    // The Tuple Desc describing the tuple containing the new unPacked columns
    // It is generated when the expression is generated.
    //
    ExpTupleDesc *indexValueTupleDesc = 0;

    ValueIdList indexValueList;

    if (indexValue() != NULL_VALUE_ID)
    {
        indexValueList.insert(indexValue());

        expGen->processValIdList(indexValueList,
                                 ExpTupleDesc::SQLARK_EXPLODED_FORMAT,
                                 indexValueTupleLen,
                                 indexValueAtp,
                                 indexValueAtpIndex,
                                 &indexValueTupleDesc,
                                 ExpTupleDesc::SHORT_FORMAT);

        GenAssert(indexValueTupleLen == sizeof(Int32),
                  "UnPackRows::codeGen: Internal Error");
    }

    // If a packingFactor exists, generate a move expression for this.
    // It is assumed that the packingFactor expression evaluates to a
    // 4 byte integer.
    //
    ex_expr *packingFactorExpr = 0;
    ULng32 packingFactorTupleLen;

    if(packingFactor().entries() > 0) {
        expGen->generateContiguousMoveExpr(packingFactor(),
                                           -1,
                                           unPackColsAtp,
                                           unPackColsAtpIndex,
                                           ExpTupleDesc::SQLARK_EXPLODED_FORMAT,
                                           packingFactorTupleLen,
                                           &packingFactorExpr);

        GenAssert(packingFactorTupleLen == sizeof(Int32),
                  "UnPackRows::codeGen: Internal Error");
    }

    // Generate the UnPack expressions.
    //
    // characteristicOutputs() - refers to the list of expressions
    // to be move to another tuple.
    //
    // 0 - Do not add conv. nodes.
    //
    // unPackColsAtp - this expression will move data to the
    // unPackColsAtp (0) ATP.
    //
    // unPackColsAtpIndex - within the unPackColsAtp (0) ATP, the destination
    // for this move expression will be the unPackColsAtpIndex TP. This should
    // be the next to the last TP of the work ATP. (The indexValue will be in
    // the last position)
    //
    // SQLARK_EXPLODED_FORMAT - generate the move expression to construct
    // the destination tuple in EXPLODED FORMAT.
    //
    // unPackColsTupleLen - This is an output which will contain the length
    // of the destination Tuple.
    //
    // &unPackColsExpr - The address of the pointer to the expression
    // which will be generated.
    //
    // &unPackColsTupleDesc - The address of the tuple descriptor which is
    // generated.  This describes the destination tuple of the move expression.
    //
    // SHORT_FORMAT - generate the unPackColsTupleDesc in the SHORT FORMAT.
    //
    ex_expr *unPackColsExpr = 0;

    expGen->
    genGuardedContigMoveExpr(selectionPred(),
                             getGroupAttr()->getCharacteristicOutputs(),
                             0, // No Convert Nodes added
                             unPackColsAtp,
                             unPackColsAtpIndex,
                             ExpTupleDesc::SQLARK_EXPLODED_FORMAT,
                             unPackColsTupleLen,
                             &unPackColsExpr,
                             &unPackColsTupleDesc,
                             ExpTupleDesc::SHORT_FORMAT);

#pragma nowarn(1506)   // warning elimination 
    workCriDesc->setTupleDescriptor(unPackColsAtpIndex,
#pragma warn(1506)  // warning elimination 
                                    unPackColsTupleDesc);

#pragma nowarn(1506)   // warning elimination 
    returnedCriDesc->setTupleDescriptor(unPackColsAtpIndex,
#pragma warn(1506)  // warning elimination 
                                        unPackColsTupleDesc);


    // expressions for rowwise rowset implementation.
    ex_expr * rwrsInputSizeExpr = 0;
    ex_expr * rwrsMaxInputRowlenExpr = 0;
    ex_expr * rwrsBufferAddrExpr = 0;
    ULng32 rwrsInputSizeExprLen = 0;
    ULng32 rwrsMaxInputRowlenExprLen = 0;
    ULng32 rwrsBufferAddrExprLen = 0;

    const Int32 rwrsAtp = 1;
    const Int32 rwrsAtpIndex = workCriDesc->noTuples() - 2;
    ExpTupleDesc * rwrsTupleDesc = 0;
    ValueIdList rwrsVidList;
    if (rowwiseRowset())
    {
        rwrsVidList.insert(this->rwrsInputSizeExpr()->getValueId());
        expGen->generateContiguousMoveExpr(rwrsVidList,
                                           0 /*don't add conv nodes*/,
                                           rwrsAtp, rwrsAtpIndex,
                                           ExpTupleDesc::SQLARK_EXPLODED_FORMAT,
                                           rwrsInputSizeExprLen,
                                           &rwrsInputSizeExpr,
                                           &rwrsTupleDesc,ExpTupleDesc::SHORT_FORMAT);

        rwrsVidList.clear();
        rwrsVidList.insert(this->rwrsMaxInputRowlenExpr()->getValueId());
        expGen->generateContiguousMoveExpr(rwrsVidList,
                                           0 /*don't add conv nodes*/,
                                           rwrsAtp, rwrsAtpIndex,
                                           ExpTupleDesc::SQLARK_EXPLODED_FORMAT,
                                           rwrsMaxInputRowlenExprLen,
                                           &rwrsMaxInputRowlenExpr,
                                           &rwrsTupleDesc,ExpTupleDesc::SHORT_FORMAT);

        rwrsVidList.clear();
        rwrsVidList.insert(this->rwrsBufferAddrExpr()->getValueId());
        expGen->generateContiguousMoveExpr(rwrsVidList,
                                           0 /*don't add conv nodes*/,
                                           rwrsAtp, rwrsAtpIndex,
                                           ExpTupleDesc::SQLARK_EXPLODED_FORMAT,
                                           rwrsBufferAddrExprLen,
                                           &rwrsBufferAddrExpr,
                                           &rwrsTupleDesc,ExpTupleDesc::SHORT_FORMAT);

        expGen->assignAtpAndAtpIndex(rwrsOutputVids(),
                                     unPackColsAtp, unPackColsAtpIndex);
    }

    // Move the generated maptable entries, to the localMapTable,
    // so that all other entries can later be removed.
    //
    for(ValueId outputValId = getGroupAttr()->getCharacteristicOutputs().init();
            getGroupAttr()->getCharacteristicOutputs().next(outputValId);
            getGroupAttr()->getCharacteristicOutputs().advance(outputValId)) {

        generator->addMapInfoToThis(localMapTable, outputValId,
                                    generator->getMapInfo(outputValId)->
                                    getAttr());

        // Indicate that code was generated for this map table entry.
        //
        generator->getMapInfoFromThis(localMapTable, outputValId)->codeGenerated();
    }

    NABoolean tolerateNonFatalError = FALSE;

    if (isRowsetIterator() && (generator->getTolerateNonFatalError())) {
        tolerateNonFatalError = TRUE;
        setTolerateNonFatalError(RelExpr::NOT_ATOMIC_);
    }


    // Allocate the UnPack TDB
    //
    ComTdbUnPackRows *unPackTdb = NULL;

    if (rowwiseRowset())
    {
        unPackTdb =
            new (space) ComTdbUnPackRows(NULL, //childTdb,
                                         rwrsInputSizeExpr,
                                         rwrsMaxInputRowlenExpr,
                                         rwrsBufferAddrExpr,
                                         rwrsAtpIndex,
                                         givenCriDesc,
                                         returnedCriDesc,
                                         workCriDesc,
                                         16,
                                         1024,
                                         (Cardinality) getGroupAttr()->
                                         getOutputLogPropList()[0]->
                                         getResultCardinality().value(),
                                         2, 20000);
    }
    else
    {

        // Base the initial queue size on the est. cardinality.
        // UnPackRows does not do dyn queue resize, so passed in
        // queue size values represent initial (and final) queue
        // sizes (not max queue sizes).
        //
        queue_index upQueueSize =
            (queue_index)getGroupAttr()->getOutputLogPropList()[0]->getResultCardinality().value();

        // Make sure it is at least 1024.
        upQueueSize = (upQueueSize < 1024 ? 1024 : upQueueSize);

        // Make sure that it is not more the 64K.
        upQueueSize = (upQueueSize > 65536 ? 65536 : upQueueSize);

        unPackTdb =
            new (space) ComTdbUnPackRows(childTdb,
                                         packingFactorExpr,
                                         unPackColsExpr,
#pragma nowarn(1506)   // warning elimination 
                                         unPackColsTupleLen,
                                         unPackColsAtpIndex,
                                         indexValueAtpIndex,
                                         givenCriDesc,
                                         returnedCriDesc,
                                         workCriDesc,
                                         16,
                                         upQueueSize,
                                         (Cardinality) getGroupAttr()->
                                         getOutputLogPropList()[0]->
                                         getResultCardinality().value(),
                                         isRowsetIterator(),
                                         tolerateNonFatalError);
    }

#pragma warn(1506)  // warning elimination 
    generator->initTdbFields(unPackTdb);

    // Remove child's outputs from mapTable, They are not needed
    // above.
    //
    generator->removeAll(localMapTable);

    // Add the explain Information for this node to the EXPLAIN
    // Fragment.  Set the explainTuple pointer in the generator so
    // the parent of this node can get a handle on this explainTuple.
    //
    if(!generator->explainDisabled()) {
        generator->setExplainTuple(addExplainInfo(unPackTdb,
                                   childExplainTuple,
                                   0,
                                   generator));
    }

    // Restore the Cri Desc's and set the return object.
    //
    generator->setCriDesc(givenCriDesc, Generator::DOWN);
    generator->setCriDesc(returnedCriDesc, Generator::UP);
    generator->setGenObj(this, unPackTdb);


    return 0;
}
// UnPackRows::copyTopNode ----------------------------------------------
// Copy a chain of derived nodes (Calls RelExpr::copyTopNode).
// Needs to copy all relevant fields.
// Used by the Cascades engine.
//
// Inputs: derivedNode - If Non-NULL this should point to a node
//         which is derived from this node.  If NULL, then this
//         node is the top of the derivation chain and a node must
//         be constructed.
//
// Outputs: RelExpr * - A Copy of this node.
//
// If the 'derivedNode is non-NULL, then this method is being called
// from a copyTopNode method on a class derived from this one. If it
// is NULL, then this is the top of the derivation chain and an UnPackRows
// node must be constructed.
// 
// In either case, the relevant data members must be copied to 'derivedNode'
// and 'derivedNode' is passed to the copyTopNode method of the class
// below this one in the derivation chain (RelExpr::copyTopNode() in this
// case).
// 
RelExpr *
UnPackRows::copyTopNode(RelExpr *derivedNode, CollHeap *outHeap)
{
  UnPackRows *result;

  if (derivedNode == NULL)
    // This is the top of the derivation chain
    // Create an empty UnPackRows node.
    //
    {
      if (rowwiseRowset())
	result = new (outHeap) UnPackRows(0, 
					  (ItemExpr*)NULL, 
					  (ItemExpr*)NULL, 
					  (ItemExpr*)NULL, NULL);
      else
	result = new (outHeap) UnPackRows();
    }
  else
    // A node has already been constructed as a derived class.
    //
    result = (UnPackRows *) derivedNode;

  // Copy the relavant fields.

  result->unPackedTable() = unPackedTable();

  result->unPackExpr() = unPackExpr();

  result->packingFactor() = packingFactor();

  result->maxPackingFactor_ = getMaxPackingFactor();

  result->indexValue() = indexValue();

  result->sysKeyId() = sysKeyId();

  result->originalPreds() = originalPreds();
  result->rewrittenPreds() = rewrittenPreds();

  result->setRowwiseRowset(rowwiseRowset());

  // copy pointer to expressions
  // These are not available after bindNode()
  //
  if (unPackExprTree() != NULL)
    result->unPackExprTree() = unPackExprTree()->copyTree(outHeap)->castToItemExpr();

  if (packingFactorTree() != NULL)
    result->packingFactorTree() = 
      packingFactorTree()->copyTree(outHeap)->castToItemExpr();

  if (rwrsInputSizeExpr_ != NULL)
     result->rwrsInputSizeExpr_ = rwrsInputSizeExpr_->copyTree(outHeap)->castToItemExpr();

  if (rwrsMaxInputRowlenExpr_ != NULL)
     result->rwrsMaxInputRowlenExpr_ = rwrsMaxInputRowlenExpr_->copyTree(outHeap)->castToItemExpr();

  if (rwrsInputSizeExpr_ != NULL)
     result->rwrsBufferAddrExpr_ = rwrsBufferAddrExpr_->copyTree(outHeap)->castToItemExpr();

  result->rwrsOutputVids_ = rwrsOutputVids_;

  // Copy any data members from the classes lower in the derivation chain.
  //
  return RelExpr::copyTopNode(result, outHeap);
}
Exemplo n.º 4
0
int jb()
{
	JET_ERR err;

	eseInstance instance;
	if (instance.init(0) != JET_errSuccess)
	{
		return instance.getLastError();
	}

	eseSession session;
	if (session.init(instance.id()) != JET_errSuccess)
	{
		return session.getLastError();;
	}

	eseDatabase db(session.id());
	err = db.open("test2.edb");
	if (err == JET_errDatabaseDuplicate )
	{
		err = db.create("test2.edb");
	}
	if (err != JET_errSuccess)
	{
		return err;
	}

	eseColumn* col0 = new eseColumn("PK", JET_coltypLong, JET_bitColumnAutoincrement); // will be destroyed by table's destructor
	eseColumn* col1 = new eseColumn("Value", JET_coltypText, 0, 1024, 1200); // will be destroyed by table's destructor

	eseIndex indexKey("PK_index", IndexKey("+PK"), JET_bitIndexPrimary);
	eseIndex indexValue("Value_index", IndexKey("+Value"), JET_bitIndexUnique);

	eseTable table(db.id(), session.id());


	switch (err = table.open("TestTable"))
	{
		case JET_errSuccess:
			break;
		case JET_errObjectNotFound: // Table does not exists, open it
			err = table.create("TestTable", col0, col1, indexKey, indexValue);
			if (err != JET_errSuccess) return err;
			break;
		default:
			return err;
	}

// Inserting Values
	wchar_t* stringsTolnsert[] = { L"FirstInsertedRow2", L"InSecondInsertedRow2", L"ThirdInsertedRow2", L"FourinsertedRow2", L"Fourinse" };
	for (size_t n = 0; n != sizeof(stringsTolnsert) / sizeof(stringsTolnsert[0]); ++n)
	{
		err = table.insert(1, stringsTolnsert[n]); // insert to the second column (numbering starts from zero)
	}

// List content of the table
	err = table.setCurrentIndex(indexValue);
	if (err != JET_errSuccess)  return err;
	
	for (err = table.setCursor(JET_MoveFirst); JET_errSuccess == err; err = table.setCursor(JET_MoveNext))
	{
		int nPK = 0;
		err = table.get_column(0, &nPK);
		if (JET_errSuccess != err) break;

		std::wcout << nPK;

		wchar_t buffer[1024] = { 0 };
		err = table.get_column(1, buffer, 1024);
		std::wcout << L'\t' << buffer << std::endl;
	}
	if (JET_errNoCurrentRecord != err) return err;

	std::wcout << std::endl;

// Search value in the table
	err = table.setCursor(JET_MoveFirst); // first movce to begining using the current index
	if (JET_errSuccess != err) return err;
	
	wchar_t bufferSearchCriteria[] = L"Fo"; //  then set the search criteria
	err = ::JetMakeKey(session.id(), table.id(), &bufferSearchCriteria, sizeof(bufferSearchCriteria), JET_bitNewKey);
	if (JET_errSuccess != err) return err;

	for (err = ::JetSeek(session.id(), table.id(), JET_bitSeekGE); !(err < 0); err = table.setCursor(JET_MoveNext) )
	{
		int nPK = 0;
		err = table.get_column(0, &nPK);
		if (JET_errSuccess != err) break;
		std::wcout << nPK;

		wchar_t buffer[1024] = { 0 };
		err = table.get_column(1, buffer, 1024);
		std::wcout << L'\t' << buffer << std::endl;
	}
	if (JET_errNoCurrentRecord != err) return err;
	std::wcout << std::endl;

// Another search in the table
	err = table.setCursor(JET_MoveFirst);
	if (JET_errSuccess != err) return err;

	err = ::JetMakeKey(session.id(), table.id(), &bufferSearchCriteria, sizeof(bufferSearchCriteria), JET_bitNewKey | JET_bitPartialColumnStartLimit);
	if (JET_errSuccess != err) return err;

	err = ::JetSeek(session.id(), table.id(), JET_bitSeekGE);
	if (err < 0) return err;

	err = ::JetMakeKey(session.id(), table.id(), &bufferSearchCriteria, sizeof(bufferSearchCriteria), JET_bitNewKey | JET_bitPartialColumnEndLimit);
	if (JET_errSuccess != err) return err;

	for (err = ::JetSetIndexRange(session.id(), table.id(), JET_bitRangeInclusive | JET_bitRangeUpperLimit);
		!(err < 0); 
		table.setCursor(JET_MoveNext) )
	{
		int nPK = 0;
		err = table.get_column(0, &nPK);
		if (JET_errSuccess != err) break;

		std::wcout << nPK;

		wchar_t buffer[1024] = { 0 };
		err = table.get_column(1, buffer, 1024);
		std::wcout << L'\t' << buffer << std::endl;
	}
	return 0;
}