I want to write a method which exports a table of references. This is required because each line of it could have its own structure. So I'm declaring the type like this:
... TYPE STANDARD TABLE OF REF TO data.
I thought it would be a neat idea if I could immediately modify the tables last row instead of having a separate workarea just for appending.
Why does this work...
FIELD-SYMBOLS: <lfs_struct> TYPE REF TO DATA.
" ...
APPEND INITIAL LINE TO ei_lines ASSIGNING <lfs_struct>.
CREATE DATA <lfs_struct> TYPE (<lfs_field>-segnam).
ASSIGN <lfs_struct>->* TO <lfs_target>.
...but this doesn't?
DATA: lo_struct TYPE REF TO data.
" ...
APPEND INITIAL LINE TO ei_lines REFERENCE INTO lo_struct.
CREATE DATA lo_struct TYPE (<lfs_field>-segnam).
ASSIGN lo_struct->* TO <lfs_target>.
With 'work' I mean that the value of the appended row really changes. If I assign something to <lfs_target> like I do in the second example, it changes in the structure itself - but not inside the table.
Apparently I am changing the reference with the last example. But why does it work with Field-Symbols then?
The reason why your code works with a field symbol but not a data object is because of how those two deal with data in memory in a different way. There are similar concepts in C++, even though naming in ABAP is a bit confusing when you are used to C++:
In ABAP a field symbol is a bit like a reference in C++ (or like a dereferenced C++ pointer, as SAP calls it). It does not allocate memory for its own data, but rather refers to some existing field / data object. After assigning a data object to the field symbol, if you access that data object via the field symbol, then you don't ever talk to the field symbol itself, but always to the data object directly! (This is the crucial part in your case, as we see in a bit.)
Now in your first example you create the field symbol, which does nothing yet:
FIELD-SYMBOLS: <lfs_struct> TYPE REF TO DATA.
Only after creating the new line for your internal table and assigning that newly allocated memory to your field symbol <lfs_struct>, the field symbol points to some data (the table line). Then you allocate some more memory dynamically:
CREATE DATA <lfs_struct> TYPE (<lfs_field>-segnam).
Now your internal table ei_lines points to the newly appended table line (memory address), as does your field symbol. That memory address in turn points to the newly created data from CREATE DATA. Important to note is that, as said, you don't access the field symbol itself, but the memory where it refers to!
In the second example however you first allocate memory for a new data object:
DATA: lo_struct TYPE REF TO data.
Then again you allocate new memory for a new table line (APPEND) and put a reference to that memory address into your data object lo_struct. Now the interesting part: You dynamically create another data (object) and save the pointer to that new data into lo_struct. Thus now lo_struct doesn't refer to the new table line any longer, but to the newly created data from CREATE DATA.
TL;DR In the first example you CREATE DATA and save the reference to that data into the object where your field symbol <lfs_struct> refers to, which is the new table line in ei_lines. In the second example, however, you also create a new table line and refer to it via lo_struct, but when you CREATE DATA afterwards, you store the reference to that new data again into lo_struct, thus overwriting the original reference to the new table line.
Related
I am new to DB2 and I'm working with an IBM i series system. I have an object with a special column "X". I want to store data for X in another object whenever some criteria satisfied and I can get data from the original object for both special records(which data have been stored in another object) and normal data (which values stored in the original object).
How can I link this column to another object? can DB2 data link: data-link help me in this situation? if yes, how can I implement that? I can't find a complete tutorial on how to do this.
I will appreciate any help.
I am trying Sense/Net Community edition features.
I defined and installed content type called "Vacation Request" successfully.
I want to know what is the purpose of "mapping" field in table: SchemaPropertyTypes
Many thanks,
I really, really hope you are asking this only out of curiosity, and not because you want to change something manually in the db - because it is not recommended :). Please always access the content repository through the API, do not query or modify the db directly.
Property types and values
Simple property values (like int or short text values) are stored in the FlatProperties table. This is a fixed-with table, containing a predefined number of columns dedicated to different types (e.g. x pieces of string columns, y pieces of int columns - see column names in the table).
Property definitions are stored in the SchemaPropertyTypes table, as you have found out.
The zero-based Mapping field in the SchemaPropertyTypes table defines the column index in the FlatProperties table for a particular property. E.g. a value of a string property with mapping 6 will be stored in the FlatProperties table's 'nvarchar_7' column (note the index is shifted by one, because the column name index is one-based).
If you take a look at the PropertyInfoView view (not table), it may help clarifying this: the last column of the view is a computed column that displays the column name that you can look up in the flat properties table.
(there are other useful SQL views there that display data in a more readable way)
Property 'overflow'
It is possible to register more properties of the same type (e.g. int) than can fit in one row in the FlatProperties table. Solution: Sense/Net stores these nodes in multiple rows - this is why there is a Page column there.
Although MS SQL Server supports a huge number of columns for some time, this design has been kept for compatibility reasons.
This is why you see mapping values in PropertyInfoView like 249 with column name nvarchar_10: the value is stored on page 3, which means that content occupies 3 records in the FlatProperties table.
'Other' property types
You may have noticed that in case of reference or long text properties there is no mapping. This is because we do not store them in the FlatProperties table, they have their own tables like ReferenceProperties or TextPropertiesNText.
I have the following problem:
I'm testing many BAPI's and dont want to create a Table with the corosponding types for the rows, each time I call a new BAPI.
Is it possible to generate s.th. like a generic table like:
DATA foo TYPE ANY TABLE.
and use this to put it as the table parameter to get the result of the bapi?
No, this is not possible - you can't declare variables using a generic type. However, you could try to determine the data type (e. g. using RPY_FUNCTIONMODULE_*) and then use CREATE DATA to create the table dynamically using a reference. Check the documentation of CREATE DATA for an example.
I have the following question:
I have a dypro and added via the layout builder a dict delement: mara-matnr
Now I see it in my element list:
Now I wanted to know, how to access the value of the matnr in my PAI which looks like this:
MODULE user_command_1000 INPUT.
" HOW TO ACCESS THE VALUE OF MATNR HERE?
ENDMODULE.
I have to guess what you did to get that far, and I’d strongly recommend not to continue along that road. What I’d rather do is
create a new dictionary structure (not a transparent table!) that contains the screen fields you need
use the TABLES statement with the structure to declare a global variable in your program or function pool top include
place the fields of the structure on the screen, just like you did with the MARA fields in your example
use the fields of your global variable in your coding
The way you prepared the screen, you would have to add a global variable named MARA with the structure of the transparent table MARA, probably using the statement TABLES mara. While this is perfectly possible, it’s also really dangerous - you could end up changing the database contents inadvertedly, especially since you seem to be rather new to the system.
This is probably one of those that is so simple I can't see it. I have a string variable called Market. The variable is user chosen and is the exact same name as one of many tables in my dataset. Basically I am having the user choose which table they want in a combobox, then I want to use that variable to access the table. So if the user picks "Market1" then I want to open the table named Market1.
I am simplifying here, but need to know how to open:
For ds.<variable here>.rows.count - 1
'perform steps
Next
How do I inject the variable correctly? Thanks ahead of time!
Dataset has Tables property, which accepts table name as a parameter. So in your case if string variable Market holds table name, you can access the table by referring to ds.Tables(Market)