Known issues for database protocols
This section describes troubleshooting and limitations for database protocols.
Tip: For general troubleshooting and limitations, see Known issues.
Troubleshooting all database protocols
Evaluating error codes
When a Vuser executes an LRD function, the function generates a return code. A return code of 0 indicates that the function succeeded. For example, a return code of 0 indicates that another row is available from the result set. If an error occurs, the return code indicates the type of error. For example, a return code of 2014 indicates that an error occurred in the initialization.
There are four types of return codes, each represented by a numerical range:
Type of Return Code
|
Range
|
---|---|
Informational
|
0 to 999
|
Warning
|
1000 to 1999
|
Error
|
2000 to 2999
|
Internal Error
|
5000 to 5999
|
For more detailed information on the return codes, see the Function Reference.
You can evaluate the return code of an LRD function to determine if the function succeeded. The following script segment evaluates the return code of an lrd_fetch function:
static int rc; rc=lrd_fetch(Csr15, -13, 0, 0, PrintRow4, 0); if (rc==0) lr_output_message("The function succeeded"); else lr_output_message("The function returned an error code:%d",rc);
Two-tier database scripting tips
The following section offers solutions for two-tier database scripts.

Answer: The failure may be a result of trailing spaces in your data values. Even though the data values that you type directly into the GUI are probably truncated, you should manually eliminate them from your data file. Tab-delimited files can hide trailing spaces and therefore obscure problems. In general, comma-delimited files are recommended. You can view the files in Excel to see if things are correct.

Answer: The lrd_close_cursor function may not have been generated or it may be in the end section instead of the action section. You need to add a cursor close function or move it from the end section to make the script iterate successfully.
Opening a new cursor may be costly in terms of resources. Therefore, we recommend that you only open a cursor once in the actions section during the first iteration. You can then add a new parameter that contains the iteration number as a string by using the Iteration Number type. Call this parameter IterationNum. Then, inside the actions section replace a call to open a new cursor, for example,
lrd_open_cursor(=;Csr1, Con1, 0);
with
if (!strcmp(lr_eval_string("<IterationNum>"), "1"))
lrd_open_cursor(=;Csr1, Con1, 0);

Answer: The problem, most likely, is an SQL data type that is not supported by VuGen. For Microsoft SQL, you can often work around this issue by replacing the undefined error message in vdf.h with "DT_SZ" (null terminated string). Although this is not the actual datatype, VuGen can compile the script correctly. Please report the problem and send the original script to customer support.

Answer: VuGen is failing because it is trying to bind a variable with a longer length than what was allocated during recording. You can correct this by enlarging the variable definition in vdf.h to receive a longer string back from the database. Search this file for the unique numeric identifier. You can see its definition and length. The length is the third element in the structure. Increase this length as required and the script will replay successfully.
For example:
lrd_assign(=;_2_D354, "<ROW_ID>", 0, 0, 0);
In vdf.h, search for _2_D354 and find this:
static LRD_VAR_DESC _2_D354 = {
LRD_VAR_DESC_EYECAT, 1, 10, LRD_BYTYPE_ODBC,
{0 ,0, 0}, DT_SZ, 0, 0, 15, 12};
Change it to:
static LRD_VAR_DESC _2_D354 = {
LRD_VAR_DESC_EYECAT, 1, 12, LRD_BYTYPE_ODBC,
{0,, 0}, DT_SZ, 0, 0, 15, 12};
The complete definition of LRD_VAR_DESC appears in lrd.h. You can find it by searching for typedef struct LRD_VAR_DESC
.

UPDATE
, INSERT
or DELETE
when using ODBC and Oracle?
Answer: You can use lrd functions to obtain this information. For ODBC, use lrd_row_count. The syntax is:
int rowcount;
.
.
.
lrd_row_count(Csr33, =;rowcount, 0);
Note that lrd_row_count must immediately follow the pertinent statement execution.
For Oracle you can use the fourth argument of lrd_exec.
lrd_exec(Csr19, 1, 0, =;rowcount, 0, 0);
If you are using Oracle's OCI 8, you can use the fifth argument of lrd_ora8_exec.
lrd_ora8_exec(OraSvc1, OraStm3, 1, 0, =;uliRowsProcessed, 0, 0, 0, 0, 0);

