Robert Cemper · Jan 14, 2025 go to post

like this:

/// using $ZZFIX() custom function
Class rcc.GetFixZZ Extends %Library.String
{
Parameter LENGTH As %String = 10;
Parameter ALIGN As %String = "LEFT";
Parameter PADCHAR As %String = " ";
Method Get() As %String [ CodeMode = generator, ServerOnly = 1 ]
{
	set code=+%parameter("LENGTH")_","""_$E(%parameter("PADCHAR")_" ",1)_""""
	set code=code_","_("RIGHT"=$zcvt(%parameter("ALIGN"),"U"))_")"
	$$$GENERATE(" quit $ZZFIX(%val,"_code )
	QUIT $$$OK
}
ClassMethod StorageToLogical(%val As %String) As %String [ CodeMode = generator, ServerOnly = 1 ]
{
	set code=+%parameter("LENGTH")_","""_$E(%parameter("PADCHAR")_" ",1)_""""
	set code=code_","_("RIGHT"=$zcvt(%parameter("ALIGN"),"U"))_")"
	$$$GENERATE(" quit $ZZFIX(%val,"_code )
	QUIT $$$OK
} }
Robert Cemper · Jan 14, 2025 go to post

Though, if you need this functionality over multiple namespaces
I'd suggest to use a Language Extension:
#1 an .inc for the the code definition in namespace %SYS
 

ROUTINE ZZFIX [Type=INC]
/// fix length string + padding + l/r-adjustment
ZZFIX(%val, len , pad = "", right = 0)
        if right quit $e($tr($j("",len)," ",$e(pad_" "))_%val,*+1-len,*)
        quit $e(%val_$tr($j("",len)," ",$E(pad_" ")),1,len)

#2 add this line to %ZLANGF00.mac

#include ZZFIX 

after compiling it you may run a test in any namespace

USER>set test="213abc"
USER>write $ZZFIX(test,10,"*")
213abc****
USER>write $ZZFIX(test,10,"*",1)
****213abc
USER>write $zzfix(test,5,"*",1)
13abc
USER>write $zzfix(test,15,"$")
213abc$$$$$$$$$
USER>write $zzfix(test,15,"$",1)
$$$$$$$$$213abc
USER>

If available this could of course also replace the
ClassMethod in the DataType definition.
It's a matter of taste.

Robert Cemper · Jan 14, 2025 go to post

I just felt the need of the last extension  to adjust it to reality.

A side effect: because of the implementation as Classmethod

ClassMethod Fix(%val, rcc, rccp = "", rccal = 0) As %String

You can apply it dynamically to any String/Number that you get in hands.
(that's how I tested the core functionality)

Robert Cemper · Jan 13, 2025 go to post

Thank you @Jeffrey Drumm !
Yet another idea:
Sometimes you may want a static non-blank padding character.
e.g. ****123 or 345~~~~
this is included as Parameter PADCHAR as %String =" "  ;  default= blank

/// padding other than " " might be useful in some cases
Class rcc.GetFixSqlPad Extends %Library.String
{

Parameter LENGTH As %String = 10;

Parameter ALIGN As %String = "LEFT";

Parameter PADCHAR As %String = "";

Method Get() As %String [ CodeMode = generator, ServerOnly = 1 ]
{
    set code=+%parameter("LENGTH")_","""_$E(%parameter("PADCHAR")_" ",1)_""""
    set code=code_","_("RIGHT"=$zcvt(%parameter("ALIGN"),"U"))_")"
        
    $$$GENERATE(" quit ##class(rcc.GetFixSqlPad).Fix(%val,"_code )
    QUIT $$$OK
}

ClassMethod StorageToLogical(%val As %String) As %String [ CodeMode = generator, ServerOnly = 1 ]
{
    set code=+%parameter("LENGTH")_","""_$E(%parameter("PADCHAR")_" ",1)_""""
    set code=code_","_("RIGHT"=$zcvt(%parameter("ALIGN"),"U"))_")"
        
    $$$GENERATE(" quit ##class(rcc.GetFixSqlPad).Fix(%val,"_code )
    QUIT $$$OK
}

/// PADCHAR=" "; LEFT=0, RIGHT=1 
ClassMethod Fix(%val, rcc, rccp = "", rccal = 0) As %String
{
    if rccal{
        set %val=$e($tr($j("",rcc)," ",$e(rccp_" "))_%val,*+1-rcc,*)
        }
    else {
        set %val=$e(%val_$tr($j("",rcc)," ",$e(rccp_" ")),1,rcc)
        }	
    quit %val
}

}
Robert Cemper · Jan 12, 2025 go to post

This doesn't work for SQL - Therefore a new version
 

Class rcc.GetFixSql Extends %Library.String
{

Parameter LENGTH As %String = 10;
Parameter ALIGN As %String = "LEFT";
Method Get() As %String [ CodeMode = generator, ServerOnly = 1 ]
{
    set code=+%parameter("LENGTH")_","_("RIGHT"=$zcvt(%parameter("ALIGN"),"U"))_")"
    $$$GENERATE(" quit ##class(rcc.GetFixSql).Fix(%val,"_code )
    QUIT $$$OK
}

ClassMethod LogicalToDisplay(%val As %String) As %String [ CodeMode = generator, ServerOnly = 0 ]
{
    set code=+%parameter("LENGTH")_","_("RIGHT"=$zcvt(%parameter("ALIGN"),"U"))_")"
    $$$GENERATE(" quit ##class(rcc.GetFixSql).Fix(%val,"_code )
    QUIT $$$OK
}

ClassMethod LogicalToOdbc(%val As %String) As %String [ CodeMode = generator, ServerOnly = 1 ]
{
    set code=+%parameter("LENGTH")_","_("RIGHT"=$zcvt(%parameter("ALIGN"),"U"))_")"
    $$$GENERATE(" quit ##class(rcc.GetFixSql).Fix(%val,"_code )
    QUIT $$$OK
}

// only required for SQL Display Logical mode !
ClassMethod StorageToLogical(%val As %String) As %String [ CodeMode = generator, ServerOnly = 1 ]
{
    set code=+%parameter("LENGTH")_","_("RIGHT"=$zcvt(%parameter("ALIGN"),"U"))_")"
    $$$GENERATE(" quit ##class(rcc.GetFixSql).Fix(%val,"_code )
    QUIT $$$OK
}

/// LEFT=0, RIGHT=1 
ClassMethod Fix(%val, rcc, rccal = 0) As %String
{
    if rccal{
        set %val=$e($j(%val,rcc),*+1-rcc,*)
        }
    else {
        set %val=$e(%val_$j("",rcc),1,rcc)
        }	
    quit %val
}

}
Robert Cemper · Jan 12, 2025 go to post

A more compact data type with LENGTH and ALIGN
For RIGHT alignment I cut off oversized data by LENGHT counted from the end.
 

Class rcc.GetFixAligned Extends %Library.String
{
Parameter LENGTH As %String = 10;
Parameter ALIGN As %String = "LEFT";

Method Get() As %String [ CodeMode = generator, ServerOnly = 1 ]
{
    set rcc=+%parameter("LENGTH")
    if "RIGHT"=$zcvt(%parameter("ALIGN"),"U") {
        set code="$e($j(%val,"_rcc_"),*+1-"_rcc_",*)"
        }
    else {
        set code="$e(%val_$j("""","_rcc_"),1,"_rcc_")"
        }	
    $$$GENERATE(" Quit "_code)
    QUIT $$$OK
}
}
Robert Cemper · Jan 12, 2025 go to post

Sorry, no idea!  It was the first time I met this suspicious parameter.
My personal style is quite traditional.

Robert Cemper · Jan 11, 2025 go to post

by extending %RegisteredObject you lost the basic data type
and all other parameters of %String
this should do it:

Class rcc.FixStr Extends (%Library.String, rcc.FixStr.Props)
{
/// Fill value according to LENGTH parameter
Method Get() As %String [ CodeMode = generator, ServerOnly = 1 ]
{
	set tCode="$e(%val_"""_$j("",+%parameter("LENGTH"))
	set tCode=tCode_""",1,"_+%parameter("LENGTH")_")"
	$$$GENERATE( "  Quit "_tCode)
	QUIT $$$OK
}
}
Robert Cemper · Jan 3, 2025 go to post

My personal congratulations to the winners to complete the challenge in time
👍👏😎

Robert Cemper · Jan 2, 2025 go to post

different approach:

SELECT LI.id from FDRD_Com.List LI
JOIN FDRD_Com.Prod PR
ON LI.vehicle = PR.Car 
WHERE PE.ProductLineName='Toyota'
AND PR.Car is not null  -- might be obsolete
Robert Cemper · Jan 2, 2025 go to post

IN is expecting a list.

Did you ever try

select id from FDRD_Com.List where vehicle IN
(select LIST(Car) from FDRD_Com.Prod where ProductLineName='Toyota' and Car is not null)


on the sub select ?

Robert Cemper · Dec 31, 2024 go to post

As an active participant you know the practical case.
Though most readers that never touched AOC might be confused.
The original intention was to exclude parts not solved in ObjectScript:
(e.g Java, C# JS, ....)
It turned out this was not possible to implement with acceptable effort.

Robert Cemper · Dec 31, 2024 go to post

Big THANK YOU @Jani Hurskainen for sharing your story.
I'm impressed by the progress you made on ObjectScript
after only 1,5 years maybe 30% of working time,

AoC examples are definitely different from the target cases ObjectScript was designed for.
Its top target is the underlaying database, string manipulation and less math functionality.

My best wishes for Health and Success  for the New Year
Robert

Robert Cemper · Dec 29, 2024 go to post

In 2021 I published my article IRIS easy ECP workbench
with a related a Docker based demo on OEX.
All you need is the ECP enabled license for containers or Platform Independent
Community version is not ECP enabled

Robert Cemper · Dec 27, 2024 go to post

Thank you @Evgeny Shvarov !
I'd like to underline especially the use of  Docker.

My hundreds reviews in OEX wouldn't be possible without it with my limited test environment.
It's not only the option to run various  versions in parallel to my personal setup,
but much more the possibility to clean out all traces and specific settings just with a click.
If you ever tried to remove COMPLETELY an IRIS installation with all traces
from Windows you may understand me.
And with the available templates it is a really easy exercise to compose
your personal customized package with almost no effort and
test it over and over from scratch.


​​​​​​

Robert Cemper · Dec 17, 2024 go to post

Suggestion:
you crate your own stored procedure to decide during SELECT
example:

/// Return NEW for first occurance of item 
/// otherwise return OLD
Class User.ItemStat Extends %RegisteredObject
{
ClassMethod NewOld(item As %String = "") As %String [ SqlProc ]
{
    if item="" quit "?"
    if $d(^||list(item)) quit "OLD"
    if $i(^||list(item)) quit "NEW"
}
}

How to use it:

SELECT *, ItemStat_NewOld(item) as Status
FROM items order by 2

Result:

ID	date	  item	Status
1	09/13/1932	A	NEW
2	04/06/1933	D	NEW
10	06/15/1940	A	OLD
4	11/26/1940	A	OLD
6	02/19/1956	B	NEW
8	04/22/1957	D	OLD
7	05/01/1959	D	OLD
9	06/29/1961		?
3	07/04/1992	B	OLD
5	12/08/2020	D	OLD
Robert Cemper · Dec 16, 2024 go to post

%ZSTOP routine may log the last user.

But it has no information on an external stopped process. E.g from MGMT portal

Robert Cemper · Dec 12, 2024 go to post

Looking forward to hear your story!
That's often of much more value than the pure code..   

Robert Cemper · Dec 10, 2024 go to post

Somewhere in your data structure you have a property / Column  of type DATE
the content seems to be a null_string (string of length zero) instead of a real SQL NULL (empty, no value)
My guess:  it's one of the 8 Dob ( Date of Birth ?) named fields
check the related contents  
  

Robert Cemper · Dec 4, 2024 go to post

Similar to previous years I will provide the results of our private leaderboard 

  • It will sort by published ranking but separate DC members from "guests"
  • The matching of DC members is a manual task 
  • if I missed you pls. let me know your identity in AoC by DC mail  to add your DC flag
  • due to private issue my updates might show delays sometimes
  • 2 test sets with results are available on OEX: AoC2024-test or GitHub: AoC2024_test
  • I just added a column to show completion of parts in the exercises
    • -  no part
    • 1 only part 1  (silver star)
    • 2 only part 2 (another silver star)
    • 3 1+2 both parts completed (gold star) 
DCrank  AOCrank Scores  Stars   ok%     ----- Code Parts OK -----       Name
0       ---     ----    ----    ---     ----*----*----*----*----*       --- DC Members ---
1       7       7361    50      100     3333333333333333333333333       abdul-manaan
2       8       7296    50      100     3333333333333333333333333       Yuval Golan
3       9       5310    36      72      3333333333333331331------       JFerreB
4       11      2598    18      36      333333333----------------       Peter Zubiago
5       13      2537    17      34      333333331----------------       Oskari Kosonen
6       14      2052    14      28      3333313---1--------------       Keith Avery
7       15      1928    13      26      3333331------------------       Jani Hurskainen
8       17      1639    11      22      333311--1----------------       Ivo ver eecke
9       18      1278    9       18      33331--------------------       TylerFeldhege
10      21      875     6       12      333----------------------       rhodery
11      23      695     5       10      331----------------------       Chris Marais
12      24      565     4       8       33-----------------------       Oliver Wilms
13      ---     ----    ----    ---     -------------------------       --- ISC internals ---
14      2       7592    50      100     3333333333333333333333333       TestSet 1
15      3       7545    50      100     3333333333333333333333333       TestSet 2
16      22      811     6       12      333----------------------       Junhee Lee
17      ---     ----    ----    ---     -------------------------       --- unknow in DC ---
18      1       7683    50      100     3333333333333333333333333       Dominik Znidar
19      4       7540    50      100     3333333333333333333333333       Joaquin Derrac Rus
20      5       7539    50      100     3333333333333333333333333       Jarjar 314
21      6       7527    50      100     3333333333333333333333333       (anonymous user #1128565)
22      10      3295    23      46      3333313-1331311----------       (anonymous user #4293990)
23      12      2569    18      36      33333-331-1-3------------       Sloan Kanaski
24      16      1902    13      26      33331111--1--------------       Chhayank Warad
25      19      1083    8       16      3333---------------------       Noah Dohrmann
26      20      1064    8       16      3333---------------------       (anonymous user #214666)
27      25      427     3       6       31-----------------------       Gary Nguyen
 
28 Rows(s) Affected
 
UTC 2024-12-30 08:28:42
EST 2024-12-30 03:28:42
 
Robert Cemper · Nov 21, 2024 go to post

Hi @Jeffrey Drumm ;
different approach: use your own datatype that always returns fixed MAXLEN string:

 

/// Make fixlength String according to MAXLEN parameter
Class rcc.GetFix Extends %Library.String
{
/// Fill value <var>%val</var> to <a href="#MAXLEN">MAXLEN</a> characters.
Method Get() As %String [ CodeMode = generator, ServerOnly = 1 ]
{
	set code="$e(%val_"""_$j("",+%parameter("MAXLEN"))
	set code=code_""",1,"_+%parameter("MAXLEN")_")"
	$$$GENERATE( "  Quit "_code)
	QUIT $$$OK
}
}

and a test class:

Class rcc.FixTest Extends %RegisteredObject
{
Property test As rcc.GetFix(MAXLEN = 12);
}

and now some check from terminal:
 

SAMPLES>set z=##class(rcc.FixTest).%New() set z.test="rob"
SAMPLES>write z.test,$L(z.test)
rob         12

SAMPLES>;some oversized string
SAMPLES>set z.test=";some oversized string"
SAMPLES>write z.test,$L(z.test)
;some oversi12
SAMPLES>  

Hope this helps you along
 

Robert Cemper · Nov 11, 2024 go to post

#2)
Every LOCK persists until the process is ended or the LOCK is removed explicitely (LOCK -....)
it is not related to any error handling.

#1)
depends on your design.
If there is no conflict of subscripts between ADD and REMOVE possible there is no need of a Lock 

Robert Cemper · Nov 7, 2024 go to post

no need for this COPY
if your docker-compose.yml contains

    volumes:
      - ./:/home/irisowner/dev
 

Robert Cemper · Oct 27, 2024 go to post
  • .MAC  and much more .INT  are an almost 1:1 image of the runtime .OBJ code
  • they get implicitely compiled by ZSAVE command
  • while any .CLS gets first stored with a lot of internal parameters where XML is faster than UDL
  • then it's translated to .INT(at least) including all extra params,  
  • and inherited pieces and other features for comfort 
  • and then compiled as any other .INT for the final .OBJ 

So comparing .CLS  to .MAC/.INT is like comparing a goat to the final cheese you buy.