Marcin Chyłek Blog

pgAdmin v1.10.0 released

Została wydana stabilna oznaczona numerem v1.10.0 wersja pgAdmina. Pojawiły sie nowe bajery jak np. “graphical query builder” i lepsza obsługa PostgreSQL 8.4.

Kilka screenów prezentujących nowe funkcjonalności nowego PgAdmina.

visualtour01

Graphical query builder - budowanie zapytań za pomocą myszy.

visualtour02

pgScript scripting framework.

visualtour04

Wsparcie dla obiektów FTS.

visualtour41

Tryb edycji i wykonania SQL z poziomu edycji tabeli.

Więcej informacji: http://www.pgadmin.org/visualtour.php

Kategoria: PHP, PostgreSQL | Marcin Chyłek | Komentarze: 1

Symfony, Propel, PostgreSQL - Multi database (obsługa wielu baz danych w aplikacji)

W aplikacjach internetowych czasami musimy wykorzystać w jednym serwisie wiele baz danych, nieraz nawet wiele różnych baz danych. Mój wpis będzie prezentował proste przykłady użycia wielu baz z wykorzystaniem frameworka Symfony. Dla przykładu użyje bazy danych PostgreSQL oraz ORM Propela 1.3.

W przykładzie wykorzystam 2 tabele: “users” z bazy “db1″ (załóżmy, że to główna bazy serwisu z użytkownikami) i “requests” z bazy “db2″ (baza w której zapisywane są statystyki z żądań do aplikacji). Modele wygenerowane będą dla bazy PostgreSQL. W kolejnym etapie zaprezentuje w jaki sposób można załadować przykładowe dane pochodzące z data/fixtures.

Definiowanie baz w pliku databases.yml

Edytujemy config/databases.yml

all:
  propel:
    class:        sfPropelDatabase
    param:
      classname:  PropelPDO
      dsn:        pgsql:dbname=db1;host=panic user=db1 password=db1
      hostspec:   pgsql
      port:       5432
      encoding:   utf8

  stat:
    class:        sfPropelDatabase
    param:
      classname:  PropelPDO
      dsn:        pgsql:dbname=db2;host=panic user=db2 password=db2
      hostspec:   pgsql
      port:       5432
      encoding:   utf8

Pierwszym krokiem jest zdefiniowanie połączeń do baz danych. Główną nazwę połączenia będzie “propel” a drugą “stat”

Ustawienie pliku propel.ini

propel.database        = pgsql
propel.database.driver = pgsql
propel.database.url    = pgsql:dbname=db1;host=panic user=db1 password=db1

W pliku propel.ini ustawiamy połączenie z główną bazę danych. “propel.database” odpowiada za generowanie kodu SQL dla danych baz, np.: MySQL, PostgreSQL, Oracle. Jeśli chcemy generować SQL dla wybranego typu bazy, to musimy zmienić na odpowiednią wartość. Można to uzyskać z linii koment ustawiajac –phing-arg

Przykład dla MySQLa:

./symfony propel:build-all --no-confirmation --connection=stat --phing-arg="Dpropel.database=mysql"

Przykład dla Oracle:

./symfony propel:build-all --no-confirmation --connection=stat --phing-arg="Dpropel.database=oracle"

Definiowanie tabel w config/schema.yml

Jak w przykładzie z optymalizacją Propela dobrym nawykiem jest rozdzielenie różnego typu struktur na osobne pliki schema.yml. Główną definicja tabel można zapisać w pliku schema.yml a dodatkową strukturę bazy w osobnym pliku, np w pliku stat_schema.yml.

Plik config/schema.yml

propel:
  users:
    id:              { type: integer, required: true, primaryKey: true, autoincrement: true }
    created_at:      { type: timestamp }
    name:            { type: varchar, size: 255 }
    surname:         { type: varchar, size: 255 }

Plik config/stat_schema.yml

stat:
  _attributes:       { package: lib.stat_model }
  requests:
    id:              { type: integer, required: true, primaryKey: true, autoincrement: true }
    created_at:      { type: timestamp }
    module:          { type: varchar, size: 255 }
    action:          { type: varchar, size: 255 }

W pliku stat_schema.yml, użyłem package: lib.stat_model – czyli miejsce, w którym zostaną wygenerowane modele wykorzystujące bazę “db2″, lib.stat_model = lib/stat_model.

Po zdefiniowaniu struktur i baz przechodzimy do generowania modeli i stworzenia struktur tabel w bazach danych.

