Reference a table through a string representation of the name - progress-4gl

I'm trying to write a modular procedure, where I pass in a string representation of a table name, and query/update that table.
What I tried was something to this affect:
PROCEDURE foo:
DEFINE INPUT PARAMETER chTableName AS CHARACTER NO-UNDO.
FIND FIRST VALUE(chTableName) NO-LOCK
WHERE blahblahblah NO-ERROR.
IF AVAIL VALUE(chTableName) THEN
ASSIGN
VALUE(chTableName).value = foo.
END PROCEDURE.
This obviously does not work, but hopefully this will get the point across of what I'm trying to accomplish.
Any help or info in this matter would be appreciated. Thanks.

Hopefully you are running version 9 or better where dynamic queries are available.
procedure x:
define input parameter tbl as character no-undo.
define input parameter fld as character no-undo.
define input parameter xyz as character no-undo.
define variable qh as handle no-undo.
define variable bh as handle no-undo.
define variable fh as handle no-undo.
create buffer bh for table tbl.
create query qh.
qh:set-buffers( bh ).
qh:query-prepare( "for each " + tbl ).
qh:query-open.
do transaction:
qh:get-first( exclusive-lock ).
fh = bh:buffer-field( fld ).
display fh:buffer-value.
fh:buffer-value = xyz.
end.
delete object bh.
delete object qh.
return.
end.
run x ( "customer", "name", "fred" ).
find first customer no-lock.
display name.

This can get you started:
DEFINE TEMP-TABLE tt NO-UNDO
FIELD a AS INTEGER.
PROCEDURE foo:
DEFINE INPUT PARAMETER pcTable AS CHARACTER NO-UNDO.
DEFINE INPUT PARAMETER pcWhere AS CHARACTER NO-UNDO.
DEFINE INPUT PARAMETER pcField AS CHARACTER NO-UNDO.
DEFINE INPUT PARAMETER piValue AS INTEGER NO-UNDO.
DEFINE VARIABLE hBuffer AS HANDLE NO-UNDO.
DEFINE VARIABLE hQuery AS HANDLE NO-UNDO.
CREATE BUFFER hBuffer FOR TABLE pcTable.
CREATE QUERY hQuery.
hQuery:SET-BUFFERS(hBuffer).
hQuery:QUERY-PREPARE("FOR EACH " + pcTable + " WHERE " + pcWhere).
hQuery:QUERY-OPEN().
hQuery:GET-FIRST().
IF hBuffer:AVAILABLE THEN DO:
ASSIGN
hBuffer:BUFFER-FIELD(pcField):BUFFER-VALUE = piValue NO-ERROR.
IF ERROR-STATUS:ERROR THEN DO:
MESSAGE "Failed" VIEW-AS ALERT-BOX ERROR.
END.
END.
DELETE OBJECT hBuffer.
DELETE OBJECT hQuery.
END PROCEDURE.
CREATE tt.
ASSIGN tt.a = 1.
RUN foo( INPUT "tt"
, INPUT "tt.a = 1"
, INPUT "a"
, INPUT 2).
DISPLAY tt.

Related

Progress 4GL - update

how can I check if update was successful when I run this For Each
FOR EACH products
WHERE products.name = "ProductsName":
update price = 1000.
END.
Sometimes this For Each is ok, but sometimes when record is lock it doesn't work. I need run this For Each via WebSpeed and return true when For Each is successful or false when not. How can I get this result?
You should add more details to your request, but try this it might help get you started:
procedure update_items:
define output parameter records_read as integer no-undo.
define output parameter records_updated as integer no-undo.
define output parameter records_locked as integer no-undo.
define buffer item for item.
define buffer item_update for item.
define variable retry_count as integer no-undo.
for each item no-lock:
accumulate 1 (total).
records_read = (accum total 1).
retry_count = 0.
repeat for item_update:
find item_update exclusive-lock
where rowid(item_update) = rowid(item)
no-wait no-error.
if locked item_update then do:
if retry_count > 5 then do:
records_locked = records_locked + 1.
leave.
end.
retry_count = retry_count + 1.
do on endkey undo, leave:
pause 3 no-message.
end.
undo, next.
end.
if not available item_update then do:
/*If that matters you can code for it too*/
leave.
end.
item_update.Price = 1000.
release item_update.
records_updated = records_updated + 1.
leave.
end.
end.
end.
define variable items_read as integer no-undo.
define variable items_updated as integer no-undo.
define variable items_locked as integer no-undo.
run update_items(output items_read,
output items_updated,
output items_locked).
display items_read items_updated items_locked with side-labels 1 col.

