Skip to content
umitkrkmzPublic

About

Veritabanı şemalarını tarayıcıda yıldız haritası olarak çizer · Draws database schemas as a star map in the browser

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

sqlSchema

Şema dosyalarını bir yıldız haritası olarak çizen, tarayıcıda çalışan açık kaynak görselleştirici.
An open-source, in-browser viewer that draws database schemas as a star map.

MIT Bağımlılık yok Derleme yok

Türkçe · English

sqlSchema: 318 tablolu bir telekom şemasının galaksi görünümü

Türkçe

sqlSchema, veritabanı şema dosyalarını tarayıcıda okur ve bir gökyüzü haritası olarak çizer:

  • Her tablo bir yıldızdır.
  • Her ilişki iki yıldız arasında bir çizgidir.
  • Her şema bir gökyüzü bölgesi, her veritabanı bir galaksidir.

Yaklaştıkça yıldızlar kolon listeli tablo kartlarına dönüşür ve ilişkiler karga ayağı (crow's foot) notasyonuyla okunur.

draw.io kadar elle uğraştırmaz, veri modelleme aracı kadar ağır değildir. Amaç, şemaya ilk kez bakan birinin "hangi tablo neye bağlı?" sorusunun cevabını birkaç saniyede görmesi.

İçindekiler

  1. Öne çıkanlar
  2. Hızlı başlangıç
  3. Haritayı okumak
  4. Birden fazla dosya ve migration
  5. Desteklenen veritabanları
  6. MongoDB
  7. Adlandırma profili
  8. Örnekler
  9. Şemayı dışa aktarmak
  10. Dil
  11. Proje yapısı ve geliştirme
  12. Sınırlar
  13. Katkı, güvenlik, lisans

Öne çıkanlar

  • Saf HTML, CSS ve JavaScript. Bağımlılık yok, derleme adımı yok; klasörü açmanız yeterli.
  • Gizlilik: dosyalar tarayıcıdan çıkmaz, hiçbir sunucuya gönderilmez.
  • Sekiz veritabanı: Oracle, SQL Server, MySQL, MariaDB, PostgreSQL, SQLite, Cassandra ve MongoDB.
  • Tek dosya, birden fazla dosya ya da bütün bir klasör: bölünmüş dökümler, migration klasörleri (Flyway, golang-migrate), çok veritabanlı projeler.
  • Karga ayağı notasyonu: kardinalite NOT NULL, UNIQUE ve PK bilgisinden çıkarılır.
  • Tahmini ilişkiler: FK tanımlı olmayan eski sistemlerde, Cassandra'da ve MongoDB'de bağlantılar kolon adlarından bulunur.
  • Adlandırma profili: şemada hangi adlandırma kalıplarının ne oranda kullanıldığını ve baskın kalıba uymayan tabloları gösterir.
  • Ölçek: 2 862 tabloluk 4,7 MB'lık bir döküm yaklaşık 0,6 saniyede açılır, bir karenin çizimi 10 ms'nin altında kalır.
  • Türkçe ve İngilizce arayüz.

Hızlı başlangıç

  1. Depoyu indirin ya da klonlayın.
  2. index.html dosyasını tarayıcıda açın.
  3. Şema dosyalarınızı ya da klasörü sayfaya sürükleyin. Alternatifler: Dosya aç (birden fazla dosya seçilebilir), Klasör, Yapıştır, Örnekler.

Örnek dosyaları ve sürüklenen klasörleri tarayıcı yalnızca sayfa bir sunucu üzerinden açıldığında okuyabilir. Bunun için proje klasöründe şu komutu çalıştırıp http://localhost:8000 adresine gidin:

python -m http.server 8000

index.html doğrudan dosyadan (file://) açıldığında da uygulama çalışır. Klasörleri sürüklemek yerine Klasör düğmesiyle seçin. Gömülü küçük örnek her durumda açılır.

Hareket Sonuç
Tekerlek / iki parmak Yakınlaştır
Sürükle Kaydır
Tık Tabloyu seç, ayrıntı panelini aç
Çift tık Tabloya yaklaş, kolonları göster
/ Tablo ya da kolon ara
F Tümünü sığdır
C Kolon ayrıntılarını gizle / göster
↑ / ↓, Enter Paneldeki ilişkiler arasında dolaş, seçilen tabloya git
Alt + ← / → Gezinme geçmişinde geri / ileri
Esc Odak modunu kapat / seçimi bırak

Haritayı okumak

Yakınlaştırma düzeyine göre üç görünüm vardır:

Görünüm Ne görünür
Galaksi Veritabanları, şemalar ve şemalar arası ilişki demetleri (çizgi üstündeki sayı = ilişki adedi)
Takımyıldız Tablolar yıldız olur: boyut = bağlantı sayısı, renk = şema. Seçili tablonun çizgilerinde karga ayağı ve kolon adı yazar.
Yakın plan Tablolar kart olur; çizgiler doğrudan FK ve PK kolon satırlarına bağlanır.

Görünüm menüsünde kolon ayrıntıları, tahmini ilişkiler, sözlük bağlantıları, ızgara ve takımyıldız gruplaması seçenekleri var. Kolon ayrıntıları kapatılınca (kısayolu C) yakın planda kartlar yalnızca tablo adını gösterir ve çizgiler kartın başlığına bağlanır. Böylece yalnızca tablolar ve ilişkileri kalır. Ayrıntı paneli kolonları göstermeye devam eder. Seçim tarayıcıda hatırlanır.

Seçili tablo, vurgulu ilişkileri ve ayrıntı paneli

Ayrıntı panelinde kolonlar, açıklamalar, tanımın geçtiği dosya ve satır ile her ilişkinin Türkçe okunuşu yer alır: "Her INVOICE kaydı mutlaka bir BILLING_ACCOUNT kaydına bağlı. Bir BILLING_ACCOUNT kaydının sıfır ya da çok INVOICE kaydı olabilir."

Odak modu, seçili tablonun yalnızca 1 ya da 2 adım uzaklıktaki komşularını bırakır, gerisini söndürür.

İlişki izlemek. Paneldeki bir ilişkiye tıklamak (ya da ↓ ile seçip Enter) o tabloya gider. Panelin üstündeki iz gezilen tabloları sırasıyla gösterir (ABONE › IS_EMRI › CIHAZ); izdeki bir ada, ‹ › düğmelerine ya da Alt + ← / → tuşlarına basarak geri ve ileri gidilir. Böylece fareye dokunmadan şema baştan sona gezilebilir.

Yakın plan: kolon satırlarına bağlanan çizgiler ve karga ayağı uçları

Karga ayağı

Çizginin bir ucundaki işaret, o uçtaki tablodan kaç kayıt olabileceğini söyler. Tabloya yakın işaret üst sınırdır, dıştaki alt sınırdır.

İşaret Anlamı Şemadan nasıl çıkarılıyor
──‖ tam olarak bir FK kolonu NOT NULL; gömülü belgenin sahibi
──○┼ sıfır ya da bir FK kolonu NULL olabilir, ya da FK aynı zamanda PK/UNIQUE (1:1)
──○< sıfır ya da çok FK'yi taşıyan tablonun varsayılanı; ObjectId dizileri
──┼< bir ya da çok DDL ile zorlanamaz (trigger ya da uygulama kuralı gerekir), bu yüzden haritada çıkmaz

Çizgiler, yıldızlar, etiketler

Çizgi Anlamı
Düz Tanımlı yabancı anahtar ya da Mongoose ref
Uzun kesikli Kolon açıklamasındaki @ref etiketiyle tanımlı ilişki (aşağıya bakın)
Kesikli Tahmini ilişki (aşağıya bakın); Görünüm menüsünden kapatılabilir
Noktalı Devre dışı FK (DISABLE, RELY DISABLE NOVALIDATE, T-SQL NOCHECK)
Kesik-noktalı MongoDB gömülü belge: alt belge sahibinin içinde yaşar
Yıldız Anlamı
Dolu yıldız Tablo; büyüklük = bağlantı sayısı, renk = şema
Halka Ara tablo (M:N): PK'si iki FK'den oluşur ya da saf bağlantı tablosudur
Küçük, soluk yıldız Uydu: MongoDB gömülü alt belgesi, sahibinin yanında durur
Kesikli halka Bir FK'nin başvurduğu ama dosyalarda tanımı olmayan tablo

Kartlarda PK birincil anahtarı, FK yabancı anahtarı, CK Cassandra sıralama (clustering) anahtarını gösterir. Soluk kolon adı, kolonun NULL olabileceği anlamına gelir.

Takımyıldızlar. Küçük şemalar tek bir takımyıldızdır. Büyük şemalar, tablo adı öneklerine (CUSTOMER_*, INVOICE_*) ve bağlantılara göre takımyıldızlara bölünür. Her yıldız, takımyıldızındaki parlaklık sırasına göre Bayer usulü bir ad alır (α Billing, β Billing). Yerleşim deterministiktir: aynı dosyalar her açılışta aynı haritayı verir.

Tahmini ilişkiler. Şu iki durumda kesikli çizgiyle çizilir:

  • FK tanımlı değil ama kolon adı başka bir tablonun PK'siyle aynı: CDR.SUBSCRIPTION_ID → SUBSCRIPTION.SUBSCRIPTION_ID.
  • X_ID / xId kolonu, PK'si ID ya da _id olan X tablosunu gösteriyor: orders.customerId → customers._id.

Tipler uyuşmuyorsa ya da birden fazla aday varsa çizilmez.

Açıklamadan ilişki: @ref. Bazı ilişkiler FK ile tanımlanamaz. En sık örnek, genel bir sözlük tablosunun (SOZLUK: ID, TIP_ID, AD) yalnızca bir tipine bağlanan kolonlardır. Veritabanı "yalnızca TIP_ID = 7 olan satırlar" diye bir kısıt koyamaz. Bu ilişkiler kolon açıklamasına yazılan bir etiketle haritaya eklenir:

COMMENT ON COLUMN ABONE.DURUM_ID IS 'Abone durumu. @ref SOZLUK.ID (TIP_ID = 7)';
COMMENT ON COLUMN SESSION_LOG.USERID IS 'The user ID. @ref USERS';
Yazım Anlamı
@ref TABLO Hedefin birincil anahtarına
@ref TABLO.KOLON Hedefin belli bir kolonuna (TABLO.KOLON yoksa ŞEMA.TABLO sayılır)
@ref ŞEMA.TABLO.KOLON Şemayla birlikte
… (KOŞUL) Parantez içi koşul çizginin ve panelin üstüne yazılır
  • Nereden okunur: etiket açıklamanın herhangi bir yerinde olabilir. Oracle ve PostgreSQL COMMENT ON COLUMN, MySQL satır içi COMMENT '…' ve SQL Server sp_addextendedproperty açıklamaları okunur.
  • Haritada: bu ilişkiler tahmin değil, DBA'nın beyanıdır; uzun kesikli çizgiyle ve panelde "açıklamadan" etiketiyle gösterilir.
  • FK ile birlikte: kolonda zaten bir FK varsa yalnızca koşul ona eklenir.
  • Hata: bulunamayan bir hedef ayrıştırma raporunda uyarı olarak listelenir.

Sigorta örneğinde durum kolonları genel kod tablosuna (KOD_TABLO) bu yolla bağlanır.

Sözlük tabloları. Genel kod tablosuna yüzlerce kolon bağlandığında çizgiler haritayı boğar ve sözlük dev bir merkez olur. Bu yüzden en az iki koşullu ilişkinin hedefi olan tablo sözlük sayılır:

  • Haritada: ona giden çizgiler çizilmez. Kartta kolonun tipi yerine → KOD_TABLO rozeti görünür. Çizgi yalnızca sözlük ya da bağlanan tablo seçilince ya da üzerine gelinince çizilir.
  • Yerleşimde: sözlük ilişkileri tabloları birbirine çekmez; sözlük şemanın ortasına oturup öbürlerini sıkıştırmaz.
  • Panelde: sözlük seçilince Sözlük kullanımı bölümü hangi koşulun hangi kolonlarca kullanıldığını listeler (KOD_TIP = 'POLICE_DURUM' → POLICE.POLICE_DURUM).
  • Elle seçim: paneldeki Sözlük olarak göster / Sözlük değil düğmesi otomatik kararı değiştirir; seçim tarayıcıda hatırlanır.
  • Çizgi olarak: Görünüm → Sözlük bağlantılarını çiz ile çizgiler her zaman çizilir.

Sözlük ağırlıklı örnek: SOZLUK tablosuna giden bağlantılar çizgi yerine kartlarda rozet olarak

Sözlük ağırlıklı örneğinde 30'dan fazla kolon tek bir SOZLUK tablosuna bağlıdır.

Birden fazla dosya ve migration

Dosyalar tek bir modelde birleşir; ad çözümleme en sonda yapılır. Bu yüzden şu durumlar sorun çıkarmaz:

  • Bir dosyadaki FK'nin başka bir dosyadaki tabloyu göstermesi.
  • constraints.sql dosyasının alfabetik sırada ddl.sql'den önce gelmesi.

Sağ alttaki N dosya bağlantısı dosya listesini açar. Burada:

  • Dosyaları tek tek çizime katabilir ya da çıkarabilirsiniz.
  • Her dosyanın lehçesini ve kaç tablo içerdiğini görürsünüz.
  • "Ayrı veritabanı" seçeneğini açabilirsiniz.

Dosya başına takımyıldız. Bir şemanın tabloları birden fazla dosyadan geliyorsa, her dosyanın tabloları kendi takımyıldızında toplanır. Ekipler modülleri çoğunlukla dosyalara ayırdığı için harita da bu ayrımı korur.

  • Ayrı dururlar: farklı dosyaların takımyıldızları, aralarında ilişki olsa da birbirinden açıkça uzak durur.
  • Sınır ve ad: her takımyıldız ince bir daireyle sınırlanır ve adı sınırın üstüne yazılır.
  • Ad: dosya yolundan gelir; aynı adlı dosyalar klasörleriyle ayrılır (POLICE/tablolar, HASAR/tablolar).

Sigorta örneği: tek şemada her modül dosyası kendi takımyıldızında

Migration klasörlerinde dosya bir modülü değil bir sürümü gösterir; orada ve MongoDB'de tablolar ad öneki ve ilişkiye göre gruplanır. Görünüm → Takımyıldızlar ile seçim elle değiştirilebilir: Otomatik, Dosyaya göre ya da Ad ve ilişkiye göre.

Okuma sırası migration araçlarının kurallarını izler:

Araç Dosyalar Davranış
Flyway V1__init.sql, V1_1__x.sql, V2__y.sql Sürüm numarasına göre (V10, V2'den sonra). R__*.sql en sonda, U*__ geri alma betikleri atlanır.
golang-migrate, dbmate 000001_x.up.sql .down.sql atlanır.
Zaman damgalı 20240115093000_x.sql Zaman sırasına göre.
Numaralı / diğer 01_tables.sql, a2.sql < a10.sql Doğal ad sırası.

Migration'lar baştan sona uygulanır ve harita şemanın son hâlini gösterir. Bunun için şu ifadeler işlenir:

  • RENAME TO, RENAME COLUMN
  • DROP TABLE, DROP COLUMN, DROP CONSTRAINT
  • ALTER COLUMN … TYPE, MODIFY, CHANGE
  • T-SQL sp_rename, MySQL RENAME TABLE

Ayrı veritabanları. Farklı lehçelerden dosyalar birlikte açılırsa (örneğin MySQL siparişler, MongoDB katalog, PostgreSQL raporlama) her klasör kendi galaksisi olarak çizilir.

Üç veritabanı üç ayrı galaksi olarak

Desteklenen veritabanları

Oracle SQL Server MySQL / MariaDB PostgreSQL SQLite Cassandra
CREATE TABLE, satır içi ve tablo seviyesi kısıtlar ✓ ✓ ✓ ✓ ✓ ✓ PRIMARY KEY ((a, b), c)
ALTER TABLE … ADD CONSTRAINT ✓ ✓ WITH CHECK/NOCHECK ✓ ✓ ONLY
Kolon değişiklikleri MODIFY ALTER COLUMN MODIFY, CHANGE ALTER COLUMN … TYPE
Yeniden adlandırma, silme RENAME, DROP sp_rename, DROP RENAME TABLE, DROP RENAME, DROP RENAME, DROP
CREATE UNIQUE INDEX (1:1 tespiti) ✓ ✓ ✓ ✓ ✓
Tablo / kolon açıklamaları COMMENT ON sp_addextendedproperty COMMENT '…' COMMENT ON

Çizime girmeyenler. View, sequence, trigger, package, procedure, function, type, grant ve INSERT raporda sayılır ama çizilmez. Ayrıştırıcı bunların içindeki ; işaretlerine takılmaz:

  • PL/SQL blokları / satırına kadar bütün tutulur.
  • T-SQL blokları GO satırına kadar bütün tutulur.
  • MySQL blokları DELIMITER ayracına kadar bütün tutulur.

Sorun çıkarmayanlar:

  • SQL*Plus komutları
  • Oracle depolama ve partition ifadeleri
  • PostgreSQL $$ gövdeleri ve PARTITION OF parçaları
  • CQL // yorumları ve map<text, int> tipleri

Kodlama. Dosya UTF-8, UTF-16 (SSMS'in varsayılanı) ya da Windows-1254 olabilir; kodlama otomatik seçilir.

MongoDB

MongoDB'de DDL yoktur. Şema üç kaynaktan çıkarılır; aynı koleksiyon birden fazla kaynakta geçiyorsa tek tabloda birleşir.

Kaynak Örnek Okunan
mongosh betikleri (.js) db.createCollection('x', { validator: { $jsonSchema } }), collMod, createIndex(…, { unique }) Alanlar, tipler, zorunlu alanlar, açıklamalar, enum değerleri
Mongoose modelleri (.js, .ts) new Schema({ author: { type: ObjectId, ref: 'User' } }) Alanlar ve ref ilişkileri. Koleksiyon adları Mongoose'un çoğul kurallarıyla türetilir.
Örnek belgeler (.json, .jsonl, .ndjson) mongoexport çıktısı İlk 5 000 belgeden alan birleşimi; Extended JSON ($oid, $date)

Gömülü nesneler ve nesne dizileri, sahibinin yanında duran uydu tablolara (users.profile, orders.items) dönüşür.

MongoDB: koleksiyonlar, uydu alt belgeler ve tahmini ilişkiler

Adlandırma profili

Ekipte yazılı bir adlandırma standardı yoksa ilk adım, şemada fiilen ne kullanıldığını görmektir. Sağ alttaki adlandırma bağlantısı adları şu boyutlarda sayar ve oranlarıyla gösterir:

Boyut Kalıplar
Tablo ve kolon adı harf düzeni BÜYÜK_HARF, küçük_harf, PascalCase, camelCase
Birincil anahtar adı ID, <TABLO>_ID, <TABLO>_NO / _KOD, tablo adıyla ilgisiz
Yabancı anahtar kolonu <HEDEF>_ID, <HEDEF>_NO / _KOD, rol önekli (GONDEREN_MUSTERI_ID, AGENT_USER_ID → APP_USER), hedefin PK adıyla aynı, yalnızca rol adı (SAHIBI), hedef adını içermeyen (CHZ_REF)
Tablo adı tekil / çoğul (tahmini), TBL_ gibi önekler
Karakterler ve uzunluk Türkçe / ASCII dışı karakter, 30 karakteri aşan adlar
  • Her boyutta baskın kalıp ve ona uymayanlar listelenir. Listedeki bir ada tıklamak tabloyu seçer.
  • En çok kullanılan kalıbın payı %60'ın altındaysa "baskın" denmez; pencere belirgin baskın kalıp yok uyarısı gösterir. %51'e %49 gibi bir dağılım, şemada iki ayrı alışkanlık olduğunu söyler.
  • Kapsam seçimiyle profil tek bir şema için hesaplanır. Böylece hangi modülün hangi alışkanlıkla yazıldığı ayrılır.
  • Tutarlılık puanı, her boyutta baskın kalıba uyan adların ortalama oranıdır.
  • Markdown indir profili ekiple paylaşmak için bir dosyaya yazar.

Araç bir kural dayatmaz: ID mi <TABLO>_ID mi doğru, buna ekip karar verir.

Orana katılmayanlar:

  • Bileşik PK'ler, PK'si üst tablodan gelen 1:1 tablolar ve PK'siz tablolar. Bunlar ayrıca gösterilir.
  • CREATED_BY, UPDATED_BY, GUNCELLEYEN, KAYIT_KULLANICI gibi denetim kolonları. Kullanıcı tablosuna bağlı olsalar da kendi yerleşik kalıpları vardır; ayrıca sayılırlar.
  • Tahmini ilişkiler: zaten ada dayandıkları için yalnızca tanımlı FK'ler sayılır.
  • MongoDB koleksiyonlarının _id ve ref alanları.

Adlandırma profili: PK, FK ve harf düzeni kalıpları, oranları ve baskın kalıba uymayanlar

Karışık adlandırma örneği bu özellik için hazırlanmıştır: iki ekibin farklı alışkanlıklarla tablo eklediği bir Oracle şeması.

Örnekler

samples/ altındaki örnekler sentetiktir: gerçek bir kuruma ait değildir. Her biri bir sektörün tipik yapısını ve bir aracın gerçek dışa aktarım biçimini taklit eder. Örnekler menüsünden açılırlar.

Örnek Veritabanı Senaryo
Küçük telekom Oracle 20 tablo, uygulamaya gömülü
Telekom BSS/OSS Oracle SQL Developer dökümü tek dosyada: 318 tablo, 16 şema, partition, trigger, paket
Telekom, şema başına dosya Oracle Aynı şema 16 dosyaya bölünmüş; bütün FK'ler en sondaki dosyada
Çekirdek bankacılık SQL Server SSMS "Generate Scripts": UTF-16, GO, IDENTITY, açıklamalar
Sigorta (eski sistem) Oracle Modül başına klasör, Türkçe adlar, hiç FK yok
Pazaryeri e-ticaret MySQL mysqldump --no-data, DELIMITER'lı yordam
Hastane bilgi sistemi PostgreSQL OMOP CDM biçimi: tablolar, PK, FK, indeks ve açıklamalar ayrı dosyalarda
Lojistik / kargo PostgreSQL Flyway, 14 sürüm: adı değişen ve silinen tablolar, partition
IoT telemetri Cassandra İki keyspace, sorgu başına tablo
Sosyal medya MongoDB $jsonSchema + Mongoose + mongoexport
Saha servisi mobil uygulaması SQLite sqlite3 .dump, çevrimdışı önbellek
Çok veritabanlı e-ticaret MySQL + MongoDB + PostgreSQL Mikroservisler, her klasör ayrı galaksi
Karışık adlandırma Oracle İki ekip, iki alışkanlık: PK ID ve <TABLO>_ID, kuralsız FK'ler, ORM tabloları
Sözlük ağırlıklı Oracle Bütün kodlar tek bir SOZLUK tablosunda; 30'dan fazla kolon ona @ref ile bağlı

Şemayı dışa aktarmak

Veritabanı Nasıl
Oracle, SQL Developer Araçlar → Veritabanı Dışa Aktarma, yalnızca DDL. "Nesne türüne göre ayrı dosyalar" çıktısı klasör olarak açılabilir.
Oracle, SQL*Plus / SQLcl Aşağıdaki DBMS_METADATA betiği
SQL Server SSMS → veritabanı → Tasks → Generate Scripts (yalnızca şema)
MySQL / MariaDB mysqldump --no-data veritabani > sema.sql
PostgreSQL pg_dump --schema-only veritabani > sema.sql
SQLite sqlite3 app.db .schema > sema.sql
Cassandra cqlsh -e "DESCRIBE KEYSPACE telemetry" > sema.cql
MongoDB Doğrulayıcı betikleri, Mongoose model klasörü ya da mongoexport --limit 1000 çıktıları

Migration kullanan projelerde db/migration klasörünü olduğu gibi açmanız yeterlidir.

-- Oracle: veri sözlüğünden DDL ve açıklamalar
SET LONG 20000000 LONGCHUNKSIZE 20000000 PAGESIZE 0 LINESIZE 32767 TRIMSPOOL ON FEEDBACK OFF
EXEC DBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRANSFORM, 'SQLTERMINATOR', TRUE);
EXEC DBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRANSFORM, 'SEGMENT_ATTRIBUTES', FALSE);
SPOOL sema.sql
SELECT DBMS_METADATA.GET_DDL('TABLE', table_name, owner) FROM all_tables WHERE owner IN ('CRM', 'BILLING');
SELECT DBMS_METADATA.GET_DEPENDENT_DDL('COMMENT', table_name, owner) FROM all_tables t
 WHERE owner IN ('CRM', 'BILLING')
   AND (EXISTS (SELECT 1 FROM all_tab_comments c WHERE c.owner = t.owner AND c.table_name = t.table_name AND c.comments IS NOT NULL)
     OR EXISTS (SELECT 1 FROM all_col_comments c WHERE c.owner = t.owner AND c.table_name = t.table_name AND c.comments IS NOT NULL));
SPOOL OFF

Dil

Arayüz Türkçe ve İngilizcedir. İlk açılışta sistem dili Türkçe ise Türkçe, değilse İngilizce seçilir. Sağ üstteki TR / EN düğmeleriyle değiştirilebilir; seçim tarayıcıda hatırlanır. Bir bağlantıda dili sabitlemek için ?lang=tr ya da ?lang=en kullanılabilir.

Paylaşılabilir bağlantılar. URL parametreleriyle bir örnek, bir tablo ve yakınlaştırma düzeyi doğrudan açılabilir:

index.html?lang=tr&sample=telekom&select=BILLING_ACCOUNT&zoom=0.9&legend=0

Açılışta bir pencere göstermek için pop=naming, pop=report ya da pop=files eklenir. center=TABLO bir tabloyu seçmeden ortalar.

Proje yapısı ve geliştirme

index.html          sayfa iskeleti, lejant
style.css           görünüm
js/                 tarayıcıda bu sırayla yüklenir; hepsi globalThis.sqlSchema ad alanına ekler
  i18n.js           Türkçe / İngilizce sözlükler, dil seçimi
  lexer.js          tokenizer, ifade ayırıcı, lehçe tahmini
  sql-parser.js     DDL → sıralı işlem listesi (create, fk, rename, drop ...)
  mongo.js          $jsonSchema, Mongoose ve JSON belgelerinden aynı işlem listesi
  files.js          dosya sıralama (Flyway, golang-migrate), ayrıştırıcı seçimi
  model.js          işlemleri uygular: tablolar, ilişkiler, kardinalite, ara tablo, tahmini ilişki
  layout.js         veritabanı → şema → takımyıldız → yıldız, hiyerarşik kuvvet yerleşimi
  conventions.js    adlandırma profili: kalıplar, oranlar, baskın kalıba uymayanlar
  sample-small.js   gömülü küçük örnek
  render.js         canvas çizimi, kamera, karga ayağı
  ui.js             yükleme, dosya listesi, arama, panel, rapor, URL parametreleri
samples/            sentetik örnekler ve catalog.js (üretilir)
tools/              örnek ve ekran görüntüsü üreticileri, sektör tanımları
tests/run.js        bütün örnekleri, ayrıştırıcı kenar durumlarını ve çevirileri denetler
docs/images/        README görüntüleri (tr/ ve en/)

Geliştirme komutları (Node 18+, bağımlılık yok):

node tests/run.js                                  # testler
node tools/gen-samples.js                          # samples/ klasörünü yeniden üretir
node tools/screenshots.js http://localhost:8000/   # README görüntülerini yeniler (Chrome gerekir)

Ayrıştırıcı, model, yerleşim ve adlandırma profili DOM'a dokunmaz; Node'da require edilebilir. Konsoldan inceleme için window.sqlSchema açıktır:

sqlSchema.S.model.tables.filter(t => t.junction).map(t => t.name)
sqlSchema.loadText('CREATE TABLE a (id int PRIMARY KEY);', 'deneme.sql')

Sınırlar

  • View'lar ve view'lar üzerinden kurulan ilişkiler çizilmez.
  • Tahmini ilişkiler yalnızca kolon adlarına dayanır; adlandırma kuralı tutarsız şemalarda eksik ya da fazla çıkabilir. MongoDB'de authorId gibi koleksiyon adıyla eşleşmeyen alanlar bağlanmaz.
  • CREATE TABLE … AS SELECT tabloları kolonsuz görünür.
  • MongoDB şeması örnek belgelerden çıkarılıyorsa yalnızca o belgelerde görülen alanlar listelenir.
  • Değişkenle kurulan dinamik Mongoose şemaları (new Schema(buildFields())) okunmaz.

Katkı, güvenlik, lisans

Lütfen hata bildirirken gerçek bir kuruma ait şema paylaşmayın; tablo adlarını değiştirmek yeterlidir.

MIT lisansı ile dağıtılır.

↑ başa dön


English

sqlSchema reads database schema files in the browser and draws them as a star map:

  • Every table is a star.
  • Every relationship is a line between two stars.
  • Every schema is a region of sky, and every database is a galaxy.

Zoom in and the stars turn into table cards with columns, and relationships read in crow's foot notation.

It is less manual than draw.io and lighter than a data-modelling tool. The goal is that someone seeing a schema for the first time can answer "what is connected to what?" in seconds.

Contents

  1. Highlights
  2. Quick start
  3. Reading the map
  4. Multiple files and migrations
  5. Supported databases
  6. MongoDB
  7. Naming profile
  8. Samples
  9. Exporting a schema
  10. Language
  11. Project layout and development
  12. Limitations
  13. Contributing, security, license

Highlights

  • Plain HTML, CSS and JavaScript. No dependencies, no build step; just open the folder.
  • Privacy: files never leave the browser and are not sent to any server.
  • Eight databases: Oracle, SQL Server, MySQL, MariaDB, PostgreSQL, SQLite, Cassandra and MongoDB.
  • One file, many files or a whole folder: split dumps, migration folders (Flyway, golang-migrate), multi-database projects.
  • Crow's foot notation: cardinality is derived from NOT NULL, UNIQUE and primary keys.
  • Inferred relationships: links are found from column names in legacy systems without FKs, in Cassandra and in MongoDB.
  • Naming profile: shows which naming patterns the schema uses, in what proportion, and which tables depart from the dominant pattern.
  • Scale: a 4.7 MB dump with 2,862 tables opens in about 0.6 s, and a frame draws in under 10 ms.
  • Turkish and English interface.

Quick start

  1. Download or clone the repository.
  2. Open index.html in a browser.
  3. Drag your schema files or a folder onto the page. Alternatively use Open files (multiple selection allowed), Folder, Paste or Samples.

The browser can read the sample files and dropped folders only when the page is served. Run this in the project folder and open http://localhost:8000:

python -m http.server 8000

The app also works when index.html is opened directly from disk (file://). In that case choose folders with the Folder button instead of dragging them. The embedded small sample always opens.

Gesture Result
Wheel / pinch Zoom
Drag Pan
Click Select a table, open the detail panel
Double-click Zoom into a table, show its columns
/ Search tables or columns
F Fit everything
C Hide / show column details
↑ / ↓, Enter Move through the panel's relationships, go to the chosen table
Alt + ← / → Back / forward in the navigation history
Esc Leave focus mode / clear the selection

Reading the map

The view changes with the zoom level:

View What you see
Galaxy Databases, schemas and bundles of relationships between schemas (the number on a line = relationship count)
Constellation Tables become stars: size = number of links, colour = schema. The lines of the selected table show crow's feet and column names.
Close-up Tables become cards; lines attach directly to the FK and PK column rows.

The View menu holds the column details, inferred relations, lookup links, grid and constellation grouping options. With column details off (shortcut C), close-up cards show only the table name and lines attach to the card header, leaving just tables and their relationships. The detail panel still lists the columns. The choice is remembered in the browser.

A selected table, its highlighted relationships and the detail panel

The detail panel lists:

  • the columns and their comments
  • the file and line where the table is defined
  • a plain-language reading of every relationship, such as "Every INVOICE record belongs to exactly one BILLING_ACCOUNT record. A BILLING_ACCOUNT record can have zero or many INVOICE records."

Focus mode keeps only the neighbours one or two steps away from the selected table and dims everything else.

Following relationships. Clicking a relationship in the panel (or picking it with ↓ and pressing Enter) goes to that table. The trail at the top of the panel lists the tables visited in order (ABONE › IS_EMRI › CIHAZ); click a name in it, the ‹ › buttons, or press Alt + ← / → to go back and forward. The whole schema can be walked without touching the mouse.

Close-up: lines attached to column rows, with crow's foot ends

Crow's foot

The mark at the end of a line tells how many records can exist on that side. The mark next to the table is the upper bound; the outer one is the lower bound.

Mark Meaning How it is derived from the schema
──‖ exactly one FK column is NOT NULL; owner of an embedded document
──○┼ zero or one FK column is nullable, or the FK is also a PK/UNIQUE (1:1)
──○< zero or many default for the table holding the FK; arrays of ObjectIds
──┼< one or many DDL cannot enforce it (it needs a trigger or application rule), so it is never drawn

Lines, stars and tags

Line Meaning
Solid Declared foreign key or Mongoose ref
Long-dashed Relationship declared with a @ref tag in the column comment (see below)
Dashed Inferred relationship (see below); can be turned off in the View menu
Dotted Disabled FK (DISABLE, RELY DISABLE NOVALIDATE, T-SQL NOCHECK)
Dash-dot MongoDB embedded document: the sub-document lives inside its owner
Star Meaning
Filled star Table; size = number of links, colour = schema
Ring Junction table (M:N): its PK is made of two FKs, or it is a pure link table
Small faded star Satellite: an embedded MongoDB sub-document, placed next to its owner
Dashed ring Referenced by an FK but not defined in the files

On cards, PK marks a primary key, FK a foreign key and CK a Cassandra clustering key. A faded column name means the column is nullable.

Constellations. A small schema is one constellation. Large schemas are split by table-name prefix (CUSTOMER_*, INVOICE_*) and by links. Each star gets a Bayer-style designation by brightness within its constellation (α Billing, β Billing). The layout is deterministic: the same files always give the same map.

Inferred relationships are drawn dashed in two cases:

  • No FK is declared, but the column name equals another table's primary key: CDR.SUBSCRIPTION_ID → SUBSCRIPTION.SUBSCRIPTION_ID.
  • An X_ID / xId column points to a table X whose key is ID or _id: orders.customerId → customers._id.

They are not drawn when the types disagree or when there is more than one candidate.

Relationships from comments: @ref. Some relationships cannot be declared as FKs. The most common case is columns that point to only one type in a generic lookup table (SOZLUK: ID, TIP_ID, AD). The database cannot express "only rows where TIP_ID = 7". Such relationships are added to the map with a tag in the column comment:

COMMENT ON COLUMN ABONE.DURUM_ID IS 'Subscriber status. @ref SOZLUK.ID (TIP_ID = 7)';
COMMENT ON COLUMN SESSION_LOG.USERID IS 'The user ID. @ref USERS';
Syntax Meaning
@ref TABLE To the target's primary key
@ref TABLE.COLUMN To a specific column of the target (read as SCHEMA.TABLE when TABLE.COLUMN does not exist)
@ref SCHEMA.TABLE.COLUMN With the schema
… (CONDITION) The condition in parentheses is written on the line and in the panel
  • Where it is read: the tag can be anywhere in the comment. Oracle and PostgreSQL COMMENT ON COLUMN, MySQL inline COMMENT '…' and SQL Server sp_addextendedproperty descriptions are all read.
  • On the map: these relationships are not guesses but the DBA's statement; they are drawn long-dashed and tagged "from comment" in the panel.
  • With an FK: if the column already has an FK, only the condition is added to it.
  • Errors: a target that cannot be found is listed as a warning in the parse report.

In the insurance sample, status columns point to the generic code table (KOD_TABLO) this way.

Lookup tables. When hundreds of columns point to a generic code table, the lines swamp the map and the lookup becomes a giant hub. So a table that is the target of at least two conditional relationships counts as a lookup table:

  • On the map: lines to it are not drawn. On the card, a → KOD_TABLO badge replaces the column type. The line is drawn only while the lookup or the referencing table is selected or hovered.
  • In the layout: lookup relationships do not pull tables together, so the lookup does not sit in the middle of the schema and squeeze the rest.
  • In the panel: selecting the lookup shows a Lookup usage section listing which columns use which condition (KOD_TIP = 'POLICE_DURUM' → POLICE.POLICE_DURUM).
  • By hand: the Show as lookup table / Not a lookup table button in the panel overrides the automatic choice; it is remembered in the browser.
  • As lines: View → Draw lookup links always draws the lines.

Lookup-heavy sample: links to the SOZLUK table shown as badges on the cards instead of lines

In the Lookup-heavy sample, more than 30 columns point to a single SOZLUK table.

Multiple files and migrations

All files are merged into one model and names are resolved at the end. So these cases just work:

  • an FK in one file pointing to a table in another
  • constraints.sql sorting before ddl.sql

The N files link in the bottom-right corner opens the file list. There you can:

  • include or exclude individual files
  • see each file's dialect and table count
  • turn on "separate database"

One constellation per file. When a schema's tables come from more than one file, each file's tables gather in their own constellation. Teams usually split modules into files, so the map keeps that split.

  • Kept apart: constellations of different files stay clearly apart even when they are related.
  • Boundary and name: each constellation is outlined with a thin circle, with its name above the outline.
  • Name: taken from the file path; files with the same name are told apart by their folders (POLICE/tablolar, HASAR/tablolar).

Insurance sample: each module file in its own constellation within one schema

In a migration folder a file is a version, not a module; there, and for MongoDB, tables are grouped by name prefix and relationships. View → Constellations changes the choice by hand: Automatic, By file or By name and relationships.

Reading order follows the conventions of migration tools:

Tool Files Behaviour
Flyway V1__init.sql, V1_1__x.sql, V2__y.sql By version number (V10 after V2). R__*.sql last, U*__ undo scripts skipped.
golang-migrate, dbmate 000001_x.up.sql .down.sql skipped.
Timestamped 20240115093000_x.sql By time.
Numbered / other 01_tables.sql, a2.sql < a10.sql Natural name order.

Migrations are applied from first to last, and the map shows the final state of the schema. These statements are applied:

  • RENAME TO, RENAME COLUMN
  • DROP TABLE, DROP COLUMN, DROP CONSTRAINT
  • ALTER COLUMN … TYPE, MODIFY, CHANGE
  • T-SQL sp_rename, MySQL RENAME TABLE

Separate databases. When files of different dialects are opened together (for example orders in MySQL, a catalogue in MongoDB and reporting in PostgreSQL), each folder is drawn as its own galaxy.

Three databases drawn as three galaxies

Supported databases

Oracle SQL Server MySQL / MariaDB PostgreSQL SQLite Cassandra
CREATE TABLE, inline and table-level constraints ✓ ✓ ✓ ✓ ✓ ✓ PRIMARY KEY ((a, b), c)
ALTER TABLE … ADD CONSTRAINT ✓ ✓ WITH CHECK/NOCHECK ✓ ✓ ONLY
Column changes MODIFY ALTER COLUMN MODIFY, CHANGE ALTER COLUMN … TYPE
Renames and drops RENAME, DROP sp_rename, DROP RENAME TABLE, DROP RENAME, DROP RENAME, DROP
CREATE UNIQUE INDEX (1:1 detection) ✓ ✓ ✓ ✓ ✓
Table / column comments COMMENT ON sp_addextendedproperty COMMENT '…' COMMENT ON

Not drawn. Views, sequences, triggers, packages, procedures, functions, types, grants and INSERTs are counted in the report but not drawn. The parser does not trip over the ; inside them:

  • PL/SQL blocks are kept whole up to the / line.
  • T-SQL blocks are kept whole up to the GO line.
  • MySQL blocks are kept whole up to the DELIMITER mark.

Also handled:

  • SQL*Plus commands
  • Oracle storage and partition clauses
  • PostgreSQL $$ bodies and PARTITION OF children
  • CQL // comments and map<text, int> types

Encoding. Files may be UTF-8, UTF-16 (the SSMS default) or Windows-1254; the encoding is detected automatically.

MongoDB

MongoDB has no DDL. The schema is taken from three sources; a collection that appears in several of them is merged into one table.

Source Example What is read
mongosh scripts (.js) db.createCollection('x', { validator: { $jsonSchema } }), collMod, createIndex(…, { unique }) Fields, types, required fields, descriptions, enum values
Mongoose models (.js, .ts) new Schema({ author: { type: ObjectId, ref: 'User' } }) Fields and ref relationships. Collection names follow Mongoose's pluralisation rules.
Sample documents (.json, .jsonl, .ndjson) mongoexport output Union of fields across the first 5,000 documents; Extended JSON ($oid, $date)

Embedded objects and arrays of objects become satellite tables (users.profile, orders.items) placed next to their owner.

MongoDB: collections, satellite sub-documents and inferred relationships

Naming profile

When a team has no written naming standard, the first step is to see what the schema actually uses. The naming link in the bottom-right corner counts names along these dimensions and shows their shares:

Dimension Patterns
Table and column name case UPPER_SNAKE, lower_snake, PascalCase, camelCase
Primary key name ID, <TABLE>_ID, <TABLE>_NO / _CODE, unrelated to the table name
Foreign key column <TARGET>_ID, <TARGET>_NO / _CODE, role prefix (SENDER_CUSTOMER_ID, AGENT_USER_ID → APP_USER), same as the target PK, role name only (OWNER), not containing the target name (CHZ_REF)
Table name singular / plural (estimated), prefixes such as TBL_
Characters and length Turkish / non-ASCII characters, names longer than 30 characters
  • Each dimension lists the dominant pattern and the names that do not follow it. Clicking a name selects its table.
  • If the most used pattern has less than 60%, it is not called dominant; the window shows no clear dominant pattern. A 51% to 49% split means the schema has two separate habits.
  • Scope computes the profile for a single schema, which separates the habits of different modules.
  • The consistency score is the average share of names that follow the dominant pattern in each dimension.
  • Download Markdown writes the profile to a file to share with the team.

The tool imposes no rule: whether ID or <TABLE>_ID is right is the team's decision.

Not counted in the shares:

  • Composite PKs, 1:1 tables whose PK comes from the parent, and tables without a PK. These are shown separately.
  • Audit columns such as CREATED_BY, UPDATED_BY, GUNCELLEYEN and KAYIT_KULLANICI. They point to the user table but follow their own established pattern; they are counted separately.
  • Inferred relationships: only declared FKs are counted, because inferred ones are already based on names.
  • The _id and ref fields of MongoDB collections.

Naming profile: PK, FK and case patterns with their shares and the names that depart from the dominant pattern

The Mixed naming sample was made for this feature: an Oracle schema to which two teams added tables with different habits.

Samples

The samples under samples/ are synthetic: they do not belong to any real organisation. Each imitates the typical structure of a sector and the real export format of a tool. Open them from the Samples menu.

Sample Database Scenario
Small telecom Oracle 20 tables, embedded in the app
Telecom BSS/OSS Oracle SQL Developer dump in one file: 318 tables, 16 schemas, partitions, triggers, packages
Telecom, one file per schema Oracle The same schema split into 16 files; all FKs in the final file
Core banking SQL Server SSMS "Generate Scripts": UTF-16, GO, IDENTITY, descriptions
Insurance (legacy system) Oracle A folder per module, Turkish names, no FKs at all
Marketplace e-commerce MySQL mysqldump --no-data, a DELIMITER procedure
Hospital information system PostgreSQL OMOP CDM layout: tables, PKs, FKs, indexes and comments in separate files
Logistics / parcel delivery PostgreSQL Flyway, 14 versions: renamed and dropped tables, partitioning
IoT telemetry Cassandra Two keyspaces, table-per-query design
Social network MongoDB $jsonSchema + Mongoose + mongoexport
Field service mobile app SQLite sqlite3 .dump, offline cache
Polyglot e-commerce MySQL + MongoDB + PostgreSQL Microservices, one galaxy per folder
Mixed naming Oracle Two teams, two habits: PK ID and <TABLE>_ID, irregular FKs, ORM tables
Lookup-heavy Oracle Every code lives in a single SOZLUK table; more than 30 columns point to it with @ref

Exporting a schema

Database How
Oracle, SQL Developer Tools → Database Export, DDL only. The "separate files per object type" output can be opened as a folder.
Oracle, SQL*Plus / SQLcl The DBMS_METADATA script below
SQL Server SSMS → database → Tasks → Generate Scripts (schema only)
MySQL / MariaDB mysqldump --no-data mydb > schema.sql
PostgreSQL pg_dump --schema-only mydb > schema.sql
SQLite sqlite3 app.db .schema > schema.sql
Cassandra cqlsh -e "DESCRIBE KEYSPACE telemetry" > schema.cql
MongoDB Validator scripts, the Mongoose models folder, or mongoexport --limit 1000 output

For projects that use migrations, open the db/migration folder as it is.

-- Oracle: DDL and comments from the data dictionary
SET LONG 20000000 LONGCHUNKSIZE 20000000 PAGESIZE 0 LINESIZE 32767 TRIMSPOOL ON FEEDBACK OFF
EXEC DBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRANSFORM, 'SQLTERMINATOR', TRUE);
EXEC DBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRANSFORM, 'SEGMENT_ATTRIBUTES', FALSE);
SPOOL schema.sql
SELECT DBMS_METADATA.GET_DDL('TABLE', table_name, owner) FROM all_tables WHERE owner IN ('CRM', 'BILLING');
SELECT DBMS_METADATA.GET_DEPENDENT_DDL('COMMENT', table_name, owner) FROM all_tables t
 WHERE owner IN ('CRM', 'BILLING')
   AND (EXISTS (SELECT 1 FROM all_tab_comments c WHERE c.owner = t.owner AND c.table_name = t.table_name AND c.comments IS NOT NULL)
     OR EXISTS (SELECT 1 FROM all_col_comments c WHERE c.owner = t.owner AND c.table_name = t.table_name AND c.comments IS NOT NULL));
SPOOL OFF

Language

The interface is available in Turkish and English. On first visit Turkish is chosen if the system language is Turkish, English otherwise. Switch with the TR / EN buttons in the top-right corner; the choice is remembered in the browser. Use ?lang=tr or ?lang=en to pin the language in a link.

Shareable links. URL parameters open a sample, a table and a zoom level directly:

index.html?lang=en&sample=telekom&select=BILLING_ACCOUNT&zoom=0.9&legend=0

Add pop=naming, pop=report or pop=files to open a window on load. center=TABLE centres a table without selecting it.

Project layout and development

index.html          page shell, legend
style.css           styles
js/                 loaded in this order; each file adds to the globalThis.sqlSchema namespace
  i18n.js           Turkish / English dictionaries, language selection
  lexer.js          tokenizer, statement splitter, dialect detection
  sql-parser.js     DDL → ordered operation list (create, fk, rename, drop ...)
  mongo.js          the same operation list from $jsonSchema, Mongoose and JSON documents
  files.js          file ordering (Flyway, golang-migrate), parser selection
  model.js          applies operations: tables, relationships, cardinality, junctions, inference
  layout.js         database → schema → constellation → star, hierarchical force layout
  conventions.js    naming profile: patterns, shares, names that depart from the dominant pattern
  sample-small.js   embedded small sample
  render.js         canvas drawing, camera, crow's feet
  ui.js             loading, file list, search, panel, report, URL parameters
samples/            synthetic samples and catalog.js (generated)
tools/              sample and screenshot generators, sector definitions
tests/run.js        checks every sample, parser edge cases and translations
docs/images/        README images (tr/ and en/)

Development commands (Node 18+, no dependencies):

node tests/run.js                                  # tests
node tools/gen-samples.js                          # regenerate samples/
node tools/screenshots.js http://localhost:8000/   # refresh README images (needs Chrome)

The parser, model, layout and naming profile never touch the DOM and can be required in Node. window.sqlSchema is exposed for inspection in the console:

sqlSchema.S.model.tables.filter(t => t.junction).map(t => t.name)
sqlSchema.loadText('CREATE TABLE a (id int PRIMARY KEY);', 'test.sql')

Limitations

  • Views and relationships expressed only through views are not drawn.
  • Inferred relationships rely on column names only; schemas with inconsistent naming can produce missing or extra links. In MongoDB, fields such as authorId that do not match a collection name are not linked.
  • CREATE TABLE … AS SELECT tables appear without columns.
  • When a MongoDB schema comes from sample documents, only fields seen in those documents are listed.
  • Dynamic Mongoose schemas built from variables (new Schema(buildFields())) are not read.

Contributing, security, license

When reporting a bug, please do not share a schema that belongs to a real organisation; renaming the tables is enough.

Released under the MIT license.

↑ back to top

About

Veritabanı şemalarını tarayıcıda yıldız haritası olarak çizer · Draws database schemas as a star map in the browser

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages