2 puan yazan GN⁺ 2024-10-16 | 1 yorum | WhatsApp'ta paylaş
  • Güncel WASM destekli tarayıcılarda sqlite3’ü doğrudan kullanmak isteyen geliştiriciler için WebAssembly ve JavaScript API belgelerini tek yerde toplayan bir merkez
  • Hızlı çalıştırma için 3 adımlı HOWTO ile başlanabilir; indirme, npm modülü, derleme ve Emscripten ayrıntı belgeleriyle kurulum ve dağıtım yolları kontrol edilebilir
  • API belgeleri; yükleme yöntemleri, istemci kodu tarifleri, kalıcı depolama, JS API’de C yapıları, sanal tablolar ve tablo değerli fonksiyonlar yazmaya kadar uzanır
  • SQLime, Evolu, SQLiteNext, sqlite-wasm-esm, sqlite-wasm-http gibi gerçek kullanım örnekleri ile sql.js, wa-sqlite, absurd-js gibi öncü projeler birlikte derlenmiş
  • Tarayıcı SQLite, OPFS, IndexedDB ve WASI ile ilgili kaynakları bağlayarak web ortamında SQLite kullanmak için uygulama seçeneklerini hızlıca karşılaştırmayı sağlar

sqlite3 WASM belgelerinin kapsamı

Kullanım örnekleri ve ilgili ekosistem

  • Bu projeyi kullanan üçüncü taraf projeler

    • SQLime: veritabanı tarayıcı arayüzü sağlar
    • Evolu: gizlilik, kullanım kolaylığı ve tedarikçiye bağımlı olmamaya odaklanan local-first platform
    • SQLiteNext: bu projeyi next.js ile entegre eden demo
    • sqlite-wasm-esm: bu projenin Vite araç zincirinde nasıl kullanılacağını gösterir
    • sqlite-wasm-http: HTTP üzerinden doğrudan sunulan veritabanlarına salt okunur erişim sağlayan SQLite VFS
  • Önceki çalışmalar ve komşu projeler

    • Alon Zakai’nin sql.js projesi: WebSQL hariç tutulduğunda tarayıcıda sqlite3’ün doğrudan kullanıldığı ilk örnek olarak bilinir ve 2012 tarihli commit’e kadar uzanır
    • Roy Hashimoto’nun wa-sqlite projesi: sqlite3 veritabanları için OPFS storage uygulamasının ilk örneği olarak bilinir; JS tarafındaki SQLite VFS çalışmalarını da içerir
    • James Long’un absurd-js projesi: sqlite3 veritabanını IndexedDB veritabanı içinde saklama yöntemini gösterir
    • postgres-wasm: tarayıcıda Postgres database server çalıştırır
    • Jaccwabyt: WASM’de barındırılan C yapılarını JS koduyla manipüle etmeye yarayan küçük bir JS kütüphanesidir; bu projenin OPFS sqlite3_vfs uygulamasını desteklemek için oluşturulmuştur
    • CoWasm: “Collaborative WebAssembly for Servers and Browsers” projesidir; demo app içinde sqlite3 shell uygulamasının WASM derlemesi yer alır
    • absurder-js: Nicholas G. Piesco’nun absurd-js’i yeniden tasarladığı projedir; ayrıca bir SQLite forum duyurusu vardır
    • sqlite-wasm-rs: wasm32-unknown-unknown derlemeleri için Rust SQLite binding’leri sağlar
  • Dış belgeler ve yazılar

1 yorum

 
GN⁺ 2024-10-16
Hacker News yorumları
  • Tarayıcıda bellek içi SQLite çalıştırırken, Litestream ve Cloudflare Durable Objects’in kullandığı yönteme benzer şekilde WAL günlük kopyalarını sunucuya akıtmak ilginç olabilir
    WebSocket kullanılabilir; aralıklı fetch() POST istekleriyle de mümkün görünüyor. Sonraki ziyaretlerde sunucu tarafındaki veriler kullanılarak istemci SQLite yeniden doldurulur
    Ancak SQLite forum yazısına bakılırsa, varsayılan SQLite WASM derlemesinde WAL modu olmadığı için özel bir derleme gerekecek gibi

    • Burada “öyle çalışmaz” denebilecek birden fazla katman var
      Bellek içi SQLite WAL kullanmaz ve tarayıcı Wasm’ı, SQLite’ın WAL modunun beklediği paylaşımlı bellek API’si gibi şeyleri desteklemez
      Litestream çok hassas bir WAL yapılandırması gerektirir; yerel SQLite’ın varsayılan yapılandırmasında tesadüfen iyi örtüşür, ancak Wasm’da bunu yeniden üretmek zordur
      Cloudflare Durable Objects Litestream’den ilham almış olabilir ama gerçek çalışma biçimi oldukça farklıdır; LiteFS ve Turso için de aynı şey geçerlidir
      SQLite değişikliklerini akıtma şeklindeki büyük fikir mümkündür, ancak iş yükü büyüktür ve tarayıcı Wasm’ının eşzamanlılık modeli nedeniyle uygulaması zordur
      Söz konusu forum yazısını daha önce ben yazmıştım ve sunucu tarafı Wasm SQLite derlemesinde WAL’ı çalıştırmıştım; ancak bu, tarayıcıda kullanılabilir ya da mümkün bir seçenek değildi
    • Ağustos 2022’de buna benzer bir kavram kanıtı yaptım ve Twitter DM gönderdim ama yanıt alamadım. Kullanıcı adım justjs14
      O zamanki kodu bulmam gerekir, ancak tarayıcıda VFS’li SQLite’ı Wasm’a derleyip DB’yi açıyor, değişiklik yaptıktan sonra WAL’ı sunucuya push/pull edebiliyordum. İster elle ister WebRTC ile tarayıcılar arasında senkronizasyon da mümkündü; tarayıcı istemcisine GitHub token’ı verirseniz GitHub Pages üzerinde de çalışıyordu
      İlgilenirseniz yeniden baştan çalıştırılabilir hale getirebilirim. O dönemde bu yaklaşımla çok deney yaptım ve en azından bazı uygulamalar için yararlı olabileceğini düşünüyorum
      Yalnızca pull özelliği olan demo da burada: https://just.billywhizz.io/sqlite/demo/#https://just.billywhizz.io/sqlite/demo/db/chinook.db
    • Buradaki diğer düşüncelerin aksine WAL kopyalarını akıtmanın teknik olarak mümkün olduğunu düşünüyorum. Ancak VFS içinde uygulanması gerekir
      “Paylaşımlı bellek” SharedArrayBuffer olabilir; DB bağlantısını aynı anda yalnızca bir tane açarsanız normal buffer da mümkün olur. Örneğin zaten yaygın olan bir SharedWorker içinde bu yapılabilir
      Uygulaması basit olmayacaktır ama kesinlikle mümkündür. Aslında daha büyük sorun, satır düzeyinde değil blok düzeyindeki değişiklikleri yakalamasıdır
      Bu nedenle tüm DB replikasyonu için kullanılabilir, ancak bazı satırları başka kullanıcılarla paylaşmak gibi kısmi senkronizasyon zordur
      Kısmi senkronizasyon için satır düzeyinde değişiklik gerekiyorsa tetikleyiciler veya SQLite session extension gibi şeyler kullanmak gerekir: https://sqlite.org/sessionintro.html
      PowerSync’te istemci tarafı tetikleyiciler kullanıyoruz ve tetikleyici bakım işi dışında büyük bir dezavantaj bulamadım
    • https://electric-sql.com/ gibi bir şeyi mi kastediyorsunuz?
    • Bu “hydration” fikrini tam olarak anladığımdan emin değilim, ama son zamanlarda Wasm’dan yararlanarak backend mantığının bir kısmını tarayıcıda çalıştırmaya ilgi duymaya başladım
      Örneğin genel şablon render etme veya bazı Htmx endpoint’leri Wasm ile çalıştırılırsa, sıradan sunucu tarafı web framework’lerinde de OP’nin bahsettiğine benzer bir SQLite Wasm deposuyla çevrimdışı özellikler sunulabilir
      Tam Django örneği: https://github.com/m-butterfield/django_webassembly
      Makrolarla istemci/sunucu ayrımı yapan minimal Rust örneği: https://github.com/richardanaya/wasm-service
      Wasm olmadan benzer bir işi daha fazla makroyla yapan Clojure Electric: https://github.com/hyperfiddle/electric
      Microsoft tarafındaki son web araçlarından B ile başlayan bir şey de var
      Son birkaç yılda Python ekosisteminin şaşırtıcı derecede büyük bir kısmı Wasm desteği kazandı ve bu yaklaşımda kullanılabilir hale geldi. Yalnızca bariz makine öğrenmesiyle ilgili kütüphaneler değil, Pygame ve Pyxel gibi oyun kütüphaneleri de var; SDL2 destek eklediğine göre çoklu dokunmatik UI kütüphanesi Kivy desteği de yakında mümkün görünüyor
      Herhangi bir bilgisayarda kod çalıştırmak ve gerekirse web tarayıcısı sanal alanı içinde platform bürokrasisinden veya ücretlerinden kaçınmak için pek çok yeni olasılık var gibi görünüyor
  • Belgede bu bileşenlerin ilk olarak 3.40’ta açık beta olarak çıktığı, topluluk geri bildirimlerine göre 3.41’de API’nin kararlı hale getirilmesinin planlandığı yazıyor
    Ancak en güncel SQLite sürümü 2024-08-13 tarihli 3.46.1 olduğu için, muhtemelen API kararlılığı çoktan sağlandı ama belge güncellenmemiş gibi görünüyor
    SQLite ekibi WASM sürümünü paketleyen resmi bir npm paketi çıkarsa iyi bir dağıtım yolu olur gibi. Sonradan gördüğüme göre yanıtlara bakılırsa zaten varmış
    Kişisel olarak en sevdiğim SQLite-in-WASM hâlâ Pyodide varyantı. Resmi SQLite uygulamasından çok daha uzun süredir var ve Pyodide kullanınca WASM SQLite, Python standart kütüphanesinin bir parçası olarak beraberinde geliyor
    https://lite.datasette.io/ adresinde bu şekilde kullanılıyor ve https://pyodide.org/en/stable/console.html üzerinde de denenebiliyor
    sqlite3.connect(':memory:') ile select sqlite_version() çalıştırınca 2022-06-25 tarihli 3.39.0 çıkıyor; bu yüzden Pyodide’ın sürüm yükseltmeye ihtiyacı var gibi görünüyor. Bu sürüm emscripten’den devralınıyor gibi: https://github.com/emscripten-core/emscripten/blob/main/tools/ports/sqlite3.py

    • API kararlılığı doğru. Bir dahaki sefere bilgisayarın başına geçtiğimde ilgili ifadeyi güncellemeye çalışacağım
      Ancak SQLite ekibinin resmi bir npm paketi çıkarması söz konusu olmayacak. Biz yalnızca saf JS dağıtıyoruz ve dil dışı araç desteği tavşan deliğine girmeyi kesin biçimde reddediyoruz. Proje üyelerinin hiçbiri bu tür araçları kullanmıyor
      Thomas Steiner’ın bakımını yaptığı “resmen onaylı” npm derlemesini destekliyoruz, ancak hiçbir JS framework’ünü aktif geliştirme hedefi olarak görmüyoruz
      npm dâhil belirli bir framework’ü doğrudan desteklemek, o framework’ü onayladığımız izlenimi yaratabilir; biz de üçüncü taraf projeleri onaylama izleniminden aktif olarak kaçınıyoruz
    • SQLite ekibi bunu zaten bir süredir yapıyor gibi görünüyor. JS modülünde @sqlite.org/sqlite-wasm paketini jsdelivr üzerinden getirip sqlite3-bundler-friendly.mjs ve sqlite3.wasm dosyalarını yüklemek yeterli
      Böylece SQLite’ın C API’si ve oo1 nesne yönelimli API’si kullanılabiliyor; normal type=module script etiketiyle ya da Deno’da da çalışıyor
      Örnek HTML burada: https://github.com/Ciantic/experimenting-sqlite-wasm/blob/main/standalone.html
    • https://github.com/sqlite/sqlite-wasm
      sqlite-wasm, Pyodide’dan çok daha hızlı yüklendiği için Python’a ihtiyacınız yoksa ilki daha iyi bir seçenek
    • DuckDB WASM, Pyodide’dan bağımsız olarak kullanılabiliyor ve SQLite eklentisi de mümkün
      Ancak epey sınırlı görünüyor. sqlite_version() olmadığı için sürümü bile kontrol edemedim; depodaki sürüm de 3.38.1 ile oldukça eski
      Mevcut DuckDB web shell’i, dün çıkan 1.1.2 için SQLite eklentisi henüz yayımlanmadığından SQLite eklentisini yükleyemiyor. Önceki sürüm yakın zamanda güncellenen WASM edisyonuyla çalışıyor
      Spatial extension, GDAL, vektör arama gibi şeyler de eklenebiliyor: https://github.com/duckdb/duckdb-wasm/releases/tag/v1.29.0
      Kendi “SQL web shell”inizi yapmak da çok zor değildi, fakat dokümantasyon yeterince eksiksiz değildi
      https://github.com/duckdb/sqlite_scanner/blob/main/src/sqlite/sqlite3.h
    • O sayfadaki FAQ’yu okumak yardımcı olabilir
  • Go’da kullanırken ncruces’in Wasm SQLite paketi https://github.com/ncruces/go-sqlite3 gerçekten hoşuma gidiyor
    cznic’in Go paketi de harika, ama bu Wasm sürümü OpenBSD gibi ortamlarda da iyi çalışıyor

  • WebSQL aslında sadece SQLite olmalıydı; öyle olsaydı offline-first ve genel uygulama depolama ekosistemi çok daha iyi olurdu
    Şimdi bile bir ihtimal var mı? SQLite’ı soyutlayıp aşırı ayrıntılı şekilde spesifikasyona bağlamak yerine, tarayıcıların desteklemesi gereken SQLite API sürümünü belirtip bunu düzenli olarak yükseltemez miyiz?

    • Tarayıcıda “düzenli olarak sürüm yükseltme” yaklaşımı epey sorunlu olma potansiyeline sahip
      Web’in temel noktalarından biri, mümkün olduğunca mevcut şeylerin çalışmaya devam etmesi gerektiğidir; böyle breaking change’ler zordur
      Spesifikasyon birkaç sürümü listeleyip web sayfasının seçmesine izin verse bile, tarayıcılar artık desteklenmiyor olabilecek eski SQLite sürümlerini tutmak gibi zorlu bir yük üstlenmek zorunda kalır. Her sürüm de yaklaşık 1 MB yer kaplıyor
      Bu durumda, her web sitesinin kendi seçiminin bedelini şimdi olduğu gibi üstlenmesine izin vermek daha iyi değil mi diye düşünüyorum
      Ortak kaynakların tekrar tekrar indirilmesinden endişe ediliyorsa, bu başka CDN’lerin de zaten kabullendiği bir sorun. Ortak bağımlılıklar için paylaşımlı önbellekleme çözümü, yalnızca SQLite’a özgü bir çözümden çok daha değerli olurdu
      Mevcut yaklaşım, tarayıcının sağladığı bir sürümden daha iyi görünüyor
    • SQLite’ı seviyorum, ama tüm tarayıcılara koymak için çeşitli tuhaf davranışları olduğunu kabul etmek gerekiyor. Bu yüzden SQLite benzeri bir API daha iyi olabilir
    • WebSQL’in tutunmamış olmasını daha ziyade iyi bir şey olarak görüyorum
      Artık gerektiğinde 410 KB sıkıştırılmış WASM blob olarak güncel SQLite’ı getirebiliyoruz. Tarayıcının dayattığı SQLite sürümüne bağlı kalsaydık, şu anda 10 yıllık bir sürümü kullanıyor olabilirdik
  • Sayfayı hızlıca gözden geçirince kullanım senaryosunu pek anlayamadım
    Daha somut olarak, bu IndexedDB’nin alternatifi olabilir mi? Veriler kalıcı mı tutuluyor, yoksa SQLite dosyasını doğrudan File System API ya da IndexedDB/localStorage içinde mi saklamak gerekiyor?

    • Tanıtım sayfasına göre bu projenin hedeflerinden biri, mümkün olduğu ölçüde kullanılabilir JS API’leriyle istemci tarafı kalıcı depolamayı desteklemek
      Şu anda Origin-Private FileSystem (OPFS) ve çok sınırlı da olsa window.localStorage, window.sessionStorage backend’leri üzerinden depolama buna dahil
  • Son dönemde local-first alanına çok ilgi duyuyorum ama tarayıcının yerleşik depolama API’lerini, özellikle IndexedDB’yi kullanmakla karşılaştırınca SQLite’ı gömmek epey ağır geliyor
    Başlıca açık kaynak kütüphaneler de genel olarak yerleşik API’leri kullanıyor gibi görünüyor
    WebAssembly ile bir başka çalıştırılabilir dosya eklemeye çalışmak yerine, tarayıcının yerel depolaması üzerinde SQLite benzeri bir API ve senkronizasyon sağlayan açık kaynak bir çözüm görmek isterdim

    • SQL’in IndexedDB API’sinden daha kolay kullanılabildiği söylenebilir; örneğin if() filtresi yerine WHERE cümlesi kullanmak bellek ve CPU kullanımını azaltabilir
    • TinyBase ilginizi çekebilir. Kendi yaptığım bir kütüphane
  • Resmî indirme sayfasından alıp mjs dosyalarını ve “bundler-friendly” dosyaları tamamen kaldırsanız bile, asgari SQLite Wasm bağımlılığı yaklaşık 1,3 MB oluyor
    Tarayıcı uygulamaları için biraz büyük görünüyor; ancak günümüzde Wasm başka yerlerde de çalıştırıldığı için bu tür ortamlarda daha mantıklı olabilir

    • Yine de iyi sıkıştırılıyor. sqlite3.js ve Wasm ham hâliyle 1,3 MB ama JS’i küçültüp iki dosyayı Brotli ile sıkıştırınca 410 KB’a kadar düşüyor
    • Modern bir web uygulamasında 1,3 MB’ın gayet makul bir boyut olduğunu düşünüyorum. Özellikle siteye ilk ziyaretten sonra önbelleğe alınacaktır
      Sadece kullanıcı ayarlarını saklamak gibi bir iş için elbette SQLite indirmeye gerek yok; ama tam teşekküllü bir veritabanının avantaj sağladığı işler için 1 MB yüzünden fazla endişelenip boşuna tekerleği yeniden icat etmeye gerek yok
      Diğer yorum doğruysa ağ üzerinden zaten en başta 1,3 MB bile olmayacaktır
    • Tarayıcıda zaten IndexedDB’nin yerleşik olduğu gerçeğiyle birlikte değerlendirilmesi gereken bir unsur
      Yine de Figma veya Photoshop benzeri uygulamalar, makine öğrenimi uygulamaları gibi uygulama kodu ve verisi zaten büyük olan tarayıcı uygulamalarında 1,3 MB ciddi bir ek yük olmayabilir
      Wasm ayrıştırmasının JS’e göre oldukça hızlı olduğu da dikkate değer. Bu iddia için şu anda kaynak bulamadım ama konuyla ilgili en az bir iyi yazı vardı
      https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API
    • WebAssembly’nin sandbox modelini düşünmek gerekiyor. Teorik olarak program, burada SQLite, çalıştırılmasının uygun olduğu her yerde çalışabilir
      Yerel makine de olabilir, merkezi sunucu da olabilir, yakındaki bir edge de olabilir
    • Sunucu tarafında eşzamanlılığı ve dosya kilitlemeyi farklı ele alan ayrı bir Wasm SQLite build’ine ihtiyaç duyulması çok olası
      Ayrıca WASI hâlâ bir cevap olmaktan çok uzak. SQLite amalgamation WASI ile düzgün derleniyor, ancak eşzamanlılık çözülmemiş bir sorun
      Wasm tabanlı SQLite sürücüsünü kullanılabilir hâle getirmek için VFS’yi sıfırdan oluşturmam gerekti
      https://github.com/ncruces/go-sqlite3/blob/main/vfs/README.md
  • Bir süre Rust ekosisteminde bunu çalıştırmaya uğraştım ama blessed.rs’in SQL wrapper’ları olan rusqlite, sqlx henüz bundan yararlanamıyor gibi görünüyordu
    Doğrudan sarmalamak da zordu; emscripten Wasm kodunun wasm32-unknown-unknown ile uyumlu çalışmasını sağlamanın yolunu bulamadım
    Sonuçta bir şekilde JS wrapper gerekiyor; bu durumda da söz konusu crate’lerin beklediği arayüzleri uygulayıp JS’ten dışa açmak gerekiyor. Bu Rust tarafında çözülürse gerçekten harika olur

    • Bununla ilgili çalışma yürütüyorum. İlgileniyorsanız ya da katkı vermek istiyorsanız buraya katılabilirsiniz: https://github.com/rhashimoto/wa-sqlite/discussions/154
      Esasen wasm-bindgen içinde SQLite emscripten build’ini extern C header’ı olarak içe almak, paylaşımlı dizi tamponlarına erişim mümkün olacak şekilde çok iş parçacıklı modda derlemek ve VFS’yi Rust ile yeniden uygulamak gerekiyor
      Bundan sonra SQLite satırlarına ham Wasm baytları olarak erişilebilecek ve Rust-SQLite tarzı bir wrapper ya da entegrasyon yapılabilecek
      Bağlantı havuzu gibi kolaylıklar hâlâ olmayacak; ancak Wasm’da DB’yi exclusive mode ile kullanmak muhtemelen daha iyi olacaktır
    • Bu SQLite build’ini Rust’ın Diesel SQLite’ı ile çalışır hâle getiren şey burada: https://github.com/xmtp/diesel-wasm-sqlite
      Bu hafta 0.2 sürümünü hazırlıyoruz ve birkaç sorunu düzelteceğiz. Bunun dışında Diesel ORM’yi native gibi kullanabilirsiniz
    • emscripten Wasm kodu ile wasm32-unknown-unknown’ı uyumlu hâle getirme konusunda iyi haberler var
      Emscripten ve Rust’ın Wasm üzerinde iyi birlikte çalışmasını sağlamaya yönelik bir plan var: https://github.com/rustwasm/wasm-bindgen/pull/4014#issuecomment-2356908451
    • Ben de bunu epey uzun süredir bekliyordum. Yaklaşık 1 yıldır beklemede olan birkaç PR var; kavram kanıtlarını gördüm ama gerçekten kullanılabilir bir şey olmaktan çok uzaktılar
  • SQLite’in Wasm derlemesini ve Chicory çalışma zamanını kullanarak saf JVM üzerinde çalışan bir SQLite kütüphanesi oluşturmuşlar: https://github.com/dylibso/sqlite-zero
    Üretime hazır olmayı hedeflemekten çok bir deney gibi, ancak bağımlılıksız SQLite araçlarını JVM ekosistemine getirmek için yararlı olabilir diye düşünüyorum

    • Dosya sistemi erişimi nasıl oluyor? WASI mi?
  • Genel bir soru: Hangi durumlarda tüm veritabanını gönderip sorguları tarayıcının işlemesine bırakmak daha avantajlı olur?
    Başka bir deyişle, kullanıcı deneyimini geleneksel sunucuda barındırılan DB modeline göre iyileştirmek için bunu ne zaman kullanırsınız?

    • Kişisel olarak bunu statik olarak barındırılan web sitelerinde kullanıyorum; bu yüzden sunucuda barındırılan bir veritabanı zaten bir seçenek değildi
      Uygun bir sürücüyle tüm veritabanını göndermek yerine gerekli veritabanı parçalarını stream edebilirsiniz: https://github.com/mmomtchev/sqlite-wasm-http
      Tüm FTS veritabanını indirmeden SQLite tam metin araması yapabilirsiniz. Arama terimi yeterince kısaysa çoğunu alırsınız ama tamamını değil
    • Bu yazının başlığını görünce aklıma sezgisel olarak offline-first uygulamalarda PouchDB ile CouchDB’nin etkileşim biçimi gibi bir şey geldi
      https://medium.com/offline-camp/couchdb-pouchdb-and-hoodie-as-a-stack-for-progressive-web-apps-a6078a985f18
    • Çevrimdışı kullanımda büyük miktarda veriyle çalışırken iyi olabilir
      Ses kütüphanesinden 3D modelleme yazılımına kadar pek çok şey mümkün. Değişiklikleri yerelde oluşturup kalıcı hale getirir, ardından düzenli olarak veya tekrar çevrimiçi olduğunda sunucu tarafıyla senkronize edersiniz
    • Birden fazla servisle doğrudan iletişim kuran panolar geliştiriyorum. Benim sunucumda yalnızca erişim kontrolü ve token yönetimi için çok az veri var; asıl veri sunucuma gelmiyor
      Bu tür uygulamalar istemci tarafı gömülü DB için iyi adaylar