Passing Field Symbol value to Return parameter of method - methods

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.

Related

Codeigniter 4 - how to get the first row and the last row of a result

I am trying to get the first row and the last row of a query result. I see from Ci4's docs, there are two methods to help, namley, getFirstRow([$type = 'object']) and getLastRow([$type = 'object']) but I am having difficulty using them. Here is my method so far:
function getLoginFailCount($login_fail_ip, $max_login_attempts = 3, $within_seconds = 320){
$builder = $this->builder('login_fail');
$builder->where('login_fail_ip', $login_fail_ip);
$builder->orderBy('login_fail_created_at','DESC');
$query = $builder->get(3);
print_r($query->getFirstRow($query));
}
I get an error at getFirstRow as follows;
Argument 1 passed to CodeIgniter\Database\BaseResult::getFirstRow() must be
of the type string, object given
How can I get getFirstRow() to work? Doesn't this doc definition say I need to pass it an object? Why does the error say it my be of type string
Well in the documentation for getFirstRow() it states that you can use
$row = $query->getFirstRow() // which will give you an object
OR
$row = $query->getFirstRow(‘array’) // which will give you an Array
So your error message, which states...
Argument 1 passed to CodeIgniter\Database\BaseResult::getFirstRow()
must be of the type string, object given
Would make you look and say to yourself, I had better go and read the documentation. So you can either pass in nothing, or a String 'array'.
So now can you see why
$query->getFirstRow($query))
does not make any sense! Why would you pass in the $query object as parameter.
You may have misread the documentation. I see you stated getFirstRow([$type = 'object'])
You might have got a little confused by that...
[$type = 'object'] means that the $type is defaulted to be the string 'object' so the returned type is an object by default with No Parameter being passed in.
If you want it to return an array, then you would specify the string 'array'. So then the $type parameter would be set to the string 'array' and return an array instead of an object.
Does that help!

Get components of DDIC structure with includes

I am using cl_abap_structdescr->get_components to get a list of fields in a structure. It works fine when I use it on locally declared structure types, but when I use it on DDIC structures, it doesn't give me the results I expect.
Reproducable example:
TYPES: BEGIN OF gty_outtab,
infty TYPE infty,
uname TYPE uname,
bdate TYPE datum,
btime TYPE uzeit,
pernr TYPE pernr_d,
opera TYPE hr_opera,
begda TYPE begda,
endda TYPE endda,
END OF gty_outtab.
DATA: lr_infty_structdescr TYPE REF TO cl_abap_structdescr,
lr_outtab_structdescr TYPE REF TO cl_abap_structdescr,
lt_outtab_components TYPE STANDARD TABLE OF abap_componentdescr,
lt_infty_components TYPE STANDARD TABLE OF abap_componentdescr.
" works as expected
lr_outtab_structdescr ?= cl_abap_structdescr=>describe_by_name( 'GTY_OUTTAB' ).
lt_outtab_components = lr_outtab_structdescr->get_components( ).
" doesn't work as expected
lr_infty_structdescr ?= cl_abap_structdescr=>describe_by_name( 'P0008' ).
lt_infty_components = lr_infty_structdescr->get_components( ).
BREAK-POINT.
Results:
That's okay for GTY_OUTTAB:
There are only two fields for P0008 although it contains many more fields (see below):
I already tried using cl_abap_typedescr instead and googled, but every code I find online looks just like mine?
Here is the definition of P0008 which contains many fields as you can see:
Of course after posting this, I found the reason why (german thread). Apparently, if the given structure contains included structures, then get_components won't break them up. Three solutions have been suggested in the thread and they all work great for me. Since I only need the structures' fieldnames, I will use option 1.
DATA: lt_infty_complist1 TYPE abap_compdescr_tab,
lt_infty_complist2 TYPE STANDARD TABLE OF fieldname,
lt_infty_complist3 TYPE abap_component_tab.
" 1 - get full fieldname list, but with barely any typedescription
lt_infty_complist1 = lr_infty_structdescr->components.
" 2 - get full fieldname list of DDIC structures, but without typedescription
SELECT fieldname
FROM dd03l
INTO TABLE lt_infty_complist2
WHERE tabname = 'P0008'.
DELETE lt_infty_complist2 WHERE table_line = '.INCLU--AP'
OR table_line = '.INCLUDE'.
" 3 - get full component list
" function code from: https://www.abapforum.com/forum/viewtopic.php?f=18&p=59840)
PERFORM return_components USING lr_infty_structdescr CHANGING lt_infty_complist3.
There is a method on cl_abap_structdescr called get_included_view( ) that will expand the included structures
Method GET_RTTS_FOR_LOCAL_TABLE of helper-class CL_CACS_RTTS_HELPER seems to do exactly what you want and what lacks your option 1
CALL METHOD cl_cacs_rtts_helper=>get_rtts_for_local_structure
EXPORTING
id_tabname = 'P0008'
receiving
ro_data = DATA(ro_struct)
.
It fetches all components of a structure into reference data object and also includes absolute types:
In the same class there is get field list method, which may be sufficient.
data: lo_incl_stru TYPE REF TO cl_abap_structdescr,
lt_field_list TYPE ddfields.
lt_field_list = lo_incl_stru->get_ddic_field_list( p_including_substructres = abap_true ).
If that isnt enough.... try
METHODS recursive_get_components
IMPORTING
io_structdescr TYPE REF TO cl_abap_structdescr
RETURNING
VALUE(rt_components) TYPE abap_component_tab.
METHOD recursive_get_components.
DATA:
lo_incl_stru TYPE REF TO cl_abap_structdescr,
lt_incl_comp TYPE abap_component_tab,
l_curr_index TYPE i.
FIELD-SYMBOLS: <comp> LIKE LINE OF rt_components,
<incl_comp> LIKE LINE OF lt_incl_comp.
rt_components = io_structdescr->get_components( ).
LOOP AT rt_components ASSIGNING <comp>.
IF <comp>-as_include = 'X'.
lo_incl_stru ?= <comp>-type. " not the include struc type
l_curr_index = sy-tabix. " and the index it is to be included
DELETE rt_components INDEX l_curr_index.
lt_incl_comp = recursive_get_components( io_structdescr = lo_incl_stru ).
LOOP AT lt_incl_comp ASSIGNING <incl_comp>.
INSERT <incl_comp> INTO rt_components INDEX l_curr_index.
l_curr_index = l_curr_index + 1.
ENDLOOP.
ENDIF.
ENDLOOP.
ENDMETHOD.

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.

