2012-05-24 4 views
6

Estoy trabajando en una aplicación OSS basada en Java SqlHawk que como una de sus características es ejecutar secuencias de comandos sql de actualización contra un servidor.¿Cómo puedo admitir la instrucción SQL GO en una aplicación Java/jtds?

Microsoft ha hecho una convención dividir una secuencia de comandos en lotes con la instrucción GO, lo cual es una buena idea, pero solo pide coincidencias falsas en la cadena.

En el momento en que tienen una muy rudimentaria:

// split where GO on its own on a line 
Pattern batchSplitter = Pattern.compile("^GO", Pattern.MULTILINE); 
... 
String[] splitSql = batchSplitter.split(definition); 
... 

qué tipo de obras, pero es propenso a ser disparado por cosas como quoted GO statements o sangría cuestiones.

Creo que la única manera de hacer esto realmente confiable es tener un analizador SQL en la aplicación, pero no tengo ni idea de cómo hacerlo, o si en realidad podría ser menos confiable (especialmente dada esta herramienta admite múltiples DBMS).

¿De qué maneras podría solucionar este problema? Los ejemplos de código me serían muy útiles aquí.

Relevant sqlHawk code en github.

Actualmente se usa jtds para ejecutar los lotes encontrados en los scripts.

+1

Lo hice a su manera cuando tuve que hacer algo similar. Solo se usa internamente y funciona bien para nosotros. – brain

+1

Idem aquí ... Está lejos de ser infalible y debe decidir si desea respaldar cosas como 'GO 100'. El principal obstáculo en mi humilde opinión es cuando el GO forma parte de un */bloque de comentarios * /. Esos requieren un poco de procesamiento adicional. (elimine todos los comentarios y bloque de comentario primero, luego haga la división es lo que hicimos) PD: Puede prefijar el código con 'SET PARSEONLY ON 'y si no hay' Sintaxis incorrecta cerca de GO 'no hay necesidad de dividir el código ... de lo contrario, podría usar la ubicación de la línea indicada por el error para "identificar dónde dividir un' GO '... podría funcionar, se siente más complejo de lo necesario ... – deroby

+0

ejemplo, para complicar las cosas: 'EXEC (' SET EN parseonly; SELECT * FROM t_entity; IR; IMPRIMIR 0')' – deroby

Respuesta

1

GO es un comando separador de lote de cliente. Puedes reemplazarlo por; No debe enviarse en su SQL dinámico EXEC.

USE master 
GO --<----- client actually send the first batch to SQL and wait for a response 
SELECT * from sys.databases 
GO 

debería traducirse en

Application.Exec("USE master"); 
Application.Exec("SELECT * from sys.databases"); 

o puede escribir de esta manera:

Application.Exec("'USE master;SELECT * from sys.databases") 

Más sobre GO http://msdn.microsoft.com/en-us/library/ms188037(v=sql.90).aspx

+0

Gracias, pero eso no me da ninguna pista de cómo podría realizar de manera confiable la división en Java. Creo que tienes razón sobre EXEC pero no lo he verificado. –

1

Ok, así que esto no va ser exactamente lo que quieras, pero tu mig lo encuentro un comienzo. Lancé SchemaEngine (que forma el núcleo de la mayoría de mis productos) como fuente abierta here. Allí, encontrará el código C# que hace lo que quiere de manera muy confiable (es decir, no tropezar con cadenas, comentarios, etc.). También es compatible con la sintaxis 'GO x' para repetir un lote x veces.

Si descarga eso y echa un vistazo en /Atlantis.SchemaEngine/Helpers, encontrará una clase llamada BatchParser.cs que contiene un método llamado ParseBatches, que hace más o menos lo que dice en la lata.

Cuestiones relacionadas