6.9 Veritabanı kimlik kartı (IVD$DATABASE), ALTER DATABASE … SET STATE ve başlangıç betiği

<< İçindekileri Görüntülemek İçin Tıklayın >>

Yer:  Teknik Kılavuzlar > IVEDI SQL Kullanıcı Kılavuzu > 6. Veri tanımlama (DDL) >

6.9 Veritabanı kimlik kartı (IVD$DATABASE), ALTER DATABASE … SET STATE ve başlangıç betiği

Her veritabanında tek satırlık bir ivd$database tablosu vardır; CREATE DATABASE yazar (MASTER'ınkini sunucu açılışı): GUID, ad, MASTER'daki kayıt kimliği (ivd$master_object_id; MASTER'ın kendi kartında 0), durum, katalog biçim sürümü (ivd$catalog_version; değeri 23), motor sürümü, uygulama (işlemci, bayt sırası, işletim sistemi, derleyici), depo motoru ile sürümü ve disk biçimi (ör. SQLite 3.53.3 / SQLite format 3, Firebird'de ODS 13.1), karakter kümesi, makine adı, yaratan login, yaratılış zamanı (UTC), başlangıç betiği (ivd$startup_script), görev zamanlayıcı bayrağı (ivd$task_scheduler), açıklama (ivd$description) ve seviye damgaları (ivd$level3_version / ivd$level3_generated ile ivd$level4_version / ivd$level4_generated — aşağıda kendi bölümü var). Satır yalnız şu yollardan değişir: veritabanı MASTER'a bağlanırken (CREATE ve OPEN DATABASE MASTER kimliğini tazeler), COMMENT ON DATABASE (açıklama; aynı metin veritabanının kendi ivd$objects satırına ve MASTER'daki kayıt satırına da yazılır), başlangıç betiği komutları, durum komutu ve seviye damgalarını yazan komutlar. Bu komutlar her ALTER DATABASE gibi yalnız geçerli veritabanında çalışır ve COMMIT'te uygulanır:

SET CATALOG rop_db;
ALTER DATABASE rop_db SET STATE READ_ONLY;
-- ACTIVE | RESTRICTED | READ_ONLY | OFFLINE
-- (CREATING / UPGRADING / LEVEL3_UPDATE motorundur, SET STATE ile verilemez; MASTER hep ACTIVE)
COMMIT;

Tabloya doğrudan yazılamaz (katalog tablosu, INSUFFICIENT_PRIVILEGE). Durumlar motorca uygulanır; durum bir yetkiyle aşılmaz, ALTER DATABASE ise her durumda çalışır (durumu geri almanın yolu odur):

DurumEtkisi
ACTIVEKısıt yok.
READ_ONLYOkuma ve çağrı serbest; her yazma ve DDL DATABASE_READ_ONLY (SQLSTATE 25006) — SYSDBA dahil herkes için.
RESTRICTEDYalnız sahip, SYSDBA, SYSADMIN üyesi (ve kimliksiz sistem bağlantısı) kullanabilir, açabilir, SET CATALOG ile geçebilir; diğerleri DATABASE_NOT_AVAILABLE (55000).
OFFLINEHerkes için her erişim DATABASE_NOT_AVAILABLE; yalnız ayrıcalıklı kimlik açabilir ve geçebilir, orada yalnız ALTER DATABASE … SET STATE çalışır. Katalog okunur kalır.
UPGRADINGKatalog yükseltmesi sürerken ya da yarım kaldıysa; yalnız SYSDBA açabilir ve orada yalnız yükseltme komutu çalışır (bkz. “Katalog sürümü ve ALTER DATABASE … UPGRADE”).
LEVEL3_UPDATEKatalog yükseltildi, seviye 3 yeniden üretilmeyi bekliyor; RESTRICTED gibi. ALTER DATABASE … SET LEVEL 3 VERSION … GENERATED … kendiliğinden ACTIVE'e döndürür.
CREATINGYaratılış sürerken; yarım kalmış yaratılış açılamaz.

6.9.1 Başlangıç betiği: ALTER DATABASE … SET | DROP STARTUP SCRIPT

Kartın ivd$startup_script kolonu bir MQL betiğinin metnini tutar. Betik, veritabanı sunucuya her bağlandığında o veritabanında koşar: OPEN DATABASE başarıyla bittiğinde ve MASTER'da kayıtlı bir veritabanı ilk kullanımda tembel açıldığında, açan bağlantıda ve işlemde, arama yolu SYS iken. MASTER'ın betiği sunucu açılışında kendi sistem bağlantısında koşar. Betiğin hataları açan deyimin hatası olarak raporlanır; betik her bağlanışta yeniden koştuğu için idempotent yazılmalıdır. CREATE DATABASE ve yükseltme bekleyen bir açılış betiği koşturmaz.

SET CATALOG rop_db;
ALTER DATABASE rop_db SET STARTUP SCRIPT 'insert into acilis_log(n) values (1);';
ALTER DATABASE rop_db SET STARTUP SCRIPT FROM FILE 'rop_db_startup.sql';
ALTER DATABASE rop_db DROP STARTUP SCRIPT;
COMMIT;
  • FROM FILE dosyayı derleme anında okur ve metnini karta yazar; dosya sonradan değişirse komut yeniden çalıştırılmalıdır. UTF-8 okunur, baştaki BOM atılır. Göreli yol, komutu içeren betik dosyasının dizinine göredir (#include gibi; client: / server: önekleri de #include'daki gibi geçerlidir — bkz. bölüm 10, “Dosya dahil etme”); betik dosyasından gelmeyen bir komutta çalışma dizinine göredir. ${APPDIR}, ${CONFIGDIR}, ${TEMP} gibi yer tutucular çözülür. Bulunamayan dosya SYNTAX_ERROR verir.
  • Boş metin ve DROP STARTUP SCRIPT kolonu NULL yapar.
  • Hizmetin MASTER'ı için betik çalışan ajana msql ile verilir; dosya sunucudaysa server: öneki yazılır: ALTER DATABASE MASTER SET STARTUP SCRIPT FROM FILE 'server:${APPDIR}/lsp_startup.sql';

6.9.2 Belge havuzu: ALTER DATABASE … SET DOCUMENTS

Ajanın belge havuzu (müşteri belgeleri: NetsimApp'in /ClientREST/Doc* uçları, MCP'nin doc_* araçları, IMPORTDOC) her veritabanı için ayrı tanımlanır. INTERNAL havuzu veritabanının kendi deposuna, DATABASE <ad> ilişkili başka bir kayıtlı veritabanının deposuna bağlar; OFF bağı kaldırır. Değer COMMIT'te yalnız MASTER'daki kayıt satırının DOCUMENTS niteliğine yazılır (kart değişmez). İlişkili veritabanı kayıtlı olmalı ve veritabanının kendisi olmamalıdır; MASTER için verilemez. Havuz SQLite, PostgreSQL (katalog dışındaki ivd$docs şemasında) ya da Firebird (doc$ tabloları; tam metin dizini ajanın belleğinde) depolu olabilir.

SET CATALOG musteri_1;
ALTER DATABASE musteri_1 SET DOCUMENTS INTERNAL;
COMMIT;

SET CATALOG musteri_2;
ALTER DATABASE musteri_2 SET DOCUMENTS DATABASE musteri_2_belge;
COMMIT;

6.9.3 Bağlantı parametreleri: ALTER DATABASE … SET PARAMETERS

ALTER DATABASE <ad> SET PARAMETERS '<bağlantı dizesi>' MASTER'daki kayıt satırının ENGINE PARAMETERS niteliğini yeniden yazar (sunucu, port, depo adı, kimlik…). Değeri ****** olan bir anahtar kayıtlı değerini korur (yönetim arayüzü kullanıcı adı ve parolayı böyle maskeler); dizede yazılmayan anahtar düşer. Parola kayıt satırına açık metin olarak yazılmaz, mühürlenerek (Password=enc:…) saklanır. Yeni değerler veritabanı yeniden açıldığında geçerli olur — bağlanmamış işçi süreç, CLOSE DATABASE + OPEN DATABASE ya da ajanın yeniden başlatılması; açık depo bağlantıları eskisiyle sürer, deyim bunu bir uyarıyla söyler. MASTER için verilemez; Recreate reddedilir.

Açılamayan kaydın onarımı. Depoya bağlanılamayan bir kayda (parola değişmiş, sunucu taşınmış) SET CATALOG geçemez. Böyle bir kayda iki öğe herhangi bir veritabanından (örneğin MASTER'dan) verilir ve yalnız kayıt satırını yazar; veritabanı bir sonraki kullanımda açılır. Açılana kadar her biri tek başına verilmelidir, öteki ALTER DATABASE öğeleri açık veritabanı ister. SET ENGINE USER açık olduğu halde depoya artık bağlanamayan kayda da (servis kullanıcısının parolası ajan çalışırken depoda değişmiş) böyle verilir: kayıt satırıyla birlikte açık veritabanının bağlantı parametreleri de yenilenir, ajanı yeniden başlatmak gerekmez.

  • ALTER DATABASE <ad> SET ENGINE USER [PASSWORD '…'] — servis kullanıcısının parolası depoda değiştiyse (önerilen yol): oturumda SET STORAGE CREDENTIALS ile verilen süper kullanıcıyla servis kullanıcısı yeniden kurulur, kayıt onun mühürlü parolasını alır. Süper kullanıcı parolası kayda yazılmaz.
  • ALTER DATABASE <ad> SET PARAMETERS '…' — sunucu, port ya da veritabanı adı değiştiyse.
set storage credentials user 'postgres' password '***';
alter database satis set engine user;
commit;
set storage credentials none;
SET CATALOG musteri_1;
ALTER DATABASE musteri_1 SET PARAMETERS 'Server Name=10.5.7.4; Port=5432; Database Name=musteri_1; User Name=******; Password=******; Catalog Schema=netsim';
COMMIT;

6.9.4 Depo kimliği: ALTER DATABASE … SET ENGINE USER

ALTER DATABASE <ad> SET ENGINE USER [PASSWORD '<parola>'] kayıt satırındaki depo kimliğini motorun kendi servis kullanıcısına çevirir (yapılandırmadaki engineUser; öndeğer IVD$ENGINE, boş bırakılırsa özellik kapalıdır). CREATE DATABASE ve OPEN DATABASE kaydı açarken bu işi kendiliğinden yapar: deyimde verilen kullanıcı adı ve parola yalnız kurulum kimliğidir, servis kullanıcısı deponun süper kullanıcısıyla kurulur (PostgreSQL'de LOGIN SUPERUSER rolü, Firebird'de ADMIN ROLE'lü kullanıcı) ve kayda o yazılır; kurulamazsa verilen kimlik kalır ve bir uyarı yazılır. Bu komut var olan bir kaydı sonradan geçirmek ya da kurulumu yinelemek içindir ve oturumda önce SET STORAGE CREDENTIALS USER '<süper kullanıcı>' PASSWORD '<parola>' verilmesini ister (bkz. “Oturum ayarları”). Parola verilmezse aynı depo sunucusundaki başka bir kaydın parolası, o da yoksa üretilen bir parola kullanılır; verilen parola aynı sunucudaki öteki kayıtlara da yazılır (sunucu başına tek parola). Kayıt satırı ve açık motorun bağlantı parametreleri yeniden yazılır, her süreç depoyu sonraki kullanımda yeni kimlikle açar. MASTER için verilemez; kimlik doğrulaması olmayan depolarda (sqlite, bellek) ve OS Authentication ile açılan bağlantıda iş yapmaz.

SET STORAGE CREDENTIALS USER 'postgres' PASSWORD 'masterkey';
SET CATALOG musteri_1;
ALTER DATABASE musteri_1 SET ENGINE USER;
COMMIT;
SET STORAGE CREDENTIALS NONE;

6.9.5 Görev zamanlayıcı: ALTER DATABASE … SET TASK SCHEDULER

Kartın ivd$task_scheduler kolonu, hizmetin görev zamanlayıcısının bu veritabanı için çalışıp çalışmayacağını söyler: hem ürünün ZMGOREV döngüsü hem de SYS.Scheduler paketiyle tanımlanan işler (ivd$scheduler_jobs) buna bakar. Değer COMMIT'te karta ve MASTER'daki kayıt satırının TASK SCHEDULER niteliğine birlikte yazılır; hizmet kayıtları MASTER'dan okur. Öndeğer kapalıdır (NULL). MASTER için de verilebilir — motorun kendi işleri orada da çalışır.

Zamanlayıcı açıkken her iş kendi alt sürecinde ve SYSTEM kimliğiyle koşar; aynı işin önceki koşusu bitmeden yenisi başlamaz, farklı işler paralel gider. İş listesi attachJob / enableJob / disableJob / startJob / resetJob / detachJob çağrılarından hemen sonra, en geç de beş dakikada bir yeniden okunur; yeni bir iş için hizmeti yeniden başlatmak gerekmez. Bir iş tipi (Scheduler.Job'dan türeyen TYPE) düşürülünce o tipe bağlı işler de ivd$scheduler_jobs'tan silinir. SET TASK SCHEDULER ON | OFF da çalışan hizmette izlenir: dağıtıcı kümesi birkaç saniye içinde yeniden kurulur, açılan veritabanı için dağıtıcı eklenir, kapananınki kaldırılır. Koşu sonunda ivd$last_status, ivd$run_count, ivd$failure_count ve sıradaki zaman (ivd$next_run) yazılır.

SET CATALOG rop_db;
ALTER DATABASE rop_db SET TASK SCHEDULER ON;
COMMIT;

SELECT upper(a.ivd$value)
  FROM master.sys.ivd$object_attributes a
  JOIN master.sys.ivd$objects o ON o.ivd$object_id = a.ivd$object_id
 WHERE o.ivd$type = 'DATABASE' AND o.ivd$object_name = 'ROP_DB'
   AND a.ivd$attribute_name = 'TASK SCHEDULER';   -- TRUE

Veritabanı yeniden kaydedilirken (OPEN DATABASE) nitelik karttan yeniden yazılır.

6.9.6 Çalışma kipi: ALTER DATABASE … SET EXECUTION

Veritabanının çalışma kipini (IVEDI ya da STORAGE, bkz. CREATE DATABASE) değiştirir. Değer COMMIT'te karta yazılır ve o andan sonraki deyimlerde geçerlidir.

SET CATALOG urun_db;
ALTER DATABASE urun_db SET EXECUTION STORAGE;
COMMIT;

SELECT execution FROM urun_db.sys.ivd$v_database;   -- STORAGE

6.9.7 Depo lehçesinde metin: NATIVE_SQL

NATIVE_SQL, deponun kendi lehçesinde yazılmış bir metni taşır. Motor metni değerlendirmez; depoya gönderilen SQL'e olduğu gibi yazar. İki biçimi vardır — bir değerin beklendiği yere giren ifade biçimi ve bir deyimin beklendiği yere giren deyim biçimi. Her ikisinde de depo başına ayrı metin verilebilir:

NATIVE_SQL ( [<depo>] '<metin>' {, [<depo>] '<metin>'} [ AS <tip> ] )

<depo> yerine POSTGRESQL, FIREBIRD, SQLITE, ODBC gibi bir depo motoru adı yazılır; depo adı verilmeyen metin öndeğerdir ve adı geçmeyen bütün depolar onu kullanır. IVEDI adıyla verilen metin motorun kendi lehçesindedir ve depoya hiç gitmez: kodu motorun kendisi çalıştırdığında kullanılır (aşağıda). AS <tip> ifadenin tipini söyler ve sonuç o tipe çevrilir; verilmezse ifade VARIANT derlenir ve değer deponun döndürdüğü tipte kalır. Bir koşulda (IF, WHERE, CHECK) tipin derleme anında belli olması için AS BOOLEAN yazın.

Yetki

Depoya ya da işletim sistemine doğrudan inen her şey yalnız SYSADMIN login'ine (ve SYSDBA'ya) açıktır: NATIVE_SQL, EXECUTE STATEMENT … ON EXTERNAL, #SHELL yönergeleri, FileSystem ve OS paketleri ve ALTER DATABASE … SET STARTUP SCRIPT. Denetim derlemede yapılır: başka bir login bunları yazarsa deyim INSUFFICIENT_PRIVILEGE ile reddedilir. SYSADMIN'in yazdığı bir yordam, görünüm ya da başlangıç betiği bunları kullanıyorsa, onu çağırma hakkı olan her kullanıcıda çalışır.

Yordam ve tetikleyici gövdesinde. NATIVE_SQL metin dönüşümünde anlam taşır: kod deponun lehçesine çevrilirken (EXECUTION STORAGE veritabanında depoya kurulan yordam, tetikleyici, kısıt, hesaplanan kolon; #MODE CONVERT TO) depoya uyan metin, ifadenin durduğu yere olduğu gibi yazılır. Aşağıdaki koşul Firebird'e IF (RDB$GET_CONTEXT('SYSTEM', 'DB_NAME') NOT CONTAINING 'flymetadata') THEN olarak gider; metin dönüştürülen gövdenin parçası olduğu için gövdenin değişkenlerini ve NEW. / OLD. alanlarını deponun kendi yazımıyla kullanabilir. AS <tip> yalnız ifadenin IVEDI'deki derleme tipini verir, depoya giden metne eklenmez.

IF (NATIVE_SQL(FIREBIRD   'RDB$GET_CONTEXT(''SYSTEM'', ''DB_NAME'') NOT CONTAINING ''flymetadata''',
               POSTGRESQL 'TRUE',
               IVEDI      'a > 3'
               AS BOOLEAN)) THEN
  ...

Kodu motor çalıştırdığında. Kod depoya kurulmayıp motorda çalışıyorsa — EXECUTION IVEDI veritabanı, üst düzey EXECUTE BLOCK, IVEDI_ONLY nesne — sıra şudur:

  1. EXECUTION STORAGE veritabanında bu depo için metin varsa depoda çalışır: ifade o veritabanının depo bağlantısında SELECT <metin> ile hesaplanır (Firebird'de her SELECT'in bir kaynağı olması gerektiğinden … FROM RDB$DATABASE), deyim aynı bağlantıda çalıştırılır. Metin depoda kendi başına çalıştığı için gövdenin değişkenlerini göremez; depo oturumunun bağlamını görür.
  2. Yoksa IVEDI metni varsa motor onu EXECUTE EMBEDDED gibi, bulunduğu yerin bağlamında derleyip çalıştırır: yerel değişkenler, parametreler ve tetikleyicinin NEW. / OLD. alanları görünür; ifadenin değeri AS <tip>'e çevrilir.
  3. İkisi de yoksa ifade NULL olur, deyim hiçbir şey yapmaz.
CREATE TABLE kural
(
  id      integer not null,
  adet    integer,
  fiyat   numeric(15,2),
  --  hesaplanan kolon: her depo kendi yazımıyla
  toplam  numeric(15,2) generated always as
            (NATIVE_SQL(POSTGRESQL 'adet * fiyat', FIREBIRD 'adet * fiyat', 'adet * fiyat' AS NUMERIC(15,2))),
  constraint kural_pk primary key (id),
  --  depo tarafında denetlenecek kısıt
  constraint kural_adet_chk check (NATIVE_SQL('adet > 0' AS BOOLEAN))
);

Nerede işe yarar. EXECUTION STORAGE kipinde CHECK kısıtlarını ve hesaplanan kolonları depo çalıştırır; motorun bunları anlaması gerekmez, yalnızca doğru metni göndermesi gerekir. ADOPT TABLE de depodan okuduğu CHECK ve hesaplanan kolon ifadelerini böyle saklar — ifade kaybolmaz, benimsenen tablo yeniden kurulduğunda aynı metin geri gider.

Sınırı. EXECUTION IVEDI kipinde IVEDI metni verilmemiş bir NATIVE_SQL bir uyarı verir ve değeri NULL'dur; o kipte bir IVEDI metni ekleyin ya da kısıtı ve hesaplanan kolonu doğrudan IVEDI ifadesiyle yazın. Metin depoya olduğu gibi gittiği için içeriği depo reddederse hata deponun hatasıdır.

Deyim biçimi

Aynı yapı bir deyim olarak da yazılır: bir yordamın ya da tetikleyicinin gövdesinde, ya da üst düzeyde. Metinler ve seçim kuralı ifade biçimiyle aynıdır; tek fark AS <tip> kabul edilmemesidir — bir deyim değer üretmez.

NATIVE_SQL ( [<depo>] '<metin>' {, [<depo>] '<metin>'} )

Asıl işi, lehçe farkının bir ifade değil bir deyim olduğu durumdur. #IFDEF dalı derleme anında ve bütün akış için seçer; tek bir katalog nesnesi iki lehçenin metnini birden taşıyamaz. Deyim biçiminde iki dal da nesnenin kendi gövdesinde durur ve hangisinin ineceğini hedef seçer:

CREATE PROCEDURE oturum_degeri_yaz(ad varchar(30), deger varchar(30))
AS
BEGIN
  NATIVE_SQL(POSTGRESQL 'PERFORM set_config(''netsim_sess.'' || ad, deger, false)',
             FIREBIRD 'RDB$SET_CONTEXT(''USER_SESSION'', :ad, :deger)');
END;

Sınırı. EXECUTION IVEDI kipinde bu deyim hiçbir şey yapmaz — motor depo lehçesindeki bir metni çalıştıramaz. Derleyici bunu bir uyarıyla söyler; sessizce hiçbir şey yapan bir deyim kusurları saklar. #MODE CONVERT'te uyarı verilmez: orada metin hedefe iner.

Sonlandırıcı. Üretilen metinde deyimin sonuna ; konur, üç durum dışında:

  • hedef lehçe için metin verilmemişse deyim hiç yazılmaz, ; da yazılmaz;
  • metin zaten ; ile bitiyorsa ikincisi yazılmaz;
  • Firebird'de metin END ile bitiyorsa yazılmaz — bileşik bloktan (FOR … DO BEGIN … END) sonra ; Firebird PSQL'inde geçersizdir. END ile biten bir ifade deyimi (x = CASE … END) sonlandırıcı ister: onu metnin sonuna ; yazarak verin.

Metinde makro. Dizgi içindeki {$MAKRO} dizginin her satırında açılır — çok satırlı düz dizgide ve q'{…}' biçiminde de. Dizgi içindeki çıplak makro adı açılmaz.

Gövdesi depo metni olan görünüm

Bir görünümün sorgusu yalnız deponun kendi sistem tablolarıyla yazılabiliyorsa (Firebird'de MON$ / SEC$, PostgreSQL'de pg_stat_activity / pg_roles), gövde AS'tan sonra tek bir NATIVE_SQL olur. Motor bu metni ayrıştırmaz; bu yüzden kolon listesinde her kolonun tipi yazılır ve kolonlar kataloğa bu bildirimden girer:

CREATE VIEW fly$atta (att_id integer, usr varchar(63))
  AS NATIVE_SQL(FIREBIRD 'select mon$attachment_id, mon$user from mon$attachments',
                POSTGRESQL 'select pid, usename from pg_stat_activity');
  • EXECUTION STORAGE veritabanında görünüm depoda, o depo için seçilen metinle kurulur ve satırları depodan okunur.
  • EXECUTION IVEDI kipindeki veritabanında görünüm kataloğa girer ama okunamaz: sorgu UNSUPPORTED_FEATURE ile adıyla reddedilir.
  • #MODE CONVERT TO <hedef> çıktısına hedefin metni yazılır; hedefin metni verilmemişse hata verir.
  • Metnin sonundaki ; yazılmaz.
  • Tipsiz bir kolon, kolon listesi olmayan bir NATIVE_SQL görünümü, AS SELECT görünümünde kolon tipi ve WITH CHECK OPTION derlemede hatadır; görünüm güncellenemez.

6.9.8 Seviye sınırı komutları ve seviye damgaları

Bir IVEDI veritabanındaki nesneler nesne kimliklerine göre dört düzeye ayrılır. Düzey, nesnenin kime ait olduğunu ve onu kimin değiştirebileceğini söyler:

DüzeyKimlik aralığıNeKim yazar
15001 – 5499Katalog tabloları (ivd$objects, ivd$database …) Yalnız motor; SQL ile yazılamaz
25501 – 5999 (tablolar), 6001 – 6499 (görünümler) Sistem uygulama tabloları ve IVD$V_* sistem görünümleri Motor kurar; tablolara kullanıcı kodu sıradan DML ile yazar
310.000.000 –İşletme uygulamasının nesneleri (ürünün tabloları, yordamları, görünümleri) Ürünün veritabanı kurulum betiği
420.000.000 –Kullanıcının kendi nesneleriSon kullanıcı

Yeni bir veritabanında kimlik dizisi (SYS.IVD$OBJECT_ID) seviye 3'ün başındadır, yani ilk yaratılan nesne 10.000.000 alır. Seviye 3 ile 4 arasındaki sınırı iki komut çizer ve bunlar kaynak veritabanı kurulurken çalışır:

SET CATALOG urun_db;
ALTER DATABASE urun_db BEGIN LEVEL 3 VERSION '5.2.0.1540';   -- seviye 3 kurulumu başlıyor
  -- ... ürünün bütün tabloları, domainleri, yordamları, görünümleri ...
ALTER DATABASE urun_db END LEVEL 3;                          -- bundan sonrası kullanıcının
COMMIT;
ALTER DATABASE <db> BEGIN LEVEL 3 VERSION '<sürüm>' [PRODUCT '<kod>']
Karta seviye 3 sürümünü yazar ve üretim zamanını motor damgalar (o an, UTC). Kimlik dizisine dokunmaz — dizi zaten seviye 3'ün başındadır. PRODUCT seviyelerin kimin olduğunu karta yazar (ivd$product); paketle taşınır ve yükseltmede karşılaştırılır.
ALTER DATABASE <db> END LEVEL 3
Kimlik dizisini seviye 4'ün başına (20.000.000) taşır, böylece bundan sonra doğan her nesne kullanıcının olur. Dizi zaten 20.000.000'un üstündeyse dokunmaz ve bunu bir uyarıyla söyler: geri sarmak, var olan seviye 4 nesneleriyle kimlik çakışması demek olurdu.
ALTER DATABASE <db> BEGIN LEVEL 4 VERSION '<sürüm>' [PRODUCT '<kod>']
Karta seviye 4 sürümünü yazar (üretim zamanını yine motor damgalar) ve aynı anda END LEVEL 3'ün dizi işini yapar, yani sınırı da çizer: kullanıcı/müşteri nesnelerini üreten bir betik tek deyimle hem “buradan sonrası seviye 4” der hem de kendi sürümünü damgalar.

END LEVEL 4 yoktur: seviye 4 son seviyedir, dizinin taşınacağı bir yer yoktur.

İkisi de ALTER DATABASE'in birer dalıdır: adı yazılan veritabanı geçerli katalog olmalıdır (önce SET CATALOG) ve başka bir değişiklikle aynı deyimde birleştirilemezler. Yalnız üst düzey deyimdirler — saklı bir yordam veritabanının kimlik kartını sessizce değiştiremez — ve ALTER DATABASE yetkisini isterler (sahip, SYSDBA ya da SYSADMIN üyesi). İkisi de COMMIT'te uygulanır.

Hedef veritabanının damgalanması

Kurulmuş bir ürün veritabanı yükseltildiğinde seviye 1–2 motorun güncel metadatasına gelir, seviye 3 ise ürün tarafından yeniden üretilmeyi bekler. Motor bunu kendisi işaretler: seviye 3 damgası taşıyan bir veritabanı başarılı bir ALTER DATABASE … UPGRADE sonunda LEVEL3_UPDATE durumuna geçer ve o durumda yalnız sahibine, SYSDBA'ya ve SYSADMIN üyelerine açıktır. Seviye 3 güncellemesi bittiğinde son adım şudur:

SET CATALOG urun_db;
ALTER DATABASE urun_db SET LEVEL 3 VERSION '5.2.0.1541' GENERATED '2026-09-18 01:02:03';
COMMIT;

Aynı komutun seviye 4 yazımı da vardır — ALTER DATABASE <db> SET LEVEL 4 VERSION '<sürüm>' GENERATED '<zaman>' — ve aynı işi yapar. İkisi de sonuna PRODUCT '<kod>' alabilir. Tek farkı durum: LEVEL3_UPDATE seviye 3'ün yeniden üretilmeyi beklediği anlamına geldiği için o durumu yalnız seviye 3 damgası kaldırır.

Burada iki değer de açıkça verilir ve ikisi de kaynak veritabanının kartından kopyalanır; motor kendi saatini yazmaz. Sebebi şudur: iki veritabanının seviye 3'ünün aynı olup olmadığı ancak aynı damgayı taşımalarıyla anlaşılır — hedefin kendi güncelleme zamanını yazması bu karşılaştırmayı yok ederdi. Komut aynı kart güncellemesinde durumu da ACTIVE'e çeker, yani ayrıca SET STATE yazmak gerekmez. (Daha kısıtlı bir durum — RESTRICTED, READ_ONLY, OFFLINE — işletmecinin kendi kararıdır ve korunur.)

Damgayı okumanın yolu IVD$V_DATABASE görünümüdür:

SELECT database_name, catalog_version, state, product,
       level3_version, level3_generated, level4_version, level4_generated
  FROM ivd$v_database;

İki seviyenin damgası birbirinden bağımsızdır: EXPORT LEVEL 3|4 taşıdığı seviyenin damgasını pakete koyar, UPGRADE LEVEL 3|4 onu hedefe birebir kopyalar ve sürüm karşılaştırmasını (yön, gerileme kapısı, ivd$upgrade komutlarının sürüm aralığı) o seviyenin damgasıyla yapar, DROP LEVEL 3|4 ise o seviyenin damgasını temizler.

6.9.9 Seviye paketleri, benimseme ve tek tablo yükseltmesi

Seviye 3'ün (ve 4'ün) bir sürümden ötekine taşınması için motorun dört aracı vardır: kaynaktan bir paket yazmak, hedefi paketle karşılaştırmak, kataloğu olmayan depo tablolarını kataloğa benimsemek ve tek bir tabloyu yeni tanımına yükseltmek.

Burada komutların kendisi anlatılır: sözdizimi, seçenekler ve her birinin ne yaptığı. Bir üretim veritabanını hangi durumda hangi sırayla yükselteceğiniz — kataloğu hiç olmayan eski bir veritabanı, sürümler arası geçiş, seviyeyi baştan kurmak, benimseme sırası ve yükseltmenin reddettiği durumlar — işletme konusudur ve Netsim System Agent Kurulum ve Yönetim Kılavuzu belgesinin “Bakım ve yükseltme” bölümünde, örnek betikleriyle birlikte durur.

EXPORT LEVEL 3 | 4 TO '<dosya>' [MIN VERSION '<v>']

SET CATALOG kaynak_db;
EXPORT LEVEL 3 TO 'urun_5.2.0.1541.ivdpkg' MIN VERSION '5.1.1.1532';
EXPORT LEVEL 3 TO 'client:urun_5.2.0.1541.ivdpkg';   --// msql'in makinesine, çalışma dizinine

Hedef 'client:<yol>' ise paket sunucuda geçici bir dizinde üretilip istemciye gönderilir (msql yazar; var olan dosyanın üstüne yazmaz); aynı önek UPGRADE LEVEL … FROM'da paketi istemciden okur. Sonuç kümesinin son satırı PACKAGE | INFO olarak aktarılan bayt sayısını yazar.

Kaynağın o seviyedeki katalog satırlarını bir pakete yazar. Paketin içeriği motorun kendi kurduğu bir sqlite veritabanıdır: içinde taze seviye 1–2 kataloğu, kaynağın seviye 3 (ya da 4) nesnelerinin katalog satırları, o seviyenin ivd$upgrade komutları, tohum verisi ve kartın o seviyeye ait damgası bulunur. Seviyenin tabloları varsayılan olarak satırlarıyla birlikte pakete girer; bir tablo ATTRIBUTES ("ns.seed" = 'N') ile dışarıda kalır. Birincil anahtarı olmayan tablonun ve anahtarı GENERATED ALWAYS AS IDENTITY olan tablonun verisi taşınmaz (SKIPPED satırı). Satırı olmayan tablo pakette yer kaplamaz: yapısı zaten katalogla taşınır, rapor da boş tabloları ayrıca sayar.

Dosyanın biçimi önek + zip'tir. İlk 1024 bayt IVDPKG1 imzası ve tek satırlık bir JSON başlıktır; gerisi, tek girdisi package.sqlite olan bir zip arşividir. Başlık, sürüm denetimi için gereken her şeyi paketi açmadan verir: biçim numarası, ürün kodu, seviye, o seviyenin sürümü ve üretim damgası, kaynak veritabanının adı, katalog sürümü, üreten motorun sürümü, paketin üretim zamanı (UTC), açılmış ve sıkıştırılmış boyutlar ve açılmış içeriğin SHA-256 özeti — özet, paket her açıldığında doğrulanır. Zip'in kendi konumları mutlak olduğundan dosya, sıradan bir zip aracıyla da açılır.

MIN VERSION '<v>' paketin uygulanabileceği en eski hedef sürümünü başlığa yazar (minFromVersion). UPGRADE LEVEL, kartındaki damgası bundan eski olan — ya da damga taşımayan — hedefi hiçbir şey uygulamadan reddeder. Alt sınır paketin kendi seviye sürümünden yeni olamaz.

Paket saydam okunur: sqlite motoru Database Name değerinin önekli bir paket olduğunu tanır, içeriği geçici bir dosyaya açar ve onu açar. Böylece hem UPGRADE LEVEL … FROM hem de düz bir OPEN DATABASE … STORAGE ENGINE SQLITE paketi doğrudan okur; geçici dosya CLOSE'da silinir ve böyle bir veritabanı süreçler arasında paylaşılmaz (her süreç kendi kopyasını açar). Önekli olmayan bir dosya paket sayılmaz ve reddedilir — böyle bir dosyayı EXPORT LEVEL ile yeniden üretin.

Seviye 3 10.000.000 – 19.999.999, seviye 4 20.000.000 ve üstü kimlikleri kapsar. Bir nesnenin sahip şeması başka bir seviyede olabilir (müşterinin tablosu ürünün şemasında durabilir); paket o şemanın satırını ad çözümlemesi için taşır, ama karşılaştırmaya sokmaz — başka seviyenin şeması ne yaratılır ne düşürülür. Üst düzey deyimdir, ALTER DATABASE yetkisi ve ayrıcalıklı kimlik ister, deyim anında çalışır.

ALTER DATABASE <db> UPGRADE LEVEL 3 | 4 FROM '<dosya>' [PREVIEW | CONFIRMED] [ALLOW DOWNGRADE] [ADOPT CODE] [CONVERT TO SECURITY | CONVERT TO NORMAL] [TERMINATE SESSIONS]

Hedefin o seviyesini paketle karşılaştırır. Eşleme adla yapılır (sahip zinciri ve tür); nesne kimlikleri veritabanları arasında aynı değildir. Eylem listesi CREATE, DROP, ALTER (ayrıntıda neyin değiştiği), ATTRIBUTES, paketin bu hedefte çalışacak ivd$upgrade komutları (COMMAND), SUMMARY ve VERSION satırlarından oluşur. Komutlar etkin olanlardır, depo motoru kapısından geçenlerdir ve hedefin seviye 3 sürümü komutun sürüm aralığındaysa listelenir. PREVIEW ile hiçbir şey yazılmaz.

Hedefin sürümü yalnız kartından okunur. Yükseltme komutlarının sürüm penceresi, gerileme ve alt sınır denetimleri hedefin ivd$database kartındaki seviye damgasına dayanır; başka bir kaynaktan sürüm okunmaz ve tahmin edilmez. Kartında seviye 3 damgası olmayan hedefe UPGRADE LEVEL 3 uygulanmaz: önizleme VERSION satırını gösterir, uygulama reddedilir. Böyle bir veritabanının (örneğin ADOPT LEVEL 3 ile benimsenmiş ya da DROP LEVEL 3 ile boşaltılmış) damgası ALTER DATABASE ... SET LEVEL 3 VERSION '<v>' GENERATED '<zaman>' ile yazılır; benimseme damga yazmaz. Seviye 4'te damga yoksa yükseltme uygulanır ama hiçbir yükseltme komutu koşmaz (WARNING satırı). Paketin alt sınırı (EXPORT LEVEL ... MIN VERSION) varsa damgası ondan eski hedef MINIMUM satırıyla reddedilir.

Seviye 3 boşken seviye 4 yüklenmez. Katalogda seviye 3 bandından hiçbir nesne yoksa UPGRADE LEVEL 4 — PREVIEW dahil, paket dosyasına bakılmadan — reddedilir ve önce UPGRADE LEVEL 3 koşulması gerektiğini söyler: seviye 4 nesneleri seviye 3'e dayanır (tablolarına yabancı anahtar, yordamlarına çağrı). Ölçüt katalogdaki seviye 3 nesne sayısıdır, damga değil. ADOPT bu kapıya tabi değildir — paket yüklemez, depoda zaten duran tabloyu kataloğa yazar.

Kolon kaybının kapısı seviyeye göre değişir. Seviye 4 kullanıcının kendi nesnelerini taşır: kazayla düşürülen bir kolonun geri dönüşü olmadığı için orada açık onay istenir. Seviye 3 ürünün kataloğudur ve denetimden geçmeden yayınlanmaz, yani değişiklik zaten bilerek yapılmıştır; orada rapor uyarır ve koşu durmaz. Uyarı satırları önizlemede de görünür, yani uygulamadan önce okunabilir.

Yanlış ürünün paketi uygulanmaz. Kartta ürün kodu varsa (ivd$product) ve paketinki farklıysa yükseltme hiçbir şey uygulamadan durur — bu bir onay sorusu değil, yanlış dosyadır; geçiş yolu yoktur. Hedefte kod yoksa paketinki yazılır, pakette yoksa karşılaştırılacak bir şey olmaz. Önizleme reddedilmez, PRODUCT satırında iki kodu da gösterir.

Tabloları veritabanıyla örtüşmeyen seviye 3 paketi uygulanmaz. Ürün kodu aynı ürünün iki derlemesini ayırmaz: güvenlikli derleme tablolarını NS_ önekiyle kurar, normal derleme öneksiz. Veritabanı boş değilse (katalogda ya da depoda en az 20 ürün tablosu) ve paketin seviye 3 tablolarının yarısından azı veritabanında adıyla bulunuyorsa yükseltme hiçbir şey uygulamadan durur; geçiş yolu yoktur. Önizleme reddedilmez, MISMATCH satırında iki sayıyı gösterir. Seviye 4 paketleri ve boş veritabanı bu denetimin dışındadır.

Koşu boyunca veritabanı bakımdadır. ACTIVE bir veritabanı uygulama evresinin başında LEVEL3_UPDATE durumuna çekilir — o sırada yalnız sahibi, SYSDBA ve SYSADMIN üyeleri kullanabilir — ve koşu hatasız biterse ACTIVE'e döner. Seviye 3'te hata varsa orada bırakılır; anlamı zaten "seviye 3 yeniden üretilmeyi bekliyor"dur. Daha kısıtlı bir duruma (RESTRICTED, READ_ONLY, OFFLINE) dokunulmaz. Aynı veritabanında ikinci bir yükseltme başlatılamaz: koşan yükseltmenin süreci canlıysa ikincisi reddedilir.

Sürüm gerilemesi ALLOW DOWNGRADE ister. Paketin sürümü veritabanınınkinden eskiyse yükseltme uygulanmaz; önizleme reddedilmez, raporuna DOWNGRADE satırı düşer. Karşılaştırma yükseltilen seviyenin kendi damgasıyla, iki damga da doluyken yapılır; parça parça sayısaldır (harfler yok sayılır, 2.0.0-beta ile 2.0.0 eşit sayılır) ve eşit sürüm serbesttir. ALLOW DOWNGRADE ayrı bir cümleciktir: CONFIRMED veri kaybını onaylar, bu ise sürümün geriye gitmesini — biri ötekinin yerine geçmez.

Kod nesneleri tablolardan önce düşer, paketten yeniden kurulur. Uygulama evresinde tanımlar ve tablolar kataloğa alındıktan sonra o seviyenin katalogdaki bütün kod nesneleri (görünüm, yordam, işlev, tetikleyici) bağımlılık sırasıyla motorun DROP'uyla düşürülür — bu depodan da düşürür — ve tablo değişiklikleri ancak ondan sonra uygulanır; paketin kodu ardından temiz CREATE ile kurulur. Böylece depoda kalan eski kod, paketin kaldırdığı bir kolona bağlı olduğu için tablo değişikliğini engellemez. Düşürülemeyen bir paket nesnesi (örneğin seviye 4'te bir bağımlısı var) yerinde kalır, raporda KEPT satırıyla görünür ve paketin metniyle yeniden tanımlanır. Depoda olup katalogda olmayan kod nesneleri için ADOPT CODE karar verir: yazılmazsa (öndeğer) bunlar depodan doğrudan düşürülür (DROP satırı, ayrıntısı storage only; PREVIEW aynı satırları gösterir); yazılırsa önce kataloğa benimsenir, sonra katalogdakilerle birlikte düşürülür. Yalnız paketin nesne taşıdığı şemalara bakılır: hedefin başka şemalarındaki ve paketin boş açtığı şemalardaki (ürünün EKLENTI'si gibi) nesnelere dokunulmaz. Yordam ve işlev tek ad kümesidir (PostgreSQL'de tek çıkışlı yordam depoda işlev olarak durur). İşlevi tablonun şeması dışında duran bir tetikleyici, paketin tablosuna bağlı olsa da düşürülmez (KEPT satırı). Birbirini çağırdığı için depodan düşmeyen yordam, işlev ve tetikleyicilerin (Firebird) gövdesi bildirimleri korunarak boşaltılır (STUB satırı; seçilebilir yordam SUSPEND'i, işlev RETURN NULL'u korur) ve düşürme yeniden denenir; yine de düşmeyen (örneğin bir tablo kolonunun kullandığı işlev) benimsenip paketin metniyle yeniden tanımlanır. Paketin birbirini çağıran kodu da aynı yolla kurulur: önce boş gövdeli bildirimler, sonra tam metin.

Tek başına kullanım. Yükseltme her adımı kendi COMMIT'iyle uygular; koşu boyunca veritabanını başka oturum kullanmamalıdır. Kart durumu koşu boyunca LEVEL3_UPDATE'tir (yalnız sahip, SYSDBA ve SYSADMIN girer). Ayrıca: veritabanını kullanan başka bir IVEDI kullanıcı oturumu varsa 10 saniye beklenir, kalırsa yükseltme reddedilir. Depo yeni oturumlara kapatılır — PostgreSQL'de CONNECT yetkisi PUBLIC'ten ve depo kullanıcısı dışındaki rollerden geri alınır (süper kullanıcılar bağlanabilir; depo kullanıcısı veritabanının sahibi ya da süper kullanıcı değilse kapı kurulamaz ve rapora WARNING düşer), Firebird'de geçici bir ON CONNECT tetikleyicisi (IVD$UPGRADE_GATE) depo kullanıcısı ve SYSDBA dışındaki bağlantıyı reddeder. Depoya doğrudan bağlı açık oturumlar (uygulama, psql, isql; motorun kendi bağlantıları sayılmaz) 10 saniye beklenir; kalanlar TERMINATE SESSIONS yazılmışsa kapatılır, yazılmamışsa yükseltme reddedilir. Kapı koşu bitince — hata ya da ret dahil — açılır; süreç koşu ortasında çökerse kapı MASTER kaydında kalır ve ajan bir sonraki açılışta onu açar. Önizleme açık oturumları SESSION / WARNING satırları olarak listeler.

Depo karşılaştırması. UPGRADE LEVEL hedefin kataloğundaki seviye nesnelerini depodakilerle de karşılaştırır: tablolar ve kolonları, domain'ler, diziler, görünümler ve EXECUTION STORAGE veritabanında yordam, fonksiyon ve tablo tetikleyicileri. Katalogda olup depoda olmayan her biri önizlemede WARNING satırıdır. Yükseltme, paket adımlarından önce eksik kolonu katalog tanımıyla depoya ekler (öndeğeri sabitse mevcut satırlara yazılır); depoda olmayan bir tablo, domain, dizi ya da kod nesnesi pakette varsa onu yalnız katalogdan düşürür (katalogdaki bağımlılarıyla birlikte, depoya dokunmadan) ve paketin olağan adımları onu yeni nesne olarak depoyla birlikte kurar. Pakette olmayan eksik nesneye dokunulmaz. Depodaki kolon sırası katalogdakinden farklıysa (kolon depoya elle sona eklenmiş) WARNING yazılır; Firebird deposunda kolonlar kataloğun sırasına taşınır (PostgreSQL kolon sırasını değiştiremez). Katalogda bir domain'le tanımlı kolon depoda o domain'e bağlı değilse (elle tip değişikliği, adsız sistem domain'i) WARNING yazılır ve kolon domain'e bağlanır (Firebird ve PostgreSQL): boş değerler domain'in öndeğerini alır, PostgreSQL'de kolonun NOT NULL'u geri gelir; kolona bağlı kod nesneleri düşürülüp paketten yeniden kurulur. Depoda olup katalogda olmayan kolona dokunulmaz, paketin düşürdüğü nesneler karşılaştırılmaz. Veritabanı Metadata Operations=OFF ile açıksa ve paket yapıyı değiştiriyor ya da depo kataloğun gerisinde kalmışsa yükseltme reddedilir (önizlemede MISMATCH satırı): o seçenekle depo DDL'i gönderilmez, değişiklik yalnız kataloğa yazılırdı.

Güvenlik yapısı. Ürünün güvenlikli derlemesi tablolarını NS_X adıyla kurar ve her birinin üstüne X görünümünü koyar; normal derlemede X tablodur. Veritabanının hangisi olduğu kimlik kartındaki bayraktır: ALTER DATABASE <db> SET SECURITY ON | OFF (ivd$v_database.security). EXPORT LEVEL kaynağın bayrağını pakete yazar ve UPGRADE LEVEL paketin bayrağı hedefinkinden farklıysa uygulamayı reddeder (önizlemede MISMATCH satırı): güvenlikli paket normal veritabanına, normal paket güvenlikli veritabanına uygulanmaz. Bayrağı taşımayan eski bir pakette karşılaştırma yapılmaz, tablo örtüşmesi denetimi kalır. Normal bir veritabanını güvenlikliye çevirmenin yolu CONVERT TO SECURITY'dir: güvenlikli paket normal veritabanına uygulanır, her X tablosunun satırları (ortak kolonlar; NS_X'in ek güvenlik kolonları kendi öndeğerleriyle) NS_X'e kopyalanır, X tablosu düşer, X görünümü kurulur ve hatasız biterse kart SECURITY ON olur. Ters yön CONVERT TO NORMAL'dır: normal derlemenin paketi güvenlikli veritabanına uygulanır, X görünümü (pakette olmadığı için) kod adımında düşer, X tablosu kurulur, her NS_X tablosunun satırları (ortak kolonlar; NS_X'in ek güvenlik kolonları bırakılır) X'e kopyalanır, NS_X veri kaybı onayı istemeden düşer, komutlardaki $(NS_) boş açılır ve hatasız biterse kart SECURITY OFF olur. İkisi de yalnız seviye 3'te çalışır; birincisi yalnız normal hedefe güvenlikli paketle, ikincisi yalnız güvenlikli hedefe normal paketle. ivd$upgrade komutlarındaki (EXECUTE SQL, EXECUTE SQL FOR, OPEN SQL) $(NS_) ifadesi komut çalışmadan hemen önce açılır: güvenlikli hedefte (ve dönüşümde) NS_, normal hedefte boş; NATIVE_SQL sarmalının içi dahil. Paket metni $(NS_)'yi açılmadan taşır.

PREVIEW yazılmazsa, listenin ardından şema nesneleri uygulanır:

  1. Pakette olmayan kod nesneleri (görünüm, yordam, işlev, tetikleyici, paket, tip) ve değişecek bir tabloya — doğrudan ya da başka bir kod nesnesi üzerinden — bağımlı olanlar düşürülür.
  2. Pakette olup hedefte olmayan şemalar, diziler ve domainler kaynak metinleriyle kurulur. Değişmiş olanlar SKIPPED raporlanır.
  3. Tabloların tanımı paketteki nesneden üretilir: kolonlar (tip ya da domain, öndeğer, NOT NULL, kimlik), kısıtlar, öznitelikler. Tablolar eski aracın "bütün tablolar" sırasıyla, üç aralıkta işlenir: Table.Insert aralığında hedefte olmayan tablolar CREATE TABLE ile kurulur ve var olan bütün tabloların eksik kolonları eklenir (UPGRADE TABLE … WITH DEFAULTS ADD ONLY); Table.Update aralığında tip, NULL'luk, öndeğer, kısıt ve kolon sırası paketinkine getirilir (UPGRADE TABLE … WITH DEFAULTS; yalnız sırası farklı tablo da işlenir); Table.Delete aralığında pakette olmayan kolonlar düşürülür. Satır verisi korunur; her olay bir ve yalnız bir kez çalışır. Tablolar yabancı anahtar sırasıyla (hedef önce) işlenir; kurulmamış bir tabloya başvuran anahtar ikinci geçişte eklenir. Katalogda olmayan ama depoda aynı adla duran bir kolon (elle eklenmiş) düşürülmez, benimsenip paketin tipine çevrilir. Pakette olup katalogda olmayan bir tablo depoda duruyorsa önce benimsenir: yükseltme fiziksel şekli okur, ADOPT TABLE'ın yolundan kataloğa yazar (depoya DDL gitmez, kimlik seviyenin bandından gelir) ve farkı UPGRADE TABLE … WITH DEFAULTS ile uygular — satırlar korunur. Kataloğu DROP LEVEL ile boşaltılmış bir veritabanının seviyesi bu sayede tek deyimle, elle şema kurmadan ve ADOPT çağırmadan yeniden kurulur. Yalnızca paketin adını taşıdığı tablolar benimsenir; kataloğun hiç bilmediği bir tabloya dokunulmaz.
  4. İndeksler adla eşlenir: tanımı değişen düşürülüp yeniden kurulur, pakette olmayan düşürülür, yeni olan kurulur.
  5. Pakette olmayan seviye tabloları düşürülür. Satır taşıyan bir tablonun düşürülmesi CONFIRMED ister: boş tablo sessizce düşer, dolu olan önizlemede satır sayısıyla birlikte CONFIRM satırı olarak listelenir ve onaysız koşu reddedilir. Satır sayısı okunamayan tablo dolu sayılır.
  6. Kolon düzeyinde veri kaybı — değeri olan bir kolonun düşürülmesi, satırların sığmadığı bir daraltma ve NULL taşıyan bir kolona NOT NULL eklenmesi (boşluklar WITH DEFAULTS ile doldurulur) — seviye 4'te CONFIRMED ister, seviye 3'te yalnızca uyarı olarak raporlanır. Denetim satır sayar: boş tablo ve sığan veri sessizce geçer; yalnız sayısal daraltmada şema farkı yeterli sayılır. Satır sayısı okunamayan kolon riskli sayılır.
  7. Kod nesneleri paketteki kaynak metinleriyle, derlendikleri arama yolunda kurulur: yeni olanlar ve ilk adımda düşürülenler CREATE ile, değişmiş ya da geçersiz olanlar CREATE OR ALTER ile (kimlik, haklar ve öznitelikler korunur). Değişmeyenlere dokunulmaz. Birbirine bağlı nesneler, ilerleme durana kadar yinelenen turlarla sıralanır. Önizleme, hedefte geçersiz damgalı (IVD$VALID = 'N') seviye nesnelerini, katalogda saklanan ilk geçersizlik nedeniyle (IVD$INVALID_REASON) birlikte WARNING satırı olarak gösterir.
  8. Tohum verisi hedefte birincil anahtara göre birleştirilir: olmayan satır eklenir, hedefte fazla olan satıra dokunulmaz. Anahtarı identity olan bir tabloda satırlar açık anahtar değerleriyle geldiği için birleştirmeden sonra hedefin kimlik dizisi en büyük anahtarın bir üstüne çekilir (rapordaki SEED / SEQUENCE satırı) — yoksa ilk gerçek INSERT tohum satırıyla çakışırdı. Hedefte zaten bulunan satır güncellenmez; tablo ATTRIBUTES ("ns.seed.update" = 'Y') taşıyorsa paketteki değerlerle güncellenir. Paketin sahip olduğu satırları bir koşulla belirten tablo (ATTRIBUTES ("ns.seed.scope" = 'GUVENLIK_SINIF_NO < 0'), tablonun kolonlarıyla, nitelemesiz) o kapsamda hedefi pakete eşitler: olmayan satır eklenir, değeri farklı olan güncellenir (yalnız farklı olanlar), pakette olmayan silinir; kapsam dışındaki satırlara (müşterinin kayıtları) dokunulmaz. Silmeler yabancı anahtar sırasının tersiyle, eklemeler ebeveynden başlar. Rapor tablo başına eklenen / güncellenen / silinen satırı yazar; fark yoksa satır UNCHANGED'dır. Tetikleyiciler bu adımda kuruludur ama öndeğerde susturulur; tetikleyicilerinin çalışmasını isteyen tablo ATTRIBUTES ("ns.seed.triggers" = 'Y') yazar. Depoda koşan tetikleyiciler (PostgreSQL, Firebird) ürünün kendi kalıbıyla susar: motor bağlantıyı bakım kipine alır (SetUtilityMode(1)), tetikleyici gövdeleri de GetUtilityMode() <> 1 ile korunduğu için kendileri çekilir. Bu işlevleri taşımayan bir veritabanında ya da bakım kipine geçmeye yetkisi olmayan bir bağlantıda uyarı yazılır ve tetikleyiciler açık kalır.
  9. Açıklamalar (COMMENT ON), yerelleştirme satırları (FOR LOCALE) ve haklar da paketle taşınır: önizleme nesne başına DESCRIPTION, LOCALIZATION ve PRIVILEGES satırları verir, uygulama hedefteki karşılıklarını kaynağınkiyle değiştirir. Hak satırının alıcısı adla eşlenir; hedefte o adda bir kullanıcı ya da rol yoksa satır SKIPPED raporlanır, veren ise hedefin SYSTEM kullanıcısıdır.
  10. Hiç hata yoksa kaynağın seviye 3 damgası (sürüm ve üretim zamanı) birebir yazılır ve LEVEL3_UPDATE durumu kalkar.

Yeni nesneler seviyenin kimlik aralığından kimlik alır. Her deyim kendi COMMIT'iyle çalışır; bir nesnenin hatası ötekileri durdurmaz ve deyimin metniyle birlikte ERROR satırı olur. Son satır (APPLY) kaç deyimin uygulandığını ve kaç hata olduğunu verir.

Yükseltme komutları. Paketin ivd$upgrade satırları (bu seviye, etkin, bu depo motoru, hedefin eski sürümü aralıkta) adlarıyla eşleşen olayda, ivd$position sırasıyla çalışır. Olay adları <Nesne>.<Olay>.<Before|After> biçimindedir ve her olay kendi adımında bir kez çalışır:

OlayNe zaman
Upgrade.Run.BeforeHer şeyden önce
Privilege|Role|Generator|Exception|Function.Delete.Before/After, Trigger|View|Procedure|Function.Destroy.Before/AfterDüşürme pencereleri; kod nesneleri ön evrede düşürüldüğü için bu olaylar yalnız komutları için art arda çağrılır
Domain|Generator|Exception|Function.Insert|Update.Before/AfterYeni domain, dizi, istisna ve dış işlevlerin kurulmasının önünde ve ardında (bu sırayla)
Table.Insert|Update.BeforeTablolar kurulmadan / yükseltilmeden önce
Table.Insert.AfterYeni tablolar kurulduktan ve var olan bütün tabloların yeni kolonları eklendikten sonra; tip ve sıra henüz değişmedi, düşecek kolonlar hâlâ yerinde — bir alanı ikiye bölen ya da iki alanı birleştiren dönüştürücü eski ve yeni kolonu burada birlikte görür
Table.Update.AfterTip, NULL'luk, öndeğer, kısıt ve kolon sırası değiştikten sonra — düşecek kolonlar hâlâ yerinde
Index.Insert|Update|Delete.Before/Afterİndekslerin önünde ve ardında
Table.Delete.Before/AfterKolon ve tablo düşürmelerinin önünde ve ardında; eski kolondan yenisine veri göçü Table.Delete.Before'da yazılır
Domain.Delete.Before/AfterTablo düşürmelerinin ardından; pakette olmayan domainler düşürülmediği için yalnız komutları çalışır
Trigger|View|Procedure|Function.Insert|Update.Before/AfterKod nesnelerinin kurulmasının önünde ve ardında
Privilege.Update.Before/After, Upgrade.Run.AfterEn sonda, damgadan önce
EXECUTE SQL
ivd$data'daki SQL'i çalıştırır.
EXECUTE SQL FOR
ivd$data: 1) satırından sonra satırları veren bir SELECT, 2) satırından sonra her satır için çalışan SQL; %KOLON% o satırın değeriyle değiştirilir.
OPEN SQL
Sorguyu çalıştırır, satır sayısını raporlar.
MESSAGE, WARNING
Metni sonuç listesine yazar.
CONFIRM
Önizlemede listelenir. Paket etkin bir CONFIRM satırı taşıyorsa önizlemesiz yükseltme CONFIRMED yazılmadan reddedilir.

Bir komut hata verirse: ivd$abort_on_error = 'Y' ise yükseltme o noktada durur — o ana kadar yapılanlar kalır, sonraki adımlar çalışmaz, damga yazılmaz ve yükseltme düzeltme sonrası yeniden çalıştırılabilir; aksi halde hata bir WARNING satırı olur ve yükseltme sürer.

ivd$upgrade — yükseltme komutları

Şema farkının kendi başına çözemediği işler (kolon yeniden adlandırma, tablo birleştirme/ayırma, öndeğer atama) bu seviye 2 tablosunun satırlarıyla yazılır; satırlar seviye paketiyle taşınır.

KolonAnlamı
ivd$levelKomutun seviyesi: 3 ya da 4
ivd$event, ivd$positionKomutun bağlandığı yükseltme olayı ve olay içindeki sırası
ivd$commandEXECUTE SQL, EXECUTE SQL FOR, OPEN SQL, CONFIRM (önizlemede de çalışır), MESSAGE, WARNING
ivd$dataKomutun metni (IVEDI lehçesi). Depo motoruna göre ayrı satır yoktur: iki lehçede aynı işi yapan bir komut tek satırdır ve iki metni de NATIVE_SQL deyimiyle taşır — NATIVE_SQL(POSTGRESQL '…', FIREBIRD '…'). Metin verilmeyen bir depoda deyim sessizce boş geçer, hata vermez.
ivd$start_version, ivd$end_versionHedefin eski seviye 3 sürümü bu aralıktaysa çalışır: başlangıç dahil, bitiş hariç (start ≤ eski < end; bitiş, değişikliğin yapıldığı sürümdür). Noktalı parçalar sayı olarak karşılaştırılır. Damgasız hedefte bütün komutlar çalışır.
ivd$utility_modeKomutun deponun hangi utility mode'unda çalışacağı (ürünün SetUtilityMode / GetUtilityMode işlevleri): 0 Normal, 1 Bakım, 2 Dönüşüm, 3 Veri düzeltme, 4 Veri iyileştirme, 5 Geliştirici; boş ise kipe dokunulmaz. EXECUTE SQL, EXECUTE SQL FOR ve OPEN SQL bu kipte çalışır, komut bitince önceki kip geri yazılır; ürünün tetikleyicileri GetUtilityMode() <> n ile kendilerini çeker. Kip yalnız depo yürütmeli (Firebird, PostgreSQL) ve bu işlevleri taşıyan veritabanında vardır; kurulamazsa rapora uyarı düşer ve komut geçerli kipte çalışır.
ivd$abort_on_error, ivd$active, ivd$description, ivd$creation Hata davranışı, etkinlik, açıklama, satırın girildiği an