Generowanie modeli i struktur baz danych dla “db1″ i “db2″

./symfony propel:build-all --no-confirmation

Modele dla baz danych zostały wygenerowane. Struktura tabel została stworzona tylko w pierwszej bazie “db1″ - ponieważ to połączenie jest domyślne. Aby stworzyć strukturę tabel w bazie “db2″ musimy wymusić połączenie z bazą “db2″ (czyli połączenie o nazwie “stat”).

./symfony propel:build-all --no-confirmation –connection=stat

Przykład wykorzystania modeli

Przykłady:

$obj1 = UsersPeer::retrieveByPK(1);

$obj2 = RequestsPeer::retrieveByPK(1);

Wykorzystując model nie musimy podawać połączenia, chyba że chcemy aby dany model był wykorzystany jawnie do “innej” bazy, “innej” mam tutaj na myśli bazy danych o takiej samej strukturze tabeli jaka jest zdefiniowana w modelu.

Ładowanie przykładowych danych (data/fixtures)

Podobnie jak w przypadku definicji struktur bazy danych rozdzielamy ładowanie danych. Dla bazy “db1” będzie to katalog data/fixtures a dla bazy “db2” data/stat_fixtures

Wywołanie tasków - dla domyślnej bazy danych “db1″ :

./symfony propel:data-load

Ładowanie danych do bazy “db2″ wymaga podania odpowiedniego połączenie i ustawienia katalogu z którego dane będą wczytywane.

./symfony propel:data-load --connection=stat --dir="data/stat_fixtures"

Można definiować n takich baz. Jeśli np. chcielibyśmy operować na takich samych tabelach w różnych bazach danych to możemy w modelach wymuszać konkretne połączenia, wszystko zależy od projektu i jego wymagań.

Kategoria: Bazy danych, MySQL, Oracle, PHP, PostgreSQL, Propel, Symfony | Marcin Chyłek | Komentarze: 4

Gentoo - Instalacja PostgreSQL 8.3.x i PHP

Aktualizując ostanio serwer miałem problem z upgrade na nowszą wersje PostgreSQLa więc opiszę swoje rozwiązanie na blogu.

Jeśli mamy już zainstalowaną wcześniejszą wersje PostgreSQLa to robimy backup.

pg_dumpall > postgres-backup.dump

Następnie wrzucamy do /etc/portage/package.keywords wpisy w celu odblokowania wersji niestabilnych.

echo "dev-db/postgresql-base ~amd64" >> /etc/portage/package.keywords
echo "dev-db/postgresql-server ~amd64" >> /etc/portage/package.keywords
echo "virtual/postgresql-server ~amd64" >> /etc/portage/package.keywords
echo "virtual/postgresql-base ~amd64" >> /etc/portage/package.keywords
echo "app-admin/eselect-postgresql ~amd64" >> /etc/portage/package.keywords

Kolejnym etapem jest usunięcie dev-db/postgresql dev-db/libpq

emerge --unmerge dev-db/postgresql dev-db/libpq

I możemy instalować nową wersję PostgreSQLa

emerge virtual/postgresql-base virtual/postgresql-server
emerge --config =dev-db/postgresql-server-8.3.5

Zostaje tylko wystartowanie bazy i dopisanie do skryptów startowych.

/etc/init.d/postgresql-8.3 start
rc-update add postgresql-8.3 default

Jeśli z jakiś przyczyn php wyrzuca, że nie chce działać to musimy przekompilować.

Kategoria: Bazy danych, Gentoo, Linux, PHP, PostgreSQL | Marcin Chyłek | Komentarze: 2

PostgreSQL, pl/python - usuwanie rekordów z zależnymi elementami (plikami)

Moja dzisiejsza notatka będzie pewnym przykładem rozwiązania problemu, z którym często się spotykam, ale z pewnych ograniczeń, postanowiłem to rozwiązać trochę w inny sposób. Metoda ta oczywiście znajduje się poniżej.

Często z baz danych usuwamy rekordy, które są odzwierciedleniem obrazków na dysku, ale jak usunąć rekord a wraz z nim plik zależny, który nie zawsze znajduje się fizycznie na tej samej maszynie? Dlaczego akurat uzależniać, usuwanie pliku od bazy danych? Powodów może być kilka, np wiele powtarzających się mechanizmów obsługujących ten sam mechanizm. Wydawać by się mogło że refaktoryzacja kody to załatwi ale niestety różnie to bywa i często do ideału daleka droga.

Przykład z życia – obliczamy punkty fotek w funkcji plpgsql a następnie niepotrzebne rekordy są usuwane wraz z fotkami zapisanymi fizycznie na dysku, oczywiście PHP w tym momencie nie ma dostępu do tego rekordu.

Konkrety: PostgreSQL i język proceduralny

Baza danych taka jak PostgreSQL, umożliwia obsługę wielu proceduralnych języków np. :

  • pl/pgsql
  • pl/tcl
  • pl/python
  • pl/perl
  • pl/sh

Dla przykładu wykorzystam pl/python

Załóżmy, że mamy tabele images z polami, id, created_at, name, path, gdzie path bedzie scieżka na naszym serwerze

CREATE TABLE images
(
   id serial,
   created_at timestamp without time zone DEFAULT NOW(),
   image_name character varying(100) NOT NULL,
   path character varying(255) NOT NULL,
   CONSTRAINT pkey_id PRIMARY KEY (id)
);

Usuwając rekord z tabeli images chcemy usunąć plik fizycznie z dysku. Pierwszą rzeczą jest dodanie obsługi języka plpython, oczywiście z poziomu superuser’a.

CREATE LANGUAGE plpythonu;

Pozostaje nam tylko stworzenie triggera, który wywoła funkcję usuwania pliku z dysku po usunięciu rekordu.

CREATE OR REPLACE FUNCTION delete_images()
RETURNS trigger AS
'
  import os
  os.unlink( TD["old"]["path"] )

  return "OK"
'
LANGUAGE 'plpythonu' VOLATILE;

CREATE TRIGGER delete_images_trigger
BEFORE DELETE
ON images
FOR EACH ROW
EXECUTE PROCEDURE delete_images();

Pozostaje nam jeszcze dodać przykładowy rekord a następnie go usunąć

INSERT INTO images (name, path) values ('test', '/home/songoq/pg_test/a')

Dla testu tworzymy plik na dysku

touch /home/songoq/pg_test/a

Usuwamy rekord

DELETE FROM images WHERE id = 1

Przykład można bardziej rozbudować o obsługę błędów, sprawdzanie czy plik istnieje lub poprzez wywołanie shella usunąć go z zewnętrznego serwera, ograniczeniem jest tylko wyobraźnia programisty :D

Kategoria: Bazy danych, Linux, PHP, PostgreSQL, Python | Marcin Chyłek | Komentarze: 0

PostgreSQL - Procedural Language (przyszłość języków)

Używając PostgreSQL’a możemy wykorzystywać kilka języków proceduralnych:

  • PL/pgSQL podobny składnią do języka PL/SQL w bazie Oracle
  • języki skryptowe: PL/Perl, plPHP, PL/Python, PL/Ruby, PL/sh i PL/Tcl
  • kompilowane: C, C++, PL/Java
  • PL/R

PostgreSQL jest często wykorzystywany przez programistów serwisów WWW (konfiguracja w postaci PostgreSQL + PHP) to mimo tego, że istnieje język plPHP to obecnie najpopularniejszym językiem jest PL/pgSQL - dlatego pewnie, że wywodzi się od PL/SQL (Oracle).

Zastanawiam się dlaczego tak się dzieje, co powoduje że nie używa się pozostałych języków? Weźmy na przykład Ruby - oczywiście w bazie PostgreSQL mamy możliwość jego wykorzystania. PL/Ruby jest rozwijany od 2002 roku, mimo wielkiej popularności Ruby wśród programistów PHP język raczej nie należy do tych prężnie się rozwijających. C, C++ dlaczego nie? Prawie każdy programista miał styczność z tymi językami a jednak PL/pgSQL.

Przeglądając TODO Postgresa i MySQLa widać, że developerzy tych baz starają się implementować większość funkcjonalności, które firma Oracle wprowadziła do swojej bazy jakiś czas temu. Tak czy inaczej Oracle jest pionierem na rynku jeśli chodzi o bazy danych i wprowadzenie zmian lub dodanie nowych mechanizmów powoduje, że reszta systemów bazodanowych podąża za nimi.

Czy warto wdrożyć plPHP czy PL/Ruby? Każdy musi na to pytanie sobie sam odpowiedzieć.

Dla osób chcących wdrożyć się w PL/Ruby lub plPHP zapraszam na:

PL/Ruby
plPHP

Kategoria: Bazy danych, PostgreSQL | Marcin Chyłek | Komentarze: 0
Starsze »