Java - recorrer el array de sentencias

 
Vista:
sin imagen de perfil

recorrer el array de sentencias

Publicado por kathe (2 intervenciones) el 25/10/2016 13:53:11
hola tengo un problema era por si me podias ayudar me cuesta mucho programar y me han pedido en clase lo siguiente:

Tenemos que recorrer el array de sentencias , y esto lo haces con un FOR o un foreach
- Comprobar que todas empiezan por insert
- Tras el insert existe un INTO
- tras el INTO existe un nombre de tabla (LEARNSQL_PROVINCIAS, LEARSQL_CCAA)
- tras la tabla tiene que existir "VALUES (" Y al final tiene que existir un parentesis)


MUCHAS GRACIAS DE ANTEMANO
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder

recorrer el array de sentencias

Publicado por YYanes (144 intervenciones) el 25/10/2016 17:29:19
Hola Kathe:

el ejercicio que propones está muy interesante. Para resolver todos estos puntos debes de hacer uso de las funciones de la clase String, en especial de indexOf(cadenaString) y charAt(posicion). Y bién, ¿para qué sirven estas dos funciones?, pues la primera te devuelve la posición de una sub-cadena dentro de la cadena String, y la segunda te devuelve el caracter de una posición dada dentro del String, por ejemplo:

1
2
3
4
5
String cadena = "mi cadena string";
int pos = cadena.indexOf("mi"); //devuelve cero, pues 'mi' tiene index cero dentro de la cadena
int pos2 = = cadena.indexOf("cad"); //devuelve 3, pues 'cad' tiene index 3 dentro de la cadena
 
cadena.charAt(5); // devuelve el caracter de index 5 (posición 6), es decir, devuelve 'd'

Ahora bien, entrando en la solución a tu ejercicio: te propongo esta variante que verifica que, dado un arreglo de sentencias (arreglo de Strings cullos valores de cada posición son sentencias SQL simples), te revisa cada una de estas verificando lo siguiente:
-cada cadena comienza con 'insert' (sin importar mayúsculas ni minúsculas)
-continúa con 'into' (sin importar mayúsculas ni minúsculas)
-seguidamente viene el nombre de la tabla seguido por 'values('
-y finalmente cierra con paréntesis ')'

Advertencias sobre la solución que estoy a punto de ofrecerle:
-se asume que entre cada segmento a verificar (por ejemplo, entre 'insert' e 'into') existe obligatoriamente un espacio sencillo (solo un espacio), no he tenido tiempo de validarla para casos en los que haya más de un espacio.
-en el segmento 'values(' no habrá ningún espacio entre la 's' y el paréntesis '(', ejemplo: 'values(' está OK, 'values (' indicará error.

Muy bien, sin más... aquí le va mi variante:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
//--asumiendo que tienes un ArrayList<String> de sentencias:
for(int i=0; i<arregloSentencias.length(); i++){
   RevisarLinea(arraylistSentencias.get(i), i+1);
}
 
//si lo que tienes es un arreglo de String sería entonces
for(int i=0; i<arregloSentencias.length(); i++){
   RevisarLinea(arraylistSentencias[i], i+1);
}
 
//---- lo más importante es el siguiente método, que dado un String (la línea) y un int (posición de dicha línea dentro del array), 
//---- revisará su estructura e informará errores:
 
public void RevisarLinea(String linea, int posLinea){
      int posIni = 0;
      int posFin = 0;
      while(linea.charAt(posFin) != ' ' && posFin<linea.length()-1){
          posFin++;
      }
      String parte1 = linea.substring(0, posFin);
      if(parte1.compareToIgnoreCase("insert")!=0)
        JOptionPane.showMessageDialog(this, "La línea " + posLinea + " no comienza por 'insert'");
      posIni = posFin;
      if(posFin<linea.length())
         posFin++;
 
     //--- verificación del INTO -----     
          while(linea.charAt(posFin) != ' ' && posFin<linea.length()-1){
              posFin++;
          }
          String parte2 = linea.substring(posIni, posFin).trim();
          if(parte2.compareToIgnoreCase("into")!=0)
            JOptionPane.showMessageDialog(this, "La línea " + posLinea + " no continúa con 'INTO' luego del 'insert'");
          posIni = posFin;
          posFin++;
 
      //--- verificación de la existencia de nombres de tablas, también
      //--- de la existencia de 'values(' en la cadena después del nombre de la tabla
         int indexCadena = linea.indexOf("values(");
         if(indexCadena>-1){ // significa que 'values(' existe
             if(posFin == indexCadena) //'values(' tiene una longitud de 7 caracteres
                JOptionPane.showMessageDialog(this, "La línea " + posLinea + " no tiene nombre de tabla antes del 'values('");
         }
        else
          JOptionPane.showMessageDialog(this, "A la línea " + posLinea + " le falta el 'values('");
      //--------------------
      if(linea.charAt(linea.length()-1) != ')')
          JOptionPane.showMessageDialog(this, "A la línea " + posLinea + " le falta el paréntesis de cierre ')'");
    }
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
1
Comentar
sin imagen de perfil

