13 Searching for Objects in the BRM Database

This chapter explains the Oracle Communications Billing and Revenue Management (BRM) object search strategy, including the types of searching that BRM performs by default and what you need to know about searching if you are writing custom applications to use with BRM.

About Searching for Objects

In this context, searching means looking in your BRM database for objects that meet criteria that you specify. That is, you search for the Portal object IDs (POIDs) of all the classes that share certain characteristics.

There are two main types of searching:

  • Simple searching on a single class and its inherited classes. This usually means searching for a specific account.

  • Complex searching across multiple classes at the same time. For example, searching for all accounts located in a specific city that used a specific service, includes both the /account and /service classes.

These searches can be carried out on one or more database schemas, depending on your implementation.

There are two other options for the SEARCH opcodes:

  • Count-only searches count and return the number of POIDS that match your search criteria. They do not return POIDs. A count-only search is performed when the PCM_OPFLG_COUNT_ONLY parameter is used.

  • Calculate-only searches return a single calculated value such as a sum or average. A calculate-only search is performed when the PCM_OP_CALC_ONLY_1 parameter is used.

About Search Templates

To search for objects in the database, you use a search template. The template can be predefined and stored in a /search storable object in the BRM database or defined at runtime when a search opcode is called. When you define the template at runtime, you include the search query on the search opcode input flist. The advantage of defining the template at runtime is that you do not have to create it and store it in the database first.

BRM includes a number of predefined /search storable objects in the BRM_Home/sys/dd/data/init_objects.source file that you can use as templates. (BRM_Home is the directory in which BRM is installed.) The predefined search templates are stored in the SEARCH_T table in the database when BRM is installed. Each of these templates has a predefined ID, such as 230 or 231.

You can also create your own search objects. When you define a search, look in the init_objects.source file to see whether a template for your search exits. If one does not exist, create it and load it into the database. Your /search storable object can then be used in a call to the search opcode.

If you create a predefined search template, add a copy of the new template to init_objects.source. Adding the template has the following advantages:

  • You avoid assigning duplicate search template IDs.

  • All search templates are in a single location, making them easy to find.

  • In testing mode, you can automatically load the new search templates if you need to re-create the database.

    Important:

    When you upgrade to a new BRM release, make sure you copy your custom templates to the new init_objects.source file.

About the Search Input Flist

You specify the search criteria and the results you want returned from the search on the input flist of the search opcode.

Three fields are required on the input flist:

  • Search POID: Specifies a /search storable object. See "Search POID".

  • PIN_FLD_ARGS array: Specifies the arguments in the search criteria. See "Argument List".

  • PIN_FLD_RESULTS array: Specifies which fields to return from the search. See "Results Array".

If you define a search template at runtime (when the search is executed), two more fields are required:

  • PIN_FLD_TEMPLATE: Specifies the search query in the form of a string. See "Search Query".

  • PIN_FLD_FLAGS: Specifies the type of search to perform. See "Flags".

An optional PIN_FLD_PARAMETERS field can be included in the flist when you use a predefined search template. This field specifies a subclass that contains the search arguments. See "Using the PIN_FLD_PARAMETERS Field".

You can specify the start row and end row of the search result to be retrieved from the search result set by using the optional PIN_FLD_MIN_ROW and PIN_FLD_MAX_ROW fields in the input flist. See "Limiting Search Results by Using the PIN_FLD_MIN_ROW and PIN_FLD_MAX_ROW Fields".

Search POID

The search POID identifies the search template to use for the search.

  • If you predefine a search template and store it in a search object, you add the POID of the /search object to the input flist. The POID specifies which predefined search template to use:

    0 PIN_FLD_POID          POID [0] 0.0.0.1 /search 301 0
      
    
  • If you define the search template at runtime, you add the search object POID to the input flist with an object ID of 0 or -1, and you define the search query in a PIN_FLD_TEMPLATE field on the input flist:

    0 PIN_FLD_POID           POID [0] 0.0.0.1 /search 0 0
    0 PIN_FLD_TEMPLATE        STR [0] "select X from /account where F1 like V1"
      
    

    For more information, see "About Search Templates".

Argument List

You specify the arguments for the search query in the PIN_FLD_ARGS array. Each array element contains one argument. You must provide at least one argument.

You should always put the POID of the storable class type you want returned in the PIN_FLD_ARGS array. If you do not, the search returns an error.

The maximum number of search arguments is 32. The array element ID specifies which argument is contained in the array element. For example, element ID 1 corresponds to argument 1.

The arguments in the PIN_FLD_ARGS array are referenced in the where clause of the search query. If the search criteria specified in the where clause exist in a class other than the one specified in the search query, an attempt is made to convert the POID type of the unspecified class to the specified class, which causes an error.

Results Array

You specify which fields you want returned from the storable objects you are searching in the PIN_FLD_RESULTS array. One element is returned for each storable object that was matched.

Note:

You specify the storable objects themselves in the PIN_FLD_ARGS array.

Results can be returned in the following ways:

  • To return all the fields from a matched storable object, put the PIN_FLD_RESULTS element on the input flist with a value of NULL.

  • To return only a count of matching objects, put the PIN_FLD_RESULTS element on the input flist with a value of NULL and use the PCM_OPFLG_COUNT_ONLY flag. The number of matching results is returned as the element ID of the PIN_FLD_RESULTS array in the output flist.

  • To return only those fields you specify, the PIN_FLD_RESULTS element on the input flist must contain a sub-flist with the specified fields.

  • To return a single value that is calculated from the matched storable objects, put the PIN_FLD_RESULTS element that includes a single PIN_FLD_AMOUNT field on the input flist. Set the search flag to SRCH_CALC_ONLY.

To indicate the maximum number of records to return, specify that number as the element ID of the PIN_FLD_RESULTS element. To return all records, use zero. If you are doing a count-only or calculate-only search, only one value is returned.

If you call for a calculate-only search by using the PIN_FLD_CALC_ONLY_1 flag, the PIN_FLD_RESULTS array must contain only one PIN_FLD_AMOUNT field with an element ID of 1.

Search Query

When you define a search template at runtime, you specify the search query in the PIN_FLD_TEMPLATE field. The template is in the form of an SQL-like search string. The length of the string is limited to 2048 characters. For example, "select X from <object> where <expression>". For more information, see "Search Query Syntax".

Flags

You can specify the following searches using the PIN_FLD_FLAGS field on the input flist:

  • 256: SRCH_DISTINCT

    This search type returns only unique data; that is, duplicate POIDs are not returned. Using this flag is recommended to avoid duplicate data. To skip this feature, set the value to 0.

    Note:

    This flag performs distinct operations on POIDs only. If any other datatype is used in the input query, SRCH_DISTINCT does not return distinct results. This flag cannot be used when using an order by clause while performing a complex search. In this case, set the flag value to 0.
  • 512: SRCH_EXACT

    Use this flag to search arrays. This flag applies the where clause in the search string to arrays. If this flag is not used, the search opcode might return array elements that do not match the search criteria. For more information, see "Performing Exact Searches".

    Tip:

    To specify both SRCH_EXACT and SRCH_DISTINCT flags, you can add their values (512 and 256) and enter 768 in the PIN_FLD_FLAGS field.
  • 1024: SRCH_WITHOUT_POID

    This search type returns data without POIDs for each result. For more information, see "Search without POID".

There are also two flags that you can use in the call to a search opcode:

  • PCM_OPFLG_COUNT_ONLY

    This search type returns only the number of POIDs that matched the search criteria. The value of the PIN_FLD_RESULTS element on the input flist must be NULL.

  • A calculate-only flag

    This search type returns a value, such as a sum or average. There are two forms of the calculate-only flag:

    • SRCH_CALC_ONLY_1

      Use this flag to return a single value.

    • SRCH_CALC_ONLY

      Use this flag to return one or more values.

    For more information, see "Search Query Syntax for Calculate-Only Searches".

Search Query Syntax

The search query is part of the search template. You include it in either the predefined template before storing it in the database or in the PIN_FLD_TEMPLATE field on the input flist at runtime.

Important:

SQL queries must adhere to the limitations imposed by the database. For information, see your database documentation.

Use the following syntax for search queries:

"select X from object_name where expression"

where:

  • X is a placeholder for the fields being requested, which are specified in the PIN_FLD_RESULTS array on the input flist.

  • object_name is the type name of the storable object that contains the arguments.

    The name can be fully specified; that is, it can include the specific subclass, or it can take an optional parameter (for example, /event/$1). The $1 parameter is substituted with the value of the PIN_FLD_PARAMETERS field on the search flist. If PIN_FLD_PARAMETERS is not included on the flist, the $1 is null. See "Using the PIN_FLD_PARAMETERS Field".

    Note:

    The storable class type you specify in the search query tells BRM where to find the arguments in the where clause. It does not indicate the storable class type to return.
  • expression is an SQL expression such as "where F1 = V1 and F2 = V2".

    The column names and literal values (Fn and Vn) are replaced by the field names and field values specified in the PIN_FLD_ARGS array on the input flist. The column name and value indexes must be contiguous and correspond with the elements in the arguments array starting with element ID 1. That is, F1 and V1 correspond to the field name and value in PIN_FLD_ARGS[1], F2 and V2 to the field name and value in PIN_FLD_ARGS[2], and so on.

About Searching for Objects by Their POID Subcomponent

You can search for objects by specifying any of the following POID subcomponents in the search expression:

  • Database number

  • Storable class type

  • Object ID

  • Revision number

In addition to the Fn = Vn expression, you can use any one of the following expressions in the where clause of the search query template:

Searching for Objects by the POID Database Number

The following example shows the PCM_OP_SEARCH input flist with the POID database number specified in the search query:

0 PIN_FLD_POID           POID [0] 0.0.0.1 /search/pin 0 0 
0 PIN_FLD_FLAGS           INT [0] 256 
0 PIN_FLD_TEMPLATE        STR [0] "select X from /service where F1.db = V1 " 
0 PIN_FLD_RESULTS       ARRAY [*] allocated 20, used 1 
1   PIN_FLD_POID         POID [0] 0.0.0.1 /service/ip -1 0 
0 PIN_FLD_ARGS          ARRAY [1] allocated 20, used 1 
1   PIN_FLD_POID         POID [0] 0.0.0.1 /service/% 1 0 

Searching for Objects by the POID Type

The following example shows the PCM_OP_SEARCH input flist with the POID type specified in the search query:

0 PIN_FLD_POID           POID [0] 0.0.0.1 /search/pin 0 0
0 PIN_FLD_FLAGS           INT [0] 256
0 PIN_FLD_TEMPLATE        STR [0] "select X from /service where F1.type like V1 "
0 PIN_FLD_RESULTS       ARRAY [3] allocated 1, used 1
1   PIN_FLD_POID         POID [0] 0.0.0.1 /service/ip -1 0
0 PIN_FLD_ARGS          ARRAY [1] allocated 1, used 1
1   PIN_FLD_POID         POID [0] 0.0.0.1 /service/IP 1 0

Searching for Objects by the POID Object ID

The following example shows the PCM_OP_SEARCH input flist with the POID object ID specified in the search query:

0 PIN_FLD_POID           POID [0] 0.0.0.1 /search/pin 0 0
0 PIN_FLD_FLAGS           INT [0] 256
0 PIN_FLD_TEMPLATE        STR [0] "select X from /service/ip where F1 like V1 AND F2.id = V2"
0 PIN_FLD_RESULTS       ARRAY [0] allocated 2, used 2
1   PIN_FLD_POID         POID [0] 0.0.0.1 /service/ip -1 0
1   PIN_FLD_ACCOUNT_OBJ  POID [0] 0.0.0.1 /account -1 0
0 PIN_FLD_ARGS          ARRAY [1] allocated 1, used 1
1   PIN_FLD_POID         POID [0] 0.0.0.1 /service/ip -1 0
0 PIN_FLD_ARGS          ARRAY [2] allocated 1, used 1
1   PIN_FLD_ACCOUNT_OBJ  POID [0] 0.0.0.1 /account 24295 1 0

Searching for Objects by the POID Revision Number

The following example shows the PCM_OP_SEARCH input flist with the POID revision number specified in the search query:

0 PIN_FLD_POID           POID [0] 0.0.0.1 /search/pin 0 0
0 PIN_FLD_FLAGS           INT [0] 256
0 PIN_FLD_TEMPLATE        STR [0] "select X from /account where F1.rev = 10 "
0 PIN_FLD_RESULTS       ARRAY [0] allocated 2, used 2
1   PIN_FLD_POID         POID [0] 0.0.0.1 /account -1 0
1   PIN_FLD_NAMEINFO    ARRAY [*] allocated 0, used 0
0 PIN_FLD_ARGS          ARRAY [1] allocated 1, used 1
1   PIN_FLD_POID         POID [0] 0.0.0.1 /account 1897978 0

Search Query Syntax for Count-Only Searches

You can search using the following syntax:

”select result from object_name where expression

where result is a count value returned when a search is performed using the PCM_OPFLG_COUNT_ONLY flag. This flag returns only the number of matches found by the search.

The following example shows the PCM_OP_SEARCH input flist for counting the total journal objects:

...
0 PIN_FLD_POID           POID [0] 0.0.0.1 /search -1 0
0 PIN_FLD_TEMPLATE       STR [0] "select X from /journal where F1 = V1 " 
0 PIN_FLD_FLAGS          INT [0] 0
0 PIN_FLD_ARGS           ARRAY [1]
1 PIN_FLD_POID           POID [0] 0.0.0.1 /journal -1 0
0 PIN_FLD_RESULTS          ARRAY [*] NULL
...

To run opcodes using testnap, use the xop command:

vxop PCM_OP_SEARCH 0x10 1

where 0x10 is a PCM_OPFLG_COUNT_ONLY flag and 1 is the buffer.

The opcode returns the count as the index of the PIN_FLD_RESULTS array. For example:

...
0 PIN_FLD_POID           POID [0] 0.0.0.1 /search -1 0
0 PIN_FLD_RESULTS       ARRAY [7] NULL array ptr
...

where 7 is the total journal count.

Search Query Syntax for Calculate-Only Searches

You can search using the following syntax:

”select result from object_name where expression

where result is a calculated value returned when a search is performed by using the calculate-only flag. There are two forms of the calculate-only flag:

  • SRCH_CALC_ONLY_1

    This flag returns a single value. You specify one calculation in the search query. For example:

    "select sum( F1 ) from object_name where expression"

    Important:

    You must include spaces around F1.

    F1 references the field value of PIN_FLD_ARGS array element 1 on the input flist. You must include the PIN_FLD_AMOUNT field with an element ID of 1 as the only field in the PIN_FLD_RESULTS array.

  • SRCH_CALC_ONLY

    This flag can return one or more values. You specify each calculation in the search query. For example:

    "select sum( F1 ), avg( F2 ) from object_name where expression"

    For multiple results, you must include a PIN_FLD_AMOUNT field in the PIN_FLD_RESULTS array for each result to return.

    If you use SRCH_CALC_ONLY with the PCM_OPFLG_SRCH_CALC_RESULTS flag not set (which is the default), all PIN_FLD_AMOUNT values are returned in the PIN_FLD_RESULTS array. For example:

    ...
    0 PIN_FLD_RESULTS      ARRAY [0]
    1   PIN_FLD_AMOUNT   DECIMAL [1]
    1   PIN_FLD_AMOUNT   DECIMAL [2]
    ...
      
    

    If you use SRCH_CALC_ONLY with the PCM_OPFLG_SRCH_CALC_RESULTS flag set, each PIN_FLD_AMOUNT value is returned in its own PIN_FLD_RESULTS array. For example:

    0 PIN_FLD_RESULTS      ARRAY [0]
    1   PIN_FLD_AMOUNT   DECIMAL [0]
    0 PIN_FLD_RESULTS      ARRAY [1]
    1   PIN_FLD_AMOUNT   DECIMAL [0]
    ....
    

Using the PIN_FLD_PARAMETERS Field

When you use a predefined search template, you can use an optional $1 object type parameter in the from clause of the search query. This parameter specifies a subclass and allows you to specialize the search without having to modify the stored template.

You use a PIN_FLD_PARAMETERS field when you use the $1 parameter. The $1 parameter in the search template is replaced by the value of the PIN_FLD_PARAMETERS field on the input flist.

For example, if your template search query is the following:

"select X from /device/$1 where F1 = V1 "

and your input flist contains the following:

...
0 PIN_FLD_ARGS       ARRAY [1] allocated 20, used 1
1   PIN_FLD_POID      POID [0] 0.0.0.1 /device/sim -1 0
0 PIN_FLD_PARAMETERS   STR [0] "sim"
...
  

The string "sim" is substituted for the $1 parameter in the search template and the search looks for the arguments in the /device/sim storable class.

Important:

  • Using this field does not restrict the search to storable objects of the type it specifies. To restrict the search, specify the class type POIDs in a PIN_FLD_ARGS array.

  • Be sure to format the value of PIN_FLD_PARAMETERS on the input flist correctly. For example, a value of portal\user_info\ on the input flist does not work, and the search fails without returning an error message. However, when using portal\user_info without the trailing '\', the search succeeds.

Limiting Search Results by Using the PIN_FLD_MIN_ROW and PIN_FLD_MAX_ROW Fields

You use the optional PIN_FLD_MIN_ROW and PIN_FLD_MAX_ROW fields in the input flist of the PCM_OP_SEARCH opcode to retrieve the records from the search result set using the start row and end row numbers. For example, if the PCM_OP_SEARCH opcode returns 1000 records in the search result set, if PIN_FLD_MIN_ROW is set to 200 and PIN_FLD_MAX_ROW is set to 300, the records from row number 200 to 300 are retrieved.You can navigate through the search result set both in forward and backward directions. For example, after retrieving the records from 200 to 300, you can step backward through the search result set to retrieve the records from 100 to 200.After the PCM_OP_SEARCH opcode is triggered, any modified records in the database are retrieved from the search result set only when the next time the PCM_OP_SEARCH opcode is triggered.

Important:

Opcodes that support multiple database schemas (for example, PCM_OP_GLOBAL_SEARCH and PCM_OP_GLOBAL_STEP_SEARCH) do not support retrieving the search results using row numbers.

Using the "in" Operator

Using the SQL in operator in your query is another way of simplifying your search criteria. If you use in, you must use the BRM syntax requirements for this operator:

Note:

When using the in operator, only POIDs and strings can be searched and POIDs must be type only.

For example, "select X from /config where F1 in ( V1 , '/config/locales_map' ) "

The where clause syntax must be entered exactly as shown and follow these requirements:

  • There must be one space before in.

  • There must be one space after in and also after the parenthesis following in.

  • There must be one space between V1 and the following comma.

    Note:

    The space between V1 and the comma is only required when using the in operator.
  • All values in the query using an in operator must be inside parenthesis.

    For example:

    ...where F1 in ( V1 , '/config/locales_map' ) and F2 in ( V2 ) "
      
    

A search using the following input flist will return the entire contents of /config/notify and /config/locales_map:

0 PIN_FLD_POID     POID [0] 0.0.0.1 /search -1 0
0 PIN_FLD_FLAGS     INT [0] 256
0 PIN_FLD_TEMPLATE  STR [0] "select X from /config where F1 in (V1 , '/config/locales_map' )"
0 PIN_FLD_ARGS    ARRAY [1] allocated 20, used 1
1   PIN_FLD_POID   POID [0] 0.0.0.1 /config/notify -1 0
0 PIN_FLD_RESULTS ARRAY [*] NULL array ptr

Searching Subclasses

Because a subclass inherits the attributes of its parent class, a simple search includes results from all subclasses of the class specified in the arguments array, provided they match the search criteria. You only need to specify the most derived class which has a referenced argument in the where clause.

To constrain your search to criteria that exist only in a subclass, you must use this subclass on the query itself.

For example, the /config/notify object contains a PIN_FLD_EVENTS array, but its parent class, /config, does not. If your search argument is contained in the PIN_FLD_EVENTS array of the /config/notify object, but you specify the /config object, the search will fail.

The faulty flist looks like this:

0 PIN_FLD_POID           POID [0] 0.0.0.1 /search -1 0 
0 PIN_FLD_FLAGS           INT [0] 256
0 PIN_FLD_TEMPLATE        STR [0] "select X from /config where F1 = V1 "
0 PIN_FLD_ARGS          ARRAY [1] allocated 20, used 1
1   PIN_FLD_EVENTS      ARRAY [0] allocated 20, used 1
2      PIN_FLD_TYPE_STR   STR [0] "/event/session"
0 PIN_FLD_RESULTS       ARRAY [*] NULL array ptr
  

The correct flist specifies the subclass containing the argument:

0 PIN_FLD_POID           POID [0] 0.0.0.1 /search -1 0
0 PIN_FLD_FLAGS           INT [0] 256
0 PIN_FLD_TEMPLATE        STR [0] "select X from /config/notify where F1 = V1 "
0 PIN_FLD_ARGS          ARRAY [1] allocated 20, used 1
1   PIN_FLD_EVENTS      ARRAY [0] allocated 20, used 1
2      PIN_FLD_TYPE_STR   STR [0] "/event/session"
0 PIN_FLD_RESULTS       ARRAY [*] NULL array ptr

Returning Specific Classes

You must specify the storable objects you want returned in the PIN_FLD_ARGS array in the search input flist. A search will return objects of the superclass or any other derived class. If you want to return only objects from the specified class, the POID of the class type must be -1.

To return only one specified class, include it in the arguments array:

0 PIN_FLD_TEMPLATE    STR [0] "select X from /device/sim where F1 = V1 "
0 PIN_FLD_ARGS      ARRAY [1] allocated 1, used 1 
1   PIN_FLD_POID     POID [0] 0.0.0.1 /device/sim -1 0 
...
  

To return more than one class type, but restrict the results to only those types specified, add the class type POID for each type to return to the PIN_FLD_ARGS array and set each POID to -1:

0 PIN_FLD_TEMPLATE    STR [0] "select X from /device/sim where F1 = V1 "
0 PIN_FLD_ARGS      ARRAY [1] allocated 1, used 1 
1   PIN_FLD_POID     POID [0] 0.0.0.1 /device/sim -1 0 
0 PIN_FLD_ARGS      ARRAY [2] allocated 1, used 1 
1   PIN_FLD_POID     POID [0] 0.0.0.1 /device/num -1 0 
...
  

To return only a specific class and all its subclasses, add the POID of the parent class type to the argument list, set the POID to -1, use a like operator in the where clause, and add a percent sign (%) at the end of the class type:

Note:

The like operator is used only when searching for strings.
0 PIN_FLD_TEMPLATE    STR [0] "select X from /device/sim where F1 like V1 "
0 PIN_FLD_ARGS      ARRAY [1] allocated 1, used 1 
1   PIN_FLD_POID     POID [0] 0.0.0.1 /device/sim% -1 0 
...

Returning Entire Arrays

Because arrays are fields in storable classes, to return an array you must add it to the PIN_FLD_RESULTS array in the search opcode input flist. To return the entire contents of an array, you specify the array and give it a NULL value. A NULL array is different from an empty array in which elements are allocated but not used.

For example, to retrieve the entire contents of the PIN_FLD_NAMEINFO array from the /account object, use the following input flist:

0 PIN_FLD_POID        POID [0] 0.0.0.1 /search -1 0
0 PIN_FLD_FLAGS        INT [0] 256
0 PIN_FLD_TEMPLATE     STR [0] "select X from /account where F1 = V1 "
0 PIN_FLD_ARGS       ARRAY [1] allocated 20, used 1
1   PIN_FLD_POID      POID [0] 0.0.0.1 /account 12345 0
0 PIN_FLD_RESULTS    ARRAY [*]     NULL array ptr
1   PIN_FLD_NAMEINFO ARRAY [*] NULL  (instead of: ALLOCATED 20, USED 0 )NULL
  

When constructing this flist in your application, to add a NULL array you must use PIN_FLIST_ELEM_SET instead of PIN_FLIST_ELEM_ADD.

For example:

PIN_FLIST_ELEM_SET(flistp, NULL, PIN_FLD_NAMEINFO, PCM_RECID_ALL, ebufp);
  

The following entry is incorrect because it adds an empty array instead of a NULL array:

PIN_FLIST_ELEM_ADD(flistp, PIN_FLD_NAMEINFO, PCM_RECID_ALL, ebufp);

Search Template Examples

You must provide all arguments for each search template. The following logic is used when a search is performed:

If the results flist is a NULL flist {
    if CM_OPFLG_COUNT_ONLY is set {
        return the count of matched objects (search count)
    } else {
        return each of the entire objects that matches
          (search robj)
    }
} else {
    If this is a calculated search {
        return the result of the calculation
    } else {
        for each object matched, return just those fields
          specified on the RESULTS flist
    }
}

Using a Predefined Template

The following example is a predefined search template that you store in the database as a /search object. The search query placeholders are replaced by the values specified in the arguments array in the input flist, which determine the objects you search for.

-- 301 -- 2 arg = search in /pop
insert into search_t (
        poid_db, poid_type, poid_id0, poid_rev,
        name,
        created_t, mod_t,
        --
        flags,
        template
) values (
        DB_NO, '/search', 301, 1,
        '2 arg = search in /pop',
        DATE, DATE,
        --
        SRCH_DISTINCT,
        'select X from /pop where F1 = V1 and F2 = V2 '
);
  

The template ID is 301 and the where clause has two arguments. You need to enter the search template in the database with the valid date values and database number. Your search template will not work unless it is in the database. When your application performs a search, it calls ID #301 and your flist must contain the two arguments.

To create a predefined search template:

  1. Create a search flist that specifies the template. The following example shows how to create a search flist that specifies the above template:

    /***********************************************************
             * Allocate the flist for searching.
    ***********************************************************/
    flistp = PIN_FLIST_CREATE(ebufp);
      
    /***********************************************************
     * Get the database number.
    ***********************************************************/
    poidp = (poid_t *)PIN_FLIST_FLD_GET(in_flistp, PIN_FLD_POID,0, ebufp);
    database = PIN_POID_GET_DB(poidp);
      
    /***********************************************************
    * Use 301, the 2 arg search for pop objects.
    ***********************************************************/
    vp = PIN_FLIST_FLD_GET(in_flistp, PIN_FLD_ANI, 1, ebufp);
    id = (u_int64)301;
    objp = PIN_POID_CREATE(database, "/search", id, ebufp);
    PIN_FLIST_FLD_PUT(flistp, PIN_FLD_POID, (void *)objp, ebufp);
      
    /***********************************************************
    * Return pop that matches ani and is a primary pop.
    ***********************************************************/
    a_flistp = PIN_FLIST_ELEM_ADD(flistp, PIN_FLD_ARGS, 1, ebufp);
    aniarray_flistp = PIN_FLIST_CREATE(ebufp);
    /*
    ** PIN_FLD_ANI for our first arg.
    */
    PIN_FLIST_FLD_SET(aniarray_flistp, PIN_FLD_ANI, vp, ebufp);
    PIN_FLIST_ELEM_SET(a_flistp, aniarray_flistp, PIN_FLD_ANIS, 0,ebufp );
    /*
    ** PIN_FLD_TYPE for our second arg.
    */
    a_flistp = PIN_FLIST_ELEM_ADD(flistp, PIN_FLD_ARGS, 2, ebufp);
    aniarray_flistp = PIN_FLIST_CREATE(ebufp);
    PIN_FLIST_FLD_SET(aniarray_flistp, PIN_FLD_TYPE, (void *)&type,ebufp);
    PIN_FLIST_ELEM_SET(a_flistp, aniarray_flistp,PIN_FLD_ANIS, 0, ebufp);
    PIN_DESTROY_FLIST(aniarray_flistp,ebufp);
      
    /***********************************************************
    * Put on the PIN_FLD_RESULTS array for our results.
    ***********************************************************/
    PIN_FLIST_ELEM_SET(flistp, (void *)NULL, PIN_FLD_RESULTS, -1, ebufp);
      
    /***********************************************************
    * Call the DM to do the search.
    ***********************************************************/
    PCM_OP(ctxp, PCM_OP_SEARCH, 0, flistp, &r_flistp, ebufp);
      
    

    The search flist fields passed in might look like this:

    0 PIN_FLD_POID      POID [0] 0.0.0.2 /search 301 0
    0 PIN_FLD_ARGS     ARRAY [1] allocated 20, used 1
    1   PIN_FLD_ANIS   ARRAY [0] allocated 20, used 1
    2      PIN_FLD_ANI   STR [0] "408343"          
    0 PIN_FLD_ARGS     ARRAY [2] allocated 20, used 1
    1   PIN_FLD_ANIS   ARRAY [0] allocated 20, used 1
    2      PIN_FLD_TYPE  INT [0] 4
    0 PIN_FLD_RESULTS  ARRAY [*] Null pointer
      
    
  2. Load the search template into the database. You can use testnap to load the search template into the database. For more information, see "Creating a New Search Object".

  3. Add a copy of the new search template to the init_objects.source file.

When Storage Manager receives the flist, it first queries the database to find the template with poid_id 301. When it has the template, it looks for the PIN_FLD_ARGS array on your input flist and substitutes field numbers with field names and values with the values passed in. It then performs the search and returns the matching storable objects from the database.

In this example, no specific fields were specified to be returned, so the entire storable object that matches the search criteria is returned.

Defining the Search Template at Runtime

You can perform a search without using a predefined, stored template by including a template field in the search flist.

The following example shows how to create a search flist that specifies a runtime search template:

/***********************************************************
         * Allocate the flist for searching.
***********************************************************/
flistp = PIN_FLIST_CREATE(ebufp);
char * template = "select X from /pop where F1 = V1 and F2 = V2 "
  
/***********************************************************
 * Get the database number.
***********************************************************/
poidp = (poid_t *)PIN_FLIST_FLD_GET(in_flistp, PIN_FLD_POID,0, ebufp);
database = PIN_POID_GET_DB(poidp);
  
/***********************************************************
* Use -1, the 2 arg search for pop objects.
***********************************************************/
vp = PIN_FLIST_FLD_GET(in_flistp, PIN_FLD_ANI, 1, ebufp);
id = -1;
objp = PIN_POID_CREATE(database, "/search", id, ebufp);
PIN_FLIST_FLD_PUT(flistp, PIN_FLD_POID, (void *)objp, ebufp);
PIN_FLIST_FLD_SET (in_flistp, PIN_FLD_TEMPLATE, template, ebufp)
  
