Invalid or NULL argument for object_id [] - oracle

I'm trying to call a function and store the result in a varabile
la_object_names fls_varchar_table := fls_varchar_table();
la_children_EASs FLS_NUMBER_TABLE := FLS_NUMBER_TABLE();
loa_objects_EASs ims_api.typo_ims_objects := ims_api.typo_ims_objects(NULL);
la_object_names := rm.sri_object_utils.get_object_names(pia_object_ids => la_children_EASs);
fls_varchar_table and FLS_NUMBER_TABLE are table of varchar and number declared in a ddl.
get_object_names function returns a fls_varchar_table
The intialization of la_children_EASs
la_children_EASs.extend(loa_objects_EASs.ims_objects.LAST);
I think there is an implicit conversion from fls_number_table to ims_api.typo_ims_objects but not viceversa
I'm getting this error:
Invalid or NULL argument for object_id [] in procedure/function
rm.sri_object_utils.get_object_name
I tried to give and hard coded argument to get_object_names method something like this:
la_object_names := rm.sri_object_utils.get_object_names(pia_object_ids => FLS_NUMBER_TABLE(31231,2313213,231231));
This returns the expected results. Any suggestion is very appreciated.

Seems that you pass parameter of wrong type to this function in first case.
In first case you pass la_children_EASs which is FLS_NUMBER_TABLE(),
in second case you pass fls_varchar_table.

Related

Passing in a JSON_OBJECT_T into SODA_DOCUMENT_T

I have a PL/SQL handler using the SODA package to manipulate a JSON database. I want to:
Read the value for key id in the payload
Write the payload JSON into a new document in the database.
To do step 1, The handler takes :body to be parsed as a JSON_OBJECT_T type, so that I can access the value for key id in the payload.
But for step 2, if I read body again when constructing with SODA_DOCUMENT_T(b_content=> :body), it will simply give me a blank document.
I also can't pass in the JSON_OBJECT_T variable in directly, like SODA_DOCUMENT_T(j_content=> jso), because that function expects a JSON type and not a JSON_OBJECT_T. I can't find the JSON type documentation, but saw in code examples the function JSON('{}') to generate one.
Reading :body_text however gives me other problems - because JSON() function cannot handle line breaks in the payload and gives an error instead.
Currently to work around this I'm using the following:
SODA_DOCUMENT_T(
j_content => JSON(jso.to_string())
)
Which seems very silly because I'm serialising it to a string again before converting it back into JSON type. Is there a proper way to read the value of a key of the payload, and pass it into the SODA_DOCUMENT_T?
Yes, you can't pass in JSON_Object_T instance to SODA_Document_T constructor. However, you may use JSON_QUERY() PL/SQL function that drills into the JSON document given a path expression and it returns a JSON type instance.
Example:
jval := JSON_QUERY(body, '$.id' RETURNING JSON);
In the above example, $.id is the path expression and json_query() returns json value corresponding to the field id starting from the root $
Documentation:
https://docs.oracle.com/en/database/oracle/oracle-database/21/adjsn/function-JSON_QUERY.html
You should now be able to pass this jval instance of type JSON to SODA_Document_T constructor.
Yes, I think you should definitely avoid back and forth conversions.
Usage:
SQL>
CREATE OR REPLACE FUNCTION process_request(body IN VARCHAR2)
RETURN JSON
IS
j JSON;
d SODA_Document_T;
BEGIN
j := JSON_QUERY(body, '$.id' RETURNING JSON);
d := SODA_Document_T(j_Content => j);
-- n := coll.insert_one(d);
RETURN j;
END;
13 /
Function created.
SQL> SELECT process_request('{"id":{"type": "string", "val": "DEADBEEF"}}') FROM dual;
PROCESS_REQUEST('{"ID":{"TYPE":"STRING","VAL":"DEADBEEF"}}')
--------------------------------------------------------------------------------
{"type":"string","val":"DEADBEEF"}
I recommend this approach. Let me know if that helps!
Alternate solution:
BTW, given a DOM, you can directly go to JSON type instance as well, using the following method in JSON_Object_T type:
MEMBER FUNCTION GET_JSON RETURNS JSON
Argument Name Type In/Out Default?
------------------------------ ----------------------- ------ --------
KEY VARCHAR2 IN
This method pretty much does the same work as JSON_Query() shown above:
SQL>
CREATE OR REPLACE FUNCTION process_body(data IN VARCHAR2)
RETURN JSON
AS
body JSON_Object_T;
j JSON;
BEGIN
body := JSON_Object_T.parse(data);
j := body.get_Json('id');
return j;
END;
11 /
SQL> SELECT process_body('{"id":{"type": "string", "val": "DEADBEEF"}}') FROM dual;
PROCESS_BODY('{"ID":{"TYPE":"STRING","VAL":"DEADBEEF"}}')
--------------------------------------------------------------------------------
{"type":"string","val":"DEADBEEF"}

