Por consiguiente, la manipulación de un árbol de mensaje grande puede requerir una gran cantidad de almacenamiento. Si diseña un flujo de mensajes que maneja mensajes grandes formados por estructuras de repetición, puede codificar sentencias ESQL específicas que ayuden a reducir la carga de almacenamiento en el intermediario. Estas sentencias permiten acceder al mensaje de forma aleatoria y secuencial, pero presuponga que no necesita acceder a todo el mensaje de una vez.
Estas sentencias ESQL hacen que el intermediario efectúe un análisis limitado del mensaje y guarde solamente esa parte del árbol de mensaje que refleje un registro individual del almacenamiento cada vez. Si el proceso requiere que retenga la información de registro a registro, por ejemplo, para calcular un precio total de una estructura de elementos repetitivos dentro de un orden, puede declarar, inicializar y mantener variables ESQL o puede guardar los valores en otra parte del árbol de mensaje, por ejemplo, en LocalEnvironment.
Esta técnica reduce la memoria utilizada por el intermediario a la necesaria para contener las corrientes de bits de entrada y salida completas, más la necesaria para los árboles de un registro. Proporciona ahorro de memoria incluso cuando se encuentra un pequeño número de repeticiones en el mensaje. El intermediario utiliza el análisis parcial y la posibilidad de analizar partes específicas del árbol de mensaje en y desde la parte correspondiente de la corriente de bits.
Puede variar estas técnicas para adaptarlas al proceso necesario para los mensajes. El ESQL siguiente proporciona un ejemplo de una implementación y es una reescritura del ejemplo de ESQL del apartado Manejar mensajes XML grandes que utiliza una sola sentencia SET con funciones SELECT anidadas para transformar un mensaje que contiene estructuras anidadas repetidas.
El ESQL es dependiente de un conjunto de mensajes denominado LargeMessageExanple que se ha creado para definir mensajes para el formato de entrada de Invoice y el formato de salida de Statement. Se ha creado un mensaje denominado AllInvoices que contiene un elemento global denominado Invoice que se puede repetir una o varias veces y un mensaje denominado Data que contiene un elemento global denominado Statement que se puede repetir una o varias veces.
Puesto que a las definiciones de los elementos y atributos se les han dado los tipos de datos correctos, las sentencias CAST utilizadas por el ESQL en el ejemplo de XML ya no son necesarias. Se ha creado un formato físico XML con el nombre XML1 en el conjunto de mensajes que permite que el MRM analice un mensaje XML correspondiente a estos mensajes.
Cuando se serializa el árbol Statement utilizando la función ASBITSTREAM, se especifican el Conjunto de mensajes, el Tipo de mensajes y el Formato del mensaje como parámetros. El parámetro Tipo de mensaje contiene la vía de acceso del mensaje al elemento que se está serializando que, en este caso, es Data/Statement porque el elemento Statement es un hijo directo del mensaje Data.
<AllInvoices> .... </AllInvoices>
El mensaje de salida es el mismo que el del apartado Manejar mensajes XML grandes.
CREATE COMPUTE MODULE LargeMessageExampleFlow_Compute CREATE FUNCTION Main() RETURNS BOOLEAN BEGIN CALL CopyMessageHeaders(); -- Crear una carpeta especial en el mensaje de salida que contenga el árbol de entrada -- Nota : SourceMessageTree es el elemento raíz de un analizado MRM CREATE LASTCHILD OF OutputRoot.MRM DOMAIN 'MRM' NAME 'SourceMessageTree'; -- Copiar el mensaje de entrada en una carpeta especial del mensaje de salida -- Nota : Esta es una copia de raíz a raíz que, por lo tanto, no creará árboles SET OutputRoot.MRM.SourceMessageTree = InputRoot.MRM; -- Crear una carpeta especial en el mensaje de salida que contenga el árbol de salida CREATE FIELD OutputRoot.MRM.TargetMessageTree; -- Preparar el bucle a través de los elementos adquiridos DECLARE sourceCursor REFERENCE TO OutputRoot.MRM.SourceMessageTree.Invoice; DECLARE targetCursor REFERENCE TO OutputRoot.MRM.TargetMessageTree; DECLARE resultCursor REFERENCE TO OutputRoot.MRM; DECLARE grandTotal FLOAT 0.0e0; -- Crear un bloque que facilite el abandono del proceso ProcessInvoice: BEGIN -- Si no hay facturas (Invoices) en el mensaje de entrada, no hay nada que hacer IF NOT LASTMOVE(sourceCursor) THEN LEAVE ProcessInvoice; END IF; -- Crear un bucle por las facturas del árbol de origen InvoiceLoop : LOOP -- Inspeccionar la factura actual y crear una sentencia coincidente SET targetCursor.Statement = THE ( SELECT 'Monthly' AS Type, 'Full' AS Style, I.Customer.FirstName AS Customer.Name, I.Customer.LastName AS Customer.Surname, I.Customer.Title AS Customer.Title, (SELECT FIELDVALUE(II.Title) AS Title, II.UnitPrice * 1.6 AS Cost, II.Quantity AS Qty FROM I.Purchases.Item[] AS II WHERE II.UnitPrice > 0.0 ) AS Purchases.Article[], (SELECT SUM( II.UnitPrice * II.Quantity * 1.6 ) FROM I.Purchases.Item[] AS II ) AS Amount, 'Dollars' AS Amount.Currency FROM sourceCursor AS I WHERE I.Customer.LastName <> 'White' ); -- Convertir la sentencia actual en una corriente de bits -- El parámetro SET se establece en el nombre del conjunto de mensajes -- que contiene la definición de MRM -- El parámetro TYPE contiene la vía de acceso del mensaje -- al elemento que se está serializando -- El parámetro FORMAT contiene el nombre del formato físico -- definido en el mensaje DECLARE StatementBitStream BLOB CAST(ASBITSTREAM(targetCursor.Statement OPTIONS FolderBitStream SET 'LargeMessageExample' TYPE 'Data/Statement' FORMAT 'XML1') AS BLOB); -- Si SELECT ha generado un resultado (es decir, si la cláusula WHERE no la -- ha filtrado), procese la sentencia IF StatementBitStream IS NOT NULL THEN -- crear un campo que contenga la corriente de bits del árbol de resultados -- El Type del elemento se establece en MRM.BitStream para indicar -- al analizador MRM que se trata de una corriente de bits CREATE LASTCHILD OF resultCursor Type MRM.BitStream NAME 'Statement' VALUE StatementBitStream; -- Añadir el importe de la sentencia actual al total SET grandTotal = grandTotal + targetCursor.Statement.Amount; END IF; -- Suprimir el árbol de sentencia real dejando solo la versión de la corriente de bits DELETE FIELD targetCursor.Statement; -- Pasar a la siguiente factura y suprimir la factura anterior y cualquier -- elemento de texto que se haya propagado con las facturas REPEAT MOVE sourceCursor NEXTSIBLING; DELETE PREVIOUSSIBLING OF sourceCursor; UNTIL (FIELDNAME(sourceCursor) = 'Invoice') OR (LASTMOVE(sourceCursor) = FALSE) END REPEAT; -- Si no hay más facturas que procesar, abandonar el bucle IF NOT LASTMOVE(sourceCursor) THEN LEAVE InvoiceLoop; END IF; END LOOP InvoiceLoop; END ProcessInvoice; -- Suprimir las carpetas de origen y destino temporales DELETE FIELD OutputRoot.MRM.SourceMessageTree; DELETE FIELD OutputRoot.MRM.TargetMessageTree; -- Finalmente añadir el total SET resultCursor.GrandTotal = grandTotal; -- Establecer la propiedad MessageType de salida en 'Data' SET OutputRoot.Properties.MessageType = 'Data'; RETURN TRUE; END; CREATE PROCEDURE CopyMessageHeaders() BEGIN DECLARE I INTEGER 1; DECLARE J INTEGER CARDINALITY(InputRoot.*[]); WHILE I < J DO SET OutputRoot.*[I] = InputRoot.*[I]; SET I = I + 1; END WHILE; END; END MODULE;