Today’s blog entry is all about how to construct and write searches in BRM. Specifically, this relates to the PCM_OP_SEARCH op-code (Op-Code #7) and its input and output FLISTs.
Searches play an important part in most BRM applications and customizations. Bending them to your will is an important skill to have.
Elements of PCM_OP_SEARCH: Input and Output FLISTs
For every op-code, there is an input and output FLIST. Since any search in BRM is just another op-code call, the same rule applies.
The PCM_OP_SEARCH Input FLIST:
To implement any search (not just BRM), we must know the following:
- What object are we searching for?
- What search criteria will be used to define the object we are looking for?
For our example, let us say we are looking for an /account object based on customer last name. Consulting our Data Dictionary in Developer Center, we can look at the structure of the account object:
We see that the last name is stored on the PIN_FLD_NAMEINFO array element in the PIN_FLD_LAST_NAME field.
Now that we know what we want to search for, lets look at the elements of the input FLIST.
PIN_FLD_POID
This field is used to indicate the database to be searched and the search template to use in conducting the search. A search POID ID of -1 indicates that a custom search template will be passed in on the input FLIST. If the search POID is positive, then the search template from the appropriate /search object will be used and a template need not be present on the Input FLIST.
Examples:
This POID indicates the use of a custom search template as a part of the INPUT flist.
0 PIN_FLD_POID POID [0] 0.0.0.1 /search -1 0
This POID indicates that search template 201 will be used.
0 PIN_FLD_POID POID [0] 0.0.0.1 /search 201 0
Looking in the search_t table in the PIN database, we see that the corresponding template is ‘select X from /account/$1 where F1 = V1 ‘
PIN_FLD_TEMPLATE
This string field is only required if the search template used has a POID ID of -1. It looks similar to SQL, and MUST include a blank space at the end (this is a great interview question to gauge someone’s BRM development expertise, by the way).
The template must include the object to be searched for as well as the arguments to be used for conducting the search.
select X from <object type> where <arguments>
Object type subclasses may be specified dynamically using a Parameter. The Parameter is specified by the use of the ‘$1’ string appended to the object type. If the object type contains a parameter, then the PIN_FLD_PARAMETER field must be present on the input FLIST. See the PIN_FLD_PARAMETER section below.
Arguments are specified by the use of F<n> and V<n> variables. F<n> stands for the field to be compared, and V<v> stands for the value of the field to be compared. The <n> value corresponds directly to an array element of PIN_FLD_ARGS that contains exactly one field and value. See the PIN_FLD_ARGS section below. Most SQL operators may be used to compare the arguments ( =, <>, IS NOT NULL, like, etc.).
Examples:
This template is a 1 argument search for /deal objects:
This search template requires the PIN_FLD_ARGS[1] Array element to be present on the search FLIST.
0 PIN_FLD_TEMPLATE STR [0] "select X from /deal where F1 = V1 "
This template is a 2 argument search for /account objects:
Notice here that we have a parameter for the object type, which requires the presence of the PIN_FLD_PARAMETER field on the input FLIST. PIN_FLD_ARGS[1] and PIN_FLD_ARGS[2] are also required.
0 PIN_FLD_TEMPLATE STR [0] "select X from /account/$1 where F1 = V1 and F2 <> V2 "
PIN_FLD_ARGS
This array holds the search criteria utilized by the F<n> and V<n> values in the search template. The <n> specifies the array element to be used for that search expression.
The following combination of PIN_FLD_TEMPLATE and PIN_FLD_ARGS:
0 PIN_FLD_TEMPLATE STR [0] “select X from /deal where F1 = V1 ” 0 PIN_FLD_ARGS [1] 1 PIN_FLD_NAME STR [0] “Network Storage”
Can be logically said to translate to:
select X from /deal where PIN_FLD_NAME = ‘Network Storage’
PIN_FLD_PARAMETER
This field allows the object type being searched for to be subclassed for the search in question.
If we want to search for /event/session, the following FLIST could be used:
0 PIN_FLD_TEMPLATE STR [0] “select X from /event/$1 where F1 = V1 ” 0 PIN_FLD_PARAMETER STR[0] “session”
If the subtype is a separate variable in our code, this becomes useful for making sure the appropriate sub-classes are returned.
PIN_FLD_FLAGS
The flags field is used to dictate the behavior of the search. Possible values for the flags include:
Zero (0): No search flags. Return all results found.
SRCH_DISTINCT (256): Do not return multiple instances of the same object in the search results.
SRCH_EXACT (512): Do not return array elements that do not match the search criteria.
PIN_FLD_RESULTS
This array element defines which fields from the result set should be returned, as well as how many results should be returned.
Examples:
Returns all object fields and an unlimited number of results:
0 PIN_FLD_RESULTS ARRAY [*] NULL array ptr
Returns all object fields and the first 25 matching objects:
0 PIN_FLD_RESULTS ARRAY [25] NULL array ptr
Returns only the PIN_FLD_NAME and PIN_FLD_POID fields from all matching objects:
0 PIN_FLD_RESULTS ARRAY [*] 1 PIN_FLD_POID POID[0] NULL 1 PIN_FLD_NAME STR[0] NULL
PCM_OP_SEARCH Result FLIST:
Search results include a PIN_FLD_POID field equal to the one passed on the input FLIST, plus a PIN_FLD_RESULTS array element for each object found that matches the search criteria.
The elements in PIN_FLD_RESULTS could include the whole object found, or a subset, depending on the PIN_FLD_RESULTS passed in on the Input search FLIST.
If no PIN_FLD_RESULTS array elements are returned, the search did not return any objects that matched the search criteria.
Putting it All Together: Some Examples
This section contains some example searches to highlight the above points.
Custom Template Unlimited Result Search for Deal by Name:
# number of field entries allocated 20, used 5 0 PIN_FLD_POID POID [0] 0.0.0.1 /search -1 0 0 PIN_FLD_RESULTS ARRAY [*] NULL array ptr 0 PIN_FLD_ARGS ARRAY [1] allocated 20, used 1 1 PIN_FLD_NAME STR [0] "Deal 1a - Measured Internet Service" 0 PIN_FLD_TEMPLATE STR [0] "select X from /deal where F1 = V1 " 0 PIN_FLD_FLAGS INT [0] 0 nap> xop 7 0 1 xop: opcode 7, flags 0 # number of field entries allocated 2, used 2 0 PIN_FLD_POID POID [0] 0.0.0.1 /search -1 0 0 PIN_FLD_RESULTS ARRAY [0] allocated 13, used 13 1 PIN_FLD_POID POID [0] 0.0.0.1 /deal 8686 2 1 PIN_FLD_CREATED_T TSTAMP [0] (976219881) 12/07/00 14:11:21 1 PIN_FLD_MOD_T TSTAMP [0] (995621794) 07/20/01 04:36:34 1 PIN_FLD_READ_ACCESS STR [0] "B" 1 PIN_FLD_WRITE_ACCESS STR [0] "S" 1 PIN_FLD_ACCOUNT_OBJ POID [0] 0.0.0.1 /account 1 0 1 PIN_FLD_DESCR STR [0] "" 1 PIN_FLD_END_T TSTAMP [0] (0) 1 PIN_FLD_FLAGS INT [0] 0 1 PIN_FLD_NAME STR [0] "Deal 1a - Measured Internet Service" 1 PIN_FLD_PERMITTED STR [0] "/service/ip" 1 PIN_FLD_START_T TSTAMP [0] (0) 1 PIN_FLD_PRODUCTS ARRAY [0] allocated 19, used 19 2 PIN_FLD_CYCLE_DISCOUNT DECIMAL [0] 0 2 PIN_FLD_CYCLE_END_CYCLE DECIMAL [0] 0 2 PIN_FLD_CYCLE_END_T TSTAMP [0] (0) 2 PIN_FLD_CYCLE_START_CYCLE DECIMAL [0] 0 2 PIN_FLD_CYCLE_START_T TSTAMP [0] (0) 2 PIN_FLD_PRODUCT_OBJ POID [0] 0.0.0.1 /product 9518 2 2 PIN_FLD_PURCHASE_DISCOUNT DECIMAL [0] 0 2 PIN_FLD_PURCHASE_END_CYCLE DECIMAL [0] 0 2 PIN_FLD_PURCHASE_END_T TSTAMP [0] (0) 2 PIN_FLD_PURCHASE_START_CYCLE DECIMAL [0] 0 2 PIN_FLD_PURCHASE_START_T TSTAMP [0] (0) 2 PIN_FLD_QUANTITY DECIMAL [0] 1 2 PIN_FLD_STATUS ENUM [0] 1 2 PIN_FLD_STATUS_FLAGS INT [0] 0 2 PIN_FLD_USAGE_DISCOUNT DECIMAL [0] 0 2 PIN_FLD_USAGE_END_CYCLE DECIMAL [0] 0 2 PIN_FLD_USAGE_END_T TSTAMP [0] (0) 2 PIN_FLD_USAGE_START_CYCLE DECIMAL [0] 0 2 PIN_FLD_USAGE_START_T TSTAMP [0] (0)
Example: Restricting the Search Results to Specific Fields:
Note that the PIN_FLD_RESULTS array on the input FLIST limits the results in the return FLIST.
# number of field entries allocated 20, used 5 0 PIN_FLD_POID POID [0] 0.0.0.1 /search -1 0 0 PIN_FLD_RESULTS ARRAY [*] allocated 20, used 2 1 PIN_FLD_POID POID [0] NULL poid pointer 1 PIN_FLD_CREATED_T TSTAMP [0] (0) 0 PIN_FLD_ARGS ARRAY [1] allocated 20, used 1 1 PIN_FLD_NAME STR [0] "Deal 1a - Measured Internet Service" 0 PIN_FLD_TEMPLATE STR [0] "select X from /deal where F1 = V1 " 0 PIN_FLD_FLAGS INT [0] 0 nap> xop 7 0 1 xop: opcode 7, flags 0 # number of field entries allocated 2, used 2 0 PIN_FLD_POID POID [0] 0.0.0.1 /search -1 0 0 PIN_FLD_RESULTS ARRAY [0] allocated 2, used 2 1 PIN_FLD_POID POID [0] 0.0.0.1 /deal 8686 2 1 PIN_FLD_CREATED_T TSTAMP [0] (976219881) 12/07/00 14:11:21
Example: Non-Custom Search using /search template 201
This search uses a non-custom template. The /search object with POID 201 is used.
# number of field entries allocated 20, used 4 0 PIN_FLD_POID POID [0] 0.0.0.1 /search 201 0 0 PIN_FLD_RESULTS ARRAY [*] allocated 20, used 3 1 PIN_FLD_POID POID [0] NULL poid pointer 1 PIN_FLD_CREATED_T TSTAMP [0] (0) 1 PIN_FLD_NAMEINFO ARRAY [*] allocated 20, used 1 2 PIN_FLD_LAST_NAME STR [0] NULL str ptr 0 PIN_FLD_ARGS ARRAY [1] allocated 20, used 1 1 PIN_FLD_NAMEINFO ARRAY [*] allocated 20, used 1 2 PIN_FLD_FIRST_NAME STR [0] "Ronald" 0 PIN_FLD_FLAGS INT [0] 0 nap> xop 7 0 1 xop: opcode 7, flags 0 # number of field entries allocated 2, used 2 0 PIN_FLD_POID POID [0] 0.0.0.1 /search 201 0 0 PIN_FLD_RESULTS ARRAY [0] allocated 3, used 3 1 PIN_FLD_POID POID [0] 0.0.0.1 /account 25469857 53148 1 PIN_FLD_CREATED_T TSTAMP [0] (1139417895) 02/08/06 10:58:15 1 PIN_FLD_NAMEINFO ARRAY [1] allocated 1, used 1 2 PIN_FLD_LAST_NAME STR [0] "Amedeo"
Example: Custom Account Search, Limit Result Set to 5 results
This result set is limited to the first 5 entries found.
# number of field entries allocated 20, used 5 0 PIN_FLD_POID POID [0] 0.0.0.1 /search -1 0 0 PIN_FLD_RESULTS ARRAY [5] allocated 20, used 3 1 PIN_FLD_POID POID [0] NULL poid pointer 1 PIN_FLD_CREATED_T TSTAMP [0] (0) 1 PIN_FLD_NAMEINFO ARRAY [*] allocated 20, used 2 2 PIN_FLD_LAST_NAME STR [0] NULL str ptr 2 PIN_FLD_FIRST_NAME STR [0] NULL str ptr 0 PIN_FLD_ARGS ARRAY [1] allocated 20, used 1 1 PIN_FLD_NAMEINFO ARRAY [*] allocated 20, used 1 2 PIN_FLD_FIRST_NAME STR [0] "%a%" 0 PIN_FLD_TEMPLATE STR [0] "select X from /account where F1 like V1 " 0 PIN_FLD_FLAGS INT [0] 0 nap> xop 7 0 1 xop: opcode 7, flags 0 # number of field entries allocated 6, used 6 0 PIN_FLD_POID POID [0] 0.0.0.1 /search -1 0 0 PIN_FLD_RESULTS ARRAY [0] allocated 3, used 3 1 PIN_FLD_POID POID [0] 0.0.0.1 /account 35862893 19 1 PIN_FLD_CREATED_T TSTAMP [0] (1268321292) 03/11/10 09:28:12 1 PIN_FLD_NAMEINFO ARRAY [1] allocated 2, used 2 2 PIN_FLD_LAST_NAME STR [0] "Funchesal" 2 PIN_FLD_FIRST_NAME STR [0] "Debrah" 0 PIN_FLD_RESULTS ARRAY [1] allocated 3, used 3 1 PIN_FLD_POID POID [0] 0.0.0.1 /account 33265410 2065 1 PIN_FLD_CREATED_T TSTAMP [0] (1238622641) 04/01/09 16:50:41 1 PIN_FLD_NAMEINFO ARRAY [1] allocated 2, used 2 2 PIN_FLD_LAST_NAME STR [0] "Ogrizlo" 2 PIN_FLD_FIRST_NAME STR [0] "Mike" 0 PIN_FLD_RESULTS ARRAY [2] allocated 3, used 3 1 PIN_FLD_POID POID [0] 0.0.0.1 /account 35856912 42 1 PIN_FLD_CREATED_T TSTAMP [0] (1267800937) 03/05/10 08:55:37 1 PIN_FLD_NAMEINFO ARRAY [1] allocated 2, used 2 2 PIN_FLD_LAST_NAME STR [0] "Christens" 2 PIN_FLD_FIRST_NAME STR [0] "Beaud" 0 PIN_FLD_RESULTS ARRAY [3] allocated 3, used 3 1 PIN_FLD_POID POID [0] 0.0.0.1 /account 28715619 15211 1 PIN_FLD_CREATED_T TSTAMP [0] (1187360056) 08/17/07 09:14:16 1 PIN_FLD_NAMEINFO ARRAY [1] allocated 2, used 2 2 PIN_FLD_LAST_NAME STR [0] "Binchini" 2 PIN_FLD_FIRST_NAME STR [0] "Ginal" 0 PIN_FLD_RESULTS ARRAY [4] allocated 3, used 3 1 PIN_FLD_POID POID [0] 0.0.0.1 /account 34456511 191 1 PIN_FLD_CREATED_T TSTAMP [0] (1252009050) 09/03/09 15:17:30 1 PIN_FLD_NAMEINFO ARRAY [1] allocated 2, used 2 2 PIN_FLD_LAST_NAME STR [0] "Ggoi" 2 PIN_FLD_FIRST_NAME STR [0] "Dhuriba"
In my next blog entry, i will illustrate how to encapsulate a search into a C function.