H2 evolution - funções de janela, CTE, JSON / XML em um banco de dados incorporado

Existem projetos de código aberto que se tornaram comercialmente bem-sucedidos no mainstream, como o PostgreSQL / Elasticsearch. Outros, por exemplo, o RethinkDB, perderam o mercado e interromperam o desenvolvimento. E o projeto de banco de dados H2 de um banco de dados incorporado escrito em java está se desenvolvendo e vivendo em seu nicho.


Para demonstrar a funcionalidade do SonarQube, Jira, Confluence, o banco de dados H2 é usado na primeira inicialização. H2 é a base para a execução de testes SQL na memória em quase qualquer projeto da JVM. Há um exemplo de um aplicativo menos conhecido pelos usuários - esse é o uso de H2 em um ignite-sql distribuído e esse já é um script pronto para produção para o uso de um banco de dados incorporado como parte de outra solução. Há menos de um mês, a versão 1.4.199 foi lançada, na qual você agora pode escrever consultas SQL bastante complexas.

Nos projetos, nunca confiei no H2 como um banco de dados completo para salvar dados em disco. Em vez disso, como um módulo para transformar dados na memória JVM, com bom suporte SQL. Mas, para esse aplicativo, era bastante limitado pela falta de funções da janela . E agora, depois de mais de meio ano desde o início do desenvolvimento do funcional , agora o H2database alcançou o SQLite . E isso se deve ao grande mérito de Yevgeny Ryazanov, de Irkutsk - nunca vi um ritmo de desenvolvimento como o dele em projetos de código aberto sem fins lucrativos. Além disso, confirmações de outros colaboradores de língua russa aparecem regularmente no repositório do projeto. E nos momentos de lançamento - o fundador do projeto Thomas Mueller .

H2 tem suporte para consultas recursivas (CTE) . Essa é a maneira padrão no SQL de trabalhar com dados hierárquicos em tabelas e decomposição de consultas (aqui você pode entrar no rake do agendador). Consultas recursivas são descritas na publicação com exemplos.

Para trabalhar com dados mal estruturados, uma implementação futura do padrão SQL / JSON será exibida. Enquanto isso, para suas necessidades, ele expandiu o H2 com a ajuda de um processador XQuery 3.1 de função personalizada baseado no BaseX . O código está disponível no projeto github H2XQueryAdapter . Esta é uma função de tabela que pode extrair dados do formato XML ou JSON usando XQuery e verificar o tipo e a restrição de not null para os valores retornados pela função. Além disso, todo o poder das expressões SQL está disponível para transformar o resultado de uma transformação XQuery na memória do processo da JVM.

A função da tabela xquery () está sobrecarregada e possui duas opções - com um parâmetro query xQuery e outro com query xQuery e a segunda string de consulta sql para formar os parâmetros para o próprio xQuery.

Uma abordagem com essas transformações provou ser excelente em um projeto para processar um volume petabyte de dados brutos em um projeto de armazenamento de dados biomédicos .

create table xresult (GR VARCHAR(500) not null,AR varchar, VER VARCHAR(50)) as select * from xquery('declare variable $getHeader as xs:boolean external := false(); declare variable $getData as xs:boolean external := true(); <csv> { if($getHeader) then( <record><mavengr>VARCHAR(500) not null</mavengr><artifactname>varchar</artifactname><versionname>VARCHAR(50)</versionname></record> ), if($getData) then(( for $row in doc("http://central.maven.org/maven2/org/springframework/spring-context/5.1.4.RELEASE/spring-context-5.1.4.RELEASE.pom")//*:dependency return <record><mavengr>{$row/*:groupId/text()}</mavengr><artifactname>{$row/*:artifactId/text()}</artifactname><versionname>{$row/*:version/text()}</versionname></record> )) } </csv>') 

Esta implementação tem limitações no formato da consulta xquery.

  • Primeiramente, é necessário declarar duas variáveis ​​externas getHeader e getData - isso é necessário para que a função da tabela não cause transformação de dados várias vezes, descartando resultados desnecessários para obter apenas os nomes e o tipo de coluna. Várias chamadas de função são recursos da base H2 trabalhando com funções java, retornando uma lista de valores.
  • Em segundo lugar, o formato do resultado deve ser semelhante à serialização csv

     <csv> <record><1> </1>...<N> </N></record> <record><1></1>...<N></N></record> </csv> 
  • Em terceiro lugar, você precisa declarar o tipo de dados, dimensão e campos obrigatórios, por exemplo: decimal (20,4) não nulo

Com a análise do tipo de dados da coluna, tentei reutilizar o analisador SQL do H2, mas ele se mostrou tão fortemente conectado a outros objetos de banco de dados que se recusou a trabalhar sem criar um banco de dados e uma sessão. Eu me consolo com o pensamento de que os desenvolvedores o fizeram para simplificar o design do aplicativo e não fazer um analisador para todas as ocasiões de gramáticas de BNF.

Você pode executar este exemplo no modo de depuração java. Novas regras de transformação podem ser desenvolvidas no editor xquery familiar ou na GUI BaseX de código aberto.

É possível transformar quase qualquer coleção de java ou POJO em uma tabela H2 virtual. Código do projeto H2POJOTable no github. No exemplo, por referência, o MemoryManagerMXBeans baseado na plataforma se transforma em uma função da tabela H2. Talvez a abordagem seja um pouco de conforto para aqueles que estão tristes com a falta de LINQ e com suporte para operações em conjuntos em Java.

 try (Statement statement = connection.createStatement()) { String pojoTableAlias = "create alias MemoryManagerMXBeans as $$ \n" + "import java.lang.management.ManagementFactory;\n" + "import java.lang.management.MemoryManagerMXBean;\n" + "import org.h2.expression.function.pojo.*;\n" + "import java.sql.*;\n" + "import java.util.Collections;\n" + "@CODE\n" + " ResultSet getRuntimeStat(Connection connection) throws Exception{\n" + " return H2PojoAdapter.toTable(connection, new CollectionWraper<>(MemoryManagerMXBean.class," + " ManagementFactory::getMemoryManagerMXBeans, Collections.emptyMap()));\n" + " }\n" + "\n$$"; statement.executeUpdate(pojoTableAlias); } try (Statement statement = connection.createStatement()) { try (ResultSet resultSet = statement.executeQuery("select * from MemoryManagerMXBeans()")) { int columnCount = assertResultSet(resultSet, new String[]{"memoryPoolNames", "name", "valid"}); assertThat(columnCount).isGreaterThan(1); } } 

Às vezes, a funcionalidade antiga do H2 falha e não é tão exigida pelos usuários. Como exemplo, em meus projetos de trabalho, os programas leem dados da URL do AWS S3 . Portanto, espero que o erro conhecido ainda seja corrigido aceitando minha solicitação de recebimento . No caminho para corrigir esse erro, há testes instáveis ​​para TLS, que também não funcionam no Java 11.

H2 permite que você use o driver ODBC PostgreSQL emulando um subconjunto de seu protocolo de rede. Teoricamente, o que também permite vinculá-lo através do FDW no PostgreSQL.

Além do próprio banco de dados, a entrega do H2 também inclui um console da web minimalista com suporte para preenchimento automático ao editar, servlet ou opção de inicialização autônoma. O H2 parece uma “faca suíça” para desenvolvedores - uma ferramenta compacta e versátil se o seu projeto já usa a JVM. Ao tentar usar esse console com um driver jdbc "torto", o DBMS Redshift fez sua primeira solicitação de entrada de olhos vermelhos no projeto. Noel Grandin , um dos participantes do projeto, me ajudou na revisão do código e aceitou as correções.

Se você precisar de um análogo do Berkeley DB Java Edition - o projeto possui MVStore - um armazenamento persistente para dados de valor-chave e, em combinação com o MVCC, o "mecanismo" por padrão nas versões recentes do banco de dados. É impressionante que o banco de dados ainda tenha suporte básico para funções geográficas e pesquisa de texto completo.

Graças aos colaboradores do H2database, todos usam esse banco de dados e relatam erros! O banco de dados H2 está em desenvolvimento desde 2005 e agora suporta funções de janela, consultas recursivas, é um dos "mecanismos" SQL mais poderosos para processamento de dados na memória da JVM e é expandido pelas funções de tabela para trabalhar com dados frouxamente estruturados.

Source: https://habr.com/ru/post/pt446380/


All Articles