can protoclass honor dictionary length in class MAXLEN

6 views
Skip to first unread message

Rich Brim

unread,
Feb 1, 2012, 1:14:13 AM2/1/12
to InterSystems: MV Community
Is it possible to get protoclass to set the MAXLEN in Class?

Rich

Michael Cohen

unread,
Feb 1, 2012, 9:48:44 AM2/1/12
to intersy...@googlegroups.com
Hi Rich,

That should not be a problem. But in testing this, I found a problem with PROTOCLASS.

I note that PROTOCLASS sets MVWIDTH based on the DICT width. You could set MAXLEN to the same value. Or, since the DICT width is generally a display width and data can wrap (not a max length), you could get fancy and use a constant or algorithm to determine the desired MAXLEN to set.

The problem I found is that MVWIDTH is only set on subsequent calls to PROTOCLASS for a DICT to reflect any changes that were made to the DICT up to the class. So the first time you run PROTOCLASS on a DICT, MVWIDTH is not set in the class. But, if you then run PROTOCLASS again, MVWIDTH is set in the class.

Rich

--
You received this message because you are subscribed to the Google Groups "InterSystems: MV Community" group.
To post to this group, send email to Cac...@googlegroups.com
To unsubscribe from this group, send email to CacheMV-u...@googlegroups.com
For more options, visit this group at http://groups.google.com/group/CacheMV?hl=en

Ed Clark

unread,
Feb 1, 2012, 10:00:41 AM2/1/12
to intersy...@googlegroups.com
What would you want to base the MAXLEN on--I assume the width defined in the dictionary? Would you want to set a MAXLEN for every property, or just some?
If you want to do it for every property based on the width, or if you already have the MAXLEN defined in a special dictionary attribute then it wouldn't be especially difficult to modify protoclass to add it, but otherwise it might be easier to just edit the class manually.
The MAXLEN parameter isn't defined for date, time, or numeric properties, which will also complicate things.

If you want to do it:

look for the line
"%SYSTEM.MV"->parseDict(dictFDSC, record, @ID)
and add after it
if %dictionary(%DictNumber,"dataType")="%String" then %dictionary(%DictNumber,"maxlen")=something
where something is the max len you want, Maybe
$get(%dictionary(%DictNumber,"width"),10)

then look for these and add the line after:
propRef->Parameters->SetAt("P","MVAUTO")
if $data(%dictionary(pord,"maxlen")) then propRef->Parameters->SetAt(%dictionary(pord,"maxlen"),"MAXLEN")

propRef->Parameters->SetAt(propRef->Parameters->GetAt("MVAUTO"):"P","MVAUTO")
if $data(%dictionary(pord,"maxlen")) then propRef->Parameters->SetAt(%dictionary(pord,"maxlen"),"MAXLEN")

IF COUNT(mva,"P") = 0 THEN propRef->Parameters->SetAt(mva:"P","MVAUTO")
if $data(%dictionary(pord,"maxlen")) then propRef->Parameters->SetAt(%dictionary(pord,"maxlen"),"MAXLEN")

then finally look for
IF $GET(%dictionary(pord,"width")) # propRef->Parameters->GetAt("MVWIDTH") THEN
propRef->Parameters->SetAt($GET(%dictionary(pord,"width")),"MVWIDTH")
END

and make a copy, replacing "width" and "MVWIDTH" with "maxlen" and "MAXLEN"

I think that covers what you need to do, but I could be missing something. Others may have a better idea.


On Feb 1, 2012, at 1:14 AM, Rich Brim wrote:

> Is it possible to get protoclass to set the MAXLEN in Class?
>
> Rich
>

Dawn Wolthuis

unread,
Feb 1, 2012, 10:08:45 AM2/1/12
to intersy...@googlegroups.com
A tidbit in case you have not hit this is that you want to put either MAXLEN="" (unlimited) OR TRUNCATE=1 on every string property. Otherwise you will get an error when saving the record using %Save() if you try to stuff a longer string into that field.  --dawn
--
Dawn M. Wolthuis

Take and give some delight today

Bill Farrell

unread,
Feb 1, 2012, 10:08:46 AM2/1/12
to intersy...@googlegroups.com
Good point.

I automatically add Get()/Set() methods for my properties (I call a custom filter for conditioning data).  Once the base class is created (MVBProtoclass having done the grunt-work for me), I go back and edit the class and add data-shape enforcement in the property where I want it.  That's a lot easier than guessing out of the DICT -- and it's easier to maintain the class than the DICT (assuming MVREPOPULATE = 1)

B

Bill Farrell