What does "read_strt" meaning here?

What does this vbscript code mean?
<%=read_strt(objRS, "ccnumber", "")%>
I want to know whats the meaning or used of read_strt on the code?
Any ideas?
The statement writes the return value of a call to the function "read_strt" to the HTML output stream. The function seems to read the value of a field/column in the current row of a database query (recordset), convert its type to String and/or test it against 'bad' (e.g. Null) values; in that case the default value ("", empty string) is returned.

Passing Field Symbol value to Return parameter of method

I have the below code which uses a method. When I try to assign the Field Symbol value [Type ANY] to the return parameter RO_TAB [Type Ref to Data], I am getting an error message OBJECTS_MOVE_NOT SUPPORTED [Conversion of type "l" to type "g" not supported.].
The issue is happening after a BW system upgrade along with which we also moved to ABAP objects. The code executes perfectly in the older version of ABAP.
The dump occurs in the below line:
RO_TAB = <lf_storage>.
I have no idea why.
method GET_LU_STORAGE_FOR_ODS.
* IMPORTS
* IF_ODS TYPE RSODSTECH
* IF_ODS_TABLE_TYPE TYPE ZODS_TAB_TYPE
* RETURNS
* RO_TAB TYPE REF TO DATA
FIELD-SYMBOLS:
<lf_storage> TYPE ANY.
DATA:
lf_index TYPE SY-TABIX,
lf_sindex TYPE STRING,
lf_name TYPE STRING.
lf_index = GET_LU_STORAGE_INDEX(
IF_ODS = IF_ODS
IF_ODS_TABLE_TYPE = IF_ODS_TABLE_TYPE ).
lf_sindex = lf_index.
CONCATENATE
'MO_LU_DATA_'
lf_sindex
INTO lf_name.
ASSIGN lf_name TO <lf_storage>.
RO_TAB = <lf_storage>.
endmethod.
You need to create a data object first, using the CREATE DATA statement. Then you can ASSIGN a field symbol to work with the dynamically created data object. There's an example in the online manual. A field symbol is not a reference, it simply places the variable assigned to it in its position. You're effectively trying to move a string (which is what lf_name is) to a reference variable, and that won't work.
You cannot assign a variable of type STRING to a variable of type REF TO DATA.
The following code snippet shows how it should be done.
DATA: lf_name TYPE string.
DATA: lo_tab TYPE REF TO DATA.
FIELD-SYMBOLS: <lf_name> TYPE string.
lf_name = 'test'.
GET REFERENCE OF lf_name INTO lo_tab.
*lf_name = lo_tab. "this is not allowed
ASSIGN lo_tab->* TO <lf_name>.
So in your case it would be sufficient to define a field symbol.
FIELD-SYMBOLS: <lf_name> TYPE STRING.
then assign the contents referenced by RO_TAB to this field symbol.
ASSIGN ro_tab->* TO <lf_name>.
and finally do the concatenation.
CONCATENATE
'MO_LU_DATA_'
lf_index
INTO <lf_name>.
That's all! No further assignments should be required.
How about just this?
lf_sindex = lf_index.
CONCATENATE
'MO_LU_DATA_'
lf_sindex
INTO RO_TAB.

How to pass in argument of type DATE to a function

