|
<< Click to Display Table of Contents >> Using an expression tree |
![]() ![]()
|
An expression tree is a filter expression of type pBYTE cast as a pCANExpr. It is a three-part block of memory, consisting of:
•Header A CANExpr structure defining size, number of nodes, and offsets.
•Node Area A series of conditional (operator and operand) branches in the tree, "nodes," defining the filter's tree of conditions. Operand nodes point to offset locations of field names or constants stored in the literal pool area.
•Literal Pool Area Used to store the field names pointed to by each field node and the constant values pointed to by each constant node.
Note that the header consists of a CANExpr structure 10 bytes in length, hence the Node Area begins at offset 10:
Header Node Area Literal Pool Area

The first node in the node area is the canBinary specifying the operand:
canExpr.iFirstNode = 10 (where 10 is offset for entire expression tree)
canExpr.iLiteralStart = 48 (where 48 is offset for entire expression tree)
canBinary.Operand1 = 12 (where 12 is offset into Node Area)
canBinary.Operand2 = 24 (where 24 is offset into Node Area)
canField.iNameOffset = 0 (where 0 is offset into Literal Pool)
canConst.iOffset = strlen( <fieldName> )+1 -- (where the constant value appears just after the field name in the Literal Pool)
Example
Normally you would use an expression tree to tightly focus a view by using a tree of conditions that could be quite complex. For the sake of clarity, in this example, we want a simple filter to display only those records where "CUST_NO>1500". Our task is to create an expression tree CUST_NO > 1500.00 to pass to DbiAddFilter. The following chart represents this expression tree:

The same expression tree is defined in C as a parameter to be passed to DbiAddFilter. The following example assumes that the compiler allocates consecutively declared variables in physically contiguous memory:
void
Filter (void)
{
hDBIDb hDb = 0; // Handle to the database.
hDBICur hCur = 0; // Handle to the table.
DBIResult rslt; // Return value from IDAPI functions.
pBYTE pcanExpr; // Structure containing filter info.
hDBIFilter hFilter; // Filter handle.
UINT16 uSizeNodes; // Size of the nodes in the tree.
UINT16 uSizeCanExpr; // Size of the header information.
UINT32 uSizeLiterals; // Size of the literals.
UINT32 uTotalSize; // Total size of the filter expression.
UINT32 uNumRecs = 10; // Number of records to display.
CANExpr canExp; // Contains the header information.
struct {
CANBinary BinaryNode;
CANField FieldNode;
CANConst ConstantNode;
}
Nodes = { // Nodes of the filter tree.
{
// Offset 0
nodeBINARY, // canBinary.nodeClass
canGT, // canBinary.canOp
sizeof(Nodes.BinaryNode), // canBinary.iOperand1
sizeof(Nodes.BinaryNode) + sizeof(Nodes.FieldNode),
// canBinary.iOperand2
// Offsets in the Nodes array
},
{
// Offset sizeof(Nodes.BinaryNode)
nodeFIELD, // canField.nodeClass
canFIELD, // canField.canOp
1, // canField.iFieldNum
0, // canField.iNameOffset: szField is the
// literal at offset 0
},
{
// Offset sizeof(Nodes.BinaryNode) + sizeof(Nodes.FieldNode)
nodeCONST, // canConst.nodeClass
canCONST, // canConst.canOp
fldFLOAT, // canConst.iType
sizeof(fConst), // canConst.iSize
8, // canConst.iOffset: fconst is the
// literal at offset strlen(szField) + 1
}};
static const char szTblName[] = "cust"; // Name of the table
static const char szTblType[] = szDBASE; // Type of table
static const char szField[] = "CUST_NO"; // Name of the field for the
// third node of the tree.
static const DFLOAT fConst = 1500.0; // Value of the constant for
// the second node of the tree.