Forwarding this to the dev list…
*From:* Qifan Chen [mailto:[email protected]] *Sent:* Wednesday, February 10, 2016 8:54 AM *To:* [email protected] *Subject:* An executor question about a null indicator during eval() I wonder if somebody can help with the connection of op_data[] within an eval() method and the call to that eval() in an TCB. Background info. An eval() method evaluates a SQL function and is usually called from a TCB. The SQL function is logically attached to the TCB representing a relational node. In the following example, the TCB is ExSequence, a relational node computes Sequence/OLAP functions. Note that the the 2nd tupp's data pointer is set to histData, a record (a row) of 56 bytes in the history buffer. The address of that record is 0x7fffcf4ee208. The eval() method is for an Offset() function. *TCB* char *histData = currentRetHistRowPtr_; pentry_up->getTupp (myTdb().tuppIndex_).setDataPointer(histData); ex_expr::exp_return_type retCode = ex_expr::EXPR_OK; // Apply the return phase expression if(returnExpr()) { retCode = returnExpr()->eval(pentry_up->getAtp(),workAtp_); if (retCode == ex_expr::EXPR_ERROR) *eval()* // Is the source null? There are two reaons the source data can be null: // 1. The row does not exist in the history buffer (srcData == NULL) // 2. The data exist but is itself NULL (srcNull == 0xFFFF) // Int32 srcIsNull = (srcData ? 0 : 1); if(srcData && srcNull) srcIsNull = *((unsigned short*)(srcNull)) == 0xFFFFU; // Get the pointer to the start of the result data. // char *dstData = op_data[0]; char *dstNull = op_data[-2 * MAX_OPERANDS + 0]; char *dstVC = op_data[- MAX_OPERANDS]; if (rc == -3) We know that op_data[0] usually points at &(op_data[2*MAX_OPERANDS+0]), which is the section of the array containing type info (Attributes) (see the comments in exp_expr.h that I copied below). In the code, however, I usually see op_data[1] and op_data[2] are the operands. Maybe the comments are not accurate? Anyway, let us continue with the eval() method in question. If I gdb stop at the line in red above, I have (gdb) p dstData $2 = 0x7fffcf4ee208 "" (gdb) p dstNull $3 = 0x7fffe27fbf20 "" This means that the dstData is pointing at histData, and dstNull is obviously outside the scope of the record. So my questions are follows. 1. Who sets up op_data and its content? 2. Whether dstNull can be reliably used? -- Regards, --Qifan // Execution // // isEvalRelevant - Returns true if eval() does any work. The eval() // methods for some clauses do nothing but serve as placeholders. These // clauses can be identified using this routine. // // eval - Actually does the work based on the pointers in the op_data // vector. The op_data vector has the following layout: // // 0 - pointer to result null indicator // 1 - TRUE if 1st arg is not NULL // 2 - TRUE if 2nd arg is not NULL // MAX_OPERANDS-1 - TRUE if MAX_OPERANDS-2(th) arg is not NULL // // MAX_OPERANDS+0 - pointer to result varchar length (NULL for non-varchar) // MAX_OPERANDS+1 - pointer to 1st arg varchar length (NULL for non-varchar) // MAX_OPERANDS+2 - pointer to 2nd arg varchar length (NULL for non-varchar) // 2*MAX_OPERANDS-1 - pointer to 2*MAX_OPERANDS-2(th) arg // // 2*MAX_OPERANDS+0 - pointer to result attribute // 2*MAX_OPERANDS+1 - pointer to 1st arg attribute (maybe null for NULL attr) // 2*MAX_OPERANDS+2 - pointer to 2nd arg attribute (maybe null for NULL attr) // 3*MAX_OPERANDS-1 - pointer to 3*MAX_OPERANDS-2(th) arg // // The processNulls method gets passed &(op_data[0]) so that addressing // the null indicators is done with op_data[0], op_data[1], etc. // The method returns EXPR_ERROR for attempt to assign a NULL to a nonnullable // column, EXPR_NULL for NULL successfully processed (assigned to a nullable // column), EXPR_OK for no error and no null -- caller must continue eval. // // The eval method gets passed &(op_data[2*MAX_OPERANDS+0]) so that // addressing the attributes is done with op_data[0], op_data[1], etc. The // null and varchar information is accessed using negative offsets: // op_data[-2*MAX_OPERANDS], etc. //
