---
url: /res/oie/cookbook/requete-sql.md
description: >-
  Manipuler du SQL en JavaScript avec le moteur Rhino dans Open Integration
  Engine et Mirth Connect
---

## Les requêtes SQL

Si votre source n'est pas un **Database Reader** et que vous souhaitez faire un requête SQL dans le transformer de la partie source
afin de vous en servir comme flux d'entrée, en modifiant la variable **msg** disponible nativement,

## Fonction sqlQueryToXML

La fonction **sqlQueryToXML** execute la requête SQL sur la connexion donnée en paramètre, et retourne un contenu de type XML
compatible avec  la variable **msg**

Ajouter cette fonction dans le Code Template dans la ressource de votre choix.

```javascript
/**
	Executes a SQL query and transforms the result set into an Mirth XML Datatype.
	
	This function iterates through all rows and columns of the provided query results. Date and
	Timestamp columns are automatically converted to ISO 8601 strings with timezone offset (e.g.,
	yyyy-MM-dd'T'HH:mm:ss.SSSXXX).

	@param {com.mirth.connect.server.util.DatabaseConnection} dbConn - The Mirth database connection
		object.
	@param {string} sqlQuery - The SQL SELECT statement to execute.
	@return {XML|null} An E4X XML object containing the results, or null if an error occurs.
*/
function sqlQueryToXML(dbConn, sqlQuery) {
	res = null;
	if (dbConn == null) {
	    logger.error("Error sqlQueryToXML : Unable to connect to the database.");
	}
	
	try {
		var results = dbConn.executeCachedQuery(sqlQuery);
		var metaData = results.getMetaData();
		var colCount = metaData.getColumnCount();

		var xmlOutput = new XML('<results></results>');

		while (results.next()) {
			var row = new XML('<result></result>');
			
			for (var i = 1; i <= colCount; i++) {
				var colName = metaData.getColumnLabel(i); // Utilise l'alias SQL si présent au lieu du nom de colonne
				var colType = metaData.getColumnTypeName(i).toUpperCase();
				var value = "";

				if (colType.indexOf("DATE") !== -1 || colType.indexOf("TIMESTAMP") !== -1) {
					var javaDate = results.getTimestamp(i);
					if (javaDate != null) {
						// Formater la date en String au format ISO avec le timezone
						value = DateUtil.formatDate("yyyy-MM-dd'T'HH:mm:ss.SSSXXX", javaDate);
					}
				} else {
					value = (results.getString(i) || "").trim();
				}

				row[colName] = value;
			}
			xmlOutput.appendChild(row);
		}

		res = xmlOutput;

	} catch (e) {
		logger.error("Error sqlQueryToXML : " + e.toString());
	}	
	
	return res;
}
```

Pour utiliser cette requête, aller dans l'onglet **Source** , puis dans **Edit transformer** , et faite **Add New Step** ,
choisisser le type de **Step** Javascript, et copier coller le code ci dessous (changer la requête SQL bien sûr).

```javascript
var query = "SELECT nom, prenom, date_naissance, ipp, episode FROM patient";

msg = sqlQueryToXML(dbConn, query);
```

Cela donne l'équivalent du **Inbound Message Template** suivant:

```xml
<results>
  <result>
    <nom>Doe</nom>
    <prenom>John</prenom>
    <date_naissance>1970-01-01T01:01:00.001</date_naissance>
    <ipp>PAT001</ipp>
    <episode>SEJ001</episode>
  </result>
</results>
```

:::tip
La balise `<results>` indique que le résultat peut retourner plusieurs lignes de données
si vous souhaitez recupérer qu'un seule ligne, vous pouvez adapter avec le code ci-dessous

```javascript
msg = sqlQueryToXML(dbConn, query);
if (msg) {
    msg = msg['result'][0];
}
```

:::

## Fonction sqlQueryAppendXML

Cette fonction va vous permettre d'exécuter une requête SQL et de retourner
un ensemble de lignes en personnalisant la racine XML.

```javascript
/**
	Executes a SQL query and transforms the result set into an Mirth XML Datatype.
	
	This function iterates through all rows and columns of the provided query results. Date and
	Timestamp columns are automatically converted to ISO 8601 strings with timezone offset (e.g.,
	yyyy-MM-dd'T'HH:mm:ss.SSSXXX).

	@param {com.mirth.connect.server.util.DatabaseConnection} dbConn - The Mirth database connection
		object.
	@param {string} sqlQuery - The SQL SELECT statement to execute.
	@param {string} elGroup - XML element to repeat per line
	@return {XML|null} An E4X XML object containing the results, or null if an error occurs.
*/
function sqlQueryAppendXML(dbConn, sqlQuery, elGroup) {
	res = null;
	var count = 0;
	if (dbConn == null) {
	    logger.error("Error sqlQueryToXML : Unable to connect to the database.");
	}
	elGroup = (typeof elGroup !== 'undefined') ? elGroup : "result";
	
	try {
		var results = dbConn.executeCachedQuery(sqlQuery);
		var metaData = results.getMetaData();
		var colCount = metaData.getColumnCount();

		var xmlOutput = new XML('<root></root>');

		while (results.next()) {
			var row = new XML('<' + elGroup +'></' + elGroup +'>');
			count += 1;
			for (var i = 1; i <= colCount; i++) {
				var colName = metaData.getColumnLabel(i); 
				var colType = metaData.getColumnTypeName(i).toUpperCase();
				var value = "";

				if (colType.indexOf("DATE") !== -1 || colType.indexOf("TIMESTAMP") !== -1) {
					var javaDate = results.getTimestamp(i);
					if (javaDate != null) {
						// Formater la date en String au format ISO avec le timezone
						value = DateUtil.formatDate("yyyy-MM-dd'T'HH:mm:ss.SSSXXX", javaDate);
					}
				} else {
					value = (results.getString(i) || "").trim();
				}

				row[colName] = value;
			}
			xmlOutput.appendChild(row);
		}

		res = xmlOutput;

	} catch (e) {
		logger.error("Error sqlQueryToXML : " + e.toString());
	}
	// on retourne l'élément parent vide lorsqu'il n'y a pas de ligne retournée
	if (res === null || count === 0) {
		return new XML('<' + elGroup +'></' + elGroup +'>');;
	}
	return res.children();
}
```

Imaginons que la variable **msg** est alimenté via une précédente requête,
et que l'on souhaite y ajouter les détails des séjours par exemple, nous
allons pouvoir ajouter le code suivant

```javascript

query = "SELECT episode, service, chambre, lit FROM sejour WHERE ipp = " + msg['ipp'].toString();

var res = sqlQueryAppendXML(dbConn, query, 'sejour');
msg.appendChild(res);
```

:::tip
Les exemples montrent l'utilisation direct de la variable **msg**, mais je recommenderais
d'utiliser une variable temporaire pour faire toute des manipulations (ex: tmpMsg),
en ensuite à la fin de surcharger **msg**

```javascript
var tmpMsg;
var res;
...
tmpMsg = sqlQueryToXML(dbConn, query);
if (tmpMsg) {
    tmpMsg = tmpMsg['result'][0];
}
...
res = sqlQueryAppendXML(dbConn, query, 'sejour');
tmpMsg.appendChild(res);

msg = tmpMsg;
```

:::