How to get common words from two different sentences by using ENTRY function in progress4gl?

How to get common words from two different sentences by using ENTRY function in progress4gl?
define variable a1 as character no-undo initial "hi dude do".
define variable a2 as character no-undo initial "hi man it".
define variable cnta as character.
define variable cntb as character.
define variable cntc as character.
define variable i as integer.
define variable j as integer.
do i = 1 to 3:
entry (i,a1,"").
do j = 1 to 3:
entry (j,a2,"").
end.
end.
/* assign cntc = cnta matches cntb . */
define variable a1 as character no-undo initial "hi dude do".
define variable a2 as character no-undo initial "hi man it".
define variable common as character no-undo.
define variable cc as integer no-undo.
define variable ii as integer no-undo.
define variable jj as integer no-undo.
define variable n1 as integer no-undo.
define variable n2 as integer no-undo.
n1 = num-entries( a1 ).
n2 = num-entries( a2 ).
do ii = 1 to n1:
do jj = 1 to n2:
if entry ( ii, a1, " ") = entry( jj, a2, " " ) then
do:
cc = cc + 1.
common = common + " " + entry( ii, a1, " " ).
end.
end.
end.
display trim( cc ) common.
Notes:
The TRIM() function is just to clean up the "common" string so it doesn't have an extra space.
For performance reasons it is good to get in the habit of obtaining NUM-ENTRIES() outside the loop rather than with every iteration of the loop. It doesn't make much difference for small strings but for large strings it can have quite an impact.
1./*if i need to get the n number of words in two sentences from the user at the run time , how to compare and the get the common words.
the following code compares and displays only first letter of the two sentence.
*/
define variable a1 as character no-undo.
define variable a2 as character no-undo.
define variable common as character no-undo.
define variable a1 as character FORMAT "x(64)" no-undo /* initial "hi d do" */.
define variable a2 as character FORMAT "x(64)" no-undo /* initial "hi d it" */.
define variable common as character FORMAT "x(64)" no-undo.
define variable c1 as character FORMAT "x(64)" no-undo.
define variable x as character FORMAT "x(64)" no-undo.
define variable y as character FORMAT "x(64)" no-undo.
define variable cc as integer no-undo initial 0.
define variable ii as integer no-undo.
define variable jj as integer no-undo.
define variable n1 as integer no-undo.
define variable n2 as integer no-undo.
set a1.
n1 = num-entries( a1,"" ).
set a2.
n2 = num-entries( a2,"" ).
do ii = 1 to n1:
do jj = 1 to n2:
if entry ( ii,a1, " ") matches entry( jj,a2, " " ) then
do:
common = entry( ii, a1, " " ).
display common .
end.
end.
end.

OpenEdge: how to remove HTML tags from a string?