ADOPT TABLE <[şema.]ad> [LEVEL 3 | LEVEL 4]

Depoda var olan ama katalogda karşılığı olmayan bir tabloyu kataloğa alır; depoya dokunmaz. Seviye 4 kullanıcısı tabloyu depoda kendi aracıyla açar ve mevcut hâlini böyle IVEDI'ye tanıtır:

SET CATALOG urun_db;
SET SEARCH_PATH TO app;
ADOPT TABLE musteri_notu;             -- seviye 4 (öndeğer)
ADOPT TABLE fatura_ek LEVEL 3;        -- ürünün bandı: ayrıcalıklı kimlik ister

Depo motoru tablonun şeklini kendi kataloğundan okur; motor bundan kendi CREATE TABLE ve CREATE INDEX metnini üretir ve yalnız kataloğa yazar. Kolonlar, tipler, öndeğerler, NOT NULL, birincil anahtar, UNIQUE kısıtları, indeksler (azalan olanlar dahil) ve yabancı anahtarlar (ON UPDATE / ON DELETE eylemleriyle) alınır. Depodaki bir domain'e bağlı kolon, katalogda aynı adlı bir domain varsa onu, yoksa temel tipi kullanır. Kimlik istenen seviyenin aralığından verilir. Hedefi katalogda olmayan bir yabancı anahtar atlanır ve raporlanır: önce hedef benimsenmelidir. EXECUTION STORAGE kipinde deponun kendi değer ürettiği kolonlar kimlik kolonu olarak, CHECK kısıtları ve hesaplanan (COMPUTED BY / GENERATED ALWAYS AS) kolonlar ise ifadeleri NATIVE_SQL içinde korunarak alınır — ifade deponun kendi lehçesindedir ve oraya olduğu gibi geri gider. EXECUTION IVEDI kipinde bunlar atlanır ve SKIPPED satırıyla raporlanır (motor deponun ifadesini değerlendiremez). İfade ya da koşullu indeksler her iki kipte de atlanır. Sonunda motor, kataloğun bu tablo için hesapladığı fiziksel adın depodaki tabloyla aynı olduğunu doğrular; değilse benimseme geri alınır.