/***********************************************************
* Return pop that matches ani and is a primary pop.
***********************************************************/
a_flistp = PIN_FLIST_ELEM_ADD(flistp, PIN_FLD_ARGS, 1, ebufp);
aniarray_flistp = PIN_FLIST_CREATE(ebufp);
/*
** PIN_FLD_ANI for our first arg.
*/
PIN_FLIST_FLD_SET(aniarray_flistp, PIN_FLD_ANI, vp, ebufp);
PIN_FLIST_ELEM_SET(a_flistp, aniarray_flistp, PIN_FLD_ANIS, 0,ebufp );
/*
** PIN_FLD_TYPE for our second arg.
*/
a_flistp = PIN_FLIST_ELEM_ADD(flistp, PIN_FLD_ARGS, 2, ebufp);
aniarray_flistp = PIN_FLIST_CREATE(ebufp);
PIN_FLIST_FLD_SET(aniarray_flistp, PIN_FLD_TYPE, (void *)&type,ebufp);
PIN_FLIST_ELEM_SET(a_flistp, aniarray_flistp,PIN_FLD_ANIS, 0, ebufp);
PIN_DESTROY_FLIST(aniarray_flistp,ebufp);
  
/***********************************************************
* Put on the PIN_FLD_RESULTS array for our results.
***********************************************************/
PIN_FLIST_ELEM_SET(flistp, (void *)NULL, PIN_FLD_RESULTS, -1, ebufp);
  
/***********************************************************
* Call the DM to do the search.
***********************************************************/
PCM_OP(ctxp, PCM_OP_SEARCH, 0, flistp, &r_flistp, ebufp);
  

The search flist fields passed in might look like this:

0 PIN_FLD_POID       POID [0] 0.0.0.2 /search/pop -1 0
0 PIN_FLD_ARGS      ARRAY [1] allocated 20, used 1
1  PIN_FLD_ANIS      ARRAY[0] allocated 20, used 1
2      PIN_FLD_ANI    STR [0] "408343"          
0 PIN_FLD_ARGS      ARRAY [2] allocated 20, used 1
1   PIN_FLD_ANIS     ARRAY[0] allocated 20, used 1
2      PIN_FLD_TYPE   INT [0] 4
0 PIN_FLD_RESULTS   ARRAY [*] Null pointer
0 PIN_FLD_TEMPLATE    STR [0] select X from /pop where F1 = V1 and F2 = V2
  

With the template field in the flist, Storage Manager looks for the PIN_FLD_ARGS array on your input flist and substitutes field numbers with field names and values with the values passed in. It then performs the search and returns the matching storable objects from the database. Note that the arguments in the PIN_FLD_ARGS array must be the specified classes and not the superclass.

In this example, no specific fields were specified to be returned, so the entire storable object that matches the search criteria is returned.

About Single-Schema Searches

There are two basic ways to search for information in a single database schema:

  • Search the schema and return all of the results at one time by calling PCM_OP_SEARCH.

  • Search the schema with PCM_OP_STEP_SEARCH, which uses PCM_OP_STEP_NEXT and PCM_OP_STEP_END to display the results as smaller sets of accounts.

The searches performed by PCM_OP_SEARCH and PCM_OP_STEP_SEARCH are identical; they take the same input flist and return the same results. The results of PCM_OP_SEARCH, however, can be very large—large enough to use all the Data Manager (DM) shared memory. If you expect the size of your search results to be very large, use the PCM_OP_STEP_SEARCH opcode for the search. Step searching has the following advantages:

  • Speed: The search results come back much faster in smaller pieces. PCM_OP_STEP_SEARCH returns the first set of results immediately; it does not wait for the entire result set to be built.

  • System Resources: PCM_OP_STEP_SEARCH allocates just enough shared memory in the DM for a single set of results at a time. PCM_OP_SEARCH results use enough shared memory for the entire result set all at one time.

The disadvantage to step searching is that you must call all three step search opcodes for each search: PCM_OP_STEP_SEARCH, PCM_OP_STEP_NEXT, and PCM_OP_STEP_END.

Performing a Search on a Single Schema

To perform a search on a single database schema, use the PCM_OP_SEARCH opcode.

This opcode enables a client application to search for storable objects that meet a set of criteria defined by the client application.

Important:

Use this opcode only to search a single, known schema. If your BRM implementation uses multiple schemas and you need to search more than one, use the PCM_OP_GLOBAL_SEARCH opcode.

For information about required fields in the input flist, see "About the Search Input Flist".

This opcode performs a search by creating a search template at runtime. To use a stored template instead, the POID must specify a template /search object. If it is specified, this opcode searches for a stored template in the database schema and uses that template for the search. For information on how to set up and use stored templates for search criteria, see "About Search Templates".

Note:

Performing a search using a /search object template stored in the database is supported but not recommended.

Search results can be manipulated by using the flist field handling macros. For a list of opcodes, see "Flist Field-Handling Macros" in BRM Developer's Reference.

Flags

The following flags are used in the call to the PCM_OP_SEARCH opcode:

Memory Management

If your search returns a large amount of data, you need to make sure there is sufficient memory available to hold that data. To control the size of the data returned, use the PCM_OP_STEP_SEARCH opcode.

For a discussion of when to use searching and step searching, see "About Single-Schema Searches".

For a discussion of the memory implications of searching, see "The Impact of Searches on Shared Memory Allocation".

Examples

For an example of a simple search, see "Simple Search Example".

For examples of input flists for complex searches, see "Complex Searches".

For a sample search program that searches for a single and multiple results, see BRM_Home/apps/sample/sample_search.c.

Performing a Step Search on a Single Schema

To perform a step search on a single database schema, use the PCM_OP_STEP_SEARCH opcode.

Important:

Use this opcode only to search a single, known schema. If your BRM implementation uses multiple schemas and you need to search more than one, use the PCM_OP_GLOBAL_SEARCH opcode.

This opcode enables a client application to define search criteria, search for storable objects using those criteria, and receive a specified number of result sets. The advantage of using this opcode instead of PCM_OP_SEARCH is that the results are returned in discrete chunks, which enables you to control resource usage in both the DM and the application.

For information on when to use PCM_OP_SEARCH and PCM_OP_STEP_SEARCH, see "About Single-Schema Searches".

This opcode must be used in combination with the PCM_OP_STEP_NEXT and PCM_OP_STEP_END opcodes to complete a step search cycle. The cycle must start with PCM_OP_STEP_SEARCH, which initiates a step search and gets the first set of PIN_FLD_RESULT elements. One or more PCM_OP_STEP_NEXT opcodes follow, each retrieving the next specified number of result sets. PCM_OP_STEP_END must come last to end the step search.

Note:

Stepping backward through the result set is not supported.

When a step search is initiated, no other functions can be performed, including another step search, until the search cycle is completed. If a second PCM_OP_STEP_SEARCH opcode is sent to the database before a first has finished its search cycle, an error is returned to the client.

The search criteria are passed in by the client application on the input flist. The input flist must contain a POID, and its type must be /search. The POID is ignored. You must also include a PIN_FLD_RESULTS array that indicates which fields and how many matching results to return for this opcode.

In the PIN_FLD_RESULTS_LIMIT field, specify the maximum number of results to be returned from all steps of the search. The information from this field is conveyed to the database so that the search is executed more efficiently. If this field is not specified, all matching results are cached, even if they are not returned.

Important:

If the search uses an order by clause, the PIN_FLD_RESULTS_LIMIT field causes incorrect sorting. Do not use the PIN_FLD_RESULTS_LIMIT field if the search includes an order by clause.

Specify search arguments in the PIN_FLD_ARGS array on the input flist. Each element of the array contains one argument for the search. You must provide at least one argument. The maximum number of search arguments is 32. Indicate which argument is contained in an array element sub-flist by specifying the element ID. For example, element ID 1 corresponds to argument 1.

Search results can be manipulated by using the flist field handling macros. For a list of opcodes, see "Flist Field-Handling Macros" in BRM Developer's Reference.

To increase performance, use PCM_OPFLG_CACHEABLE. See "Improving Performance when Working with Objects".

Examples

For an example of input and return flists for step searching, see "Step Search Example".

For examples of input flists for complex searches, see "Complex Searches".

For a sample search program that searches for a single and multiple results, see BRM_Home/apps/sample/sample_search.c.

Getting the Next Set of Search Results from a Step Search

The PCM_OP_STEP_NEXT opcode enables a client application to receive the next set of results from a search initiated by PCM_OP_STEP_SEARCH. Results of the search are returned in discrete chunks.

This opcode must be used in combination with the PCM_OP_STEP_SEARCH and PCM_OP_STEP_END opcodes to complete the step search cycle. PCM_OP_STEP_SEARCH initiates step searching and gets the first set of PIN_FLD_RESULT elements. PCM_OP_STEP_NEXT goes to the DM and gets the next set of PIN_FLD_RESULT elements. PCM_OP_STEP_END ends the step search.

Use this opcode for each set of results to be returned. Specify the maximum number of records to return as the element ID of the PIN_FLD_RESULTS element. To return no records, use zero. PCM_OP_STEP_END can be called at any time to end the search.

This opcode uses the same input flist as PCM_OP_STEP_SEARCH.

To increase performance, use the PCM_OPFLG_CACHEABLE flag. See "Improving Performance when Working with Objects".

Ending a Step Search

To end a search result that has been initiated by PCM_OP_STEP_SEARCH, use the PCM_OP_STEP_END opcode.

This opcode must be used in combination with the PCM_OP_STEP_SEARCH and PCM_OP_STEP_NEXT opcodes to complete the step search cycle. PCM_OP_STEP_SEARCH initiates step searching and gets the first set of PIN_FLD_RESULT elements. PCM_OP_STEP_NEXT retrieves the next specified number of results. PCM_OP_STEP_END ends the step search.

Simple Search Example

The following example of a simple PCM_OP_SEARCH searches for each account whose status is active and retrieves all corresponding events created in the last week:

elem_id = 0;
cookie = (pin_cookie_t)NULL;
while ((acct_flistp = PIN_FLIST_ELEM_GET_NEXT(flistp,
                        PIN_FLD_RESULTS, &elem_id, 1, &cookie, ebufp))
                != (pin_flist_t *)NULL) {
  
/* get the status of the current account */
status = PIN_FLIST_FLD_GET(acct_flist, PIN_FLD_STATUS, 0, ebufp);
  
/* process accordingly, based on status */
switch (status) {
case PIN_STATUS_ACTIVE:
/* fetch events created in the last week */
fetch_last_weeks_events(cur_flist, ebufp);
break;
case PIN_STATUS_INACTIVE:
/* do something */
break;
default:
/* log an error */
break;
}
}

fetch_last_weeks_events(acct_flist, ebufp)
{
  /*
         * Create the search flist.
         */
        s_flistp = PIN_FLIST_CREATE(ebufp);
  
        /*
         * Create and add the search poid.
         */
        search_poidp = PIN_POID_CREATE((int64)0, "/search", (int64)-1, ebufp);
        PIN_FLIST_FLD_PUT(s_flistp, PIN_FLD_POID, (void *)search_poidp, ebufp);
  
        /*
         * Add the search template.
         */
        PIN_FLIST_FLD_PUT(s_flistp, PIN_FLD_TEMPLATE,
                (void *)"select X from /event where F1 = V1 and F2 > V2 ", ebufp);
  
        /*
         * Add the search arguments.
         */
        arg_flistp = PIN_FLIST_ELEM_ADD(s_flistp, PIN_FLD_ARGS, 1, ebufp);
        acct_poidp = PIN_FLIST_FLD_TAKE(acct_flist, PIN_FLD_POID, 0, ebufp);
        PIN_FLIST_FLD_PUT(arg_flistp, PIN_FLD_ACCOUNT_OBJ, acct_poidp, ebufp);
  
        arg_flistp = PIN_FLIST_ELEM_ADD(s_flistp, PIN_FLD_ARGS, 2, ebufp);
  one_week_ago = <timestamp corresponding to 1 week ago>;        
        PIN_FLIST_FLD_PUT(arg_flistp, PIN_FLD_CREATED_T, &one_week_ago, ebufp);
  
  
        /*
         * Fetch everything.
         */
        PIN_FLIST_FLD_PUT(s_flistp, PIN_FLD_RESULT, (void *)NULL, ebufp);
  
        /*
         * Do the search.
         */
        PCM_OP(pcm_ctxp, PCM_OP_SEARCH, PCM_OPFLG_READ_UNCOMMITTED,
                s_flistp, &r_flistp, ebufp);
  
/*
 * do something with the events we just fetched
 */
}

Step Search Example

The following example shows the results of a call to PCM_OP_STEP_SEARCH. This step search has four steps.

Note:

At the end of a step search, you do not receive a results array. You receive only your search POID, as shown at the end of this example.

Input flist:

0 PIN_FLD_POID               POID [0] 0.0.0.1 /search 0 0
0 PIN_FLD_TEMPLATE            STR [0] "select X from /account where F1 like V1 "
0 PIN_FLD_FLAGS               INT [0] 0
0 PIN_FLD_ARGS              ARRAY [1]
1   PIN_FLD_NAMEINFO        ARRAY [*]
2      PIN_FLD_FIRST_CANON    STR [0] "%"
0 PIN_FLD_RESULTS           ARRAY [4]
1   PIN_FLD_ACCOUNT_NO        STR [0] ""
  

Search results:

# number of field entries allocated 5, used 5
0 PIN_FLD_POID           POID [0] 0.0.0.1 /search 0 0
0 PIN_FLD_RESULTS       ARRAY [0] allocated 2, used 2
1   PIN_FLD_ACCOUNT_NO    STR [0] "ROOT.0.0.1"
1   PIN_FLD_POID         POID [0] 0.0.0.1 /account 1 1
0 PIN_FLD_RESULTS       ARRAY [1] allocated 2, used 2
1   PIN_FLD_ACCOUNT_NO    STR [0] "0.0.0.1-8759"
1   PIN_FLD_POID         POID [0] 0.0.0.1 /account 8759 133
0 PIN_FLD_RESULTS       ARRAY [2] allocated 2, used 2
1   PIN_FLD_ACCOUNT_NO    STR [0] "0.0.0.1-9267"
1   PIN_FLD_POID         POID [0] 0.0.0.1 /account 9267 122
0 PIN_FLD_RESULTS       ARRAY [3] allocated 2, used 2
1   PIN_FLD_ACCOUNT_NO    STR [0] "0.0.0.1-9961"
1   PIN_FLD_POID         POID [0] 0.0.0.1 /account 9961 128
  

Results of the calls to PCM_OP_STEP_NEXT:

# number of field entries allocated 5, used 5
0 PIN_FLD_POID            POID [0] 0.0.0.1 /search 0 0
0 PIN_FLD_RESULTS        ARRAY [0] allocated 2, used 2
1   PIN_FLD_ACCOUNT_NO     STR [0] "0.0.0.1-10709"
1   PIN_FLD_POID          POID [0] 0.0.0.1 /account 10709 53
0 PIN_FLD_RESULTS        ARRAY [1] allocated 2, used 2
1   PIN_FLD_ACCOUNT_NO     STR [0] "0.0.0.1-10721"
1   PIN_FLD_POID          POID [0] 0.0.0.1 /account 10721 98
0 PIN_FLD_RESULTS        ARRAY [2] allocated 2, used 2
1   PIN_FLD_ACCOUNT_NO     STR [0] "0.0.0.1-10881"
1   PIN_FLD_POID          POID [0] 0.0.0.1 /account 10881 134
0 PIN_FLD_RESULTS        ARRAY [3] allocated 2, used 2
1   PIN_FLD_ACCOUNT_NO     STR [0] "0.0.0.1-11057"
1   PIN_FLD_POID          POID [0] 0.0.0.1 /account 11057 122
  
# number of field entries allocated 5, used 5
0 PIN_FLD_POID            POID [0] 0.0.0.1 /search 0 0
0 PIN_FLD_RESULTS        ARRAY [0] allocated 2, used 2
1   PIN_FLD_ACCOUNT_NO     STR [0] "0.0.0.1-12047"
1   PIN_FLD_POID          POID [0] 0.0.0.1 /account 12047 75
0 PIN_FLD_RESULTS        ARRAY [1] allocated 2, used 2
1   PIN_FLD_ACCOUNT_NO     STR [0] "0.0.0.1-12213"
1   PIN_FLD_POID          POID [0] 0.0.0.1 /account 12213 123
0 PIN_FLD_RESULTS        ARRAY [2] allocated 2, used 2
1   PIN_FLD_ACCOUNT_NO     STR [0] "0.0.0.1-12241"
1   PIN_FLD_POID          POID [0] 0.0.0.1 /account 12241 122
0 PIN_FLD_RESULTS        ARRAY [3] allocated 2, used 2
1   PIN_FLD_ACCOUNT_NO     STR [0] "0.0.0.1-12356"
1   PIN_FLD_POID          POID [0] 0.0.0.1 /account 12356 39
  
# number of field entries allocated 5, used 5
0 PIN_FLD_POID            POID [0] 0.0.0.1 /search 0 0
0 PIN_FLD_RESULTS        ARRAY [0] allocated 2, used 2
1   PIN_FLD_ACCOUNT_NO     STR [0] "0.0.0.1-12484"
1   PIN_FLD_POID          POID [0] 0.0.0.1 /account 12484 45
0 PIN_FLD_RESULTS        ARRAY [1] allocated 2, used 2
1   PIN_FLD_ACCOUNT_NO     STR [0] "0.0.0.1-12569"
1   PIN_FLD_POID          POID [0] 0.0.0.1 /account 12569 8
0 PIN_FLD_RESULTS        ARRAY [2] allocated 2, used 2
1   PIN_FLD_ACCOUNT_NO     STR [0] "0.0.0.1-12590"
1   PIN_FLD_POID          POID [0] 0.0.0.1 /account 12590 19
0 PIN_FLD_RESULTS        ARRAY [3] allocated 2, used 2
1   PIN_FLD_ACCOUNT_NO     STR [0] "0.0.0.1-12612"
1   PIN_FLD_POID          POID [0] 0.0.0.1 /account 12612 12
  
# number of field entries allocated 5, used 5
0 PIN_FLD_POID            POID [0] 0.0.0.1 /search 0 0
0 PIN_FLD_RESULTS        ARRAY [0] allocated 2, used 2
1   PIN_FLD_ACCOUNT_NO     STR [0] "0.0.0.1-12697"
1   PIN_FLD_POID          POID [0] 0.0.0.1 /account 12697 8
0 PIN_FLD_RESULTS        ARRAY [1] allocated 2, used 2
1   PIN_FLD_ACCOUNT_NO     STR [0] "0.0.0.1-12705"
1   PIN_FLD_POID          POID [0] 0.0.0.1 /account 12705 14
0 PIN_FLD_RESULTS        ARRAY [2] allocated 2, used 2
1   PIN_FLD_ACCOUNT_NO     STR [0] "0.0.0.1-12740"
1   PIN_FLD_POID          POID [0] 0.0.0.1 /account 12740 54
0 PIN_FLD_RESULTS        ARRAY [3] allocated 2, used 2
1   PIN_FLD_ACCOUNT_NO     STR [0] "0.0.0.1-13090"
1   PIN_FLD_POID          POID [0] 0.0.0.1 /account 13090 38
  
# number of field entries allocated 5, used 5
0 PIN_FLD_POID            POID [0] 0.0.0.1 /search 0 0
0 PIN_FLD_RESULTS        ARRAY [0] allocated 2, used 2
1   PIN_FLD_ACCOUNT_NO     STR [0] "0.0.0.1-13346"
1   PIN_FLD_POID          POID [0] 0.0.0.1 /account 13346 45
0 PIN_FLD_RESULTS        ARRAY [1] allocated 2, used 2
1   PIN_FLD_ACCOUNT_NO     STR [0] "0.0.0.1-13476"
1   PIN_FLD_POID          POID [0] 0.0.0.1 /account 13476 48
0 PIN_FLD_RESULTS        ARRAY [2] allocated 2, used 2
1   PIN_FLD_ACCOUNT_NO     STR [0] "0.0.0.1-13732"
1   PIN_FLD_POID          POID [0] 0.0.0.1 /account 13732 66
0 PIN_FLD_RESULTS        ARRAY [3] allocated 2, used 2
1   PIN_FLD_ACCOUNT_NO     STR [0] "0.0.0.1-13956"
1   PIN_FLD_POID          POID [0] 0.0.0.1 /account 13956 84
  
# number of field entries allocated 5, used 5
0 PIN_FLD_POID               POID [0] 0.0.0.1 /search 0 0
0 PIN_FLD_RESULTS           ARRAY [0] allocated 2, used 2
1   PIN_FLD_ACCOUNT_NO        STR [0] "0.0.0.1-14313"
1   PIN_FLD_POID             POID [0] 0.0.0.1 /account 14313 8
0 PIN_FLD_RESULTS           ARRAY [1] allocated 2, used 2
1   PIN_FLD_ACCOUNT_NO        STR [0] "0.0.0.1-14825"
1   PIN_FLD_POID             POID [0] 0.0.0.1 /account 14825 8
0 PIN_FLD_RESULTS           ARRAY [2] allocated 2, used 2
1   PIN_FLD_ACCOUNT_NO        STR [0] "0.0.0.1-14896"
1   PIN_FLD_POID             POID [0] 0.0.0.1 /account 14896 70
0 PIN_FLD_RESULTS           ARRAY [3] allocated 2, used 2
1   PIN_FLD_ACCOUNT_NO        STR [0] "0.0.0.1-15069"
1   PIN_FLD_POID             POID [0] 0.0.0.1 /account 15069 12
  
# number of field entries allocated 5, used 5
0 PIN_FLD_POID             POID [0] 0.0.0.1 /search 0 0
0 PIN_FLD_RESULTS         ARRAY [0] allocated 2, used 2
1   PIN_FLD_ACCOUNT_NO      STR [0] "0.0.0.1-15129"
1   PIN_FLD_POID           POID [0] 0.0.0.1 /account 15129 8
0 PIN_FLD_RESULTS         ARRAY [1] allocated 2, used 2
1   PIN_FLD_ACCOUNT_NO      STR [0] "0.0.0.1-15257"
1   PIN_FLD_POID           POID [0] 0.0.0.1 /account 15257 8
0 PIN_FLD_RESULTS         ARRAY [2] allocated 2, used 2
1   PIN_FLD_ACCOUNT_NO      STR [0] "0.0.0.1-15385"
1   PIN_FLD_POID           POID [0] 0.0.0.1 /account 15385 8
0 PIN_FLD_RESULTS         ARRAY [3] allocated 2, used 2
1   PIN_FLD_ACCOUNT_NO      STR [0] "0.0.0.1-15824"
1   PIN_FLD_POID           POID [0] 0.0.0.1 /account 15824 68
  

Final set of search results:

# number of field entries allocated 1, used 1
0 PIN_FLD_POID              POID [0] 0.0.0.1 /search 0 0

Note:

You do not receive a results array with the last call to PCM_OP_STEP_NEXT because there are no more search results. You call PCM_OP_STEP_END to finish the search.

Results of the call to PCM_OP_STEP_END:

# number of field entries allocated 3, used 3
0 PIN_FLD_POID              POID [0] 0.0.0.1 /search 0 0
0 PIN_FLD_ARGS             ARRAY [1] allocated 1, used 1
1   PIN_FLD_NAMEINFO       ARRAY [0] allocated 1, used 1
2      PIN_FLD_FIRST_CANON   STR [0] "%"
0 PIN_FLD_RESULTS          ARRAY [4] allocated 1, used 1
1   PIN_FLD_ACCOUNT_NO       STR [0] ""

Performing Exact Searches

To search and return array elements, you use an exact search. Exact searches enable you to limit results to only the array elements that match the search criteria.

If your search includes a where clause and you want that clause to be applied to array elements, use the SRCH_EXACT (512) flag with the PCM_OP_SEARCH and PCM_OP_STEP_SEARCH opcodes. If you do not use the SRCH_EXACT flag, the where clause is applied to the object and not limited to array elements that match the search criteria within that object. The results, therefore, include all items in the object instead of only those items in the array that match your search criteria.

For example, suppose you want to search for all /rate objects with general ledger IDs greater than 0 and element IDs less than 1001. Without the SRCH_EXACT flag, the input flist looks like this:

0 PIN_FLD_POID                     POID [0] 0.0.0.1 /search 0 0
0 PIN_FLD_TEMPLATE                  STR [0] "select X from /rate where F1 > V1 and F2 < V2 "
0 PIN_FLD_FLAGS                     INT [0] 256
  
0 PIN_FLD_ARGS                    ARRAY [1] allocated 20, used 1
1   PIN_FLD_QUANTITY_TIERS        ARRAY [0] allocated 20, used 1
2      PIN_FLD_BAL_IMPACTS        ARRAY [0] allocated 20, used 1
3         PIN_FLD_GL_ID             INT [0] 0
  
0 PIN_FLD_ARGS                    ARRAY [2] allocated 20, used 1
1   PIN_FLD_QUANTITY_TIERS        ARRAY [0] allocated 20, used 1
2      PIN_FLD_BAL_IMPACTS        ARRAY [0] allocated 20, used 1
3         PIN_FLD_ELEMENT_ID        INT [0] 1001
  
0 PIN_FLD_RESULTS                 ARRAY [0] allocated 20, used 1
1   PIN_FLD_QUANTITY_TIERS        ARRAY [0] allocated 20, used 1
2      PIN_FLD_BAL_IMPACTS        ARRAY [0] allocated 20, used 2
3         PIN_FLD_ELEMENT_ID        INT [0] 0
3         PIN_FLD_GL_ID             INT [0] 0
  

The output flist might look like this:

0 PIN_FLD_POID                    POID [0] 0.0.0.1 /search 0 0
  
0 PIN_FLD_RESULTS                ARRAY [0]allocated 2, used 2
1   PIN_FLD_POID                  POID [0] 0.0.0.1 /rate 8257 1
1   PIN_FLD_QUANTITY_TIERS       ARRAY [0] allocated 1, used 1
2      PIN_FLD_BAL_IMPACTS       ARRAY [0] allocated 2, used 2
3         PIN_FLD_ELEMENT_ID       INT [0] 978
3         PIN_FLD_GL_ID            INT [0] 13000001
  
0 PIN_FLD_RESULTS                ARRAY [1] allocated 2, used 2
1   PIN_FLD_POID                  POID [0] 0.0.0.1 /rate 8321 1
1   PIN_FLD_QUANTITY_TIERS       ARRAY [0] allocated 1, used 1
2      PIN_FLD_BAL_IMPACTS       ARRAY [0] allocated 2, used 2
3         PIN_FLD_ELEMENT_ID       INT [0] 978
3         PIN_FLD_GL_ID            INT [0] 12000065
  
0 PIN_FLD_RESULTS                ARRAY [3] allocated 2, used 2
1   PIN_FLD_POID                  POID [0] 0.0.0.1 /rate 8702 1
1   PIN_FLD_QUANTITY_TIERS       ARRAY [0] allocated 1, used 1
2      PIN_FLD_BAL_IMPACTS       ARRAY [0] allocated 2, used 2
3         PIN_FLD_ELEMENT_ID       INT [0] 978
3         PIN_FLD_GL_ID            INT [0] 1000001
  
0 PIN_FLD_RESULTS                ARRAY [2] allocated 2, used 2
1   PIN_FLD_POID                  POID [0] 0.0.0.1 /rate8446 1
1   PIN_FLD_QUANTITY_TIERS       ARRAY [0] allocated 1, used 1
2      PIN_FLD_BAL_IMPACTS       ARRAY [0] allocated 2, used 2
3         PIN_FLD_ELEMENT_ID       INT [0] 1000006
3         PIN_FLD_GL_ID            INT [0] 51000001
  

Note:

The last result is incorrect; the element ID is greater than 1001. Incorrect results such as this occur because the search finds all the objects that match the condition in the where clause but does not apply that clause to the array elements.

If you use SRCH_EXACT by entering a flag value of 512, the input flist looks like this:

0 PIN_FLD_POID                      POID [0] 0.0.0.1 /search 0 0
  
0 PIN_FLD_TEMPLATE                   STR [0] "select X from /rate where F1 > V1 and F2 < V2 "
  
0 PIN_FLD_FLAGS                      INT [0] 512
  
0 PIN_FLD_ARGS                     ARRAY [1] allocated 20, used 1
1   PIN_FLD_QUANTITY_TIERS         ARRAY [0] allocated 20, used 1
2      PIN_FLD_BAL_IMPACTS         ARRAY [0] allocated 20, used 1
3         PIN_FLD_GL_ID              INT [0] 0
  
0 PIN_FLD_ARGS                     ARRAY [2] allocated 20, used 1
1   PIN_FLD_QUANTITY_TIERS         ARRAY [0] allocated 20, used 1
2      PIN_FLD_BAL_IMPACTS         ARRAY [0] allocated 20, used 1
3         PIN_FLD_ELEMENT_ID         INT [0] 1001
  
0 PIN_FLD_RESULTS                  ARRAY [0] allocated 20, used 1
1   PIN_FLD_QUANTITY_TIERS         ARRAY [0] allocated 20, used 1
2      PIN_FLD_BAL_IMPACTS         ARRAY [0] allocated 20, used 2
3         PIN_FLD_ELEMENT_ID         INT [0] 0
3         PIN_FLD_GL_ID              INT [0] 0 
  

The output flist might look like this:

0 PIN_FLD_POID                     POID [0] 0.0.0.1 /search 0 0
  
0 PIN_FLD_RESULTS                 ARRAY [0]allocated 2, used 2
1   PIN_FLD_POID                   POID [0] 0.0.0.1 /rate 8257 1
1   PIN_FLD_QUANTITY_TIERS        ARRAY [0] allocated 1, used 1
2      PIN_FLD_BAL_IMPACTS        ARRAY [0] allocated 2, used 2
3         PIN_FLD_ELEMENT_ID        INT [0] 978
3         PIN_FLD_GL_ID             INT [0] 13000001
  
0 PIN_FLD_RESULTS                 ARRAY [1] allocated 2, used 2
1   PIN_FLD_POID                   POID [0] 0.0.0.1 /rate 8321 1
1   PIN_FLD_QUANTITY_TIERS        ARRAY [0] allocated 1, used 1
2      PIN_FLD_BAL_IMPACTS        ARRAY [0] allocated 2, used 2
3         PIN_FLD_ELEMENT_ID        INT [0] 978
3         PIN_FLD_GL_ID             INT [0] 12000065
  
0 PIN_FLD_RESULTS                 ARRAY [2] allocated 2, used 2
1   PIN_FLD_POID                   POID [0] 0.0.0.1 /rate 8702 1
1   PIN_FLD_QUANTITY_TIERS        ARRAY [0] allocated 1, used 1
2      PIN_FLD_BAL_IMPACTS        ARRAY [0] allocated 2, used 2
3         PIN_FLD_ELEMENT_ID        INT [0] 978
3         PIN_FLD_GL_ID             INT [0] 1000001
  

Note:

This search returns only objects that satisfy both parts of the where clause. Spurious results are eliminated.

Using "like" with Exact Searches

You use a like operator with an exact search to return all elements of an array that match the search criteria.

The following example returns all arrays from /account that contain any string in the PIN_FLD_FIRST_CANNON field:

