REPORTEADOR GENERICO

HOLA ALGUIEN ME PUEDE ORIENTAR, PARA DESARROLLAR UN REPORTEADOR GENÉRICO, UTILIZANDO IREPORT 3.0.0 Y NETBEANS 6.1 U 6.7, EN MI APLICACIÓN TENGO QUE PONER EN UN CAJA DE TEXTO MI CONSULTA EN MYSQL Y AL DARLE CLIC EN UN BOTÓN ME DEBE GENERAR UN REPORTE DEPENDIENDO DE LA CONSULTA QUE ANTERIORMENTE PUSE.... ESTO PUEDE SER FACTIBLE???? ESPERO Y ME PUEDAN AYUDAR....GRACIAS!!!

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.
Imagen de ezamudio

Factible pero no recomendable

Supongo que por "PONER EN UN CAJA DE TEXTO MI CONSULTA EN MYSQL" te refieres a que el usuario pueda directamente escribir una sentencia SQL y que tu programa la ejecute y le devuelva el resultado. Esto es factible pero no es recomendable, por seguridad. Aunque el usuario que utilices para la aplicación no tenga permisos de ejecución ni modificación de ninguna tabla ni datos y que solamente pueda leer registros de ciertas tablas, una aplicación como lo que mencionas es una vulnerabilidad muy grave en tu sistema porque podría un usuario teclear un query muy pesado (joins de varias tablas filtrando por columnas no indexadas, que devuelva miles y miles de registros) y pueden alentar toda la base de datos.

Si se trata solamente de un ejercicio, pues simplemente creas un Statement con el SQL que el usuario ponga, lo ejecutas como query para obtener un ResultSet, y al mismo ResultSet le puedes pedir los metadatos de la consulta (el número de columnas, así como el nombre y tipo de cada una).

Luego tendrás que ir iterando los registros para ir formando tu reporte y cuando no obtengas más, tienes que ver si es porque el ResultSet cambia o es porque ya no hay más registros (esto puede ser posible cuando se ejecuta un stored procedure que devuelve varias consultas con distintas columnas).

El código es algo asi:

Statement stmt = conexion.createStatement();
ResultSet rs = stmt.executeQuery(textBox.getText());
ResultSetMetaData meta = rs.getMetaData();
//Al meta le puedes pedir varias cosas
int cols = meta.getColumnCount(); //es el numero de columnas
//Para saber que vas a obtener de cada una
for (int i = 0; i < cols; i++) {
  String clase = meta.getColumnClassName(i); //el nombre de la clase
  String nombre = meta.getColumnName(i); //o getColumnLabel(i) tambien, para obtener el nombre que puedes usar en el reporte
  //Con estos datos puedes ir construyendo el reporte de iReport
}
while (rs.next()) {
  //iteras por cada columna del renglon
}
//Al llegar aqui ya no hay mas resultado en el ResultSet pero puede haber mas ResultSets esperando
if (stmt.getMoreResults()) {
  rs = stmt.getResultSet(); // asi obtienes el siguiente ResultSet
  //aqui tienes que volver a ejecutar todo lo obtener metadatos y volver a iterar con rs.next(), te conviene tener ese codigo en un metodo aparte
} else {
  rs.close();
}

No olvides poner todo eso en un try-catch-finally y en el finally cerrar el ResultSet si es que existe, cerrar el Statement si es que existe, y finalmente cerrar la conexion si ya no la vas a usar.

Imagen de Nopalin

Puede haber algo de seguridad

Podria utilizar un tipo de seguridad algo burda, si la cadena escrita en el textbox la trimea y que cheque que inicie con "select" entonces ahi si ya no puede mover ningun registro creo yo.

sobres

re: Puede haber algo de seguridad

que cheque que inicie con "select"

No, no, no. ¿Y si empieza con SELECT y a la mitad de la sentencia ponen un ";" y a continuación un DELETE, UPDATE, INSERT?

Vean la presentación de seguridad de ezamudio.

Saludos

Javier Castañón

Imagen de ezamudio

puro SELECT

además de lo que comenta Javier, pueden hacer un SELECT válido a una función o stored procedure que ejecute algo que modifica tablas... en fin, dejar que el usuario teclee SQL directamente es buscarse problemas. Y ya que me hizo publicidad pues pongo la liga a mi artículo acerca de inyección de SQL.

A fin de cuentas pueden proponer mil soluciones, que si parsean datos, que si permiten solamente una sentencia, etc etc; pero entonces se vuelve demasiado trabajo. Incluso lo de evitar queries que ataranten al servidor de base de datos se podría evitar con ciertos servidores; con PostgreSQL se me ocurre que primero se le pusiera un EXPLAIN al query para obtener un resultado explicando más o menos el esfuerzo que va a costar y si es demasiado, decirle al usuario que por favor optimice el query para ejecutarlo. Pero podría ser que sea absolutamente necesario ejecutar un query así... en fin. Era una simple observación; si ERIKA sabe que todo esto de la seguridad es irrelevante para la aplicación que va hacer, ya tiene ahí el ejemplo que puse para ejecutar el query (con JDBC puro, por cierto).

HOLA!!!

OK GRACIAS POR LAS SOLUCIONES QUE ME DAN LO CHEKARE ESPERO TENER EXITO EN MI APLICACION!!....GRACIAS

Imagen de Nopalin

Yo sigo en la misma

Bueno, solo un par de cosas antes de exaltarnos.
Si esta haciendo una interfaz para escribir un query generico y traer datos crudos desde la bd, significa que esa funcionalidad la va a utilizar alguien que sepa lo que esta haciendo, ahora suponiendo que no sea asi y que el usuario pueda ser malicioso, checamos que en el query escrito no haya ningun keyword que altere la base de datos, por ejemplo buscamos que en la cadena escrita no existan palabras como: UPDATE, DELETE, INSERT, o si pueden existir siempre y cuando estén encerradas entre comillas simples.

Como dije, una seguridad algo burda pero pues si el reporteador es algo que tiene que implementar, pues aunque sea que tome esas precauciones, no?

sobres