Ferramenta Java 21 para localizar consultas SQL em relatórios JasperReports
(.jrxml) e scripts (.groovy) e convertê-las do dialeto Firebird para
PostgreSQL usando o parser do jOOQ. A entrada é sempre somente leitura; os
arquivos convertidos são gravados em outro diretório.
O conversor aceita opcionalmente --schema-metadata <arquivo.json>. Esse arquivo permite
converter UPDATE OR INSERT sem MATCHING, usando a chave primária extraída do Firebird
pela ferramenta de migração.
{
"formatVersion": 1,
"tables": {
"PRODUTOS": {
"primaryKey": ["COD_EMPRESA", "COD_PRODUTO"]
}
}
}Sem os metadados, ou quando um Groovy declara uma conexão JDBC própria, a consulta é preservada e enviada para revisão.
src/main/java/br/com/jjw/jrxmlconverter/
├── JrxmlConverterApplication.java # entrada da aplicação e composição
├── cli/ # interpretação da linha de comando
├── domain/ # resultados e estados do domínio
├── groovy/ # localização e alteração segura de SQL em Groovy
├── jrxml/ # alteração controlada do JRXML
├── report/ # CSV e resumo da execução
├── service/ # orquestração do processamento
├── sql/ # conversão Firebird → PostgreSQL
└── xml/ # XML seguro e inspeção de subreports
Os testes ficam em src/test/java, seguindo a mesma organização de pacotes.
Uma descrição das responsabilidades e decisões técnicas está disponível em
docs/ARQUITETURA.md.
- JDK 21
- Maven 3.6 ou superior
mvn clean verifyO JAR executável será criado em:
target\jrxml-converter-0.2.0-SNAPSHOT.jar
O --input aceita tanto uma pasta quanto um único arquivo .jrxml ou .groovy.
Ao receber uma pasta, a busca é recursiva e pode processar os dois tipos na mesma
execução. Quando a entrada é um JRXML master isolado, subreports literais locais
("arquivo.jrxml" ou "arquivo.jasper") também são descobertos recursivamente.
java -jar target\jrxml-converter-0.2.0-SNAPSHOT.jar `
--input "C:\relatorios\firebird" `
--dry-runjava -jar target\jrxml-converter-0.2.0-SNAPSHOT.jar `
--input "C:\relatorios\firebird" `
--output ".\output\postgresql"Nas execuções seguintes, acrescente --overwrite. O programa nunca altera a
entrada. A árvore recebida é reproduzida na saída; somente o conteúdo dos
arquivos .jrxml e .groovy é convertido. Arquivos auxiliares, imagens,
configurações e descritores são copiados sem alteração. Pastas de build, IDE,
Git e saídas anteriores são ignoradas.
output\postgresql\
├── src\main\resources\... # mesma estrutura recebida, com JRXML/Groovy convertidos
├── pom.xml # arquivo auxiliar preservado
└── _conversion-reports\ # diagnósticos fora da árvore do projeto
├── jrxml\
│ ├── conversion-report.csv
│ └── review-required.txt
├── groovy\
│ ├── conversion-report.csv
│ └── review-required.txt
├── subreport-review-required.txt
└── conversion-summary.txt
Os arquivos conversion-report.csv contêm somente itens que exigem atenção
(REVIEW ou FAILED). Conversões concluídas, consultas vazias e linguagens não
SQL continuam contabilizadas no conversion-summary.txt, mas não poluem os
CSVs. O arquivo groovy/review-required.txt descreve cada pendência Groovy em
linguagem orientada à correção: o que foi encontrado, por que não houve
conversão, qual o risco no PostgreSQL, como resolver, o detalhe técnico e um
trecho limitado do SQL original.
O diretório jrxml também recebe um review-required.txt com a mesma estrutura
explicativa para cada queryString que falhou ou exige revisão.
As referências de subreport são verificadas contra todos os JRXML recebidos na
mesma execução, inclusive os que pertencem a outro projeto. O resumo separa
arquivos locais, compartilhados, ambíguos, dinâmicos e ausentes. Uma referência
com mais de um candidato não é escolhida por nome: ela é registrada em
subreport-review-required.txt com todos os caminhos possíveis.
SQLs Groovy montados por concatenação ou em fragmentos são preservados sem
alteração e recebem o estado REVIEW no CSV, com arquivo e linha. Falhas e
itens para revisão fazem o processo encerrar com código 3.
Uma falha de leitura ou um JRXML inválido é registrada no CSV sem interromper os demais arquivos do lote. Nesse caso, o arquivo problemático é copiado sem alteração para a saída, permitindo corrigir a origem posteriormente.
As queryString cuja linguagem declarada seja JSON, xPath ou outra que não
seja SQL são preservadas e registradas como IGNORED; elas não representam
falha de conversão. Consultas SQL sem CDATA também são aceitas, com o conteúdo
escapado novamente como XML depois da conversão.
Para SQLs Groovy com trechos dinâmicos, o conversor possui uma etapa conservadora
de contingência. Ela altera somente construções Firebird determinísticas, como
FIRST/SKIP, DATEADD, DATEDIFF, LIST, GEN_ID, ASCII_CHAR,
RDB$DATABASE, STARTING WITH, CONTAINING e WITH LOCK, mantendo as
interpolações Groovy.
Se não for possível provar que a alteração é segura, o conteúdo original é
preservado e recebe REVIEW.
Uma análise por AST do Groovy acompanha definições anteriores usadas nas GStrings, sem executar o script. Isso permite distinguir filtros opcionais e valores escalares de cláusulas realmente desconhecidas. Se a AST não conseguir ler um arquivo, a análise textual anterior continua disponível como fallback. O jOOQ permanece sendo o responsável pela conversão do SQL.
Quando uma GString já é compatível com PostgreSQL, o processador acompanha
definições anteriores de filtros opcionais simples, como
def empresa = condição ? "AND ..." : "". Se todas as cláusulas dinâmicas
isoladas forem compreendidas, a consulta é preservada exatamente e não entra no
relatório de revisão. Definições produzidas por métodos ou fluxos desconhecidos
continuam em REVIEW.
Os Groovy e JRXML preservam seus caminhos relativos, evitando colisões entre
arquivos homônimos e mantendo as relações entre relatórios master e subreports.
Com --overwrite, as árvores groovy e jrxml dos projetos processados são
limpas antes da nova geração, impedindo que arquivos antigos permaneçam na saída.
Quando a entrada contém vários projetos, o conversor identifica raízes por
marcadores comuns (pom.xml, Gradle, .git ou src/main) e ativa
automaticamente o modo agrupado. Cada primeira subpasta ganha uma saída própria.
Dentro de cada tipo, o caminho abaixo de resources é preservado, evitando
conflito entre arquivos homônimos:
output\conversao-geral\
├── besser-complements-102\
│ ├── groovy\besser-core\endpoints\tray\
│ └── jrxml\besser-core\reports\
└── besser-complements-1068\
├── groovy\besser-core\endpoints\
└── jrxml\besser-core\reports\
Pastas geradas ou de ferramentas (target, build, output, .git, .idea e
node_modules) não participam da busca.
A conversão garante estrutura XML/Groovy e tradução sintática dos SQLs completos identificados. A validação final ainda deve executar as consultas com parâmetros reais no PostgreSQL, compilar/renderizar os JRXML e exercitar os scripts Groovy no ambiente utilizado pelo cliente.
Depois da renderização, o conversor procura construções Firebird conhecidas que
tenham permanecido fora de textos e comentários. Nesses casos o resultado é
FAILED e o SQL original é mantido. Paginação FIRST/SKIP combinada com
UNION, INTERSECT ou EXCEPT também exige revisão, pois o limite pode
pertencer a um ramo específico da operação.
UPDATE OR INSERT sem MATCHING permanece para revisão: no Firebird a chave
pode ser obtida da chave primária da tabela, enquanto o PostgreSQL exige um alvo
de conflito para DO UPDATE. Automatizar esse caso corretamente requer os
metadados do schema ou um arquivo de mapeamento de chaves. SQLs montados por
concatenação e erros sintáticos já existentes na origem também não são
consertados por suposição.
A opção --dual-database-groovy mantém o SQL Firebird original e acrescenta a
versão convertida para PostgreSQL no mesmo arquivo Groovy. A escolha acontece em
tempo de execução por meio de isPostgreSql(), disponibilizado pelo
besser-scriptlet:
def sql = (isPostgreSql() ? """
select CODIGO from PRODUTOS limit 1
""" : """
SELECT FIRST 1 CODIGO FROM PRODUTOS
""")O PostgreSQL somente é selecionado quando o driver configurado em
jpa.jdbc.driver é reconhecido explicitamente. Se a propriedade estiver ausente
ou for desconhecida, o SQL Firebird original é preservado como alternativa
segura. Consultas marcadas como REVIEW ou FAILED não são embrulhadas nem
alteradas.
Exemplo de execução:
& "C:\Program Files\Microsoft\jdk-21.0.12.101-hotspot\bin\java.exe" `
-jar ".\target\jrxml-converter-0.2.0-SNAPSHOT.jar" `
--input "C:\caminho\dos\complements" `
--output ".\output\complements-dual" `
--overwrite `
--dual-database-groovyEsse modo afeta somente arquivos Groovy. Os JRXML continuam seguindo o fluxo de
conversão normal, pois não herdam os métodos do BesserScript.
Código de uso interno. A publicação do repositório não concede licença para copiar, modificar ou redistribuir o projeto.