Nueva publicación

Encontrar

Artículo
· 2 mayo, 2025 Lectura de 3 min

Minify XML in IRIS

In a project I'm working on we need to store some arbitrary XML in the database. This XML does not have any corresponding class in IRIS, we just need to store it as a string (it's relatively small and can fit in a string).
Since there are MANY (millions!) of records in the database I decided to reduce as much as possible the size without compressing. I know that some XML to be stored is indented, some not, it varies.
To reduce the size I decided to minify  the XML, but how do I minify an XML document in IRIS?
I searched across all the classes/utilities and I could not find a ready made code/method, so I had to implement it and it turned out to be fairly simple in IRIS using %XML.TextReader class, frankly simpler than I expected.

Since this can be useful in some other context, I decided to share this little utility with the Developer Community.
I've tested with some fairly complex XML documents and works fine, here is the code.

/// Minify an XML document passed in the XmlIn Stream, the minified XML is returned in XmlOut Stream
/// If XmlOut Stream is passed, then the minified XML is stored in the passed Stream, otherwise a %Stream.TmpCharacter in returned in XmlOut.
/// Collapse = 1 (default), empty elements are collapsed, e.g. <tag></tag> is returned as <tag/>
/// ExcludeComments = 1 (default), comments are not returned in the minified XML
ClassMethod MinifyXML(XmlIn As %Stream, ByRef XmlOut As %Stream = "", Collapse As %Boolean = 1, ExcludeComments As %Boolean = 1) As %Status
{
	#Include %occSAX
	Set sc=$$$OK
	Try {
		Set Mask=$$$SAXSTARTELEMENT+$$$SAXENDELEMENT+$$$SAXCHARACTERS+$$$SAXCOMMENT
		Set sc=##class(%XML.TextReader).ParseStream(XmlIn,.reader,,$$$SAXNOVALIDATION,Mask)
		#dim reader as %XML.TextReader
		If $$$ISERR(sc) Quit
		If '$IsObject(XmlOut) {
			Set XmlOut=##class(%Stream.TmpCharacter).%New()
		}
		While reader.Read() {
			Set type=reader.NodeType
			If ((type="error")||(type="fatalerror")) {
				Set sc=$$$ERROR($$$GeneralError,"Error loading XML "_type_"-"_reader.Value)
				Quit
			}
			If type="element" {
				Do XmlOut.Write("<"_reader.Name)
				If Collapse && reader.IsEmptyElement {
					; collapse empty element
					Do XmlOut.Write("/>")
					Set ElementEnded=1
				} Else {
					; add attributes
					For k=1:1:reader.AttributeCount {
						Do reader.MoveToAttributeIndex(k)
						Do XmlOut.Write(" "_reader.Name_"="""_reader.Value_"""")
					}
					Do XmlOut.Write(">")
				}
			} ElseIf type="chars" {
				Set val=reader.Value
				Do XmlOut.Write($select((val["<")||(val[">")||(val["&"):"<![CDATA["_$replace(val,"]]>","]]]]><![CDATA[>")_"]]>",1:val))
			} ElseIf type="endelement" {
				If $g(ElementEnded) {
					; ended by collapsing
					Set ElementEnded=0
				} Else {
					Do XmlOut.Write("</"_reader.Name_">")
				}
			} ElseIf 'ExcludeComments && (type="comment") {
				Do XmlOut.Write("<!--"_reader.Value_"-->")
			}
		}
	} Catch CatchError {
		#dim CatchError as %Exception.SystemException
		Set sc=CatchError.AsStatus()
	}
	Quit sc
}

P.S.: anyone know if there is other/simpler way to minify XML in IRIS?

3 comentarios
Comentarios (3)1
Inicie sesión o regístrese para continuar
Pregunta
· 2 mayo, 2025

I am getting date as 00010101 in CCDA if we use $ZDATEH function it is giving value out of range error

Can anyone please help me which function i can use to handle this error.

5 comentarios
Comentarios (5)3
Inicie sesión o regístrese para continuar
Artículo
· 2 mayo, 2025 Lectura de 3 min

Mini-astuce du jour : Préchargement de la licence dans l'image Docker IRIS

Qui n'a jamais développé un bel exemple avec une image IRIS Docker et vu la génération de l'image échouer dans le Dockerfile parce que la licence sous laquelle l'image a été créée ne comportait pas certains privilèges ?

Dans mon cas, je déployais dans Docker une petite application utilisant le type de données Vector. Avec la version Community, ce n'est pas un problème, car elle inclut déjà la recherche et le stockage vectoriels. Cependant, lorsque j'ai remplacé l'image IRIS par une image IRIS classique (latest-cd), j'ai constaté que la compilation de l'image, y compris des classes générées, renvoyait l'erreur suivante :

9.505 ERROR #15806: Vector Search not permitted with current license
9.505   > ERROR #5030: An error occurred while compiling class 'Inquisidor.Object.LicitacionOS'
9.505 Compiling class Inquisidor.Object.Licitacion
9.505 ERROR #15806: Vector Search not permitted with current license
9.505   > ERROR #5030: An error occurred while compiling class 'Inquisidor.Object.Licitacion'
9.538 Compiling class Inquisidor.Message.LicitacionResponse

Cette erreur m'a laissé perplexe, car moi, en tant que personne obéissante, j'avais défini dans mon docker-compose.yml le paramètre qui indique où se trouve ma licence valide :

  iris:
    init: true
    container_name: iris
    build:
      context: .
      dockerfile: iris/Dockerfile
    ports:
      - 52774:52773
      - 51774:1972
    volumes:
    - ./iris/shared:/iris-shared
    environment:
    - ISC_DATA_DIRECTORY=/iris-shared/durable
    command: --check-caps false --ISCAgent false --key /iris-shared/iris.key

Il m'a fallu un certain temps pour comprendre que le problème venait de l'image originale que j'utilisais, et non de la licence. Comme vous pouvez le constater, je ne suis pas très doué en la matière.

Le problème est survenu au moment où j'ai importé mes classes dans l'image IRIS par défaut :

RUN \
zn "%SYS" \
do ##class(SYS.Container).QuiesceForBundling() \
do ##class(Security.Users).UnExpireUserPasswords("*") \
set sc=##class(%SYSTEM.OBJ).Load("/opt/irisapp/DemoSetup.Utilities.cls","ck") \
set helper=##class(DemoSetup.Utilities).%New() \ 
do helper.EnableSSLSuperServer() \
do ##class(Security.Applications).Import("/ApplicationInquisidor.xml",.n) \
zn "INQUISIDOR" \
set sc = $SYSTEM.OBJ.LoadDir("/opt/irisapp/src/Inquisidor", "ck", , 1) \
set production = "Inquisidor.Production" \
set ^Ens.Configuration("csp","LastProduction") = production \
do ##class(Ens.Director).SetAutoStart(production) \

La compilation du code renvoyait l'erreur précédente. Que faire pour la corriger ? C'était très simple : j'ai dû envoyer la nouvelle licence à l'image IRIS initiale et lui demander de la mettre à jour dès la première ligne des commandes que j'utilisais.

La première étape consiste à déplacer la nouvelle licence vers le répertoire /mgr de l'installation, ce que j'ai fait avec ce code :

COPY --chown=$ISC_PACKAGE_MGRUSER:$ISC_PACKAGE_IRISGROUP /iris/iris.key /usr/irissys/mgr
RUN chmod +x /usr/irissys/mgr/iris.key

Le chemin d'installation d'IRIS sur notre image est /usr/irissys/mgr, et le chemin /iris/iris.key correspond à mon répertoire local. Avec la licence dans l'image IRIS, il me suffisait de demander à IRIS de la mettre à jour. J'ai donc modifié les commandes précédentes en ajoutant l'instruction suivante :

RUN \
zn "%SYS" \
do ##class(%SYSTEM.License).Upgrade() \

Et voilà ! J'ai maintenant mon image IRIS avec ma licence chargée avant l'importation et la compilation de mes classes. Plus d'erreurs de compilation.

J'espère que cela vous sera utile !

Comentarios (0)1
Inicie sesión o regístrese para continuar
Pregunta
· 2 mayo, 2025

SQLCODE: -99 when executing dynamic SQL on specific properties

Hi, I am unsure how to remove this restriction; when I am performing dynamic SQL using ##class(%SQL.Statement).%ExecDirectNoPriv(, .query, args...)

It works fine, but the moment I add specific properties from the persistent class I am performing the select on into the WHERE clause, I get: ERROR #5540: SQLCODE: -99 Message: User UnknownUser is not privileged for the operation. Despite using %ExecDirectNoPriv, I've tried with prepared statement as well, exact same situation.

I have read that it is possible to set privileges on individual properties on a persistent class, but I have no clue where to remove or change these privileges; the only solution I found is to add the role %All to UnknownUser, but that is not a fix but despite attempting to add full privileges for the persistent class for UnknownUser, I keep getting this privilege error.

5 comentarios
Comentarios (5)3
Inicie sesión o regístrese para continuar
Pregunta
· 2 mayo, 2025

IRIS Multiple Instance on a single Linux VM - status

I have a Linux server that has multiple instances installed on it (according to my documentation).

What is the best command to show:

- what instance are installed?

- what instances are running?

I did run 'iris list' but it shows only one instance.

3 comentarios
Comentarios (3)1
Inicie sesión o regístrese para continuar