I will write a JIRA case and submit the code.

Thanks --Qifan

On Tue, Feb 9, 2016 at 4:49 PM, Qifan Chen <[email protected]> wrote:

> OK. Thanks Gunnar for the suggestion to discuss the topic on the user
> dlist.
>
> I have added several display() member functions to the following executor
> classes to facilitate debugging in Generator and the executor. They perform
> reasonably well for my debug tasks.
>
> 1. atp_struct::display(const char* title, ex_cri_desc* cri = NULL):
>
> for all the tupps,
>
> for each tupp, display
>
> the data types
> the data based on the data type
>
>
> 2. ExpTupleDesc::display(const char* title):
>
> for all the attributes
>
> for each attribute: display the data type code (64, 152 etc) and data
> length (10, 15 etc)
>
>
> 3. ex_cri_desc::display(const char* title):
>
> for all the tuple (type)s
>
> for each tuple type, display data type code (64, 152 etc) and data length
> (10, 15 etc)
>
>
> Enhancement 1) is good for display data and type associated with a
> work_atp or query entries.
>
> Enhancement 2) and 3) is good for display type info associated with TDBs
> during codeGen.
>
>
>
> *Usage example 1: display of an ATP.*
>
>               retCode = returnExpr()->eval(pentry_up->getAtp(),workAtp_);
>               if (retCode == ex_expr::EXPR_ERROR)
>               {
>                 // LCOV_EXCL_START
>                 pstate->step_ = ExSeq_ERROR;
>                 break;
>                 // LCOV_EXCL_STOP
>               }
>             }
>
> *// display the result of return eval() call*
> *pentry_up->getAtp()->display("return eval result",
> myTdb().getCriDescUp());*
>
>             retCode = ex_expr::EXPR_OK;
>             //Apply post pre
>
>
> *Usage example 2: display of a CRI Desc (composite record descriptor)*
>
>
> *// display the type info for the up queue CRI*
> *returnCriDesc->display("up queue CRI for Sequence node");*
>
>   ComTdbSequence *sequenceTdb
>     = new(space) ComTdbSequence(readSeqExpr,
>                                 returnExpr,
>                                 postPred,
>                                 cancelExpression,
>                                 getMinFollowingRows(),
> #pragma nowarn(1506)   // warning elimination
>                                 historyRecLen,
>                                 historyAtpIndex,
>                                 childTdb,
>                                 givenCriDesc,
>                                 returnCriDesc,
>
>
> These display methods also can be called within gdb through the print (p)
> command, such as
>
> p pentry_up->getAtp()->display("return eval result",
> myTdb().getCriDescUp())
>
>
> Here are the results of these display functions in action.
>
> >>execute xx;
> read eval result
> 0th field: datatype=152, len=8, data=""
> 1th field: datatype=64, len=15, data="HR"
> 2th field: datatype=152, len=8, data="00230000"
> 3th field: datatype=64, len=15, data=""
>
> read eval result
> 0th field: datatype=152, len=8, data=""
> 1th field: datatype=64, len=15, data="HR"
> 2th field: datatype=152, len=8, data="00160000"
> 3th field: datatype=64, len=15, data=""
>
> read eval result
> 0th field: datatype=152, len=8, data=""
> 1th field: datatype=64, len=15, data="HR"
> 2th field: datatype=152, len=8, data="00120000"
> 3th field: datatype=64, len=15, data=""
>
> read eval result
> 0th field: datatype=152, len=8, data=""
> 1th field: datatype=64, len=15, data="HR"
> 2th field: datatype=152, len=8, data="00080000"
> 3th field: datatype=64, len=15, data=""
>
> return eval result
> 0th field: datatype=152, len=8, data="00080000"
> 1th field: datatype=64, len=15, data="HR"
> 2th field: datatype=152, len=8, data="00230000"
> 3th field: datatype=64, len=15, data=""
>
> return eval result
> 0th field: datatype=152, len=8, data="00070000"
> 1th field: datatype=64, len=15, data="HR"
> 2th field: datatype=152, len=8, data="00160000"
> 3th field: datatype=64, len=15, data=""
>
> return eval result
> 0th field: datatype=152, len=8, data="00060000"
> 1th field: datatype=64, len=15, data="HR"
> 2th field: datatype=152, len=8, data="00120000"
> 3th field: datatype=64, len=15, data=""
>
> Thanks --Qifan
>
> On Mon, Feb 8, 2016 at 8:17 PM, Qifan Chen <[email protected]> wrote:
>
>> Hi Dave.
>>
>> I found that if I commented out the line in red below, I was able to
>> access the Attributes.
>>
>> Sounds like the purpose of the code (in red) tries to conserve space in
>> executor.
>>
>> I will move some of your print code (in MdamPoint class) into
>> atp_struct.display() and document its usage.
>>
>> Thanks a lot for the help and hope that the new method will be useful.
>>
>> Thanks --Qifan
>>
>>
>> ExpTupleDesc::ExpTupleDesc(UInt32 num_attrs,
>>                            Attributes ** attrs,
>>                            UInt32 tupleDataLength,
>>                            TupleDataFormat tdataF,
>>                            TupleDescFormat tdescF,
>>                            Space * space)
>>   : numAttrs_(num_attrs),
>>     tupleDataLength_(tupleDataLength),
>>     tupleDataFormat_(tdataF),
>>     tupleDescFormat_(tdescF),
>>     NAVersionedObject(-1)
>> {
>>   if ( space != NULL )
>>     {
>>       // remember current allocated space size. Used at the end of
>>       // generation to find out total tuple desc length allocated.
>>       tupleDescLength_ = space->getAllocatedSpaceSize();
>>
>>       flags_ = 0;
>>       attrs_ = 0;
>>
>>      * if (tdescF == LONG_FORMAT)*
>>         {
>>           // allocate an array of num_attrs Attributes*. This array
>> follows
>>           // 'this' class.
>>           attrs_ = (AttributesPtr *)
>>             (space->allocateAlignedSpace(num_attrs *
>> sizeof(AttributesPtr)));
>>
>>           for (UInt32 i=0; i < num_attrs; i++)
>>             {
>>               // make a new copy of input attributes. This new attr entry
>>               // will follow the attribute array.
>>               attrs_[i] = attrs[i]->newCopy(space);
>>             }
>>         }
>>
>>       // and now find out the total length of the generated descriptor
>>       tupleDescLength_ = sizeof(*this) +
>>         space->getAllocatedSp
>>
>> On Mon, Feb 8, 2016 at 3:55 PM, Qifan Chen <[email protected]> wrote:
>>
>>> I checked the TDB and found the returnExpr() should compute a composite
>>> record of the following sort. The evaluation is OK but one of the resultant
>>> component records (valueId =10) may not be correct.
>>>
>>> (gdb) p historyIds.display()
>>> ValueIdSet
>>>   10:
>>> LEAD(cast(convert(TRAFODION.SEABASE.PERSONNEL_ASSIGNMENTS.SALARY_AMT)))
>>>   59: cast(convert(TRAFODION.SEABASE.PERSONNEL_ASSIGNMENTS.DEPT_NAME))
>>>   61: cast(convert(TRAFODION.SEABASE.PERSONNEL_ASSIGNMENTS.SALARY_AMT))
>>>
>>>
>>> The tupp in red is the correct tupp representing the evaluation result.
>>> However, it is hard to find the boundary of the actual data (for print)
>>> without the tupp descriptor.
>>>
>>>
>>>
>>> On Mon, Feb 8, 2016 at 3:34 PM, Dave Birdsall <[email protected]>
>>> wrote:
>>>
>>>> Oh, dear. Which ATPs are used for what is highly dependent on the tcb.
>>>> You might be able to figure it out from the tcb flow. Another attack is to
>>>> figure it out from the generator. (The generator methods often have
>>>> comments that describe in some detail what Atps are being used for what.)
>>>>
>>>>
>>>>
>>>> In your example, do you know that returnExpr() returned non-null? If it
>>>> returned null, it’s not clear from the code snippet that we’d expect these
>>>> to have any reasonable values. You could try moving the red code up inside
>>>> the previous right brace.
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>> *From:* Qifan Chen [mailto:[email protected]]
>>>> *Sent:* Monday, February 8, 2016 1:29 PM
>>>> *To:* Dave Birdsall <[email protected]>
>>>> *Subject:* Re: Display the data content associated with a tupp?
>>>>
>>>>
>>>>
>>>> Thanks for the method and I used that as a starting point for a method
>>>> as follows, because the record size of the tupp in question is 40 bytes
>>>> (should be 8), and I would like to use the data type of the record to guide
>>>> the display.
>>>>
>>>>
>>>>
>>>> void atp_struct::display()
>>>>
>>>> {
>>>>
>>>>    ex_cri_desc* cri = getCriDesc();
>>>>
>>>>    unsigned short tuples = numTuples();
>>>>
>>>>    for (Int32 i=0; i<tuples; i++) {
>>>>
>>>>       tupp& tup = getTupp(i);
>>>>
>>>>       ExpTupleDesc* tDesc = cri->getTupleDescriptor(i);
>>>>
>>>>
>>>>
>>>>       if ( tDesc && tDesc->attrs() ) {
>>>>
>>>>          UInt32 attrs =  tDesc->numAttrs();
>>>>
>>>>          for (Int32 j=0; j<attrs; j++) {
>>>>
>>>>              Attributes* attr = tDesc->getAttr(j);
>>>>
>>>>              Int16 dt = attr->getDatatype();
>>>>
>>>> int x = 0;
>>>>
>>>>          }
>>>>
>>>>       }
>>>>
>>>>    }
>>>>
>>>> }
>>>>
>>>>
>>>>
>>>> The method is incomplete and I have found that tDesc or tDesc->attrs()
>>>> are null pointer, for both invocations in red.
>>>>
>>>>
>>>>
>>>>             if(returnExpr())
>>>>
>>>>             {
>>>>
>>>>               retCode =
>>>> returnExpr()->eval(pentry_up->getAtp(),workAtp_);
>>>>
>>>>               if (retCode == ex_expr::EXPR_ERROR)
>>>>
>>>>               {
>>>>
>>>>                 // LCOV_EXCL_START
>>>>
>>>>                 pstate->step_ = ExSeq_ERROR;
>>>>
>>>>                 break;
>>>>
>>>>                 // LCOV_EXCL_STOP
>>>>
>>>>               }
>>>>
>>>>             }
>>>>
>>>>
>>>>
>>>> workAtp_->display();
>>>>
>>>> pentry_up->getAtp()->display();
>>>>
>>>>
>>>>
>>>>             retCode = ex_expr::EXPR_OK;
>>>>
>>>>             //Apply post predicate expression
>>>>
>>>>             if (postPred())
>>>>
>>>>             {
>>>>
>>>>               retCode =
>>>> postPred()->eval(pentry_up->getAtp(),pentry_up->getAtp());
>>>>
>>>>               if (retCode == ex_expr::EXPR_ERROR)
>>>>
>>>>               {
>>>>
>>>>                 // LCOV_EXCL_START
>>>>
>>>>                 pstate->step_ = ExSeq_ERROR;
>>>>
>>>>                 break;
>>>>
>>>>                 // LCOV_EXCL_STOP
>>>>
>>>>               }
>>>>
>>>>             }
>>>>
>>>>
>>>>
>>>> So the next question is which Atp should contain a valid tuple
>>>> descriptor?
>>>>
>>>>
>>>>
>>>> From "Executor Programming Guide",
>>>>
>>>>
>>>>
>>>> • ATPs need to be allocated for those queues that have a new record
>>>> layout (different format or number of tupps). In this case there simply are
>>>> no other queues whose ATPs could be shared. The new ATPs are created by
>>>> combining tupps from other queue entries or by creating new tupps (see
>>>> section 10.1, “class sql_buffer:” on page 18).
>>>>
>>>>
>>>>
>>>> • Similarly, ATPs need to be allocated for those queues that are at the
>>>> start of a data flow, such as the down queue to the child of a root node or
>>>> for the up queue of a leaf node.
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>> On Mon, Feb 8, 2016 at 12:23 PM, Dave Birdsall <[email protected]>
>>>> wrote:
>>>>
>>>> I made an imperfect attempt with MDAM debugging. Imperfect because the
>>>> code I wrote didn’t have datatype information, but tried to infer it from
>>>> what it saw. It was good enough for my debugging purposes at the time. See
>>>> method MdamPoint::printBrief in executor/MdamPoint.cpp.
>>>>
>>>>
>>>>
>>>> *From:* Qifan Chen [mailto:[email protected]]
>>>> *Sent:* Monday, February 8, 2016 10:11 AM
>>>> *To:* Everyone <[email protected]>
>>>> *Subject:* Display the data content associated with a tupp?
>>>>
>>>>
>>>>
>>>> Hi,
>>>>
>>>>
>>>>
>>>> I am debugging an OLAP function bug and wonder if there is a way to
>>>> display the actual data pointed to by a tupp while in gdb.  For example,
>>>> for the following piece of code snippet, histData holds the result of a
>>>> return expression evaluation. I would like to see the result while at line
>>>> 853.
>>>>
>>>>
>>>>
>>>> In compiler, we have various display methods on RelExpr and ItemExpr.
>>>> Can I do similar similar for executor?
>>>>
>>>>
>>>>
>>>> Thanks --Qifan
>>>>
>>>>
>>>>
>>>> 801             char *tuppData = pentry_up->getTupp
>>>>
>>>>  802               (myTdb().tuppIndex_).getDataPointer();
>>>>
>>>>  803
>>>>
>>>>  804             advanceReturnHistoryRow();
>>>>
>>>>  805
>>>>
>>>>  806             char *histData = currentRetHistRowPtr_;
>>>>
>>>>  807             *pentry_up->getTupp*
>>>>
>>>> * 808               (myTdb().tuppIndex_).setDataPointer(histData);*
>>>>
>>>>  809
>>>>
>>>>  810             ex_expr::exp_return_type retCode = ex_expr::EXPR_OK;
>>>>
>>>>  811             // Apply the return phase expression
>>>>
>>>>  812             if(returnExpr())
>>>>
>>>>  813             {
>>>>
>>>>  814               retCode =
>>>> returnExpr()->eval(pentry_up->getAtp(),workAtp_);
>>>>
>>>>  815               if (retCode == ex_expr::EXPR_ERROR)
>>>>
>>>>  816               {
>>>>
>>>>  817                 // LCOV_EXCL_START
>>>>
>>>>  818                 pstate->step_ = ExSeq_ERROR;
>>>>
>>>>  819                 break;
>>>>
>>>>  820                 // LCOV_EXCL_STOP
>>>>
>>>>  821               }
>>>>
>>>>  822             }
>>>>
>>>>
>>>>
>>>> ...
>>>>
>>>>
>>>>
>>>>  838             //
>>>>
>>>>  839             // Case-10-030724-7963: we are done pointing the tupp
>>>> at the
>>>>
>>>>  840             // history buffer, so point it back to the SQL buffer.
>>>>
>>>>  841             //
>>>>
>>>>  842             pentry_up->getTupp
>>>>
>>>>  843               (myTdb().tuppIndex_).setDataPointer(tuppData);
>>>>
>>>>  844
>>>>
>>>>  845             switch(retCode) {
>>>>
>>>>  846             case ex_expr::EXPR_OK:
>>>>
>>>>  847             case ex_expr::EXPR_TRUE:
>>>>
>>>>  848             case ex_expr::EXPR_NULL:
>>>>
>>>>  849
>>>>
>>>>  850               // Copy the row that was computed in the history
>>>> buffer,
>>>>
>>>>  851               // to the space previously allocated in the SQL
>>>> buffer.
>>>>
>>>>  852
>>>>
>>>>  853               str_cpy_all(tuppData, *histData*, recLen());
>>>>
>>>>
>>>>
>>>> --
>>>>
>>>> Regards, --Qifan
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>> --
>>>>
>>>> Regards, --Qifan
>>>>
>>>>
>>>>
>>>
>>>
>>>
>>> --
>>> Regards, --Qifan
>>>
>>>
>>
>>
>> --
>> Regards, --Qifan
>>
>>
>
>
> --
> Regards, --Qifan
>
>


-- 
Regards, --Qifan

Reply via email to