How can I override the getter for serial property?
I want to override getter for a serial property as a whole, because getter code depends on a class in which a property is defined.
Let's say I have CS.Serial as a serial class:
Class CS.Serial Extends %SerialObject
{
Property Year As %Integer;
Property Month As %Integer;
}And CS.Persistent as a persistent class:
Class CS.Persistent Extends %Persistent
{
Property data As CS.Serial [ SqlComputeCode = {set {*} = ##class(CS.Persistent).dataGetStatic()}, SqlComputed, Transient ];
/// data getter method in object context
Method dataGet() As CS.Serial
{
return ..data2GetStatic()
}
/// data getter method in SQL context
ClassMethod dataGetStatic() As CS.Serial
{
return $lb($lb("2017","01"),"CS.Serial")
}
}But compiling it gives me an error:
ERROR #5502: Error compiling SQL Table: CS.Persistent Table CS.Persistent has the following unmapped (not defined on the data map) fields: data_Month, data_Year %msg: Table CS.Persistent has the following unmapped (not defined on the data map) fields: data_Month, data_Year [CompileTable+36^%ocsSQLRTDict:TIME] > ERROR #5030: An error occurred while compiling class 'CS.Persistent' [CreateTable+7^%occCompile:TIME]
Is there way to override getter for a serial property?
Code.
Comments
I'm pretty sure you need to return an oref to get this working. Here's one that I was able to get working:
Class Sample.SerialGet Extends %Persistent {
Property Address as Sample.Address [calculated];
Method AddressGet() as Sample.Address {
set a=##class(Sample.Address).%New()
set a.City="Cambridge"
set a.State="MA"
set a.Zip="02142"
set a.Street="1 Memorial Drive"
quit a
}
}Terminal:
SAMPLES>s reader=##class(%XML.Reader).%New()
SAMPLES>w reader.OpenFile("/users/kbaxter/downloads/testopensinglequote.xml")
1
SAMPLES>s x=##class(Sample.SerialGet).%New()
SAMPLES>w x.Address
SAMPLES>w x.Address.Street
1 Memorial Drive
Thank you.
How can I make it work from SQL context too?
It all depends on what you wish to achieve.
For example:
Class CS.Serial Extends %SerialObject
{
Property Year As %Integer;
Property Month As %Integer;
Method %MyGetSerial() As %List [ ServerOnly = 1 ]
{
q $lb(i%Year,i%Month)
}
}
Class CS.Persistent Extends %Persistent
{
/// Property is triggered computed
Property data1 As CS.Serial [ SqlComputeCode = {set {*} = ..dataGetStatic()}, SqlComputed ];
/// Property is always computed
Property data2 As %List [ SqlComputeCode = {set {*} = ##class(CS.Persistent).dataGetStatic()}, SqlComputed, Transient ];
/// data getter method in SQL context
ClassMethod dataGetStatic() As %List
{
s s=##class(CS.Serial).%New(), s.Month=1, s.Year=2017
q s.%MyGetSerial()
; or
q $lb(2017,1)
}
}
---------
select ID,data1,data2,data1_Month,data1_Year from CS.Persistent
ID data1 data2 data1_Month data1_Year
1 2017,1 2017,1 1 2017
2 2017,1 2017,1 1 2017
3 2017,1 2017,1 1 2017
Thank you!
I copied your example, but SQL returns results saved on disk, which is expected as the data property is triggered computed
Class CS.Persistent Extends %Persistent
{
Property data As CS.Serial [ SqlComputeCode = {set {*} = ##class(CS.Persistent).dataGetStatic()}, SqlComputed ];
/// data getter method in SQL context
ClassMethod dataGetStatic() As %List
{
quit $lb(2017,1)
}
/// do ##class(CS.Persistent).test()
ClassMethod test()
{
do ..%KillExtent()
do $system.SQL.PurgeForTable($classname())
set obj = ##class(CS.Persistent).%New()
set obj.data.Month=-1
set obj.data.Year=0
set sc = obj.%Save()
write !,"Save: ",$s($$$ISOK(sc):"OK", 1:$System.Status.GetErrorText(sc)),!
zw ^CS.PersistentD
do ##class(%SQL.Statement).%ExecDirect(,"select * from "_$classname()).%Display()
}
}I execute in a terminal:
do ##class(CS.Persistent).test()
And I receive the following output:
Save: OK
^CS.PersistentD=1
^CS.PersistentD(1)=$lb("",$lb(0,-1))
ID data_Month data_Year
1 -1 0Can I make a serial class always computed?
I want to receive the following output:
Save: OK
^CS.PersistentD=1
^CS.PersistentD(1)=$lb("",$lb(0,-1))
ID data_Month data_Year
1 1 2017> Can I make a serial class always computed?
Yes, of course.
Class CS.Serial Extends %SerialObject [ NoExtent ]
{
Property Year As %Integer;
Property Month As %Integer;
}
Class CS.Persistent Extends %Persistent
{
Property data As CS.Serial [ SqlComputeCode = {set {*} = ##class(CS.Persistent).dataGetStatic()}, SqlComputed, Transient ];
ClassMethod dataGetStatic() As %List
{
quit $lb(2017,1)
}
}
Output:
^CS.PersistentD=1
^CS.PersistentD(1)=$lb("")
ID data
1 $lb(2017,1)
1 Rows(s) Affected
That is almost what I started this topic with. I get a compilation error with this code. And fields data_Year and data_Month are not getting created it seems.
It seems to me that in this case is not well suited %SerialObject.
Will be easier to use %List.