public static String explainPlanFor(String sqlRequest) throws SQLException, NamingException {
		final Connection connection = getConnection();
		if (connection != null) {
			try {
				final Database database = Database.getDatabaseForConnection(connection);
				if (database == Database.ORACLE) {
					// Si oracle, on demande le plan d'exécution avec la table PLAN_TABLE par défaut
					// avec "explain plan set statement_id = <statement_id> for ..."
					// (si mysql, on pourrait faire "explain ...",
					// sauf que les paramètres bindés ne seraient pas acceptés
					// et les requêtes update/insert/delete non plus).
					// (si db2, la syntaxe serait "explain plan for ...")

					// Si mysql il suffit de lire le ResultSet de executeQuery("explain ...")
					// qui pourrait être affiché en tableau à partir de String[][],
					// mais en oracle il faut aller lire la table plan_table
					// (http://www.java2s.com/Open-Source/Java-Document/Database-Client/squirrel-sql-2.6.5a/net/sourceforge/squirrel_sql/plugins/oracle/explainplan/ExplainPlanExecuter.java.htm)
					// le hashCode est une clé suffisamment unique car il y a peu de plans d'exécution
					// affichés simultanément, et en tout cas CounterRequest.getId() est trop long
					// pour la table oracle par défaut (SYS.PLAN_TABLE$.STATEMENT_ID a une longueur de 30)
					final String statementId = String.valueOf(sqlRequest.hashCode());
					// utilisation de la table PLAN_TABLE par défaut
					// (il faut que cette table soit créée auparavant dans oracle
					// et elle peut être créée par : @$ORACLE_HOME/rdbms/admin/catplan.sql
					// ou par @$ORACLE_HOME/rdbms/admin/utlxplan.sql si oracle 9g ou avant)
					final String explainRequest = "explain plan set statement_id = '" + statementId
							+ "' for " + normalizeRequestForExplain(sqlRequest, ':');
					// exécution de la demande
					try (final Statement statement = connection.createStatement()) {
						statement.execute(explainRequest);
					}

					// récupération du résultat
					// table PLAN_TABLE par défaut et format par défaut
					final String planTableRequest = "select * from table(dbms_xplan.display(null,?,null))";
					final String[][] planTableOutput = executeRequest(connection, planTableRequest,
							Collections.singletonList(statementId));
					final StringBuilder sb = new StringBuilder();
					for (final String[] row : planTableOutput) {
						for (final String value : row) {
							sb.append(value);
						}
						sb.append('\n');
					}
					if (sb.indexOf("-") != -1) {
						sb.delete(0, sb.indexOf("-"));
					}
					return sb.toString();
				} else if (database == Database.POSTGRESQL && POSTGRESQL_DRIVER_AVAILABLE
						&& connection.getMetaData().getDatabaseMajorVersion() >= 16) {
					// Si postgresql, on demande le plan d'exécution avec "explain (generic plan) ..."
					final PgConnection pgConnection = connection.unwrap(PgConnection.class);
					if (pgConnection != null) {
						final PreferQueryMode preferQueryMode = pgConnection.getQueryExecutor()
								.getPreferQueryMode();
						try {
							// given the parameters without values, explain (generic plan) should be executed as simple query
							// and not as prepared query which is by default.
							// (there is no other way than using postgresql "internal" api:
							// not possible using jdbc api or postgresql "public" api)
							pgConnection.getQueryExecutor()
									.setPreferQueryMode(PreferQueryMode.SIMPLE);

							// explain plan pour Postgresql 16 ou ultérieur
							// https://www.cybertec-postgresql.com/en/explain-generic-plan-postgresql-16/
							final String explainPlanRequest = "explain (generic_plan) "
									+ normalizeRequestForExplain(sqlRequest, '$');
							final StringBuilder sb = new StringBuilder();
							try (final Statement statement = connection.createStatement()) {
								try (final ResultSet resultSet = statement
										.executeQuery(explainPlanRequest)) {
									while (resultSet.next()) {
										sb.append(resultSet.getString(1)).append('\n');
									}
								}
							}
							return sb.toString();
						} finally {
							// set back the connection preferQueryMode as before
							pgConnection.getQueryExecutor().setPreferQueryMode(preferQueryMode);
						}
					}
				}
			} finally {
				if (!connection.getAutoCommit()) {
					connection.rollback();
				}
				connection.close();
			}
		}
		return null;
	}
@Test
	public void testExplainPlanFor() throws SQLException, NamingException {
		DatabaseInformations.explainPlanFor("select 1");
	}