Rozdział 5

Obiektowe własności PostgreSQL

5.1  Dziedziczenie

W PostgreSQL tabela może dziedziczyć również z kilku tabel. Struktura dziedziczenia nie może jednak zawierać cykli.

5.2  Definiowanie typów

W PostgreSQL można definiować typy w sposób zbliżony do SQL3. Definicja ma postać:

  CREATE TYPE typ AS OBJECT (
  lista atrybutów i metod
  );

Używając jej możemy zdefiniować typ dla punktów:

CREATE TYPE punkt_t AS OBJECT (
  x NUMERIC,
  y NUMERIC
);

Po zdefiniowaniu typu obiektowego używa się podobnie jak typów standardowych, np. możemy teraz zdefiniować typ dla odcinków:

CREATE TYPE odcinek_t AS OBJECT (
  początek punkt_t,
  koniec   punkt_t
);

Możemy teraz utworzyć tabelę zawierającą odcinki wraz z ich identyfikatorami (ID):

CREATE TABLE Odcinki (
  ID      INT,
  odcinek odcinek_t
);

Typy usuwamy poleceniem DROP:

  DROP TYPE odcinek_t;

Przed usunięciem typu trzeba jednak oczywiście usunąć wszystkie tabele oraz inne typy, które używają danego typu a type, więc powyższe polecenie zakończy się niepowodzeniem. Trzeba najpierw usunąć tabelę Odcinki.

Typów zdefiniowanych można również używać bezpośrednio de definiowania tabel (odpowiednik ,,rowtype'' z SQL3). W poleceniu CREATE TABLE można zastąpić listę kolumn słowem kluczowym OF i nazwą typu, np.

  CREATE TABLE Odcinki OF odcinek_t;

5.2.1  Tworzenie obiektów zdefiniowanego typu

PostgreSQL dla każdego definiowanego typu tworzy automatycznie funkcję konstruktora o tej samej nazwie. Obiekt typu punkt_t tworzy się wywołując funkcję odcinek_t od (podanej w nawiasach) listy wartości atrybutów, np.

  INSERT INTO Odcinki
  VALUES(27, odcinek_t(punkt_t(0.0, 0.0),
                       punkt_t(3.0, 4.0)));

5.3  Zapytania ze zdefiniowanymi typami

Dostęp do składowych obiektu uzyskuje się używając notacji kropkowej. Jeśli O jest pewnym obiektem typu T, którego jedną ze składowych (atrybutów lub metod) jest A, to O.A odnosi się do tej składowej w obiekcie O.

Możemy wyszukać współrzędne początków owszystkich odcinków

  SELECT o.odcinek.początek.x, o.odcinek.początek.y
  FROM Odcinki o;

Użycie aliasu jest w takich sytuacjach obowiązkowe. Zapytanie

  SELECT o.odcinek.koniec
  FROM Odcinki o;

wyszuka końce wszystkich odcinków (wypisując je ewentualnie jako wywołania konstruktora.

5.4  Odwołania do obiektów (referencje)

Dla typu t wyrażenie REF t oznacza jego typ referencyjny (,,ID obiektu''). Można go używać w definicjach kolumn:

  CREATE TABLE Odcinki (
    początek REF punkt_t,
    koniec   REF punkt_t
  );

Używając takiego typu trzeba pamiętać o pewnych ograniczeniach. Konkretne referencje muszą odnosić się do wierszy tabeli podanego typu. Na przykład dla tabeli

  CREATE TABLE Punkty OF punkt_t;

możemy umieścić w tabeli Odcinki referencje do wierszy z tej tabeli:

  INSERT INTO Odcinki
  SELECT REF(pp), REF(qq)
  FROM Points pp, Points qq
  WHERE pp.x < qq.x;

Referencje nie mogą natomiast odnosić się do obiektów występujących w kolumnach innych tabel, ani nie mogą być tworzone ad hoc (np. umieszczając w poleceniu INSERT klauzulę VALUES(REF(puntk_t(1,2)), REF(punkt_t(3,4)))).

Przechodzenie po referencji zapisuje się używając notacji kropkowej, np. poniższe zapytanie podaje współrzędne x początków i końców wszystkich odcinków w tabeli Odcinki.

  SELECT ll.początek.x, ll.koniec.x
  FROM Lines2 ll;

5.5  Tablice

W Postgresie jako typów kolumn można używać typów tablicowych. Wartością atrybutu może być wtedy cała tablica, tak jak dla kolumny b poniżej.

a b
-
- - -
- - -
-
- - -
- - -
-
- - -
- - -

Aby było to możliwe, należy najpierw zdefiniować relację jako typ, używając frazy AS TABLE OF, np.

  CREATE TYPE wielobok_t AS TABLE OF punkt_t;

definiuje typ wielobok_t jako relację, której krotki są typu punkt_t, tzn. mają dwa atrybuty x i y.

Teraz można zdefiniować relację, w której jedna z kolumn będzie reprezentowała wieloboki, tzn. zbiory punktów, np.

  CREATE TABLE Wieloboki (
    nazwa VARCHAR2(20),
    punkty wielobok_t)
  NESTED TABLE punkty STORE AS TabPunkty;

Relacje odpowiadające poszczególnym wielobokom nie są zapisywane bezpośrednio jako wartości atrybutu punkty, lecz trzyma się je w pojedynczej tabeli, której nazwę należy zadeklarować. Do tabeli tej nie można się odwoływać bezpośrednio.

Przy wstawianiu wierszy do relacji Wieloboki używa się konstruktora typu dla zagnieżdżonej relacji (wielobok_t). Wartość zagnieżdżonej relacji podaje się w nim jako rozdzielaną przecinkami listę wartości odpowiedniego typu (punkt_t), najczęściej także używając konstruktora.

  INSERT INTO Wieloboki
  VALUES('kwadrat',
         wielobok_t(punkt_t(0.0, 0.0), punkt_t(0.0, 1.0),
                    punkt_t(1.0, 0.0), punkt_t(1.0, 1.0)));

Punkty tego kwadratu podaje poniższe zapytanie:

  SELECT punkty
  FROM Wieloboki
  WHERE nazwa = 'kwadrat';