La manipolazione di una struttura ad albero del messaggio di grandi dimensioni può quindi richiedere una notevole quantità di memoria. Se si progetta un flusso di messaggi che gestisce messaggi di grandi dimensioni, costituiti di strutture che si ripetono, è possibile codificare istruzioni ESQL specifiche per ridurre il carico di memorizzazione nel broker. Tali istruzioni supportano l'accesso al messaggio sia casuale che sequenziale, ma presuppongono che non sia necessario accedere all'intero messaggio in una sola volta.
Queste istruzioni ESQL fanno in modo che il broker esegua un'analisi limitata del messaggio e conservi solo quella parte della struttura ad albero del messaggio che riflette un singolo record nella memoria alla volta. Se l'elaborazione richiede di conservare le informazioni da un record all'altro (ad esempio, per calcolare un prezzo totale da una struttura ripetuta di elementi in un ordine), è possibile dichiarare, inizializzare e conservare le variabili ESQL o salvare i valori in un'altra sezione della struttura ad albero del messaggio, ad esempio LocalEnvironment.
Questa tecnica riduce la memoria utilizzata dal broker a quella necessaria per mantenere i flussi di bit di input e di output completi, più quella richiesta per le strutture ad albero di un record. Essa consente di risparmiare memoria quando si incontra anche un numero ridotto di ripetizioni nel messaggio. Il broker utilizza l'analisi parziale e la capacità di analizzare sezioni specificate della struttura ad albero del messaggio, da e verso la parte corrispondente del flusso di bit.
E' possibile variare queste tecniche per adattarle all'elaborazione richiesta per i propri messaggi. Il seguente ESQL fornisce un esempio di implementazione ed è una riscrittura dell'esempio di ESQL in Gestione di messaggi XML di grandi dimensioni che utilizza un'unica istruzione SET con funzioni SELECT nidificate per trasformare un messaggio che contiene strutture nidificate e ripetute.
L'ESQL dipende da una serie di messaggi denominata LargeMessageExanple che è stata creata per definire i messaggi per il formato di input Invoice e per il formato di output Statement. E' stato creato un messaggio denominato AllInvoices che contiene un elemento globale denominato Invoice che può ripetersi una o più volte e un messaggio denominato Data che contiene un elemento globale denominato Statement che può ripetersi una o più volte.
Alle definizioni degli elementi e degli attributi sono stati assegnati i tipi di dati corretti, quindi, le istruzioni CAST utilizzate da ESQL nell'esempio XML non sono più richieste. E' stato creato un formato fisico XML con nome XML1 nella serie di messaggi che consente ad un messaggio XML, corrispondente a questi messaggi, di essere analizzato da MRM.
Quando la struttura ad albero Statement è serializzata utilizzando la funzione ASBITSTREAM la Serie di messaggi, il Tipo messaggio e il Formato del messaggio sono specificati come parametri. Il parametro Tipo messaggio contiene il percorso dal messaggio all'elemento serializzato che, in questo caso, è Data/Statement poiché l'elemento Statement è un child diretto del messaggio Data.
<AllInvoices> .... </AllInvoices>
Il messaggio di output è identico a quello in Gestione di messaggi XML di grandi dimensioni.
CREATE COMPUTE MODULE LargeMessageExampleFlow_Compute CREATE FUNCTION Main() RETURNS BOOLEAN BEGIN CALL CopyMessageHeaders(); -- Creare una cartella speciale nel messaggio di output per contenere la struttura ad albero di input -- Nota : SourceMessageTree è l'elemento root di un programma di analisi MRM CREATE LASTCHILD OF OutputRoot.MRM DOMAIN 'MRM' NAME 'SourceMessageTree'; -- Copiare il messaggio di input in una cartella speciale nel messaggio di output -- Nota : questa è una copia da root a root che quindi non crea strutture ad albero SET OutputRoot.MRM.SourceMessageTree = InputRoot.MRM; -- Creare una cartella speciale nel messaggio di output per contenere la struttura ad albero di output CREATE FIELD OutputRoot.MRM.TargetMessageTree; -- Prepararsi ad eseguire il loop degli articoli acquistati 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; -- Creare un blocco in modo che sia facile interrompere l'elaborazione ProcessInvoice: BEGIN -- Se non esistono fatture nel messaggio di input, non vi sono operazioni da compiere IF NOT LASTMOVE(sourceCursor) THEN LEAVE ProcessInvoice; END IF; -- Eseguire il loop delle fatture nella struttura ad albero di origine InvoiceLoop : LOOP -- Controllare la fattura corrente e creare un'istruzione corrispondente 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' ); -- Trasformare l'istruzione corrente in un flusso di bit -- Il parametro SET è impostato sul nome della serie di messaggi -- che contiene la definizione MRM -- Il parametro TYPE contiene il percorso dal messaggio -- all'elemento serializzato -- Il parametro FORMAT contiene il nome del formato fisico -- definito nel messaggio DECLARE StatementBitStream BLOB CAST(ASBITSTREAM(targetCursor.Statement OPTIONS FolderBitStream SET 'LargeMessageExample' TYPE 'Data/Statement' FORMAT 'XML1') AS BLOB); -- Se SELECT ha prodotto un risultato (cioè, non è stata filtrata -- dalla clausola WHERE), elaborare l'istruzione IF StatementBitStream IS NOT NULL THEN -- creare un campo per contenere il flusso di bit nella struttura ad albero dei risultati -- Il valore Type dell'elemento è impostato su MRM.BitStream per indicare -- al programma di analisi MRM che si tratta di un flusso di bit CREATE LASTCHILD OF resultCursor Type MRM.BitStream NAME 'Statement' VALUE StatementBitStream; -- Aggiungere l'ammontare del rendiconto corrente all'importo totale SET grandTotal = grandTotal + targetCursor.Statement.Amount; END IF; -- Eliminare l'albero reale del rendiconto lasciando solo la versione del flusso di bit DELETE FIELD targetCursor.Statement; -- Passare alla fattura successiva, rimuovendo la fattura precedente e tutti -- gli elementi di testo che potrebbero essere distribuiti nelle fatture REPEAT MOVE sourceCursor NEXTSIBLING; DELETE PREVIOUSSIBLING OF sourceCursor; UNTIL (FIELDNAME(sourceCursor) = 'Invoice') OR (LASTMOVE(sourceCursor) = FALSE) END REPEAT; -- Se non ci sono altre fatture da elaborare, interrompere il loop IF NOT LASTMOVE(sourceCursor) THEN LEAVE InvoiceLoop; END IF; END LOOP InvoiceLoop; END ProcessInvoice; -- Rimuovere l'origine temporanea e le cartelle di destinazione DELETE FIELD OutputRoot.MRM.SourceMessageTree; DELETE FIELD OutputRoot.MRM.TargetMessageTree; -- Infine aggiungere l'importo totale SET resultCursor.GrandTotal = grandTotal; -- Impostare la proprietà MessageType di output su '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;