Depo motoruTablo nerede aranır
sqlite, FirebirdTablo adıyla (şemasız)
PostgreSQLIVEDI şemasının aynı adlı (küçük harf) ad alanında, yoksa varsayılan şemada
ODBC (PostgreSQL üzerinden)Bağlantının varsayılan şemasında

Üst düzey deyimdir, deyim anında çalışır ve COMMIT eder.

ADOPT PROCEDURE | FUNCTION | TRIGGER <ad> [LEVEL 3 | LEVEL 4]

Depoda var olan bir yordamı, işlevi ya da tetikleyiciyi kataloğa alır; depoya dokunmaz. İmza (parametreler, dönüş tipi, tetikleyicinin tablosu, olayı, konumu ve etkinliği, SQL SECURITY) deponun kataloğundan, gövde deponun sakladığı metinden gelir. Firebird deposunda Firebird 4 veya üstü gerekir (RDB$SQL_SECURITY); daha eski bir sürümde deyim bunu söyleyen bir hatayla reddedilir.

DepoOkunanlar
Firebirdyordam, işlev (PSQL), tetikleyici
PostgreSQL, ODBCplpgsql yordam ve işlevleri, tetikleyiciler; arama yolunun ilk şemasına ait ad alanından. Küme döndüren işlev (RETURNS TABLE) IVEDI'de RETURNS'lü yordamdır. Tetikleyicinin gövdesi bağlı olduğu işlevin gövdesidir; IVEDI'nin kurduğu <ad>_00000 / <ad>_trigger adları IVEDI adına ve konumuna geri çözülür. LANGUAGE SQL işlevleri ve eklentilere ait işlevler okunmaz.
sqliteyalnız tetikleyici (sqlite'ta yordam yoktur), CREATE TRIGGER metninden. WHEN koşulu ve UPDATE OF <kolonlar> IVEDI'de karşılıksızdır ve tetikleyicinin anlamını değiştirir; böyle bir tetikleyici adıyla reddedilir.

EXECUTION IVEDI kipindeki bir veritabanında (sqlite'ın öntanımlısı) tetikleyiciyi motor çalıştırır; depodaki fiziksel tetikleyici de yerinde kaldığı için ikisi birden tetiklenir. Benimseme bunu bir NOTE satırıyla bildirir: fiziksel tetikleyiciyi depodan kaldırın ya da EXECUTION STORAGE kullanın.

SET CATALOG urun_db;
ADOPT TABLE musteri;               -- gövdeler tablolara başvurur: önce tablolar
ADOPT PROCEDURE musteri_bakiye;
ADOPT FUNCTION tutar_yuvarla;
ADOPT TRIGGER musteri_bi LEVEL 3;

Gövde önce MQL olarak derlenir. Derlenirse nesne sıradan bir IVEDI nesnesidir: analiz edilir, başka lehçelere çevrilir. Derlenmezse — gövde Firebird'e özgü bir yapı kullanıyorsa (Firebird'ün kendi sistem tabloları, SET BIND gibi oturum deyimleri) — gövdenin tamamı deponun metni olarak saklanır:

CREATE PROCEDURE rol_var_mi (p_ad VARCHAR(50)) RETURNS (var_mi CHAR(1)) AS
NATIVE_SQL(FIREBIRD '
begin
  var_mi = ''H'';
  if (exists(select 1 from rdb$auth_mapping where rdb$map_name = :p_ad)) then
    var_mi = ''E'';
  suspend;
end')

Böyle bir nesne aynı depoya olduğu gibi geri kurulabilir, ama başka bir lehçeye çevrilemez ve ALTER DATABASE … VERIFY LEVEL onu bildirir. Rapor iki durumu ayırır: ADOPT (MQL olarak derlendi) ve ADOPT NATIVE (depo metni olarak saklandı; ayrıntı sütunu derlemenin neden düştüğünü söyler). İkisi de düşerse benimseme durur ve iki nedeni birden bildirir. Katalogda zaten bulunan bir nesne ikinci kez benimsenmez.

Paket içindeki yordamlar ve işlevler ile kısıtların kendi tetikleyicileri bu deyimin kapsamı dışındadır; dış işlevler (UDF) ADOPT EXTERNAL FUNCTION ile alınır.

ADOPT COLLATION | SEQUENCE | DOMAIN | EXTERNAL FUNCTION | EXCEPTION | VIEW <[şema.]ad> [LEVEL 3 | LEVEL 4]

Depodaki öteki nesne türlerini kataloğa alır; depoya dokunmaz. Tanım deponun kataloğundan okunur ve motorun kendi CREATE deyimiyle kataloğa yazılır. SEQUENCE yerine GENERATOR da yazılabilir. Adın son parçası depodaki ad, öncesi (varsa) IVEDI şemasıdır — yazılmazsa arama yolunun ilk şeması.

DepoOkunanlar
Firebirdharmanlama, dizi, domain, dış işlev (UDF), istisna, görünüm. Kimlik kolonunun üreteci tablonun parçasıdır, ayrıca okunmaz. Firebird'ün harmanlamaya kendiliğinden eklediği COLL-VERSION ve ICU-VERSION ögeleri alınmaz. Dizi (array) ve hesaplanan domain reddedilir.
PostgreSQL, ODBCICU harmanlaması, dizi, domain, görünüm; arama yolunun ilk şemasına ait ad alanından. Bir kolona bağlı dizi (serial, kimlik) ve eklentilere ait nesneler okunmaz. ICU yerel ayarının -u-ks-level1, -u-ks-level2, -kc-true, -ka-shifted ögeleri ACCENT INSENSITIVE, CASE INSENSITIVE, PAD SPACE olarak geri çözülür; başka bir öge ya da ICU dışı harmanlama reddedilir. Domain'in birden çok CHECK'i AND ile birleşir.
sqliteyalnız görünüm (sqlite'ta öteki türler yoktur), CREATE VIEW metninden.

Deponun ifadesi (domain'in CHECK'i, görünümün SELECT'i) önce MQL olarak derlenir. Derlenmezse EXECUTION STORAGE kipindeki bir veritabanında depo metniyle benimsenir — görünüm CREATE VIEW v (kolon tip, …) AS NATIVE_SQL(<depo> '…'), domain CHECK (NATIVE_SQL(<depo> '…' AS BOOLEAN)) olarak; rapor bunu ADOPT NATIVE diye ayırır. EXECUTION IVEDI kipinde ifadeyi motor değerlendireceği için böyle bir nesne adıyla reddedilir.

ADOPT COLLATION harman_ci;             -- domain ve kolonlar harmanlamaya başvurur: önce o
ADOPT SEQUENCE sq_fatura;
ADOPT DOMAIN d_tutar;
ADOPT EXTERNAL FUNCTION u_yuvarla;
ADOPT EXCEPTION e_kayit_yok;
ADOPT VIEW v_acik_fatura LEVEL 3;

Gövdenin tamamı depo metni: AS NATIVE_SQL(…)

Bir yordamın, işlevin ya da tetikleyicinin gövdesi AS'tan sonra tek bir NATIVE_SQL olabilir. Metin AS'tan sonraki her şeydir: bildirimler ve kendi BEGIN … END'i. Üretilen metinde çevresine blok yazılmaz. Motorun kendi koşusunda gövde hiçbir şey yapmaz — NATIVE_SQL deyiminin kuralı.

Yükseltme geçmişi: IVD$UPGRADE_HISTORY

Kataloğa ya da bir seviyeye dokunan her işlem bu tabloya bir satır yazar: ALTER DATABASE … UPGRADE (IVD$OPERATION = UPGRADE), UPGRADE LEVEL, DROP LEVEL ve ADOPT LEVEL. Önizleme yazmaz.

KolonNe tutar
ivd$operation, ivd$levelİşlem ve seviyesi (katalog yükseltmesinde seviye boştur)
ivd$started, ivd$finishedİşlemin başlangıcı ve bitişi (UTC) — kartın damgasındaki zaman kaynağın üretim zamanıdır, bu ise bu veritabanında ne zaman koşulduğu
ivd$loginÇalıştıran kimlik
ivd$packagePaket dosyası (UPGRADE'de yedek yolu)
ivd$from_version, ivd$to_versionÖnceki ve yeni sürüm; katalog yükseltmesinde katalog biçim numaraları
ivd$optionsVerilen onaylar ve seçenekler: CONFIRMED, ALLOW DOWNGRADE, ADOPT CODE, CONVERT TO SECURITY, CONVERT TO NORMAL
ivd$created, ivd$dropped, ivd$altered, ivd$errors Eylem sayıları ve hata sayısı
ivd$resultOK | ERROR | STOPPED
ivd$engine_versionİşlemi yapan motorun sürümü
ivd$reportRaporun tamamı (eylem satırları) standart bir ZIP dosyası olarak: ilk girdi upgrade-report.txt; işlemde hata satırı varsa ikinci girdi agent-log.txt işlemin başından bu yana ajan günlüğüne yazılanları (en çok son 4 MB) taşır. Kolonu indiren herhangi bir araç açabilir; SQL'den metne çevirmek için Metadata.UpgradeReportText(ivd$report), boyutu octet_length(ivd$report) verir
SELECT ivd$started, ivd$operation, ivd$level, ivd$from_version, ivd$to_version, ivd$result, ivd$login
  FROM sys.ivd$upgrade_history ORDER BY ivd$history_id DESC;

SELECT Metadata.UpgradeReportText(ivd$report)          -- bir koşunun raporunun tamamı
  FROM sys.ivd$upgrade_history WHERE ivd$history_id = 3;

Metadata.UpgradeReportText(<ikili>) arşivin ilk girdisini metin olarak verir; zip olmayan bir değere hata atar, boş değere boş döner. Genel amaçlı bir açıcı değildir — adı bu yüzden dardır. Kolonun kendisi indirilebilir: .zip olarak kaydedilen içerik her araçta açılır.

Geçmiş hedef veritabanının içindedir: veritabanı kopyalandığında geçmişi de gider. Satır bir izdir, işin kendisi değil — yazılamazsa işlem başarısız sayılmaz, günlüğe bir uyarı düşer.

ALTER DATABASE <db> DROP LEVEL 3 | 4 [PREVIEW]

O seviyenin katalog bilgisini siler ve depoya dokunmaz: tablolar, indeksler, satır verileri ve motorun dışında kurulmuş her şey olduğu gibi kalır. ADOPT'un tersidir — benimseme depodaki tabloyu kataloğa alır, bu komut katalogdan çıkarır. Ürünün katalog geçişini baştan koşturmak için kullanılır.

SET CATALOG urun_db;
ALTER DATABASE urun_db DROP LEVEL 4 PREVIEW;   -- ne silinecek, yazmadan
ALTER DATABASE urun_db DROP LEVEL 4;
ALTER DATABASE urun_db DROP LEVEL 3;

Kapsam kimlik aralığıdır: seviye 3 = 10.000.000 – 19.999.999, seviye 4 = 20.000.000 ve üstü. Ürünün şemaları da bu aralıktadır ve silinir. Seviye 4 nesnesi dururken seviye 3 silinmez; önce DROP LEVEL 4 koşulur (seviye 4 nesneleri seviye 3'e dayanabilir). Silinenler: IVD$OBJECTS ve nesneye bağlı bütün satırlar (kolonlar, öznitelikler, yerelleştirme, bağımlılıklar — iki yön de, haklar — nesne, alıcı ya da veren o aralıktaysa, indeks kolonları) ve o seviyenin ivd$upgrade komutları. Kartın o seviyeye ait damgası da temizlenir; seviye 3'te ayrıca ACTIVE bir veritabanı LEVEL3_UPDATE durumuna geçer — o durumun anlamı zaten "seviye 3 yeniden üretilmeyi bekliyor"dur. Seviye 4 silmek durumu değiştirmez.

Seviyenin bellekte yüklü nesneleri de ayrılır (raporda UNLOAD); aynı adlarla şema ve nesneler hemen yeniden kurulabilir. Seviye 3 silinince nesne kimlik dizisi 10.000.000'e döner (raporda SEQUENCE), yeniden kurulan seviye 3 nesneleri yine seviye 3 aralığında kimlik alır. Tablolar depoda kaldığından silinen seviyeyi depodan geri almak için şemayı kurup ALTER DATABASE … ADOPT LEVEL koşun.

ALTER DATABASE yetkisi ve ayrıcalıklı kimlik ister; üst düzey deyimdir.

ALTER DATABASE <db> VERIFY LEVEL 3 | 4 FOR <hedef>

O seviyenin nesnelerini hedef lehçeye çevirmeyi dener ve çeviremediklerini listeler. Hiçbir şey yazmaz, hiçbir şey çalıştırmaz: üretilen metin atılır, ölçülen şey üretimin başarısıdır. Hedef adları #MODE CONVERT TO ile aynıdır.

SET CATALOG urun_db;
ALTER DATABASE urun_db VERIFY LEVEL 3 FOR FIREBIRD;
ALTER DATABASE urun_db VERIFY LEVEL 4 FOR POSTGRESQL;

Çevrim katı kipte (STRICT) yapılır, yani yoruma indirilen işlevsel bir yapı da kusur sayılır. Cevap alışılmış eylem sonuç kümesidir: çevrilemeyen her nesne için bir FAILED satırı (nesne, tür, neden) ve sonda bir özet. Çevrilebilen nesneler rapora girmez.

Denenenler, nesnenin motorda duran deyimleridir: yordam / işlev / tetikleyici gövdesi, görünüm SELECT'i, kolon öndeğeri ve üretilen kolon ifadesi, CHECK ifadesi; ayrıca hedefte hiç karşılığı olmayan nesne türleri (özel durum, paket).

Önce COMMIT. Bir DDL'in nesne kimliği işlendiğinde kesinleşir; işlenmemiş DDL'i olan bir oturumda o nesneler seviyenin dışında görünür ve doğrulanmaz. Rapor bunu bir NOTE satırıyla sayısıyla birlikte söyler.

ALTER DATABASE yetkisi ve ayrıcalıklı kimlik ister; üst düzey deyimdir.

ALTER DATABASE <db> ADOPT LEVEL 3 | 4 [SCHEMA <şema>] [PREVIEW]

Kaynak şema arama yolundan alınmaz. Seviye 3 yalnız ürünün NETSIM şemasından benimser (SCHEMA başka bir ad verirse sözdizimi hatası). Seviye 4 SCHEMA ile verilen şemadan, verilmezse ürünün müşteri kodu için açtığı EKLENTI'den benimser; seviye 4 NETSIM'den benimseyemez. Şema katalogda bulunmalıdır, yoksa önce CREATE SCHEMA gerekir. Koşu boyunca arama yolunun başına bu şema konur; seviye 4'te hemen arkasına NETSIM gelir (müşteri kodu ürünün domain ve tablolarına başvurur), en sonda oturumun yolu kalır. Benimsenen nesneler kaynak şemaya kurulur.

Kaynak şemaya ait, depoda olup katalogda olmayan bütün nesneleri benimser (IVD$ ile başlayan motor nesneleri hariç): önce harmanlama, dizi, domain, dış işlev ve istisna (tablolar onlara başvurur), sonra tablolar, en son işlev, görünüm, yordam ve tetikleyici — bu sırayla. Tablolar yabancı anahtar sırasıyla alınır — hedef önce. Birbirine başvuran tabloların anahtarı DEFERRED raporlanır ve bütün tablolar alındıktan sonra yalnız kataloğa eklenir. Bir nesnenin hatası ötekileri durdurmaz (ERROR satırı). PREVIEW sırayı ve sayıyı verir, yazmaz. Ayrıcalıklı kimlik ister.

Kod nesnelerinin gövdesi ve görünümlerin SELECT'i önce MQL olarak derlenir. Derlenmeyen bir tanım hemen depo metnine düşmez: çoğu zaman yalnızca sırası gelmemiş, daha benimsenmemiş bir nesneye başvurduğu içindir. Bu yüzden bütün nesneler denendikten sonra yeniden denenir; ancak bir tur hiç ilerleme sağlamazsa kalanlar NATIVE_SQL gövdeyle benimsenir. Birbirini çağıran iki yordam bu yüzden depo metni olarak kalır.

UPGRADE TABLE <ad> [WITH DEFAULTS] [ADD ONLY] [RENAME [COLUMN] <eski> TO <yeni> {, …}] ( <CREATE TABLE gövdesi> ) [PREVIEW]

Tek bir tabloyu, CREATE TABLE yazımıyla verilen yeni tanımına getirir. Motor yeni tanımı canlı tabloyla kolon adına göre karşılaştırır ve farkı uygular; satır verisi korunur. NOT NULL ve DEFAULT etkin değerleriyle karşılaştırılır: kolonun kendisininki, yoksa domain'ininki. Domain'i NOT NULL DEFAULT 'G' olan bir kolonu gövdede yalnız domain adıyla yazmak, canlı tabloda kolonun kendi NOT NULL DEFAULT 'G''si olsa da değişiklik sayılmaz; gövdedeki kolonun kendi öndeğeri farklıysa SET DEFAULT, öndeğeri yoksa ve canlı kolonun kendi öndeğeri varsa DROP DEFAULT (domain'inki görünür) uygulanır.

RENAME COLUMN <eski> TO <yeni>, gövdedeki <yeni> kolonunun canlı tablodaki <eski> kolon olduğunu söyler. Bu olmadan adla karşılaştırma yeniden adlandırmayı "eskisini düşür, yenisini ekle" diye görür ve veri kaybolur. Kolonun tip, öndeğer ve NULL'luk farkları eski kolon üzerinden uygulanır, ad en sonda değişir. Eski adı anan bir kısıt imzasıyla eşleşmez: düşer ve yeni adla yeniden eklenir. Bir kolon en çok bir kez yeniden adlandırılabilir ve hedef ad tabloda bulunmamalıdır.

UPGRADE TABLE musteri WITH DEFAULTS (
  id integer not null,
  ad varchar(80) not null,                        -- NULL'lar '' olur (WITH DEFAULTS)
  kod varchar(10) not null upgrade default 'YOK', -- bu kolonun NULL'ları 'YOK' olur
  bakiye numeric(15,2) default 0 not null,        -- tip değişir, NULL'lar DEFAULT'tan 0 alır
  yeni integer not null,                          -- yeni kolon, var olan satırlarda 0
  constraint musteri_pk primary key (id),
  constraint musteri_kod_uq unique (kod),
  check (bakiye >= 0)
);
Kolonlar
Tanımda olup tabloda olmayan kolon eklenir, tabloda olup tanımda olmayan düşürülür, tipi değişenin değerleri yeni tipe dönüştürülerek taşınır, öndeğer ve NULL'luk tanıma getirilir, kolon öznitelikleri birleştirilir. Kolon sırası tanımın sırasıdır (yalnız sıra farkı da bir değişikliktir): sıra katalogda kolon satırının ivd$objects.ivd$position değerinde (0'dan başlar) saklanır — kataloğu doğrudan okuyan istemci kolonları buna göre dizer; değeri boş olan eski satırlarda sıra nesne kimliği sırasıdır. Firebird deposunda kolonlar yerine taşınır (ALTER COLUMN … POSITION), sqlite tabloyu yeni sırayla kurar; PostgreSQL kolon sırasını değiştiremez, orada sıra yalnız kataloğa yazılır. IDENTITY ya da GENERATED kolon eklenemez ve değiştirilemez. RENAME COLUMN ile bildirilmeyen bir ad değişikliği yeniden adlandırma sayılmaz: yeni adla yazılan kolon eklenir, eski ad düşürülür.
ADD ONLY
Yalnız tanımda olup tabloda olmayan kolonlar eklenir (doldurma kuralları aynı); düşürme, tip / öndeğer / NULL'luk, sıra, kısıt ve öznitelik farklarına dokunulmaz. UPGRADE LEVEL var olan tablolara kolonları Table.Insert aralığında bununla ekler.
Kısıtlar
Adlı kısıt adıyla, adsız kısıt içeriğiyle (tür, kolonlar, yabancı anahtarda hedef tablo, hedef kolonlar ve eylemler) eşlenir. İçeriği değişen düşürülüp yeniden eklenir, tanımda olmayan düşürülür. İndeksler CREATE TABLE'ın parçası olmadığı için dokunulmaz.
UPGRADE DEFAULT <ifade>
Kolonun sonuna yazılır. Yalnız bu yükseltmede o kolonun NULL değerlerini ifadenin değeriyle doldurur; yeni kolonda var olan satırların değeri olur. Kalıcı bir DEFAULT değildir.
WITH DEFAULTS
NOT NULL olan her kolonun NULL değerlerini doldurur. Değer sırasıyla kolonun UPGRADE DEFAULT'u, yeni tanımdaki kolonun ya da domain'inin DEFAULT'u (LOCALTIMESTAMP gibi bir ifade de olabilir; ifade doldurma sırasında hesaplanır), tipin sıfır değeridir (sayı 0, metin '', mantıksal false). DEFAULT'u olmayan ve sıfır değeri olmayan bir tipte (tarih gibi) kolona UPGRADE DEFAULT yazılmalıdır.
Tetikleyiciler
Doldurma yükseltmenin kendi yazımıdır: tablonun tetikleyicileri çalışmaz.
Doldurma yoksa
NULL satırı olan bir kolonun NOT NULL'a geçişi NOT_NULL_VIOLATION ile reddedilir ve değişiklik geri alınır.
PREVIEW
Hiçbir şey yazmaz; eylem listesini (OBJECT_NAME, OBJECT_KIND, ACTION, DETAIL) döndürür. Eylemler: kolon için ADD, DROP, ALTER, FILL, ATTRIBUTES; kısıt için ADD, DROP; sonda SUMMARY.

Üst düzey deyimdir; ALTER TABLE yetkisi ister. ALTER TABLE gibi çağıranın transaction'ında çalışır ve COMMIT etmez. Firebird'de DDL COMMIT'e ertelendiği için yeni kısıtlar eklenmeden önce COMMIT edilir; NOT NULL reddi de orada COMMIT anında gelir. Var olan kolonların NULL doldurması bir UPDATE ile yapılır, dolayısıyla tablonun satır tetikleyicileri çalışır.

6.9.10 IVD$V_* sistem görünümleri

Her veritabanı, kataloğunu motordan bağımsız okumaya yarayan on sistem görünümüyle doğar. Bunlar seviye 2 nesnelerdir (kimlikleri 6001–6010), önyükleme betiğinden kurulurlar, herkese okunur, yazılamaz ve yalnız seviye 3 ile 4 nesnelerini gösterirler — motorun kendi katalog nesneleri ve yerleşik paketlerin iç nesneleri bu yüzeyin dışındadır.

GörünümNe verir
IVD$V_TABLESTablolar ve görünümler; açıklama, GUID ve ns.* / sec.* / web.* / doc.* öznitelikleri
IVD$V_COLUMNSKolonlar; tip ölçüleri, öndeğer metni, etkin açıklama ve öznitelikler (kolon > kaynak kolon > ad kuralı > domain), kolonun kendi değerleri (OWN_DESCRIPTION, OWN_DOC_SUMMARY) ve görünüm kolonunun kaynağı (BASE_TABLE, BASE_COLUMN, BASE_ALIAS)
IVD$V_DOMAINSDomainler ve öznitelikleri
IVD$V_PROCEDURESYordamlar, işlevler ve tetikleyiciler; kaynak metni, geçerlilik
IVD$V_RELATIONSKısıtlar ve başvurdukları nesneler (yabancı anahtar hedefleri)
IVD$V_INDEXESİndeksler ve anahtar kısıtları (PRIMARY KEY, UNIQUE, FOREIGN KEY) tek listede: tekil / azalan / etkin bayrakları, anahtar kolon sayısı
IVD$V_INDEX_COLUMNSİndeks ve anahtar kısıtı kolonları, kolon başına bir satır (IVD$INDEX_COLUMNS katalog tablosu); yabancı anahtarın başvurduğu kolonlar KEY_ROLE = 'R', ifade indeksinde ifade metni EXPRESSION
IVD$V_OBJECTSHer nesne bir satır: sahibinin adı ve türü, temel nesnesi (kolonun / parametrenin tipi — domain ya da yerleşik tip), konumu, kaynağı, açıklaması, geçerliliği
IVD$V_DEPENDENCIESBağımlılıklar: nesne ve kullandığı nesne, ikisinin adı ve türüyle (bir kolonu okuyan yordamın hem kolon hem tablo satırı vardır); ACCESS_MODE W: kod kolonu yazar (INSERT listesi, UPDATE / MERGE SET, tetikleyicide NEW.<kolon> = …), R: yalnız okur
IVD$V_ATTRIBUTESBütün öznitelik satırları, koşul metniyle birlikte
IVD$V_LOCALIZATIONCOMMENT ON … FOR LOCALE ile yazılmış dil sürümleri
IVD$V_DATABASEKimlik kartının tek satırı: katalog sürümü ve özeti, depo motoru, karttaki durum, ürün kodu, seviye 3 ve seviye 4 damgaları, çalışma kipi, güvenlik bayrağı

IVD$V_ATTRIBUTES ile öteki görünümlerin farkı önemlidir: bir öznitelik birden çok satır taşıyabilir (her birinin kendi koşulu vardır, FILTER_TEXT). Öteki görünümlerin öznitelik kolonları yalnız koşulsuz taban satırı verir; koşullu değerlendirme için IVD$V_ATTRIBUTES okunur ya da METADATA.ATTRIBUTE(nesne, ad) USING (…) çağrılır (en özgül eşleşen koşul kazanır).

Depoda da vardırlar. EXECUTION STORAGE kipindeki bir Firebird ya da PostgreSQL veritabanında motor bu görünümleri depoya da kurar ve PUBLIC'e SELECT hakkı verir; depoya doğrudan bağlanan bir okuyucu (Netsim.WEB, ajanın /crud/METADATA?source=ivd ucu, MCP ivd__ araçları) onları sıradan görünüm gibi sorgular. Katalog kurulurken ve her ALTER DATABASE … UPGRADE / UPGRADE LEVEL sonunda yenilenirler (rapor satırı CATALOG VIEWS). Böyle bir veritabanında motor da bu görünümleri depodaki kopyalarından okur: sorgunun koşulu ve okuduğu kolonlar depoya gider. Görünümler yalnız depoda olan bilgiyi gösterir; IVD$V_DATABASE.STATE karttaki durumdur. Veritabanının canlı durumu (yükseltme bekleyen katalogda UPGRADING) ve yükseltme nedeni IVD_DATABASE_STATE(guid) / IVD_UPGRADE_REASON(guid) işlevleriyle okunur:

SELECT IVD_DATABASE_STATE(ivd$database_guid), IVD_UPGRADE_REASON(ivd$database_guid)
  FROM sys.ivd$database;

6.9.11 Katalog sürümü ve ALTER DATABASE … UPGRADE

Kart katalog biçim sürümünü (ivd$catalog_version; değeri 23) ve meta betiklerinin özetini (ivd$catalog_hash) taşır. OPEN DATABASE kartı kullanıcı nesnelerini yüklemeden önce okur. Kart yoksa ("damgasız" katalog), sürüm ya da özet motorunkinden farklıysa ya da önceki yükseltme yarım kaldıysa veritabanı "yükseltme bekliyor" durumunda açılır: kullanıcı nesneleri yüklenmez, yalnız SYSDBA açabilir, bir uyarı verilir ve orada yalnız yükseltme komutu çalışır. Daha yeni bir sürüm ve yarım kalmış yaratılış reddedilir.

OPEN DATABASE eski_db STORAGE ENGINE sqlite PARAMETERS 'Database Name=eski.db';
SET CATALOG eski_db;
ALTER DATABASE eski_db UPGRADE PREVIEW;                 -- ne yapılacağını listeler, yazmaz
ALTER DATABASE eski_db UPGRADE BACKUP TO 'eski.bak.db'; -- önce yedek, sonra yükseltme
-- kısayol: OPEN DATABASE ... UPGRADE

İkisi de OBJECT_NAME, OBJECT_KIND, ACTION, DETAIL kolonlu bir sonuç kümesi döndürür; güncel bir katalogda küme boştur. Yükseltme:

  • Fiziksel yapı — bütün sistem tabloları (katalog ve sistem uygulama tabloları): motor tanımı kendi DDL'iyle geçici bir referans alanında kurar ve depodakiyle aynı okuyucudan geçirir. Kolon tipi, uzunluk, NULL, DEFAULT, birincil/tekil/yabancı anahtar, CHECK ve indeksler karşılaştırılır. Eksik olan kurulur, farklı olan değiştirilir; motor tanımında olmayan kolon, indeks, kısıt ve IVD$ tablosu düşürülür (katalogda kullanıcı tablosu olarak kayıtlı olan hariç). Kimlik dizileri kurulur ya da en büyük kimliğin üstüne çekilir.
  • Sistem satırları — sürüm/özet farklıysa sistem nesnelerinin katalog satırları (kimlik 1..9.999.999) güncel kaynaktan yeniden yazılır: kartı güncel MASTER ya da geçici bir bellek veritabanı.
  • Kullanıcı nesneleri — bekleyen açılışta yüklenir; yüklenemeyen kod nesnesi IVD$SOURCE'tan derlenir, olmazsa IVD$VALID = 'N' olur. Yüklenen kullanıcı nesnelerine dokunulmaz.
  • Kart yeni sürüme, özete ve önceki durumuna döner.
Not

Yükseltme veritabanını tek başına ister: başka bir bağlantı o veritabanındaysa reddedilir. Yükseltme bir işlem değildir (Firebird'ün DDL'i işlemsel değildir); yarıda kalırsa kart UPGRADING kalır ve komut yeniden çalıştırılır. Sınama modülü: sqltest/ddl/test28-open_database.sql.

BACKUP TO '<yol>' yedeği yükseltmeden önce alır; yedek alınamazsa yükseltme hiç başlamaz. Depoya göre: sqlite VACUUM INTO (dosya ajanın makinesinde); Firebird sunucunun Services API'si ile gbak (yedek sunucunun dosya sisteminde yazılır, uzak sunucuda da çalışır, araç yolu gerekmez; gbak'ın satırları DEBUG1 günlüğüne düşer); PostgreSQL pg_dump -Fc (dosya ajanın makinesinde; pg_dump conf backupTools.pgBinDir'den, yoksa libpq'nun dizininden, Windows'ta PostgreSQL kurulum kaydından, en son PATH'ten bulunur; parola komut satırına değil ortama gider). Var olan dosya her depoda reddedilir; bellek, EMR ve ODBC motorlarında seçenek desteklenmez. Sınama modülü: sqltest/ddl/test43-backup.sql.

Standart yedek döngüsü

ALTER DATABASE urun_db UPGRADE BACKUP CYCLE;
ALTER DATABASE urun_db UPGRADE LEVEL 3 FROM 'urun.xnsdbs' CONFIRMED TERMINATE SESSIONS BACKUP CYCLE;
ALTER DATABASE urun_db BACKUP CYCLE STATUS;     -- yarım kalan döngünün durumu
ALTER DATABASE urun_db BACKUP CYCLE CONTINUE;   -- kaldığı adımdan sürdür
ALTER DATABASE urun_db BACKUP CYCLE ROLLBACK;   -- döngü öncesi hâle dön

BACKUP CYCLE yükseltmeyi veritabanının kopyasında yapar (PREVIEW ile yazılmaz): 1) önceki urun_db_yedek1 ve artık urun_db_yedek0 silinir — yalnız urun_db varken; 2) oturumlar kapatılır (IVEDI oturumlarına 10 saniye, depo oturumları sonlandırılır) ve veritabanı MASTER kaydı korunarak ayrılır — depodaki öteki bağlantılar, başka bir ajanınkiler dahil, kapatılır; yalnız bu ajanın kendi süreçleri boşaltmayla bırakılır; 3) urun_db urun_db_yedek1 adını alır (dosya yine de açık kalıp adlandırma düşerse döngü kendiliğinden geri alınır, hiçbir şey değişmez); 4) ondan urun_db_yedek0 kopyası üretilir; 5) kayıt kopyayı gösterir ve yükseltme kopyada koşar; 6) başarılıysa kopya, başarısızsa urun_db_yedek1 yeniden urun_db olur. Depoya göre: sqlite ve Firebird ajanın makinesindeki dosya üzerinde (uzak Firebird sunucusunda döngü reddedilir), PostgreSQL sunucuda (ALTER DATABASE … RENAME, CREATE DATABASE … TEMPLATE; sahip, haklar ve veritabanı düzeyindeki ayarlar kopyaya taşınır).

Adım, koşan süreç, son bilgi ve sonuç MASTER'daki kaydın BACKUP CYCLE … özniteliklerinde tutulur; STATUS bunları STEP, RUNNING (Y = döngü bir süreçte koşuyor), INFO, RESULT, LAST satırlarıyla verir. Bağlantı koparsa koşu sürer; süreç çökerse ya da durdurulursa CONTINUE kaldığı adımdan sürdürür, ROLLBACK önceki hâli (urun_db_yedek1) geri koyar. Üç komut da MASTER'dan (her güncel veritabanından) çalışır; döngü yarımken veritabanı yalnız döngünün kendisi için açılır, öteki açılışlar reddedilir. Döngü yarımken yeni döngü başlatılamaz.