I've got a function in an oracle database. I need to call it from delphi. I use the following code:
procedure TForm1.Run;
var
q:TADOQuery;
begin
q:=TADOQuery.Create(nil);
q.Connection:=ADOConnection1;
q.ParamCheck:=false;
q.SQL.Add('BEGIN');
q.SQL.Add(' :RES:=Search(:P_DATE);');
q.SQL.Add('END;');
q.Parameters.AddParameter.Name:='P_DATE';
q.Parameters.ParamByName('P_DATE').Direction:=pdInput;
q.Parameters.ParamByName('P_DATE').DataType:=ftDate;
q.Parameters.ParamByName('P_DATE').Value:=Now;
q.Parameters.AddParameter.Name:='RES';
q.Parameters.ParamByName('RES').DataType:=ftFloat;
q.Parameters.ParamByName('RES').Direction:=pdOutput;
q.Parameters.ParamByName('RES').Value:=1;
q.ExecSQL;
//...
I get ora-06550 error, saying invalid number or type of parameters. If I change the P_DATE parameter to sysdate, i.e. :RES:=Search(sysdate);, it works fine.
So how can I pass an "in" parameter of type DATE to an oracle function from delphi?
Found ORA-06550 when Oracle stored function is called.. However this relates to Kylix Pascal IDE. Am I expected to meet the same behaviour for delphi? Didn't try to use oracle procedure instead of a function. Maybe this issue can be solved some how else...
Oracle doesn't have a date type for bind variables - you need to explicitly convert the bind variable to a date:
:res := search(to_date(:p_date, 'dd/mm/yyyy'));
You should then be able to pass your variable as a string matching the date format you've specified.
Try to send this parameter as a string:
.........
q.SQL.Add('BEGIN');
q.SQL.Add(' :RES:=Search(TO_DATE(:P_DATE,''YYYYMMDD''));');
q.SQL.Add('END;');
q.Parameters.AddParameter.Name:='P_DATE';
q.Parameters.ParamByName('P_DATE').Direction:=pdInput;
q.Parameters.ParamByName('P_DATE').DataType:=ftString;
q.Parameters.ParamByName('P_DATE').Value:=FormatDateTime('yyyymmdd',Now);
..........
You're doing it wrong (and I think you had a previous question deleted as being a duplicate that asked this same question (different function, but same idea) just a couple of days ago).
You're calling the function wrong in the first place.
.........
q.SQL.Add('BEGIN');
q.SQL.Add(' SELECT Search(TO_DATE(:P_DATE,''YYYYMMDD'')) FROM System.Dual;');
q.SQL.Add('END;');
q.Parameters.AddParameter.Name:='P_DATE';
q.Parameters.ParamByName('P_DATE').Direction:=pdInput;
q.Parameters.ParamByName('P_DATE').DataType:=ftDate;
q.Parameters.ParamByName('P_DATE').Value:=Now;
q.Open;
if not q.IsEmpty then // or not q.Eof
Res := q.Fields[0].AsFloat;

"Invalid use of Null" when using Str() with a Null Recordset field, but Str(Null) works fine

I'm banging my head against the wall on this one. I was looking at some old database reporting code written in VB6 and came across this line (the code is moving data from a "source" database into a reporting database):
rsTarget!VehYear = Trim(Str(rsSource!VehYear))
When rsSource!VehYear is Null, the above line generates an "Invalid use of Null" run-time error. If I break on the above line and type the following in the Immediate pane:
?rsSource!VehYear
It outputs Null. Fine, that makes sense. Next, I try to reproduce the error:
?Str(rsSource!VehYear)
I get an "Invalid use of Null" error.
However, if I type the following into the Immediate window:
?Str(Null)
I don't get an error. It simply outputs Null.
If I repeat the same experiment with Trim() instead of Str(), everything works fine. ?Trim(rsSource!VehYear) returns Null, as does ?Trim(Null). No run-time errors.
So, my question is, how can Str(rsSource!VehYear) possibly throw an "Invalid use of Null" error when Str(Null) does not, when I know that rsSource!VehYear is equal to Null?
Update: If I type the following in the Immediate window, it works as expected (no error occurs):
?Str(rsSource!VehYear.Value)
This outputs Null. Now, I know that rsSource!VehYear is actually an ADODB.Field instance, but Value is its default property, so Str should be operating on the Value property (which is Null). Even the error message ("Invalid use of Null") suggests that Str is receiving a Null parameter, but how can it treat Null differently in one case and not the other?
My only guess is the internal implementation of Str() is somehow failing to get the default property, and the "Invalid use of Null" error is happening for a different reason (something other than the parameter is causing the "Invalid use of Null", perhaps when it is trying to retrieve the default property from the Field object).
Does anyone have a more detailed, technical explanation for what is actually happening here?
In short:
?Str(rsSource!VehYear)
throws an "Invalid use of Null" error when rsSource!VehYear is Null, but
?Str(rsSource!VehYear.Value)
returns Null.
However, both Trim(rsSource!VehYear) and Trim(rsSource!VehYear.Value) return Null.
If you need a value other than a string, try using IsNull instead:
rsTarget!VehYear = IIf(IsNull(rsSource!VehYear), 0, rsSource!VehYear)
' Note 0 is the default value
The Str function will specifically check if a Null value is passed in and deal with it accordingly. When you pass in an object it attempts to convert the result of a default method to a String. The result of the default method is not passed into the Str method, but Field object is, so a check for the initial Null will fail. The Str function will continue to check the parameter type for datatypes that it supports when it realizes that it has an object, it will attempt to retrieve the default value. It doesn't re-attempt to deal with the default value as it did with the passed in argument, so the attempt to return a Null as a String will fail. It seems MS didn't expect a default value to be Null or any other invalid value for Str. For instance Str doesn't support an empty string either.
This was my workaround in the vb6-days:
rsTarget!VehYear = Trim(Str(rsSource!VehYear & ""))
the & "" will make sure there is allways at least an empty string to work with.
From memory, null database fields are Nothing (or possibly vbNull), which do not have the same rules applied to them as Null. You should just be able to do a quick check:
If (rsSource!VehYear Is Nothing) Then
' Null
Else
' Not null
End If

Resources