0 PIN_FLD_POID              POID [0] 0.0.0.1 /search -1 0
0 PIN_FLD_TEMPLATE           STR [0] "select X from /account where F1 like V1 "
0 PIN_FLD_ARGS             ARRAY [1]
1   PIN_FLD_NAMEINFO       ARRAY [*]
2      PIN_FLD_FIRST_CANON   STR [0] "%"
0 PIN_FLD_RESULTS          ARRAY [*] NULL array ptr

Exact Search Limitations

When performing a complex search (searching across multiple objects), using an array element as a join column is not supported with exact searches. In the where clause, trying to match a value in one table with a value in another table can return results that do not match your search criteria.

For example, to find all products in an account with a product name that begins with the string "Pr", you might use the following query:

"select X from /account 1, /product 2 where 1.F1 = V1 and 1.F2 = 2.F3 and 2.F4 like V4 "
  

Where the arguments array is:

0 PIN_FLD_ARGS               ARRAY [1] allocated 20, used 1
1   PIN_FLD_POID              POID [0] 0.0.0.1 /account 12345
0 PIN_FLD_ARGS               ARRAY [2] allocated 20, used 1
1   PIN_FLD_PRODUCTS         ARRAY [0]
2      PIN_FLD_PRODUCT_OBJ    POID [0] NULL
0 PIN_FLD_ARGS               ARRAY [3] allocated 20, used 1
1   PIN_FLD_POID              POID [0] NULL
0 PIN_FLD_ARGS               ARRAY [4] allocated 20, used 1
1   PIN_FLD_NAME                STR [0] "Pr%"
  

However, with an exact search, "1.F2 = 2.F3" in the where clause causes the search to return all products in the account if at least one product name starts with the string "Pr".

An alternative to using an array element as a join column with exact searches is to perform two separate searches and then compare the search results for matching data. In the above example, you search /product for products that begin with "Pr" and then perform the preceding search as shown to return all products for the /account. Then, for each POID in the /product list, iterate through the /account products list to find the matching products.

Complex Searches

You can perform a complex search across multiple objects by including each object in the object_name section of the PIN_FLD_TEMPLATE string.

In a simple search, when a client wants a list of all events pertaining to deal purchases, the client must perform two searches:

  • Get all deal POIDs (with the deal names).

  • Search on the event class (and subclasses) with each of the deal POIDs obtained from the previous search for the required event fields.

A complex search eliminates the need for cascading searches and enables the client to issue one complex search instead of multiple simple searches.

Note:

The search results include only the fields from the first class in the query.

Use the following rules when creating a complex search template:

  • When connecting separate objects types (1.F3 = 2.F4), explicitly specify the join clause as part of the template by using the form X.Fm = Y.Fn.

  • Fm and Fn must have a value specified as a NULL pointer in the PIN_FLD_ARGS array.

  • When you use an order by clause (which can be included when you have a where clause), set the SRCH_DISTINCT flag to 0.

  • A maximum of six separate objects is allowed in a complex search template.

The following example shows the template syntax to retrieve all deal-purchase events:

"select X from /event/billing/deal 1, /deal 2 where (2.F1 Like V1 and 2.F2 != V2 and 1.F3 = 2.F4 ) order by 3.F5 "

Note:

There are no stored templates available for complex searches.

Complex Search Example

The following example searches for all deal purchase events.

Input flist:

# number of field entries allocated 5, used 5
0 PIN_FLD_RESULTS           ARRAY [10]
1   PIN_FLD_SYS_DESCR         STR [0] NULL str ptr
1   PIN_FLD_ACCOUNT_OBJ      POID [0] NULL poid pointer
1   PIN_FLD_POID             POID [0] NULL poid pointer
1   PIN_FLD_END_T          TSTAMP [0] (0) <null>
0 PIN_FLD_ARGS              ARRAY [1]
1   PIN_FLD_NAME              STR [0] "%"
0 PIN_FLD_ARGS              ARRAY [2]
1   PIN_FLD_POID             POID [0] 0.0.0.1 /deal 0 0
0 PIN_FLD_ARGS              ARRAY [3]
1   PIN_FLD_DEAL_INFO   SUBSTRUCT [0]
2      PIN_FLD_DEAL_OBJ      POID [0] NULL poid pointer
0 PIN_FLD_ARGS              ARRAY [4]
1   PIN_FLD_POID             POID [0] NULL poid pointer
0 PIN_FLD_TEMPLATE             STR [0] "select X from /event/billing/deal 1, /deal 2  where ( 2.F1 Like V1 and 2.F2 != V2 and 1.F3 = 2.F4 ) "
0 PIN_FLD_FLAGS               INT [0] 256
0 PIN_FLD_POID               POID [0] 0.0.0.1 /search -1 0

Search without POID

Use the SEARCH_WITHOUT_POID (1024) flag to return data without the POID for each result. To do this, set the value to 1024.

Without the SRCH_WITHOUT_POID flag set, the input flist looks like this:

0 PIN_FLD_POID           POID [0] 0.0.0.1 /search -1 0
0 PIN_FLD_TEMPLATE       STR [0] "select X from /event where F1 like V1 "
0 PIN_FL0 PIN_FLD_ARGS   ARRAY [1] allocated 20, used 1D_FLAGS INT [0] 0
1 PIN_FLD_POID          POID [0] 0.0.0.1 /event/session -1 0
0 PIN_FLD_RESULTS       ARRAY [4] allocated 20, used 1
1 PIN_FLD_ACCOUNT_OBJ    POID [0] 0.0.0.1 /account 1 0
  

The output flist might look like this:

0 PIN_FLD_POID           POID [0] 0.0.0.1 /search -1 0
0 PIN_FLD_RESULTS        ARRAY [0] allocated 20, used 2
1 PIN_FLD_ACCOUNT_OBJ    POID [0] 0.0.0.1 /account 1 0
1 PIN_FLD_POID           POID [0] 0.0.0.1 /event/session 252887674388488909 1
0 PIN_FLD_RESULTS        ARRAY [1] allocated 20, used 2
1 PIN_FLD_ACCOUNT_OBJ    POID [0] 0.0.0.1 /account 1 0
1 PIN_FLD_POID           POID [0] 0.0.0.1 /event/session 252887674388490957 1
0 PIN_FLD_RESULTS        ARRAY [2] allocated 20, used 2
1 PIN_FLD_ACCOUNT_OBJ    POID [0] 0.0.0.1 /account 1 0
1 PIN_FLD_POID           POID [0] 0.0.0.1 /event/session 252887674388489103 1
0 PIN_FLD_RESULTS        ARRAY [3] allocated 20, used 2
1 PIN_FLD_ACCOUNT_OBJ    POID [0] 0.0.0.1 /account 1 0
1 PIN_FLD_POID            POID [0] 0.0.0.1 /event/session 252887674388491981 1
  

With the SRCH_WITHOUT_POID flag set, the input flist looks like this:

0 PIN_FLD_POID           POID [0] 0.0.0.1 /search -1 0
0 PIN_FLD_TEMPLATE       STR [0] "select X from /event where F1 like V1 "
0 PIN_FLD_FLAGS          INT [0] 1024
0 PIN_FLD_ARGS           ARRAY [1] allocated 20, used 1
1 PIN_FLD_POID           POID [0] 0.0.0.1 /event/session -1 0
0 PIN_FLD_RESULTS        ARRAY [4] allocated 20, used 1
1 PIN_FLD_ACCOUNT_OBJ     POID [0] 0.0.0.1 /account 1 0
  

The output flist might look like this:

0 PIN_FLD_POID           POID [0] 0.0.0.1 /search -1 0
0 PIN_FLD_RESULTS       ARRAY [0] allocated 20, used 1
1 PIN_FLD_ACCOUNT_OBJ    POID [0] 0.0.0.1 /account 1 0
0 PIN_FLD_RESULTS       ARRAY [1] allocated 20, used 1
1 PIN_FLD_ACCOUNT_OBJ    POID [0] 0.0.0.1 /account 1 0
0 PIN_FLD_RESULTS       ARRAY [2] allocated 20, used 1
1 PIN_FLD_ACCOUNT_OBJ    POID [0] 0.0.0.1 /account 1 0
0 PIN_FLD_RESULTS       ARRAY [3] allocated 20, used 1
1 PIN_FLD_ACCOUNT_OBJ    POID [0] 0.0.0.1 /account 1 0

About Multischema (Global) Searches

BRM includes an alternative set of opcodes designed for use with multiple database schemas. Global searches on multiple schemas are similar to searches on a single schema with two main differences:

  • No database number is specified in the search POID.

  • The PCM_OP_GLOBAL_SEARCH opcode is called instead of the PCM_OP_SEARCH opcode.

Use PCM_OP_SEARCH and the other single-schema search opcodes whenever you can because single-schema searches are the most efficient. A global search is expensive because it is performed synchronously. It opens a context to each schema and waits for all results to be returned before merging the results.

Important:

  • BRM does not support using global searches when transactions are open.

  • Single-schema searches are useful only when you know the database number of the schema. If you do not know the specific schema to search, you must use a global search.

For more information, see the following opcodes:

Performing a Global Search

To perform a global search, use the PCM_OP_GLOBAL_SEARCH opcode. This opcode searches for storable objects across multiple database schemas.

This opcode enables a client application to search for storable objects that meet a set of criteria defined by the client application. Use this opcode when you do not know enough about the target object to specify its database schema. If you do know the specific schema to search, use PCM_OP_SEARCH instead.

The input flist contains a search template for a storable object in the database. The element ID of the PIN_FLD_ARGS element on the input flist specifies which argument is contained on its sub-flist. The maximum number of search arguments is 32.

The output flist is a list of storable objects that meet the search criteria. An array of PIN_FLD_RESULTS elements is returned, one for each storable object that was matched.

If one or more schemas are returning errors, those schemas are excluded from the search, and this opcode continues the search across the rest of the schemas. Errors that cause this exclusion include the following:

  • A PCP context cannot be opened.

  • A socket cannot be opened to a DM.

  • A DM connection cannot be set to asynchronous mode.

  • A send operation to the DM fails.

  • A receive operation from the DM fails.

If the value of the PIN_FLD_RESULTS element on the input flist is NULL, each element of the returned array contains all the fields from the matched storable object.

If the PIN_FLD_RESULTS element on the input flist contains a sub-flist with fields, only those fields specified are returned for each of the matched storable objects.

You can manipulate the search results using the Flist Field Handling Macros. See the "Flist Field-Handling Macros" in BRM Developer's Reference.

Limitations

The PCM_OP_GLOBAL_SEARCH opcodes cannot do the following:

  • Perform ORDER-BY searches

  • Use the PCM_OPFLG_CALC_ONLY parameter