I have tried doing this:
REPLACE(string, "<*>", "").
but it doesn't seem to work.
REPLACE doesn't work like that. There's no wildcard matching in it.
I've included a simple way of doing this below. However, there's lots of cases that this wont work in - non well formed html etc. But perhaps you can start here and move forward by yourself.
What I do is look for < and > in the text and replace everything between it with a pipe (|) (you could select any character - preferably something not present in the text. When that's done all pipes are removed.
Again, this is a quick and dirty solution and not safe for production...
PROCEDURE cleanHtml:
DEFINE INPUT PARAMETER pcString AS CHARACTER NO-UNDO.
DEFINE OUTPUT PARAMETER pcCleaned AS CHARACTER NO-UNDO.
DEFINE VARIABLE iHtmlTagBegins AS INTEGER NO-UNDO.
DEFINE VARIABLE iHtmlTagEnds AS INTEGER NO-UNDO.
DEFINE VARIABLE lHtmlTagActive AS LOGICAL NO-UNDO.
DEFINE VARIABLE i AS INTEGER NO-UNDO.
DO i = 1 TO LENGTH(pcString):
IF lHtmlTagActive = FALSE AND SUBSTRING(pcString, i, 1) = "<" THEN DO:
iHtmlTagBegins = i.
lHtmlTagActive = TRUE.
END.
IF lHtmlTagActive AND SUBSTRING(pcString, i, 1) = ">" THEN DO:
iHtmlTagEnds = i.
lHtmlTagActive = FALSE.
SUBSTRING(pcString, iHtmlTagBegins, iHtmlTagEnds - iHtmlTagBegins + 1) = FILL("|", iHtmlTagEnds - iHtmlTagBegins).
END.
END.
pcCleaned = REPLACE(pcString, "|", "").
END PROCEDURE.
DEFINE VARIABLE c AS CHARACTER NO-UNDO.
RUN cleanHtml("This is a <b>text</b> with a <i>little</i> bit of <strong>html</strong> in it!", OUTPUT c).
MESSAGE c VIEW-AS ALERT-BOX.

how to create a temp table with dynamic field number in progress (openedge 4gl)

how to use that with out define a temp table...
CREATE TEMP-TABLE tt.
Lifted straight from the documentation:
DEFINE VARIABLE tth AS HANDLE NO-UNDO.
DEFINE VARIABLE bh AS HANDLE NO-UNDO.
DEFINE VARIABLE qh AS HANDLE NO-UNDO.
DEFINE VARIABLE buf-ord-hndl AS HANDLE NO-UNDO.
DEFINE VARIABLE buf-rep-hndl AS HANDLE NO-UNDO.
DEFINE VARIABLE fld1 AS HANDLE NO-UNDO.
DEFINE VARIABLE fld2 AS HANDLE NO-UNDO.
/* Get database table handles */
buf-ord-hndl = BUFFER Order:HANDLE.
buf-rep-hndl = BUFFER SalesRep:HANDLE.
/* Create an empty, undefined TEMP-TABLE */
CREATE TEMP-TABLE tth.
/* Give it Order table’s fields & indexes */
tth:CREATE-LIKE(buf-ord-hndl).
/* Add field like SalesRep.RepName */
tth:ADD-LIKE-FIELD("RepName","SalesRep.RepName").
/* No more fields will be added */
tth:TEMP-TABLE-PREPARE("ordx").
/* Get the buffer handle for the temp-table */
bh = tth:DEFAULT-BUFFER-HANDLE.
/* Populate the temp-table from order */
FOR EACH Order NO-LOCK:
bh:BUFFER-CREATE.
bh:BUFFER-COPY(buf-ord-hndl).
/* Add the corresponding salesrep name */
FIND SalesRep NO-LOCK WHERE SalesRep.SalesRep = Order.SalesRep NO-ERROR.
IF AVAILABLE SalesRep THEN
bh:BUFFER-COPY(buf-rep-hndl,?,"RepName,repname").
END.
/* Run a query to access the TEMP-TABLE */
CREATE QUERY qh.
qh:SET-BUFFERS(bh).
qh:QUERY-PREPARE("FOR EACH ordx WHERE ordx.OrderNum < 50 BY ordx.RepName").
qh:QUERY-OPEN().
fld1 = bh:BUFFER-FIELD("OrderNum").
fld2 = bh:BUFFER-FIELD("RepName").
/* Display the order number and the salesrep name */
REPEAT:
qh:GET-NEXT().
IF qh:QUERY-OFF-END THEN LEAVE.
DISPLAY fld1:BUFFER-VALUE() FORMAT "X(10)".
DISPLAY fld2:BUFFER-VALUE() FORMAT "X(20)".
END.
qh:QUERY-CLOSE().
bh:BUFFER-RELEASE().
DELETE OBJECT tth.
DELETE OBJECT qh.
If you are building from scratch you probably want to be using ADD-NEW-FIELD() rather than ADD-LIKE-FIELD().
If you have an XML schema you can also potentially use that to create the TT via something like:
DEFINE VARIABLE lRetOK AS LOGICAL NO-UNDO.
DEFINE VARIABLE cSourceType AS CHARACTER NO-UNDO.
DEFINE VARIABLE cFile AS CHARACTER NO-UNDO.
DEFINE VARIABLE lOverrideDefaultMapping AS LOGICAL NO-UNDO.
DEFINE VARIABLE cFieldTypeMapping AS CHARACTER NO-UNDO.
DEFINE VARIABLE cVerifySchemaMode AS CHARACTER NO-UNDO.
DEFINE VARIABLE hTable AS HANDLE NO-UNDO.
CREATE TEMP-TABLE hTable.
ASSIGN
cSourceType = "file"
cFile = "ttcust.xsd"
lOverrideDefaultMapping = FALSE
cFieldTypeMapping = "address2,CLOB"
cVerifySchemaMode = ?.
lRetOK = hTable:READ-XMLSCHEMA (cSourceType, cFile, lOverrideDefaultMapping,
cFieldTypeMapping,cVerifySchemaMode).

command to find the number of entries in a temp table

What is the command to find the number of entries/rows in a temp table? version 10.2b
/* create a temp-table so that we can test this technique
*/
define temp-table ttTest
field id as int
.
create ttTest.
id = 1.
create ttTest.
id = 2.
/* how many records?
*/
define query q for ttTest cache 0.
open query q preselect each ttTest.
display num-results( "q" ).
or you can use clasic FOR EACH:
DEFINE VARIABLE iCount AS INT NO-UNDO.
FOR EACH ttTest:
iCount = iCount + 1.
END.
DISPLAY iCount.
Here's mine, that works for any temp-table :
FUNCTION TT_NBREC RETURNS INTEGER ( INPUT pr_hd_temptable AS HANDLE ) :
DEFINE VARIABLE in_nbrec AS INTEGER NO-UNDO INITIAL 0.
DEFINE VARIABLE hd_buffer AS HANDLE NO-UNDO.
DEFINE VARIABLE hd_query AS HANDLE NO-UNDO.
DEFINE VARIABLE ch_query AS CHARACTER NO-UNDO.
DEFINE VARIABLE ch_table AS CHARACTER NO-UNDO.
DEFINE VARIABLE lg_error AS LOGICAL NO-UNDO.
ASSIGN
ch_table = pr_hd_temptable:NAME
ch_query = "FOR EACH " + ch_table + " NO-LOCK".
CREATE BUFFER hd_buffer FOR TABLE ch_table.
CREATE QUERY hd_query.
hd_query:ADD-BUFFER( hd_buffer ).
lg_error = hd_query:QUERY-PREPARE( ch_query ) NO-ERROR.
hd_query:QUERY-OPEN().
hd_query:GET-FIRST().
DO WHILE NOT hd_query:QUERY-OFF-END :
ASSIGN in_nbrec = in_nbrec + 1.
hd_query:GET-NEXT().
END.
hd_query:QUERY-CLOSE().
DELETE OBJECT hd_query.
DELETE OBJECT hd_buffer.
ASSIGN
hd_query = ?
hd_buffer = ?.
RETURN in_nbrec.
END FUNCTION.
Just pass it the handle of your temp-table and you get the number of records.
It can certainly be improved, but it works fast enough for me.