I'm creating a vanilla plain business entity. in a master-detail relation.
The first BE, (master) works find, but when making the detail BE, it compiles ok, but when issuing the call to appserver, it shows those errors on log.
Detail table has no unique index, but I have some other pairs of BE in equally circumstances, and they works as expected.
I don't know if it's related to a annoying behavior I've seen frequently:
When modifying a table, normally adding a field or so, in PDSOE (by calling data dictionary, as the option to add column to table and so, in the db structure view, won't work for me) it takes really long to be able to see the modified field in DB structure view. By long I mean several (really quite a few) restarts of PDSOE. But now I finally can't refresh the DB Structure view, by using the refresh drop option, nor restarting pdsoe (right now I count some 20 restarts of pdsoe, and can't see the field in db view). code compiles ok, syntax proposition won't handle that field... but now I don't know if this is related to errors (by the way, the knowledgebase reports totally diferent conditions for those error numbers...
Any help would be very appreciated.
I suspect the PDSOE behaviour you are seeing is not related to the errors in the BE. I would log an issue with Tech Support about that.
Does this BE work if you define a unique index on the detail table? As per the (11895) error, you need either a unique index or a KEYS phrase on the data-source for the detail table. Can you attach the code and (temp-)table definitions? The (12478) message relates to disabling Database features, so I am not sure how this is related to your issue.
This is what I have:
/* dwdevold.i*/
DEFINE TEMP-TABLE ttdwDevolucionD BEFORE-TABLE bttdwDevolucionD
FIELD Sucursal AS INTEGER INITIAL "0"
FIELD Devolucion AS INTEGER INITIAL "0" LABEL "Num Dev"
FIELD Fecha AS DATETIME LABEL "Fecha dev."
FIELD Origen AS CHARACTER INITIAL "M" LABEL "Origen"
FIELD Control# AS DECIMAL INITIAL "0" LABEL "Num Etiqueta"
FIELD Articulo AS CHARACTER LABEL "Artículo"
FIELD Cantidad AS DECIMAL INITIAL "0"
FIELD TipoDev AS INTEGER INITIAL "0" LABEL "Tipo"
INDEX SucDev IS PRIMARY UNIQUE
Sucursal DESCENDING Devolucion DESCENDING
Articulo DESCENDING Cantidad DESCENDING TipoDev DESCENDING
INDEX SucFecha Sucursal DESCENDING Fecha DESCENDING .
DEFINE DATASET dsdwDevolucionD FOR ttdwDevolucionD.
and this is the BE class file:
USING Progress.Lang.*.
USING OpenEdge.BusinessLogic.BusinessEntity.
BLOCK-LEVEL ON ERROR UNDO, THROW.
CLASS DW.dwDevolD INHERITS BusinessEntity:
/*----------------------------------------------------------------------------------*/
{"DW\dwdevold.i"}
DEFINE DATA-SOURCE srcdwDevolucionD FOR dwh.dwDevolucionD.
CONSTRUCTOR PUBLIC dwDevolD():
DEFINE VAR hDataSourceArray AS HANDLE NO-UNDO EXTENT 1.
DEFINE VAR cSkipListArray AS CHAR NO-UNDO EXTENT 1.
SUPER (DATASET dsdwDevolucionD:HANDLE).
/* Data Source for each table in dataset. Should be in table order as defined in DataSet */
hDataSourceArray[1] = DATA-SOURCE srcdwDevolucionD:HANDLE.
/* Skip-list entry for each table in dataset. Should be in temp-table order as defined in DataSet */
/* Each skip-list entry is a comma-separated list of field names, to be ignored in create stmt */
cSkipListArray[1] = "".
THIS-OBJECT:ProDataSource = hDataSourceArray.
THIS-OBJECT:SkipList = cSkipListArray.
END CONSTRUCTOR.
/*------------------------------------------------------------------------------
Purpose: Get one or more records, based on a filter string
Notes:
------------------------------------------------------------------------------*/
METHOD PUBLIC VOID ReaddwDevolD(
INPUT filter AS CHARACTER,
OUTPUT DATASET dsdwDevolucionD):
SUPER:ReadData(filter).
END METHOD.
/*------------------------------------------------------------------------------
Purpose: Create one or more new records
Notes:
------------------------------------------------------------------------------*/
METHOD PUBLIC VOID CreatedwDevolD(INPUT-OUTPUT DATASET dsdwDevolucionD):
DEFINE VAR hDataSet AS HANDLE NO-UNDO.
hDataSet = DATASET dsdwDevolucionD:HANDLE.
SUPER:CreateData(DATASET-HANDLE hDataSet BY-REFERENCE).
END METHOD. .........
This is the last version, with all the fields (almost) in the PK, and yet it shows the same errors:
[15/04/07@10:21:38.453-0500] P-000300 T-005008 1 AS -- (Procedure: 'dw/pdwDevolD.p' Line:143) Sys error 1 : No se puede obtener SAVE-WHERE-STRING por que no hay frase KEYS para la definicion de DATA-SOURCE y no se encontro un indice único en dwDevolucionD. (11895)
[15/04/07@10:21:38.453-0500] P-000300 T-005008 1 AS -- (Procedure: 'dw/pdwDevolD.p' Line:143) Sys error 2 : No se puede generar FIND para dwDevolucionD en DATA-SOURCE-ROWID. (14278)
The errors are messages I sent form a catch block inside the handler procedure on the appserver....
Thanks!
This is what I have:
/* dwdevold.i*/
DEFINE TEMP-TABLE ttdwDevolucionD BEFORE-TABLE bttdwDevolucionD
FIELD Sucursal AS INTEGER INITIAL "0"
FIELD Devolucion AS INTEGER INITIAL "0" LABEL "Num Dev"
FIELD Fecha AS DATETIME LABEL "Fecha dev."
FIELD Origen AS CHARACTER INITIAL "M" LABEL "Origen"
FIELD Control# AS DECIMAL INITIAL "0" LABEL "Num Etiqueta"
FIELD Articulo AS CHARACTER LABEL "Artículo"
FIELD Cantidad AS DECIMAL INITIAL "0"
FIELD TipoDev AS INTEGER INITIAL "0" LABEL "Tipo"
INDEX SucDev IS PRIMARY UNIQUE
Sucursal DESCENDING Devolucion DESCENDING
Articulo DESCENDING Cantidad DESCENDING TipoDev DESCENDING
INDEX SucFecha Sucursal DESCENDING Fecha DESCENDING .
DEFINE DATASET dsdwDevolucionD FOR ttdwDevolucionD.
and this is the BE class file:
USING Progress.Lang.*.
USING OpenEdge.BusinessLogic.BusinessEntity.
BLOCK-LEVEL ON ERROR UNDO, THROW.
CLASS DW.dwDevolD INHERITS BusinessEntity:
/*----------------------------------------------------------------------------------*/
{"DW\dwdevold.i"}
DEFINE DATA-SOURCE srcdwDevolucionD FOR dwh.dwDevolucionD.
CONSTRUCTOR PUBLIC dwDevolD():
DEFINE VAR hDataSourceArray AS HANDLE NO-UNDO EXTENT 1.
DEFINE VAR cSkipListArray AS CHAR NO-UNDO EXTENT 1.
SUPER (DATASET dsdwDevolucionD:HANDLE).
/* Data Source for each table in dataset. Should be in table order as defined in DataSet */
hDataSourceArray[1] = DATA-SOURCE srcdwDevolucionD:HANDLE.
/* Skip-list entry for each table in dataset. Should be in temp-table order as defined in DataSet */
/* Each skip-list entry is a comma-separated list of field names, to be ignored in create stmt */
cSkipListArray[1] = "".
THIS-OBJECT:ProDataSource = hDataSourceArray.
THIS-OBJECT:SkipList = cSkipListArray.
END CONSTRUCTOR.
/*------------------------------------------------------------------------------
Purpose: Get one or more records, based on a filter string
Notes:
------------------------------------------------------------------------------*/
METHOD PUBLIC VOID ReaddwDevolD(
INPUT filter AS CHARACTER,
OUTPUT DATASET dsdwDevolucionD):
SUPER:ReadData(filter).
END METHOD.
/*------------------------------------------------------------------------------
Purpose: Create one or more new records
Notes:[/collapse]
Yes... I was about to inform that the database table, doesn't has a unique index....
it has (Sucursal + Devolucion) and (Sucursal + Fecha)
:(
(a side question, Mike)
You mean that a solid design has unique index for every table? even I have to invent one for some of them? All my master tables has uniques, but normally, the details not necessarily have one, as not needed at all...... well, until now :(
It is not mandatory by Relational design, but for performance purposes? besides to avoid the problems in'm facing rigth now?
Thanks for a very nutritive chat...
(a side question, Mike)
You mean that a solid design has unique index for every table? even I have to invent one for some of them? All my master tables has uniques, but normally, the details not necessarily have one, as not needed at all...... well, until now :(
It is not mandatory by Relational design, but for performance purposes? besides to avoid the problems in'm facing rigth now?
Thanks for a very nutritive chat...
Flag this post as spam/abuse.
DEFINE DATA-SOURCE srcdwDevolucionD FOR dwh.dwDevolucionD KEYS (Sucursal, Devolucion, Articulo, Cantidad, TipoDev ).
Did the trick...
Thanks a lot!
- as you are facing now, ProDatasets work best with unqiue indexes.
- Users may want to change every field values that they see on the screen. With a non meaningful key, they can change whatever they want without affecting relations to other tables.
- generic comments or attachments work best with standardized keys
+1 for the premise and +1 for using GUIDs (and no, your poor eyes not being able read them is not a sufficient excuse to not use them :)
Note that ROWIDs are becoming steadily less unique across a *database* with successive releases.
-- peter
Strong agreement with Mike on this one. The unique identity of a record should remain unique, whatever you do to it. There are many easily imagined scenarios where this can keep you out of trouble. And, there is no reason to display that identifier to the user.
!!!!!!! BUT !!!!!!
When I check the dw.dwdevolucionD table, it has no records, the client didn't got any error nor rejection from the server...
and the server didn't record anything on the broker or server logs...
I'll delete the BE and start from 0...
And on your hijacked post ... (jijiji)
Do you use the GUID'ed value of a GENERATE-UUID value?
extra-processing at create time?
Avoiding storing raw values on db?
Any thoughts?
And on your hijacked post ... (jijiji)
Do you use the GUID'ed value of a GENERATE-UUID value?
extra-processing at create time?
Avoiding storing raw values on db?
Any thoughts?
Flag this post as spam/abuse.
And on your hijacked post ... (jijiji)
Do you use the GUID'ed value of a GENERATE-UUID value?
extra-processing at create time?
Avoiding storing raw values on db?
Any thoughts?
Flag this post as spam/abuse.
And on your hijacked post ... (jijiji)
Do you use the GUID'ed value of a GENERATE-UUID value?
extra-processing at create time?
Avoiding storing raw values on db?
Any thoughts?
Flag this post as spam/abuse.
Flag this post as spam/abuse.
Mostly in agreement with Mike but strongly disagree on niceness of the KEYS option, that should not be there at all but now because for some strange reason made through should be avoided like a plague, much more than the use index option but that might be just me.
Giving the developer the option to invent primary keys where not enforced by a unique index is bad, even if there is an informal primary key now that can change over time and then I can imagine one will forget to update the keys in at least one place in the whole code base.
All right....
form now on, I'll create my tables with unique PK, by guid'em
Thanks!!!
[quote user="Peter Judge"]
and no, your poor eyes not being able read them is not a sufficient excuse to not use them :)
-- peter
And....
How do you name the field on the table?...
fGUIID? PK?, what is more natural, years after?
I go with just ID on the table itself and then names like CustomerID in a related table for the join.
And...
On master,detail, you create GUID as PK for child table also? as you already should have a GUID as FK to master,
After a second thought,
I respond myself: yes. (Isn't this the origin of this long debate? To be able to update the records from a dataset )
Yes, Order has an ID, OrderLine has its own ID and OrderID pointing to the Order, and ShippingLine or whatever has its own ID and OrderLIneID pointing to the OrderLine.
Finally, what's the winner expression to get the PK?:
Jeff proposes: HEX-ENCODE(GENERATE-UUID), wich is RAW datatype. and universal reach. Should it be STRING()'ed ??
Mike suggested: GUID(GENERATE-UUID) (Note the help file suggests that GUID() should be enough, but testing on scratchpad, it won't behaves as advertised) and global reach
I've been using base64-encode(generate-uuid), but it means you need to use case-sensitive fields.
I've been using base64-encode(generate-uuid), but it means you need to use case-sensitive fields.
Flag this post as spam/abuse.
Finally, what's the winner expression to get the PK?:
Jeff proposes: HEX-ENCODE(GENERATE-UUID), wich is RAW datatype. and universal reach. It should be STRING()'ed to
Mike suggested: GUID(GENERATE-UUID) (Note the help file suggests that GUID() should be enough, but testing on scratchpad, it won't behaves as advertised) and global reach
Flag this post as spam/abuse.
Flag this post as spam/abuse.
Flag this post as spam/abuse.
Bingo.. GUID simply will do the trick!
(Btw, as Mike says, I also consider prone to errors, that some other developer bypasses the case sensitivity of a field...)
Thanks!
Bingo.. GU simply will do the trick!
(Btw, as Mike says, I also consider prone to errors, that some other developer bypasses the case sensitivity of a field...)
Thanks!
Flag this post as spam/abuse.
Reply by Mike Fechner“No need to use STRING. HEX-ENCODE produces a string of the raw output from GENERATE-UUID.“Strange. According to the docs Jeff is right. It is supposed to return a CHARACTER value. However the AVM seems to disagree (11.5 64 bit):message hex-encode (generate-uuid)returnsINPUT/OUTPUT operations are not allowed with RAW, ROWID, MEMPTR, BLOB, CLOB or LONGCHAR type variables. (11382)Is that a bug or a feature?However Jeff, the output of string(hex-encode(generate-uuid)) and just replace (guid, “-“, “”) look pretty similar. So I question your expected difference between globally unique and universally unique. As we haven’t found E.T. yet and the idiots have not yet done their one-way trip to the Mars globally seems to be equal to universally.Stop receiving emails on this subject.Flag this post as spam/abuse.
Reply by Mike Fechner“No need to use STRING. HEX-ENCODE produces a string of the raw output from GENERATE-UUID.“Strange. According to the docs Jeff is right. It is supposed to return a CHARACTER value. However the AVM seems to disagree (11.5 64 bit):message hex-encode (generate-uuid)returnsINPUT/OUTPUT operations are not allowed with RAW, ROWID, MEMPTR, BLOB, CLOB or LONGCHAR type variables. (11382)Is that a bug or a feature?However Jeff, the output of string(hex-encode(generate-uuid)) and just replace (guid, “-“, “”) look pretty similar. So I question your expected difference between globally unique and universally unique. As we haven’t found E.T. yet and the idiots have not yet done their one-way trip to the Mars globally seems to be equal to universally.Stop receiving emails on this subject.Flag this post as spam/abuse.
Flag this post as spam/abuse.
Then it should be good for us to know the variant of uuid the AVM creates, as one of the I remeber derives from mac address.. didn't?
Just a footnote to this old thread. There are a couple of issues outstanding.
One is a docu-bug. The manual as of 11.5 gives the syntax for GUID as
GUID( [UUID] )
when in fact it is
GUID[( UUID )]
i.e., the UUID seed is optional, but if it is omitted, the parens must be omitted too.
My reading of the manual ... which might be suspect, considering the above ... is that leaving out the UUID is the equvalant of
GUID( GENERATE-UUID )
For reference, base64-encode(generate-uuid) produces a case-sensitive string 24 long, hex-encode( generate-uuid ) produces a non-case-sensitive string 32 long and a simple GUID produces a non-case-sensitive string 36 long, apparently because of the addition of four dashes in fixed locations.
I would like to hear some official response to Mark Opfer's claim that using one of these three is insufficient if multiple machines is involved. This seems rather important!
Yes... indeed..
When working with this thread back then, I noticed also the bug in sintax description, but didn't reported here... As I recall I went to tech support to report it.. (at least i thought doing it)
And also, I found counter documentation the proof Mr. Opfer has found... That would be nice to dig into it...
Best Regards,