recorrer el array de sentencias

Publicado por kathe (2 intervenciones) el 26/10/2016 13:34:00
Muchas gracias YYanes me ah servido de mucho tu ayuda.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

recorrer el array de sentencias

Publicado por YYanes (144 intervenciones) el 25/10/2016 17:43:41
Viendo el código que le subí podría pensar: ¿para qué complicarse tanto si con el simple uso del "indexOf(String)" podría haber verificado la existencia de las subcadenas dentro de cada sentencia? Pues bien, esta función verifica la existencia dentro de la sub-cadena, pero no verifica la sintaxis de la misma, por ejemplo:

String cadenaSQL1 = "insert into tablaX values(1,2)";
String cadenaSQL2 = "into values(1,2) tablaX insert ";

como verás, la cadenaSQL1 está bien, pues no solo tiene todas sus partes (el 'insert', el 'into' y demás) sino que están en orden, es decir, la cadena está sintácticamente correcta; mientras que por el contrario, cadenaSQL2 lo tiene todo, pero está desorganizada. Luego viene el siguiente problema:

cadenaSQL1.indexOf("insert");
cadenaSQL2.indexOf("insert");
/* ambas devuelven un valor válido, pues la subcadena "insert" existe dentro de las 2, pero por sí sola no te dice si está antes o después del "into", eso habría que programarlo; pero ahora supongamos que verificamos que "insert" está antes de "into", por ejemplo:

if(cadenaSQL1.indexOf("insert") < cadenaSQL1.indexOf("into") )
<<todo correcto>>
else
<<mensaje de error>>

pero entonces podría surgir lo siguiente: */

String cadenaSQL1 = "insert abcabc into tablaX values(1,2)";
String cadenaSQL2 = "tablaX into values(1,2) insert ";
//- en ambos casos "insert" está antes que "into", pero en ambos casos la cadena está mal sintácticamente.

En resumen, las posibilidades para la solución son muchas, pero al menos le ofrecí la variante que le publiqué anteriormente, que aunque se le pueden hacer muchas mejoras, por lo menos funciona.

Un GigaSaludo!!!
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

recorrer el array de sentencias

Publicado por Tom (1831 intervenciones) el 25/10/2016 18:38:36
Sin depurar mucho:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import java.util.ArrayList;
/** */
public class SQLSyntax {
	/* */
	public static void validate(ArrayList<String> cads) {
		for(String s : cads) {
			System.out.printf("'%s': %s\n", s, validateStr(s));
		}
	}
	/* */
	public static boolean validateStr(String s) {
		String toks[] = s.split(" ");
		if(toks.length > 4) {
			if(toks[0].toUpperCase().equals("INSERT")) {
				if(toks[1].toUpperCase().equals("INTO")) {
					if(toks[3].toUpperCase().startsWith("VALUES") || toks[3].toUpperCase().startsWith("VALUES(")) {
						if(toks[toks.length - 1].endsWith(")")) {
							return true;
						}
					}
				}
			}
		}
		return false;
	}
 
	/* */
	public static void main(String args[]) {
		ArrayList<String> test = new ArrayList();
		test.add("insert into my_tabla values(1, 2, 3)");
		test.add("insert intomy_tabla values(1, 2, 3)");
		test.add("insertinto my_tabla values(1, 2, 3)");
 
		SQLSyntax.validate(test);
	}
}
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

recorrer el array de sentencias

Publicado por Tom (1831 intervenciones) el 25/10/2016 18:59:40
Y un poco mejor, aunque no tan fácil de seguir o cambiar:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class SQLSyntax {
	static final Pattern p = Pattern.compile("insert\\s+into\\s+\\w+\\s+values\\s*(.*)", Pattern.CASE_INSENSITIVE);
	/* */
	public static void validate(ArrayList<String> cads) {
		for(String s : cads) {
			System.out.printf("'%s': %s\n", s, validateStrR(s));
		}
	}
	/* */
	public static boolean validateStrR(String s) {
		return p.matcher(s).matches();
	}
	/* */
	public static void main(String args[]) {
		ArrayList<String> test = new ArrayList();
		test.add("insert into my_tabla values(1, 2, 3)");
		test.add("insert intomy_tabla values(1, 2, 3)");
		test.add("insertinto my_tabla values(1, 2, 3)");
 
		SQLSyntax.validate(test);
	}
}
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

recorrer el array de sentencias

Publicado por YYanes (144 intervenciones) el 25/10/2016 20:12:17
muy buena solución, sencilla pero consistente. Lo único que le falta es el tratamiento de excepciones, es decir, cada vez que falle algún IF arrojar el mensaje al usuario para que sepa en cuál sección de la sentencia se encontró el error, pero eso es algo que puede hacer la propia Kathe cuando lo pase a su programa, ¿verda?. En resumen, muy buena solución.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar