Evolusi H2 - fungsi jendela, CTE, JSON / XML dalam database tertanam

Ada proyek open source yang telah menjadi arus utama yang sukses secara komersial, seperti PostgreSQL / Elasticsearch. Lainnya, misalnya RethinkDB, kehilangan pasar dan menghentikan pengembangan. Dan proyek database H2 dari database tertanam yang ditulis dalam java sedang berkembang dan hidup di ceruknya.


Untuk menunjukkan fungsionalitas SonarQube, Jira, Confluence, database H2 digunakan pada awal pertama. H2 adalah basis untuk menjalankan tes SQL dalam memori di hampir semua proyek JVM. Ada contoh aplikasi yang kurang diketahui pengguna - ini adalah penggunaan H2 dalam ignite-sql terdistribusi dan ini sudah merupakan skrip siap produksi untuk menggunakan database tertanam sebagai bagian dari solusi lain. Kurang dari sebulan yang lalu, versi 1.4.199 dirilis di mana Anda sekarang dapat menulis pertanyaan SQL yang cukup kompleks.

Dalam proyek, saya tidak pernah mengandalkan H2 sebagai database lengkap dengan menyimpan data ke disk. Sebaliknya, sebagai modul untuk mentransformasikan data dalam memori JVM, dengan dukungan SQL yang baik. Tetapi untuk aplikasi ini, itu sangat dibatasi oleh kurangnya fungsi jendela . Dan sekarang, setelah lebih dari setengah tahun sejak awal pengembangan fungsional , sekarang H2database telah menyusul SQLite . Dan ini disebabkan oleh jasa besar Yevgeny Ryazanov dari Irkutsk - Saya belum melihat kecepatan pengembangan seperti sebelumnya dalam proyek sumber terbuka nirlaba. Juga, komit dari kontributor berbahasa Rusia lainnya secara teratur muncul di repositori proyek. Dan pada saat rilis - pendiri proyek Thomas Mueller .

H2 memiliki dukungan untuk kueri rekursif (CTE) . Ini adalah cara standar dalam SQL untuk bekerja dengan data hierarkis dalam tabel dan penguraian kueri (di sini Anda dapat menginjak penggaruk penjadwal). Kueri rekursif dijelaskan dalam publikasi dengan contoh.

Untuk bekerja dengan data yang kurang terstruktur, implementasi standar SQL / JSON yang akan datang akan muncul. Sementara itu, untuk kebutuhannya, ia telah memperluas H2 dengan bantuan fungsi kustom prosesor XQuery 3.1 berdasarkan BaseX . Kode ini tersedia di proyek github H2XQueryAdapter . Ini adalah fungsi tabel yang dapat mengekstrak data dari format XML atau JSON menggunakan XQuery dan memeriksa jenis dan batasan bukan nol untuk nilai yang dikembalikan oleh fungsi. Selanjutnya, kekuatan penuh ekspresi SQL tersedia untuk mengubah hasil transformasi XQuery menjadi memori proses JVM.

Fungsi tabel xquery () kelebihan beban dan memiliki dua opsi - dengan satu parameter xQuery query dan satu dengan xQuery query dan string kueri - sql kedua untuk membentuk parameter untuk xQuery itu sendiri.

Suatu pendekatan dengan transformasi semacam itu terbukti sangat baik dalam suatu proyek untuk memproses volume petabyte data mentah dalam proyek penyimpanan data biomedis .

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>') 

Implementasi ini memiliki batasan pada format kueri xquery.

  • Pertama, Anda perlu mendeklarasikan dua variabel eksternal getHeader dan getData - ini diperlukan agar fungsi tabel tidak menyebabkan transformasi data beberapa kali, membuang hasil yang tidak perlu untuk hanya mendapatkan nama dan jenis kolom. Panggilan fungsi berganda adalah fitur-fitur pangkalan H2 yang berfungsi dengan fungsi java mengembalikan daftar nilai.
  • Kedua, format hasil harus seperti untuk serialisasi csv

     <csv> <record><1> </1>...<N> </N></record> <record><1></1>...<N></N></record> </csv> 
  • Ketiga, Anda harus mendeklarasikan tipe data, dimensi, dan bidang yang diperlukan, misalnya: desimal (20,4), bukan nol

Dengan parsing tipe data kolom, saya mencoba menggunakan kembali parser SQL dari H2, tetapi ternyata sangat terhubung dengan objek database lain sehingga menolak untuk bekerja tanpa membuat database dan sesi. Saya menghibur diri dengan pemikiran bahwa para pengembang melakukannya untuk menyederhanakan desain aplikasi dan tidak membuat parser untuk semua kesempatan untuk setiap tata bahasa BNF.

Anda dapat menjalankan contoh ini dalam mode debug java. Aturan transformasi baru dapat dikembangkan di editor xquery yang sudah dikenal atau di open source BaseX GUI .

Dimungkinkan untuk mengubah hampir semua koleksi java atau POJO menjadi tabel H2 virtual. Kode proyek H2POJOTable di github. Dalam contoh, dengan referensi, MemoryManagerMXBeans berbasis platform berubah menjadi fungsi tabel H2. Mungkin pendekatan ini akan sedikit menghibur bagi mereka yang sedih tentang kurangnya LINQ dan dukungan untuk operasi di set di Jawa.

 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); } } 

Terkadang fungsi lama dalam H2 rusak dan tidak begitu dituntut oleh pengguna. Sebagai contoh, dalam proyek kerja saya, program membaca data dari AWS S3 URL. Karenanya, saya berharap kesalahan yang diketahui akan tetap diperbaiki dengan menerima permintaan tarik saya. Dalam perjalanan untuk memperbaiki kesalahan ini adalah tes yang tidak stabil untuk TLS, yang juga tidak berfungsi di bawah Java 11.

H2 memungkinkan Anda untuk menggunakan driver ODBC PostgreSQL meniru sebagian dari protokol jaringannya. Yang secara teoritis juga memungkinkan Anda untuk mengikatnya melalui FDW di PostgreSQL.

Selain database itu sendiri, pengiriman H2 juga mencakup konsol web minimalis dengan dukungan untuk penyelesaian otomatis saat mengedit, servlet, atau opsi startup mandiri. H2 terlihat seperti "pisau Swiss" untuk pengembang - alat yang ringkas dan serbaguna jika proyek Anda sudah menggunakan JVM. Saat mencoba menggunakan konsol ini dengan driver jdbc "bengkok", Redshift DBMS membuat permintaan tarik mata-merah pertamanya ke dalam proyek. Noel Grandin , salah satu peserta proyek, membantu saya dengan tinjauan kode dan menerima koreksi.

Jika Anda memerlukan analog dari Berkeley DB Java Edition - proyek memiliki MVStore - penyimpanan persisten untuk data nilai kunci dan, dalam kombinasi dengan MVCC, "mesin" secara default di versi terbaru dari database. Sangat mengejutkan bahwa database bahkan memiliki dukungan dasar untuk fungsi - geofungsi dan pencarian teks lengkap.

Berkat kontributor H2database, semua orang menggunakan database ini dan melaporkan kesalahan! Database H2 telah berkembang sejak 2005, dan sekarang mendukung fungsi jendela, permintaan rekursif, ini adalah salah satu "mesin" SQL paling kuat untuk memproses data dalam memori JVM dan diperluas dengan fungsi tabel untuk bekerja dengan data yang terstruktur secara longgar.

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


All Articles