Transaction Cache

To improve performance, set the PCM_OPFLG_CACHEABLE flag.

Before the start of any search opcode, the Connection Manager (CM) writes into the database all objects that are in writable cache, have changed during the transaction, and are the same object type as the expected results of the search.

See "Improving Performance when Working with Objects".

Examples

See the sample test program sample_search.c in BRM_Home/apps/sample. This program includes examples of the following:

  • A read storable object search with a single result expected

  • A read fields search with multiple results expected

Performing a Global Step Search

To perform a global step search, use the PCM_OP_GLOBAL_STEP_SEARCH opcode. This opcode step searches for storable objects across multiple BRM database schemas. This opcode enables a client application to define search criteria, search for storable objects using that criteria, and receive a specified number of result sets.

Note:

If you are searching for an object in a known database schema, use PCM_OP_STEP_SEARCH instead.

Important:

When you perform a global step search, follow best practices and call PCM_OP_GLOBAL_STEP_SEARCH before you call PCM_OP_GLOBAL_STEP_END. Calling PCM_OP_GLOBAL_STEP_END in the incorrect sequence might cause the CM to crash.

The search criteria are passed in by the client application in the form of a PCM_OP_GLOBAL_SEARCH input flist. The input flist contains a search template for a storable object in the database. The element ID of the PIN_FLD_ARGS element on the input flist specifies which argument is contained on its sub-flist. The maximum number of search arguments is 32.

Be careful when you pass in the search criteria.

  • If you have n schemas and ask for m results, (n x m) results are fetched. Any extra results are cached in memory in the CM.

  • A global search on n schemas opens n sockets, which could adversely affect performance.

PCM_OP_GLOBAL_STEP_SEARCH only initiates step searching and gets the first set of PIN_FLD_RESULT elements. PCM_OP_GLOBAL_STEP_NEXT retrieves the next specified number of results, and PCM_OP_GLOBAL_STEP_END ends the step search.

Note:

Stepping backward through the result set is not supported.

No shared memory is allocated in the DM for the results until PCM_OP_GLOBAL_STEP_NEXT gets a part of the result set. When PCM_OP_GLOBAL_STEP_END ends the search, the shared memory is freed. An array of PIN_FLD_RESULTS elements is returned, one for each storable object that was matched.

If the value of the PIN_FLD_RESULTS element on the input flist is NULL, each element of the returned array contains all the fields from the matched storable object.

If the PIN_FLD_RESULTS element on the input flist contains a sub-flist with fields, only the specified fields are returned for each of the matched storable objects.

The array size of PIN_FLD_RESULTS determines the number of PIN_FLD_RESULT elements to return to the client.

An error is returned to the client if two PCM_OP_GLOBAL_STEP_SEARCH opcodes are sent to the server. If the client is in the middle of a step search, the first search must be ended before another is initiated.

This opcode uses the same input and output flists as PCM_OP_GLOBAL_SEARCH.

Transaction Cache

To improve performance, set the PCM_OPFLG_CACHEABLE flag.

Before the start of any search opcode, the CM writes into the database all objects that are in writable cache, have changed during the transaction, and are the same object type as the expected results of the search.

See "Improving Performance when Working with Objects".

Examples

The BRM_Home/apps/sample/sample_search.c file contains example step searching code.

Getting the Next Set of Search Results from a Global Step Search

To get the next set of search results, use the PCM_OP_GLOBAL_STEP_NEXT opcode.

This opcode enables a client application to receive the next set of results from a search initiated by PCM_OP_GLOBAL_STEP_SEARCH.

The PCM_OP_GLOBAL_STEP_SEARCH opcode determines the criteria for the search, sets the size of the results, and initiates the search. See that opcode for details. This opcode only receives results; it does not perform the search. PCM_OP_GLOBAL_STEP_END ends the step search, freeing the database cursor and returning any shared memory allocated for the results by the DM.

This opcode returns the results of the search in discrete chunks. That is, it goes to the DM and gets the next set of PIN_FLD_RESULT elements. You determine the size of this result set by using the PIN_FLD_RESULTS field on the input flist.

You can manipulate the search results by using the flist field handling macros. See "Flist Field-Handling Macros" in BRM Developer's Reference.

This opcode uses the same input and output flists as PCM_OP_GLOBAL_SEARCH.

Transaction Cache

To improve performance, set the PCM_OPFLG_CACHEABLE flag.

Before the start of any search opcode, the CM writes into the database all objects that are in writable cache, have changed during the transaction, and are the same object type as the expected results of the search.

See "Improving Performance when Working with Objects".

Example

The BRM_Home/apps/sample/sample_search.c file contains example step searching code.

Ending a Global Step Search

To end a global step search, use the PCM_OP_GLOBAL_STEP_END opcode. This opcode ends global step searching that has been initiated by PCM_OP_GLOBAL_STEP_SEARCH.

PCM_OP_GLOBAL_STEP_SEARCH sets the criteria for a step search, sets the size of the results, and initiates the search. See that opcode for details. PCM_OP_GLOBAL_STEP_NEXT only receives results; it does not do a search. This opcode ends the step search, freeing the database cursor and returning any shared memory allocated for the results by the DM.

This opcode uses the same input and output flists as PCM_OP_GLOBAL_SEARCH.

The BRM_Home/apps/sample/sample_search.c file contains example step-searching code.

Global Search Example

This example searches for all accounts with a billing cycle of 6 months:

/*
* Create the search flist.
*/
s_flistp = PIN_FLIST_CREATE(ebufp);
  
/*
* Create and add the search poid.
*/
search_poidp = PIN_POID_CREATE((int64)0, "/search", (int64)-1, ebufp);
PIN_FLIST_FLD_PUT(s_flistp, PIN_FLD_POID, (void *)search_poidp, ebufp);
  
/*
* Add the search template.
*/
PIN_FLIST_FLD_PUT(s_flistp, PIN_FLD_TEMPLATE,
        (void *)"select X from /account where F1 = V1 ", ebufp);
  
/*
* Add the search argument.
*/
arg_flistp = PIN_FLIST_ELEM_ADD(s_flistp, PIN_FLD_ARGS, 1, ebufp);
num_monthly_cycles = 6;
PIN_FLIST_FLD_PUT(arg_flistp, PIN_FLD_BILL_WHEN,
        (void *)&num_monthly_cycles, ebufp);
  
/*
* Add the results we want to fetch.
*/
rslt_flistp = PIN_FLIST_ELEM_ADD(s_flistp, PIN_FLD_RESULTS, 0, ebufp);
PIN_FLIST_FLD_PUT(rslt_flistp, PIN_FLD_POID, (void *)NULL, ebufp);
PIN_FLIST_FLD_PUT(rslt_flistp, PIN_FLD_ACCOUNT_NO, (void *)NULL, ebufp);
PIN_FLIST_FLD_PUT(rslt_flistp, PIN_FLD_STATUS, (void *)NULL, ebufp);
  
/*
* Do the search.
*/
PCM_OP(ctxp->pcm_ctxp, PCM_OP_GLOBAL_SEARCH, PCM_OPFLG_READ_UNCOMMITTED,
        s_flistp, &r_flistp, ebufp);

Building the POID for the Input Flist

With multiple database schemas, all billing information, such as bill items and events for an account, must be in the same schema where the account is located. A common algorithm includes finding the POID for a BRM account object and then searching for additional data that is directly related to that account, such as bill items and events.

When building the PIN_FLD_POID (FldPoid.getInst() in Java) for the opcode input flist, it is common to use the database number of the login context. This does not work for multiple schemas. Instead, build the PIN_FLD_POID for the search input flist by using the database number from the account POID.

Building POID for the Input Flist in C

void FindBillItemsForAnAccount(pcm_context_t* pContext, poid_t* pAcctPoid)
{
// Start building the search input FList.
  
// Obsolete way:
int64 ContextDB = pin_poid_get_db(pcm_get_userid(pContext)); 
poid_t* pSearchPoid = PINApp::PoidCreate( ContextDB, _T("/search"), 0, &ebufp ); 
  
// Right way:
poid_t* pSearchPoid = PINApp::PoidCreate( pin_poid_get_db(pAcctPoid), _T("/search"), 0, &ebufp ); 
.
.
}

Building POID for the Input Flist in Java

void FindBillItemsForAnAccount(PortalContext connection, Poid acctPoid)
{
// Start building the search input FList.
  
// Obsolete way:
Poid searchPoid = new Poid( connection.getCurrentDB(), 0, "/search" ); 
  
// Right way:
Poid searchPoid = new Poid( acctPoid.getDb(), 0, "/search" ); 
.
.
}

The Impact of Searches on Shared Memory Allocation

For information about the shared memory implications of searching using PCM_OP_SEARCH or PCM_OP_GLOBAL_SEARCH, see "How BRM Allocates Shared Memory for Searches" in BRM System Administrator's Guide.

Improving Search Performance

Search operations often constitute most of the activity in the BRM database. When appropriate, it is a good idea to use the following techniques to improve search performance.

Step Search Limits

You can improve search performance by limiting the size of search results.

You can specify the maximum number of objects to be returned for the entire step search (that is, for all steps of the search) by specifying the optional PIN_FLD_RESULTS_LIMIT field in the input flist of the following opcodes:

  • PCM_OP_SEARCH

  • PCM_OP_GLOBAL_SEARCH

  • PCM_OP_STEP_SEARCH

  • PCM_OP_GLOBAL_STEP_SEARCH

In the PCM_OP_SEARCH and PCM_OP_GLOBAL_SEARCH opcodes, PIN_FLD_RESULTS_LIMIT 100 has the same effect as PIN_FLD_RESULTS [100].

This information helps the RDBMS execute the search more efficiently.

Note:

This limit does not apply to any search that uses an order by clause. It also does not apply to the PCM_OP_STEP_NEXT or PCM_OP_GLOBAL_STEP_NEXT opcodes.

Limiting the size of search results helps the database to process the query more efficiently because it can stop processing as soon as it has fetched the required number of results. For example, if a search yields 4,000,000 qualifying results, PIN_FLD_RESULTS_LIMIT 100 stops the processing after 100 matching results are found, so only a small subset of the data is scanned.

Transaction Caching

You can improve performance by caching transactions. Without caching, search operations can search the same data object repeatedly within one transaction. By letting the CM cache transactions, you eliminate this redundancy and speed transaction processing. See "Improving Performance when Working with Objects".