Check if record already exists when doing a buffer-copy - openedge

I have a piece of code which does a Buffer-Copy method, but is there any way to check before doing the buffer copy of the record already exists? I do not want to check 'unique keys' in my data dictionary.
This is the code I have at this moment:
CREATE QUERY hQuery.
hQuery:SET-BUFFERS(hBuffer).
hQuery:QUERY-PREPARE("FOR EACH " + hBuffer:NAME + " NO-LOCK ").
hQuery:QUERY-OPEN().
hQuery:GET-FIRST().
DO WHILE NOT hQuery:QUERY-OFF-END:
DO TRANSACTION ON ERROR UNDO:
hDBBuffer:BUFFER-CREATE().
hDBBuffer:BUFFER-COPY(hBuffer) NO-ERROR.

It is unclear what you are trying to accomplish and why you don't want to check unique keys "in my data dictionary" or even what you mean by that.
Your example code is very sketchy and incomplete, maybe someone else can figure out what you are trying to do and why, but I am at a loss to divine the purpose behind it. The use of handles and dynamic queries is especially puzzling. There doesn't seem to be a reason for that or any need to do that.
None the less, if I were coding a routine to copy a buffer, couldn't look up unique indexes in the dictionary, and wanted to pro-actively avoid potential collisions I might write something like this:
define temp-table oLine like orderLine.
for each orderline no-lock:
find oLine of orderLine no-error.
if not available( oLine ) then create oLine.
buffer-copy orderLine to oline.
end.
(Using static coding to keep the example simple.)
(I wouldn't really use OF - it is on my personal forbidden list, I think it is terrible from a documentation and maintenance perspective.)

I believe, as Tom has mentioned in his reply, it'd be most appropriate to have another dynamic query directed at the hDBBuffer using the BUFFER-FIELDs and BUFFER-VALUEs from hBuffer and check the NUM-RESULTS after you use QUERY-OPEN. Then delete the query for memory purposes.
But yes, you would be looking for the metadata unique keys to achieve that. I understand you don't want to do it, but it's REALLY the best way, can't stress it enough.
Now if you would really like to check for the existence of ALL the record data, look into the BUFFER-COMPARE method. You could create a second dynamic query, then cycle all records there by using buffer-compare to match the entire record you're looking at to the one you're assessing whether to create, or list the ones you wish to include or exclude. This approach is way less performatic, though, please keep that in mind.

Related

Function of Rows, Rowsets in PeopleCode

I'm trying to get a better understanding of what Rows and Rowsets are used for in PeopleCode? I've read through PeopleBooks and still don't feel like I have a good understanding. I'm looking to get more understanding of these as it pertains to Application Engine programs. Perhaps walking through an example may help. Here are some specific questions I have:
I understand that Rowsets, Row, Record, and Field are used to access component buffer data, but is this still the case for stand alone Application Engine programs run via Process Scheduler?
What would be the need or advantage to using these as opposed to using SQL objects/functions (CreateSQL, SQLExec, etc...)? I often see in AE programs where the CreateRowset object is instantiated and uses a .Fill method with a SQL WHERE Clause and I don't quite understand why a SQL was not used instead.
I've seen in PeopleBooks that a Row object in a component scroll is a row, how does a component scroll relate to the row? I've seen references to rows having different scroll levels, is this just a way of grouping and nesting related data?
After you have instantiated the CreateRowset object, what are typical uses of it in the program afterwards? How would you perform logic (If, Then, Else, etc..) on data retrieved by the rowset, or use it to update data?
I appreciate any insight you can share.
You can still use Rowsets, Rows, Records and fields in stand alone Application Engines. Application Engines do not have component buffer data as they are not running within the context of a component. Therefore to use these items you need to populate them using built-in methods like .fill() on a rowset, or .selectByKey() on a record.
The advantage of using rowsets over SQL is that it makes the CRUD easier. There are built-in methods for selecting, updating, inserting and deleting. Additionally you don't have to worry about making a large number of variables if there were multiple fields like you would with a SQL object. Another advantage is when you do the fill, the data is read into memory, where if you looped through the SQL, the SQL cursor would be open longer. The rowset, row, record and field objects also have a lot of other useful methods such as allowing you to executeEdits (validation) or copy from one rowset\row\record to another.
This question is a bit less clear to me but I'll try and explain. If you have a Page, it would have a level 0 row. It then could have multiple Level 1 rowsets. Under each of those it could have a level 2 rowsets.
Level0
/ \
Level1 Level1
/ \ / \
Level2 Level2 Level2 Level2
If one of your level1 rows had 3 rows, then you would find 3 rows in the Rowset associated with that level1. Not sure I explained this to answer what you need, please clarify if I can provide more info
Typically after I create a rowset, I would loop through it. Access the record on each row, do some processing with it. In the example below, I look through all locked accounts and prefix their description with LOCKED and then updated the database.
.
Local boolean &updateResult;
local integer &i;
local record &lockedAccount;
Local rowset &lockedAccounts;
&lockedAccounts = CreateRowset(RECORD.PSOPRDEFN);
&lockedAccounts.fill("WHERE acctlock = 1");
for &i = 1 to &lockedAccounts.ActiveRowCount
&lockedAccount = &lockedAccounts(&i).PSOPRDEFN;
if left(&lockedAccount.OPRDEFNDESCR.value,6) <> "LOCKED" then
&lockedAccount.OPRDEFNDESCR.value = "LOCKED " | &lockedAccount.OPRDEFNDESCR.value;
&updateResult = &lockedAccount.update();
if not &updateResult then
/* Error handle failed update */
end-if;
end-if;
End-for;

How can I be notified of an index being updated on DynamoDB?

I have a table (key=username, value=male or female) and an index on the values.
After I add an item to the table, I want to update the counts of males and females. However, after a successful write, as the index is a Global Secondary Index, the count query is not consistent.
Is there a way (dynamo db Streams, Lambda, ...) to monitor when the index is up to date?
Note that Im not looking for a solution that involves something else (keep count of increments in redis or ...), what I describe here is a simplified problem to especially ask a question about how can I monitor an index in dynamo.
Thanks!
I am not sure if there is any mechanism currently provided to check this but, you can easily solve this problem by adding a single line of code to your query.
ConsistentRead = True
DynamoDB has a parameter when set as true will make sure that you get latest updated value.
Now, when you add/update the item and then query the data add ConsistentRead option in it, this will ensure that you will have latest count value.
Here is the reference link.
If you are able to accomplish using other technique then please do share it.
Hope that helps.

PLSQL Procedure to change data across a full database

I've been asked to write a PLSQL procedure to 'clean up' codes in a database. The codes are varchar2 and are something like 00000001. They are used everywhere in the application. My new employer wants me to make the codes more readable as in turn the 00000001 into just 1 for everywhere they are used.
My question is how would one even go about that? I asked for clarification and it's still not clear and for fear of looking foolish I won't ask again. Any guidance would be welcome
let me start by saying that that sounds like a VERY BAD IDEA!!!!
if you persist it sound like you will need to use dynamic sql with the basic process of...
query all_tab_cols to get a list of columns( im hoping all your columns that use these codes have a naming standard.. ie xxx_CD )
loop over tab/cols to see if your value is there
update values in that table
...
profit ?
however then you get stuck by realities.. if the code is in a foreign key you cant just update it. you'd have to create a new parent record.. update all children to new parent then delete old parent.
you'd need to be very clear on what you are trying to achieve.. and more importantly, is there any value in it?
i suggest you start with a single codevalue to scope out the size of project.
manually start writing the updates you'd need for that 1 codevalue and then try to start automating it.

Generate Number with Validating rule in Access

I have a database in access for institute. there is a [Registers] Table and [Certificates] Table.
I want to give Mark to each of Registers a Mark. I want to set Validation Rule for Each
If [Certificates].[Mark]>70
Then UpdateRecord
SetField
CertificateID "GENERATE AutoNumber"
My Problem is i cant handle the CertificateID Generate with Macro. i cant use DMAX.
looking for a solution to give CertificateID to only Registers who passed the Course.
Tried "After Update" Macro and "After Insert" macro but still didnt success.
is there any other way to give AutoNumber except "DMax"?
Well, i just already found a way but not the best way.
I just added another Table as "Certificates" and renamed current(Certificates) to "Marks".
Tables and Fields
i made a query with Select a "Grade" from Certificates Table and rest from Marks. Whenever i fill a record in Grade table it generate Autonumber for "CertificateID" a new number.
For Validation i set my validation Rule in my form on Grade which i cant fill that field if Marks.Mark is less than 70. ( [Marks].[Mark] < 70)
I know its not a good way.
Still looking for better answer

Filtering a multivalued attribute in StringTemplate

I have a template which uses the same multivalued attribute in various places. I often find myself in a situation where I would like to filter the attribute before a template is applied to the individual values.
I can do this:
<#col:{c|<if(cond)><# c.Attribute2 #><endif>};separator=\",\"#>
but that is not what I want, because then there are separators in the output separating "skipped" entries, like:
2,4,,,6,,4,5,,
I can modify it to
<#col:{c|<if(c.Attribute1)><# c.Attribute2 #>,<endif>};separator=\"\"#>
Which is almost OK, but I get an additional separator after the last number, which sometimes does not matter (usually when the separator is whitespace), but sometimes does:
2,4,6,4,5,
I sometimes end up doing:
<#first(col):{c|<if(cond)><# c.Attribute2 #><endif>};separator=\"\"#>
<#rest(col):{c|<if(cond)>,<# c.Attribute2 #><endif>};separator=\"\"#>
But this approach fails if the first member does not satisfy the condition, then there is an extra separator in the beginning:
,2,4,6,4,5
Can someone give me a better solution?
First, let me point out that I think you are trying to do logic inside your template. Any time you hear things like "filter my list according to some condition based upon the data" it might be time to compute that filtered list in the model and then push it in. That said something like this might work where we filter the list first:
<col:{c | <if(c.cond)>c<endif>}:{c2 | <c2.c.attribute>}>
c2.c accesses the c parameter from the first application
The answer by "The ANTLR Guy" didn't help in my case and I found another workaround. See at Filter out empty strings in ST4

Resources