unread,
Feb 1, 2012, 10:16:04 AM2/1/12
to intersy...@googlegroups.com
Ah, I see where I could get into trouble, not having thought of that.  That's a bit of tasty radicchio my salad needs...  Then again, I'm not using MAXLENGTH, but my classmethod should honor that in case I ever do.  I can't think of a case where I would ATM, but in programming, YNK (Ya Nevah Know) eventually rears its pointed head.  Better prepared than sorry.

B

Michael Cohen

unread,
Feb 1, 2012, 10:20:15 AM2/1/12
to intersy...@googlegroups.com

class string properties default to a MAXLEN of 50 if you don’t specify one (PROTOCLASS doesn’t)

 

so yes, that is often not long enough

Dawn Wolthuis

unread,
Feb 1, 2012, 10:21:21 AM2/1/12
to intersy...@googlegroups.com
Oh, you might think you are not using MAXLEN but, in fact, if you do not explicitly state a MAXLEN, it sets it to 50. This was one of my early took-me-longer-to-figure-out-than-it-should-have moments with the metadata. So, yes, I'll reiterate just so no one else has to follow my path to get there:

YOU MUST either have MAXLEN = "" or TRUNCATE = 1 (in addition to either an explicit or implicit MAXLEN=n) on every %String property

to avoid suffering unnecessarily at some point. Smiles.  --dawn

Ed Clark

unread,
Feb 1, 2012, 10:23:01 AM2/1/12
to intersy...@googlegroups.com
Good point dawn. The %Library.String class defines a default MAXLEN parameter of 50, so if you don't override that in your class, you will get %Save errors for longer strings.
I'm lazy though. I wouldn't add MAXLEN="" to every property. I would create a class MVString derived from %String and set the MAXLEN="" there, then use that instead of %String in my classes (modifying protoclass to do so also)

Bill Farrell

unread,
Feb 1, 2012, 10:25:44 AM2/1/12
to intersy...@googlegroups.com
... and I am SO all for not suffering!

B

Dawn Wolthuis

unread,
Feb 1, 2012, 10:40:59 AM2/1/12
to intersy...@googlegroups.com
Yeah, well lazy comes in many colors, Ed. I did not want to have to consider the implications of persistent classes using our custom string type instead of the delivered %String. Cheers! --dawn

Bill Farrell

unread,
Feb 1, 2012, 10:48:43 AM2/1/12
to intersy...@googlegroups.com
Still, I'm all for saving myself from stumping my toe later.  A custom class is the way I'd handle it in VB, but seeing as how many of my forays into creating custom datatypes hasn't always worked out, it comes down to a question of "how much frustration and research can I put up with now vs the cost of not having done it later".  I know I'll have to spend the time at some point, but on both our parts it's less a matter of lazy and moreso of too much stuff to write and no time to get it done in.

Yannow how it is <smile>

Rich Brim

unread,
Feb 3, 2012, 2:29:55 PM2/3/12
to InterSystems: MV Community
I was having issue with Model giving an error on save. I modified
PROTOCLASS to add maxlen="". Here is the code and surrounding code.

IF @ID # "@ID" THEN
* Now let's parse the entry. We have another %SYSTEM.MV
class method
* we can call that will do this for us.
*
"%SYSTEM.MV"->parseDict(dictFDSC, record, @ID)

if %dictionary(%DictNumber,"dataType")="%String" then
%dictionary(%DictNumber,"maxlen")='1'
*
CONTINUE
END
END
.
.
.
pattr8 = $GET(%dictionary(pord, "attr8"))
pitype = $GET(%dictionary(pord, "itypeSource"))
ptype = $GET(%dictionary(pord, "type"))
pmvname = $GET(%dictionary(pord, "name"))
pmv = $GET(%dictionary(pord, "mv"))
passoc = $GET(%dictionary(pord, "assoc"))
pconv = $GET(%dictionary(pord, "conv"))
maxlen = $GET(%dictionary(pord, "maxlen"))
.
.
.
IF rattrno # "" THEN pdef->Parameters->SetAt(rattrno,
"MVATTRIBUTE") ;* Attribute reference
IF passoc # "" THEN pdef->Parameters->SetAt(passoc,
"MVASSOCIATION") ;* Association name
IF pattr8 # "" THEN pdef->Parameters->SetAt(pattr8,
"MVTOLOGICAL") ;* Attr 8 conversion
IF pitype # "" THEN pdef->Parameters->SetAt(pitype,
"MVITYPE") ;* Itype source
IF maxlen # "" THEN pdef->Parameters->SetAt("", "MAXLEN") ;*
maxlen source

Bill Farrell

unread,
Feb 3, 2012, 2:38:18 PM2/3/12
to intersy...@googlegroups.com
Set maxlen to the length you want rather than 1.  If you look at the resulting class in the property you're trying to set a big length for, you'll likely see a MAXLENGTH=1 instead of the desired large value.

B
Reply all
Reply to author
Forward
0 new messages