What's the difference between 'Array<_>' & 'Array'

I'm getting this error when trying to build the app:
<unknown>:0: error: cannot assign value of type 'Array<_>' to type 'Array'
but Xcode is not indicating a specific line or class for the failure.
If I could understand the difference between
Array<_>
&
Array
it may help me locate the issue.
When you app is crashing, than you can turn on All Exceptions for Debug breakpoint. This should stop on the line where the crash appears.
You find this in Xcode on the Left Panel-> BreakPoint Navigator.
Than press the + in the bottome left corner and Add Exception Breakpoint.
It looks like that you overwrite an array with an array that has a specific value definition. Good Luck :)
A generic argument clause is enclosed in angle brackets ( < > )
< generic argument list >
You can replace a type parameter with a type argument that is itself a specialized version of a generic type.For example, you can replace the type parameter T in Array < T > with a specialized version of an array, Array< Int > , Array< String >, to form an array whose elements are themselves array of integers / Strings
Regarding xour code Snippet the fix is:
u should define it with the right value ... userTweetsArray : [String] = String . or remove the : [String] because setting the value defines already the object and type :)
I don't like answering my own questions but for the sake of closure
I had this line of code
var userTweetsArray : Array = [String]()
I never actually used it. Once I removed that line the error had gone.
The error was caused by assigning an array of a type in this case String to an Array of no type.
So difference is Array<_> is an array of a type and Array is not.

Is Nothing comparison gives type mismatch

I am trying to check if the 'Listivew.Tag property is nothing'.
I used to do the 'Is Nothing' check universally for all scenarios as first check to avoid errors
Can someone explain how to do it in VB 6?
If Not .lvwLocation.Tag Is Nothing Then
'COMPANY
str = str & IIf(Len(.lvwLocation.Tag) > 0, " and u.location_id in " & .lvwLocation.Tag, "")
End If
Gives error 'type-mismatch'
Nothing is a valid value for Object variables, and Is is the way to compare object pointers.
But a VB6 control's Tag property is a String, and VB6's String type is not an Object; it's a primitive type. That means a String variable can't be assigned Nothing -- its emptiest possible value is the empty string. (And an Object variable can't be assigned a String value.) For strings just use the same equality/inequality/comparision operators that you use for other primitive (numeric/boolean/date) types:
If .lvwLocation.Tag <> "" Then ...
In VB6 it appears that using Is Nothing to compare Objects works, Every other data type that I tried did not. In .Net Nothing represents the default value of any data type and will work like you expect.
Dim test as Object
If Not test Is Nothing Then
/////
End If
Since it appears the data type of th Tag property in VB6 is a string. I would use something like:
If .lvwLocation.Tag <> "" Then
/////
End If

Resources