Answer: Occasionally, you can see a duplicate key violation when performing an Insert. You should be able to find the primary key by comparing two recordings to determine the problem. Check whether this or earlier UPDATE
or INSERT
statement should use correlated queries. You can use the data dictionary in order to find the columns that are used in the violated unique constraint.
In Oracle you can see the following message when a unique constraint is violated:
ORA-00001: unique constraint (SCOTT.PK_EMP) violated
In this example SCOTT
is the owner of the related unique index, and PK_EMP
is the name of this index. Use SQL*Plus to query the data dictionary to find the columns. The pattern for this query is:
select column_name from all_ind_columns where index_name = '<IndexName> and index_owner = '<IndexOwner>'; select column_name from all_ind_columns where index_name = 'PK_EMP' and index_owner = 'SCOTT';
Since the values inserted into the database are new, they might not appear in earlier queries, but they could be related to the results of earlier queries, such as one more than the value returned in an earlier query.
You can use the Query Analyzer to find out which columns used by the key or index. The pattern for this query is:
select C.name from sysindexes A, sysindexkeys B, syscolumns C where C.colid = B.colid and C.id = B.id and A.id = B.id and A.indid = B.indid and A.name = '<IndexName>' and A.id = object_id('<TableName>') select C.name from sysindexes A, sysindexkeys B, syscolumns C where C.colid = B.colid and C.id = B.id and A.id = B.id and A.indid = B.indid and A.name = 'IX_newtab' and A.id = object_id('newtab')
If you still encounter problems, be sure to check the number of rows changed for Updates and Inserts for both recording and replay. Very often, an UPDATE
fails to change any rows during replay, because the WHERE
clause was not satisfied. This does not directly result in an error, but it causes a table not to be properly updated, and can cause a later SELECT
to select the wrong value when correlating the query.
Also verify that there are no problems during multi-user replay. In certain instances, only one user can successfully perform an UPDATE
. This occurs with Siebel, where it is necessary to manually write a loop to overcome the problem.

Answer: Through the user application's UI, check if the updated values appear when trying to see the current data accessible to the application. If the values have not been updated, you need to determine they were not changed. Possibly, an UPDATE
statement changed one or more rows when the application was recorded, and did not change any during replay.
Check these items:
-
Verify statement. If there is a
WHERE
clause in theUPDATE
statement, verify that it is correct. -
Check for correlations. Record the application twice and compare the
UPDATE
statements from each of the recordings to make sure that the necessary correlations were performed. -
Check the total number of rows. Check the number of rows that were changed after the
UPDATE
. For Oracle, this information is stored in the fourth parameter of lrd_exec. For ODBC, use lrd_row_count to determine the number of rows updated. You can also add code to your script that prints the number of rows that were updated. If this value is 0, theUPDATE
failed to modify the database. -
Check the SET clause. Check the
SET
clause of theUPDATE
statement. Make sure that you correlated any necessary values here instead of hard-coding them. You can see this by comparing two recordings of theUPDATE
.
It certain cases, the UPDATE
works when replaying one Vuser, but not for multiple Vusers. The UPDATE
of one Vuser might interfere with that of another. Parameterize each Vuser so that each one uses different values during the UPDATE
, unless you want each Vuser to update with the same values. In this case try adding retry logic to perform the UPDATE
a second time.

