I am using Esper 5.0 and need to perform a query on data from a relational database. This is in my case a MySQL database connected via JDBC. Now I would like to formulate an EPL query on the data from the database. Hence, my query is similar to this one:
String parameter = "any"; // untrusted (!) parameter from some user input
String mySqlQuery = "SELECT `sth` FROM `mytable` WHERE `att` = " + parameter;
String query = "select sth from sql:myDB ['" + mySqlQuery + "']"
Now how can I sanitize the untrusted parameter which is then send to my MySQL database? The Esper documentation says that the query is basically passed to the database software unchanged. So what can I do? I came up with four ideas:
- Using EPL substitution parameters: Does not work, because it is not supported by Esper in SQL expressions.
- Using EPL variables: It should be possible to define a variable via something like
epService.getEPAdministrator().getConfiguration().addVariable("parameter", String.class, parameter);
, then use the syntax"SELECT `sth` FROM `mytable` WHERE `att` = ${parameter}"
for the MySQL query. Esper should replace the variable with the respective value. It is not nice to define a global variable for it, although one could again remove it withepService.getEPAdministrator().getConfiguration().removeVariable("parameter", true);
afterwards. But much more important: That also does not sanitize the untrusted parameter and does not make it safe to pass it to the database, right? - Sanitizing the parameters on the Java side: Queries on the Java side should be done via
PreparedStatement
. Since it is technically impossible to get a MySQL query string out of aPreparedStatement
, this is not an option. I do not think that there is another safe way to sanitize a parameter passed to a database on the Java side. - Defining all the constraints on the EPL side: One could probably just do a
SELECT * FROM `mytable`
without defining any constraints in order to select everything from the MySQL database and then define the constraints via EPL and use aEPPreparedStatement
for it. Is this the proper way to go? I fear that this is not really performant, because a lot of entries are read from the MySQL database which are not needed.
Any ideas?