With my clarion 6.1 I get runtime error when entering the template generated update form.
I have these two files:
platni_instrumenti FILE,DRIVER('ODBC'),OWNER('wmj'),NAME('platni_instrumenti'),PRE(plins),CREATE,BINDABLE,THREAD
KeyPLINS KEY(plins:ind_otkup_prodaja,plins:oznaka_platnog_instrumenta_u_k),NOCASE,OPT,PRIMARY
KeyPLINS_akt_ind KEY(plins:aktivnost,plins:ind_otkup_prodaja),DUP,NOCASE,OPT
Record RECORD,PRE()
ind_otkup_prodaja STRING(1)
oznaka_platnog_instrumenta_u_k STRING(5)
opis STRING(100)
indikator STRING(1)
aktivnost STRING(1)
END
END
provizija FILE,DRIVER('ODBC'),OWNER('wmj'),NAME('provizija'),PRE(pr),CREATE,BINDABLE,THREAD
KeyPR_val_akt_indIns_ins_izn KEY(pr:valuta,pr:aktivnost,pr:ind_platnog_instrumenta,pr:platni_instrument,pr:minimalni_iznos),DUP,NOCASE,OPT
KeyPR_akt_val_indIns_ins_izn KEY(pr:aktivnost,pr:valuta,pr:ind_platnog_instrumenta,pr:platni_instrument,pr:minimalni_iznos),NOCASE,OPT
KeyPR_indIns_ins_akt_val_izn KEY(pr:ind_platnog_instrumenta,pr:platni_instrument,pr:aktivnost,pr:valuta,pr:minimalni_iznos),DUP,NOCASE,OPT
Record RECORD,PRE()
valuta STRING(3)
platni_instrument STRING(5)
ind_platnog_instrumenta STRING(1)
minimalni_iznos DECIMAL(10,2)
postotak_provizije DECIMAL(5,2)
aktivnost STRING(1)
END
END
I have put in DCT the relation between KeyPLINS and KeyPR_indIns_ins_akt_val_izn with On update=Cascade on Delete=Restrict.
When i enter the update form for change it fails in primeUpdate. The exception is :
java.lang.RuntimeException: Address invalid
org.jclarion.clarion.ClarionAny.deserialize(ClarionAny.java:250)
org.jclarion.clarion.ClarionGroup.deserialize(ClarionGroup.java:485)
org.jclarion.clarion.ClarionGroup.deserialize(ClarionGroup.java:480)
org.jclarion.clarion.runtime.OverGlue.objectChanged(OverGlue.java:123)
org.jclarion.clarion.ClarionMemoryModel.notifyChange(ClarionMemoryModel.java:219)
org.jclarion.clarion.ClarionGroup$1.objectChanged(ClarionGroup.java:89)
org.jclarion.clarion.ClarionMemoryModel.notifyChange(ClarionMemoryModel.java:219)
org.jclarion.clarion.ClarionString.notifyChange(ClarionString.java:1487)
org.jclarion.clarion.ClarionString.setValue(ClarionString.java:364)
org.jclarion.clarion.ClarionObject.setValue(ClarionObject.java:190)
org.jclarion.clarion.ClarionQueue$QueueEntry.copyToGroup(ClarionQueue.java:100)
org.jclarion.clarion.ClarionQueue.restoreRecord(ClarionQueue.java:423)
org.jclarion.clarion.ClarionQueue.get(ClarionQueue.java:829)
org.jclarion.clarion.ClarionQueue.get(ClarionQueue.java:841)
clarion.Bufferedpairsclass.assignLeftToBuffer(Bufferedpairsclass.java:57)
clarion.Relationmanager.save(Relationmanager.java:541)
clarion.Windowmanager.primeUpdate(Windowmanager.java:369)
clarion.Thiswindow_20.init(Thiswindow_20.java:118)
Thanks
Nenad
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I was too fast.
Now i get no exception when entering the platni_instrumenti form. Now is the provizija form that behaves strangely. when doing change some error is returned and i can not change provizija. Also when from the provizija browse i try to delete the record i get exception ClarionSqlFile Reget not yet implemented.
I will try to investigate more.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
table in question has a primary key defined. This will explain why you cannot perform delete on provizija : it does not have a primary key
keys used for browsing tables, the key must be essentially unique. i.e. if you key on NAME and name allows duplicates, modify key so it is name+id. If a key used for browsing is not unique, then strange artefacts can occur when browsing etc
That browse actually does use a key, not file based browse
I am pretty sure clarion with ODBC access has similar limitations; though they manifest themselves in slightly different ways than in c2j.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Yes, i was missing the primary key in provizija.
There is still one thing not working:
platni_instrumenti first key: it has primary and unique. I have created browse from template and put Range on ind_otkup_prodaja with option Single value equal to IndFilt (which is string(1) local variable). It simly ignores the vairable and shows all. If i use the Filter prompt then it is OK. It might be ABC error but it seems strange.
thanks
Nenad
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I would expect single value to work. I use this regularly with my app, (clarion 5.5 ABC). Suggest look at log file generated, it logs SQL commands executed. Hopefully this will provide some clues.
To enable logging on detailed level: add following into code somewhere before point you want to log:
@java-code 'new org.jclarion.clarion.log.Debug();'
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Just looking at the code, I think that set(view,number) is incorrectly implemented in c2j. Question is whether or not clarion 6 ABC utilises this to implement single value behaviour. Looking at my clarion 6 libsrc, it appears that this would not explain error. Still, above debugging information I indicate above will help understand cause of this.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I have managed to log now. The following is strange
12/14 08:07:03 F ClarionSQLFile - SELECT A.ind_otkup_prodaja,A.oznaka_platnog_instrumenta_u_k,A.opis,A.indikator,A.aktivnost FROM platni_instrumenti A WHERE (UPPER('O')=UPPER('O') AND A.aktivnost='A') AND (upper(A.ind_otkup_prodaja)>'O' OR (upper(A.ind_otkup_prodaja)='O' AND (upper(A.oznaka_platnog_instrumenta_u_k)>=''))) ORDER BY UPPER(A.ind_otkup_prodaja),UPPER(A.oznaka_platnog_instrumenta_u_k) LIMIT 100 []
UPPER('O')=UPPER('O') has no sense but i think it is upper(A.ind_otkup_prodaja)>'O' OR … that makes it working wrong.
This is my window init procedure
ThisWindow.Init PROCEDURE
ReturnValue BYTE,AUTO
CODE
GlobalErrors.SetProcedureName('SelPlins')
SELF.Request = GlobalRequest ! Store the incoming request
ReturnValue = PARENT.Init()
IF ReturnValue THEN RETURN ReturnValue.
SELF.FirstField = ?Browse:1
SELF.VCRRequest &= VCRRequest
SELF.Errors &= GlobalErrors ! Set this windows ErrorManager to the global ErrorManager
SELF.AddItem(Toolbar)
CLEAR(GlobalRequest) ! Clear GlobalRequest after storing locally
CLEAR(GlobalResponse)
SELF.AddItem(?Close,RequestCancelled) ! Add the close control to the window amanger
Relate:platni_instrumenti.SetOpenRelated()
Relate:platni_instrumenti.Open ! File platni_instrumenti used by this procedure, so make sure it's RelationManager is open
SELF.FilesOpened = True
BRW1.Init(?Browse:1,Queue:Browse:1.ViewPosition,BRW1::View:Browse,Queue:Browse:1,Relate:platni_instrumenti,SELF) ! Initialize the browse manager
SELF.Open(QuickWindow) ! Open window
Do DefineListboxStyle
IndFilt=Ind !Ind is string parametar of the procedure and IndFilt is procedure local String(1)
BRW1.Q &= Queue:Browse:1
BRW1.RetainRow = 0
BRW1.AddSortOrder(,plins:KeyPLINS) ! Add the sort order for plins:KeyPLINS for sort order 1
BRW1.AddRange(plins:ind_otkup_prodaja,IndFilt) ! Add single value range limit for sort order 1
BRW1.AddLocator(BRW1::Sort0:Locator) ! Browse has a locator for sort order 1
BRW1::Sort0:Locator.Init(,plins:oznaka_platnog_instrumenta_u_k,1,BRW1) ! Initialize the browse locator using using key: plins:KeyPLINS , plins:oznaka_platnog_instrumenta_u_k
BRW1.SetFilter('(plins:aktivnost=''A'' )') ! Apply filter expression to browse
BRW1.AddField(plins:ind_otkup_prodaja,BRW1.Q.plins:ind_otkup_prodaja) ! Field plins:ind_otkup_prodaja is a hot field or requires assignment from browse
BRW1.AddField(plins:oznaka_platnog_instrumenta_u_k,BRW1.Q.plins:oznaka_platnog_instrumenta_u_k) ! Field plins:oznaka_platnog_instrumenta_u_k is a hot field or requires assignment from browse
BRW1.AddField(plins:opis,BRW1.Q.plins:opis) ! Field plins:opis is a hot field or requires assignment from browse
BRW1.AddField(plins:indikator,BRW1.Q.plins:indikator) ! Field plins:indikator is a hot field or requires assignment from browse
BRW1.AddField(plins:aktivnost,BRW1.Q.plins:aktivnost) ! Field plins:aktivnost is a hot field or requires assignment from browse
Resizer.Init(AppStrategy:Surface,Resize:SetMinSize) ! Controls like list boxes will resize, whilst controls like buttons will move
SELF.AddItem(Resizer) ! Add resizer to window manager
INIMgr.Fetch('SelPlins',QuickWindow) ! Restore window settings from non-volatile store
Resizer.Resize ! Reset required after window size altered by INI manager
BRW1.AddToolbarTarget(Toolbar) ! Browse accepts toolbar control
SELF.SetAlerts()
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Committed a fix to runtime. Please try now. System should not allow view to contain UPPER(fieldname) in SQL:Filter property and work as you would expect them to.
Have not encountered this one myself because my app does not use strings a first element in composite keys. All my composite key tables use numerics as first field. c2j contains a powerful SQL optimisation that only applies in these circumstances; highly recommended, for performance reasons at least, if you are going to use composite keys then make first element numeric if you possibly can.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Now it works. Thanks.
The information about the first field in key being numeric is interesting but not applicable to my project. As I told you I have to undergo the certification process. I have documents where the column names and types are specified and so immutable.
Nenad
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
With my clarion 6.1 I get runtime error when entering the template generated update form.
I have these two files:
platni_instrumenti FILE,DRIVER('ODBC'),OWNER('wmj'),NAME('platni_instrumenti'),PRE(plins),CREATE,BINDABLE,THREAD
KeyPLINS KEY(plins:ind_otkup_prodaja,plins:oznaka_platnog_instrumenta_u_k),NOCASE,OPT,PRIMARY
KeyPLINS_akt_ind KEY(plins:aktivnost,plins:ind_otkup_prodaja),DUP,NOCASE,OPT
Record RECORD,PRE()
ind_otkup_prodaja STRING(1)
oznaka_platnog_instrumenta_u_k STRING(5)
opis STRING(100)
indikator STRING(1)
aktivnost STRING(1)
END
END
provizija FILE,DRIVER('ODBC'),OWNER('wmj'),NAME('provizija'),PRE(pr),CREATE,BINDABLE,THREAD
KeyPR_val_akt_indIns_ins_izn KEY(pr:valuta,pr:aktivnost,pr:ind_platnog_instrumenta,pr:platni_instrument,pr:minimalni_iznos),DUP,NOCASE,OPT
KeyPR_akt_val_indIns_ins_izn KEY(pr:aktivnost,pr:valuta,pr:ind_platnog_instrumenta,pr:platni_instrument,pr:minimalni_iznos),NOCASE,OPT
KeyPR_indIns_ins_akt_val_izn KEY(pr:ind_platnog_instrumenta,pr:platni_instrument,pr:aktivnost,pr:valuta,pr:minimalni_iznos),DUP,NOCASE,OPT
Record RECORD,PRE()
valuta STRING(3)
platni_instrument STRING(5)
ind_platnog_instrumenta STRING(1)
minimalni_iznos DECIMAL(10,2)
postotak_provizije DECIMAL(5,2)
aktivnost STRING(1)
END
END
I have put in DCT the relation between KeyPLINS and KeyPR_indIns_ins_akt_val_izn with On update=Cascade on Delete=Restrict.
When i enter the update form for change it fails in primeUpdate. The exception is :
java.lang.RuntimeException: Address invalid
org.jclarion.clarion.ClarionAny.deserialize(ClarionAny.java:250)
org.jclarion.clarion.ClarionGroup.deserialize(ClarionGroup.java:485)
org.jclarion.clarion.ClarionGroup.deserialize(ClarionGroup.java:480)
org.jclarion.clarion.runtime.OverGlue.objectChanged(OverGlue.java:123)
org.jclarion.clarion.ClarionMemoryModel.notifyChange(ClarionMemoryModel.java:219)
org.jclarion.clarion.ClarionGroup$1.objectChanged(ClarionGroup.java:89)
org.jclarion.clarion.ClarionMemoryModel.notifyChange(ClarionMemoryModel.java:219)
org.jclarion.clarion.ClarionString.notifyChange(ClarionString.java:1487)
org.jclarion.clarion.ClarionString.setValue(ClarionString.java:364)
org.jclarion.clarion.ClarionObject.setValue(ClarionObject.java:190)
org.jclarion.clarion.ClarionQueue$QueueEntry.copyToGroup(ClarionQueue.java:100)
org.jclarion.clarion.ClarionQueue.restoreRecord(ClarionQueue.java:423)
org.jclarion.clarion.ClarionQueue.get(ClarionQueue.java:829)
org.jclarion.clarion.ClarionQueue.get(ClarionQueue.java:841)
clarion.Bufferedpairsclass.assignLeftToBuffer(Bufferedpairsclass.java:57)
clarion.Relationmanager.save(Relationmanager.java:541)
clarion.Windowmanager.primeUpdate(Windowmanager.java:369)
clarion.Thiswindow_20.init(Thiswindow_20.java:118)
Thanks
Nenad
Try the following modification: in ABUTIL.INC look for this:
Rewrite it as follows:
Let me know if the above works. If it does I'll explain what is happening. Otherwise I'll need to dig deeper.
Yes, it works.
Great!
Nenad
I was too fast.
Now i get no exception when entering the platni_instrumenti form. Now is the provizija form that behaves strangely. when doing change some error is returned and i can not change provizija. Also when from the provizija browse i try to delete the record i get exception ClarionSqlFile Reget not yet implemented.
I will try to investigate more.
Can you please check following :
table in question has a primary key defined. This will explain why you cannot perform delete on provizija : it does not have a primary key
keys used for browsing tables, the key must be essentially unique. i.e. if you key on NAME and name allows duplicates, modify key so it is name+id. If a key used for browsing is not unique, then strange artefacts can occur when browsing etc
That browse actually does use a key, not file based browse
I am pretty sure clarion with ODBC access has similar limitations; though they manifest themselves in slightly different ways than in c2j.
Yes, i was missing the primary key in provizija.
There is still one thing not working:
platni_instrumenti first key: it has primary and unique. I have created browse from template and put Range on ind_otkup_prodaja with option Single value equal to IndFilt (which is string(1) local variable). It simly ignores the vairable and shows all. If i use the Filter prompt then it is OK. It might be ABC error but it seems strange.
thanks
Nenad
I would expect single value to work. I use this regularly with my app, (clarion 5.5 ABC). Suggest look at log file generated, it logs SQL commands executed. Hopefully this will provide some clues.
To enable logging on detailed level: add following into code somewhere before point you want to log:
@java-code 'new org.jclarion.clarion.log.Debug();'
Just looking at the code, I think that set(view,number) is incorrectly implemented in c2j. Question is whether or not clarion 6 ABC utilises this to implement single value behaviour. Looking at my clarion 6 libsrc, it appears that this would not explain error. Still, above debugging information I indicate above will help understand cause of this.
I have put the code you suggested in thiswindow.init after opening the window, but there are no logs in the file. Should i do something more?
Try placing it in main clw file, immediately after CODE
I have managed to log now. The following is strange
12/14 08:07:03 F ClarionSQLFile - SELECT A.ind_otkup_prodaja,A.oznaka_platnog_instrumenta_u_k,A.opis,A.indikator,A.aktivnost FROM platni_instrumenti A WHERE (UPPER('O')=UPPER('O') AND A.aktivnost='A') AND (upper(A.ind_otkup_prodaja)>'O' OR (upper(A.ind_otkup_prodaja)='O' AND (upper(A.oznaka_platnog_instrumenta_u_k)>=''))) ORDER BY UPPER(A.ind_otkup_prodaja),UPPER(A.oznaka_platnog_instrumenta_u_k) LIMIT 100 []
UPPER('O')=UPPER('O') has no sense but i think it is upper(A.ind_otkup_prodaja)>'O' OR … that makes it working wrong.
This is my window init procedure
ThisWindow.Init PROCEDURE
ReturnValue BYTE,AUTO
CODE
GlobalErrors.SetProcedureName('SelPlins')
SELF.Request = GlobalRequest ! Store the incoming request
ReturnValue = PARENT.Init()
IF ReturnValue THEN RETURN ReturnValue.
SELF.FirstField = ?Browse:1
SELF.VCRRequest &= VCRRequest
SELF.Errors &= GlobalErrors ! Set this windows ErrorManager to the global ErrorManager
SELF.AddItem(Toolbar)
CLEAR(GlobalRequest) ! Clear GlobalRequest after storing locally
CLEAR(GlobalResponse)
SELF.AddItem(?Close,RequestCancelled) ! Add the close control to the window amanger
Relate:platni_instrumenti.SetOpenRelated()
Relate:platni_instrumenti.Open ! File platni_instrumenti used by this procedure, so make sure it's RelationManager is open
SELF.FilesOpened = True
BRW1.Init(?Browse:1,Queue:Browse:1.ViewPosition,BRW1::View:Browse,Queue:Browse:1,Relate:platni_instrumenti,SELF) ! Initialize the browse manager
SELF.Open(QuickWindow) ! Open window
Do DefineListboxStyle
IndFilt=Ind !Ind is string parametar of the procedure and IndFilt is procedure local String(1)
BRW1.Q &= Queue:Browse:1
BRW1.RetainRow = 0
BRW1.AddSortOrder(,plins:KeyPLINS) ! Add the sort order for plins:KeyPLINS for sort order 1
BRW1.AddRange(plins:ind_otkup_prodaja,IndFilt) ! Add single value range limit for sort order 1
BRW1.AddLocator(BRW1::Sort0:Locator) ! Browse has a locator for sort order 1
BRW1::Sort0:Locator.Init(,plins:oznaka_platnog_instrumenta_u_k,1,BRW1) ! Initialize the browse locator using using key: plins:KeyPLINS , plins:oznaka_platnog_instrumenta_u_k
BRW1.SetFilter('(plins:aktivnost=''A'' )') ! Apply filter expression to browse
BRW1.AddField(plins:ind_otkup_prodaja,BRW1.Q.plins:ind_otkup_prodaja) ! Field plins:ind_otkup_prodaja is a hot field or requires assignment from browse
BRW1.AddField(plins:oznaka_platnog_instrumenta_u_k,BRW1.Q.plins:oznaka_platnog_instrumenta_u_k) ! Field plins:oznaka_platnog_instrumenta_u_k is a hot field or requires assignment from browse
BRW1.AddField(plins:opis,BRW1.Q.plins:opis) ! Field plins:opis is a hot field or requires assignment from browse
BRW1.AddField(plins:indikator,BRW1.Q.plins:indikator) ! Field plins:indikator is a hot field or requires assignment from browse
BRW1.AddField(plins:aktivnost,BRW1.Q.plins:aktivnost) ! Field plins:aktivnost is a hot field or requires assignment from browse
Resizer.Init(AppStrategy:Surface,Resize:SetMinSize) ! Controls like list boxes will resize, whilst controls like buttons will move
SELF.AddItem(Resizer) ! Add resizer to window manager
INIMgr.Fetch('SelPlins',QuickWindow) ! Restore window settings from non-volatile store
Resizer.Resize ! Reset required after window size altered by INI manager
BRW1.AddToolbarTarget(Toolbar) ! Browse accepts toolbar control
SELF.SetAlerts()
For clarity, the Ind parametar is 'O'
The UPPER('O')=UPPER('O') is a clue.
I suspect this is supposed to render as A.ind_otkup_prodaja=UPPER('O')
Try following two things either or:
1) look at source code, make sure bind() is binding ind_otkup_prodaja
2) Try hacking the main clw file and change the KEYS and remove NOCASE. Recompile and see if it gets a different output.
if 2) above does indeed fix this, I think there may be a slight bug in runtime when handling evaluation of certain SQLFilter types.
I am confident that the CASE is the issue. Currently written a test that fails
Problem is that View Prop:Filter cannot properly handle UPPER(fieldname). Hopefully will have a fix shortly
The 1) did not help but with 2) it works!
Committed a fix to runtime. Please try now. System should not allow view to contain UPPER(fieldname) in SQL:Filter property and work as you would expect them to.
Have not encountered this one myself because my app does not use strings a first element in composite keys. All my composite key tables use numerics as first field. c2j contains a powerful SQL optimisation that only applies in these circumstances; highly recommended, for performance reasons at least, if you are going to use composite keys then make first element numeric if you possibly can.
Typo in my above comment. I said " System should not allow view to contain UPPER". I meant "System should now allow view to contain UPPER"
Now it works. Thanks.
The information about the first field in key being numeric is interesting but not applicable to my project. As I told you I have to undergo the certification process. I have documents where the column names and types are specified and so immutable.
Nenad