lrd_stmt(Csr9, "SELECT UOM_CODE, UOM_CODE, DESCRIPTION FROM "
"MTL_UNITS_OF_MEASURE "
"WHERE NVL(DISABLE_DATE, SYSDATE + 1) > "
"SYSDATE ORDER BY UOM_CODE", -1, 1, 1, 0);
The following error message was issued:
"lrdo.c/fjParse: "oparse" ERROR return-code=960, oerhms=ORA-00960: ambiguous column naming in select list".
Answer: Change the statement by adding an alias to at least one of the non-unique columns, thereby mapping it to a new unique name. For example:
lrd_stmt(Csr9,"SELECT UOM_CODE,UOM_CODE second, DESCRIPTION FROM"
"MTL_UNITS_OF_MEASURE "
"WHERE NVL(DISABLE_DATE, SYSDATE + 1) > "
"SYSDATE ORDER BY UOM_CODE", -1, 1, 1, 0);
Troubleshooting Oracle 2-tier Vusers
This section contains a list of common problems that you may encounter while working with Oracle Vusers, and suggested solutions.
ORA-20001 and ORA-06512
Errors ORA-20001 and ORA-06512 appear during replay when the lrd_stmt contains the pl/sql block: fnd_signon.audit_responsibility(...)
This statement fails during replay because the sign-on number is unique for each new connection.
Solution
In order to solve this problem you need to use the new correlation tool for the sign-on number. This is second assigned value in the statement.
After you scan for possible values to correlate, highlight the value of the second lrd_assign_bind() for the failed statement. Note that the values in the "correlated query" window may not appear in the same order as the actual recorded statements.
The grid containing the substitution value should appear after the lrd_stmt which contains the pl/sql block: fnd_signon.audit_user(...).
Note: Since the sign-on number is unique for every connection, you need to use correlation for each new connection that you record.
Example of Solution
The following statement failed in replay because the second value, "1498224" is the unique sign-on number for every new connection.
lrd_stmt(Csr6, "begin fnd_signon.audit_responsibility(:s,:l,:f,:a,:r,:t,:p)"
"; end;", -1, 1, 1, 0);
lrd_assign_bind(Csr6, "s", "D", =;s_D216, 0, 0, 0);
lrd_assign_bind(Csr6, "l", "1498224", =;l_D217, 0, 0, 0);
lrd_assign_bind(Csr6, "f", "1", =;f_D218, 0, 0, 0);
lrd_assign_bind(Csr6, "a", "810", =;a_D219, 0, 0, 0);
lrd_assign_bind(Csr6, "r", "20675", =;r_D220, 0, 0, 0);
lrd_assign_bind(Csr6, "t", "Windows PC", =;t_D221, 0, 0, 0);
lrd_assign_bind(Csr6, "p", "", =;p_D222, 0, 0, 0);
lrd_exec(Csr6, 1, 0, 0, 0, 0);
The sign-on number can be found in the lrd_stmt with "fnd_signon.audit_user". The value of the first placeholder "a" should be saved. The input of "a" is always "0" but the output is the requested value.
Modified code
lrd_stmt(Csr4, "begin fnd_signon.audit_user(:a,:l,:u,:t,:n,:p,:s); end;", -1, 1, 1, 0);
lrd_assign_bind(Csr4, "a", "0", =;a_D46, 0, 0, 0);
lrd_assign_bind(Csr4, "l", "D", =;l_D47, 0, 0, 0);
lrd_assign_bind(Csr4, "u", "1001", =;u_D48, 0, 0, 0);
lrd_assign_bind(Csr4, "t", "Windows PC", =;t_D49, 0, 0, 0);
lrd_assign_bind(Csr4, "n", "OraUser", =;n_D50, 0, 0, 0);
lrd_assign_bind(Csr4, "p", "", =;p_D51, 0, 0, 0);
lrd_assign_bind(Csr4, "s", "14157", =;s_D52, 0, 0, 0);
lrd_exec(Csr4, 1, 0, 0, 0, 0);
lrd_save_value(=;a_D46, 0, 0, " saved_a_D46");
Grid0(17);
lrd_stmt(Csr6, "begin fnd_signon.audit_responsibility(:s,:l,:f,:a,:r,:t,:p)"
"; end;", -1, 1, 1, 0);
lrd_assign_bind(Csr6, "s", "D", =;s_D216, 0, 0, 0);
lrd_assign_bind(Csr6, "l", " <saved_a_D46>", =;l_D217, 0, 0, 0);
lrd_assign_bind(Csr6, "f", "1", =;f_D218, 0, 0, 0);
lrd_assign_bind(Csr6, "a", "810", =;a_D219, 0, 0, 0);
lrd_assign_bind(Csr6, "r", "20675", =;r_D220, 0, 0, 0);
lrd_assign_bind(Csr6, "t", "Windows PC", =;t_D221, 0, 0, 0);
lrd_assign_bind(Csr6, "p", "", =;p_D222, 0, 0, 0);
lrd_exec(Csr6, 1, 0, 0, 0, 0);
Working with large numbers
Large numbers (NUMBER data type) sometimes appear in different format in the GRID and in the ASCII file. This difference makes it more difficult to identify numbers while searching for values to save for correlation.
For example, you could have a value appear as 1000003 in the grid, but as 1e+0006 in the Recording Log (ASCII file).
Workaround
If you have an error during replay and the correlation tool cannot locate the value in previous results, look for this value in the other format in grid.
ORA-00960
This error may occur with non-unique column names. For example:
lrd_stmt(Csr9, "SELECT UOM_CODE, UOM_CODE, DESCRIPTION FROM "
"MTL_UNITS_OF_MEASURE "
"WHERE NVL(DISABLE_DATE, SYSDATE + 1) > "
"SYSDATE ORDER BY UOM_CODE", -1, 1, 1, 0);
In this case you receive the following error:
"lrdo.c/fjParse: "oparse" ERROR return-code=960, oerhms=ORA-00960: ambiguous column naming in select list".
Workaround
Change the statement by adding an alias to at least one of the non-unique columns, thus mapping it to a new unique name. For example:
lrd_stmt(Csr9,"SELECT UOM_CODE,UOM_CODE second, DESCRIPTION FROM"
"MTL_UNITS_OF_MEASURE "
"WHERE NVL(DISABLE_DATE, SYSDATE + 1) > "
"SYSDATE ORDER BY UOM_CODE", -1, 1, 1, 0);
Alternate Workaround: remove ORDER BY from the lrd statement.
ORA-2002
Error 2002 appears when you try to use an unopened cursor. It occurs when you replay a user more than one iteration and you recorded into more than one section of the script.
Specifically, if a cursor is opened in the vuser_init section and closed in the Actions section, then you will encounter this error on the second iteration if you try to use the cursor. This is because it was closed but not re-opened.
For example: You have lrd_open_cursor in the vuser_init section and lrd_close_cursor in the Actions section. If you replay this user more than one iteration, you are going to get an error in the second iteration because you try using an unopened cursor (it was closed in the first iteration, but not re-opened in the second).
Workaround
The easiest way to solve this is to move the lrd_close_cursor or/and lrd_close_connection of the problem cursor to the vuser_end section.
Database Protocols (lrd)
Replay of recorded asynchronous operations is not supported.
Wrong Client Version
You may receive an error message when running the wrong Oracle client version:
"Error: lrdo_open_connection: "olog" LDA/CDA return-code_019: unable to allocate memory in the user side"
Workaround
You need to modify the library information in the lrd.ini file, located in the product's bin folder. This file contains the settings that indicate which version of database support is loaded during recording or replay. The file contains a section for each type of host.
For example, the following section of the lrd.ini file is for Oracle on Windows NT:
[ORACLE_WINNT]
805=lrdo32.dll+ora805.dll
816=lrdo32.dll+oci.dll
815=lrdo32.dll+oraclient8.dll
804=lrdo32.dll+ora804.dll
803=lrdo32.dll+ora803.dll
73=lrdo32.dll+ora73.dll
72=lrdo32.dll+ora72.dll
71=lrdo32.dll+orant71.dll
These settings indicate that Vusers should use the ora805.dll library if the client uses Oracle 8.0.5, oci.dll for Oracle 8.1.6, and so on.