postgreSQLã§compositeãã¿ã¼ã³
ãã®ã¨ã³ããªã¯PostgreSQL Advent Calendarã®12/17æ å½åã®ã¨ã³ããªã¨ãªãã¾ãã
postgreSQLã«ã¯ãã¼ãã«ã®ç¶æ¿ã¨é
ååã¨ãããä»RDBMSã§ã¯ãã¾ã馴æã¿ã®ãªãæ©è½ãããã¾ãã
å°ãæãã¤ããã®ã§ãã®2ã¤ãå©ç¨ãã¦Composite パターンã試ãã¦ã¿ã¾ããã
(æ(容å¨/ãã£ã¬ã¯ããª)ã¨è(ä¸èº«/ãã¡ã¤ã«)ãåä¸è¦ããã¤ã³ã¿ã¼ãã§ã¼ã¹ã§æ§é ãæ§ç¯ãããã¿ã¼ã³ã§ã)
å ããåä¸è¦ããå ±éã¤ã³ã¿ã¼ãã§ã¼ã¹ãå®ç¾©ãã¾ãã
create table entity ( id serial primary key, name text not null );
次ã«ãèãã¨ãªãfile tableãå®ç¾©ãINHERITSå¥ã§ç¶æ¿ãããã¼ãã«ãæå®ãã¾ãã
ã«ã©ã ã¯ãã¡ã¤ã«ã®æ
å ±ã¨ãªããã®ããµã³ãã«ã§è¿½å ãã¦ã¿ã¾ããã
create table file ( contents text, size integer default 0 not null, type text )INHERITS(entity);
ä»åº¦ã¯ãæãã¨ãªãdirectory tableãå®ç¾©ããã¡ããentity tableãç¶æ¿ã
ããã¦entity.id ãæ ¼ç´ããcollection ã«ã©ã å®ç¾©ãã¾ããã
create table directory ( collection integer[] )INHERITS(entity);
ãã¼ãã«ã®æºåãåºæ¥ãã¨ããã§ãã¼ã¿ãç»é²ãã¦ããã¾ãã
composite=# insert into directory ( name )values( '/' ); INSERT 0 1
composite=# SELECT * from directory ; id | name | collection ----+------+------------ 1 | / | (1 row) composite=# SELECT * from entity; id | name ----+------ 1 | / (1 row)
親ãã¼ãã«ã®entityãããã¬ã³ã¼ããåç §ã§ãããã¨ã確èªåºæ¥ã¾ãã
ç¶ãã¦ããªã¼æ§é ãä½æãã¦è¡ãã¾ãã
ãªãã¸ã§ã¯ãã®ç»é²
composite=# insert into directory ( name )values( 'home' ); INSERT 0 1 composite=# insert into directory ( name )values( 'usr' ); INSERT 0 1 composite=# insert into directory ( name )values( 'var' ); INSERT 0 1
æãã¼ãã«åãã¼ããã»ãã
array_appendé¢æ°ã§entity.idãè¨å®ãã¦ããã¾ãã
composite=# UPDATE directory set collection = array_append(collection, 2) where id = 1; UPDATE 1 composite=# UPDATE directory set collection = array_append(collection, 3) where id = 1; UPDATE 1 composite=# UPDATE directory set collection = array_append(collection, 4) where id = 1; UPDATE 1 composite=# UPDATE directory set collection = array_append(collection, 5) where id = 2; UPDATE 1 composite=# UPDATE directory set collection = array_append(collection, 6) where id = 2; UPDATE 1 composite=# UPDATE directory set collection = array_append(collection, 7) where id = 2; UPDATE 1
ããã¾ã§ã§ã¬ã³ã¼ãã¯ä»¥ä¸ã®ããã«ãªãã¾ããã
composite=# SELECT * from directory order by id; id | name | collection ----+-------+------------ 1 | / | {2,3,4} 2 | home | {5,6,7} 3 | usr | 4 | var | 5 | user1 | 6 | user2 | 7 | user3 | (7 rows)
ãèãã¨ãªããã¡ã¤ã«ãã¼ããç»é²ã
composite=# insert into file (name, contents, size, type)values( 'hoge', 'abc', length('abc'), '.txt' ); INSERT 0 1 composite=# insert into file (name, contents, size, type)values( 'foo', '<?php print "hello world"; ?>', length('<?php print "hello world"; ?>'), '.php' ); INSERT 0 1 composite=# insert into file (name, contents, size, type)values( 'bar', 'my memo...', length('my memo...'), '.txt' ); INSERT 0 1 composite=# SELECT * from file order by id; id | name | contents | size | type ----+------+-------------------------------+------+------ 8 | hoge | abc | 3 | .txt 9 | foo | <?php print "hello world"; ?> | 29 | .php 10 | bar | my memo... | 10 | .txt
ã®ããã«ç»é²ãã¾ããã
ããã¾ã§ã§entityãã¼ãã«ã¯ä»¥ä¸ã¨ãªãã¾ãã
composite=# SELECT * from entity order by id; id | name ----+------- 1 | / 2 | home 3 | usr 4 | var 5 | user1 6 | user2 7 | user3 8 | hoge 9 | foo 10 | bar (10 rows)
ãèããã¼ãããæãã«ç»é²ãã¾ãã
composite=# update directory set collection = array_append(collection, 8) where id = 5; UPDATE 1 composite=# update directory set collection = array_append(collection, 9) where id = 5; UPDATE 1 composite=# update directory set collection = array_append(collection, 10) where id = 5; UPDATE 1
æçµçã«ãæãã®æ§é ã以ä¸ã«ãã¾ããã
composite=# SELECT * from directory order by id; id | name | collection ----+-------+------------ 1 | / | {2,3,4} 2 | home | {5,6,7} 3 | usr | 4 | var | 5 | user1 | {8,9,10} 6 | user2 | 7 | user3 | (7 rows)
æå¾ã«æ§é ãå·¡åããã¹ã¯ãªãããplpgsqlã§ä½ãã¾ããã
create or replace function composite( entity.id%TYPE, TEXT ) RETURNS setof TEXT AS $$ declare sql text; relname text; name text; current text; size integer; type text; begin --ã¢ã¯ã»ã¹ãããentity.idãæ ¼ç´ããã¦ãããªãã¸ã§ã¯ãåãåå¾ --ããã§ã¯ãdirectoryã or ãfileããè¿ã£ã¦ãã¾ãã EXECUTE 'select p.relname, name from entity e, pg_class p where e.tableoid = p.oid and e.id = '||$1 into relname, name; IF relname = 'directory' THEN IF name = '/' THEN current := name; ELSE --åãã¼ãã®æã¯ç¬¬äºå¼æ°ã®è¦ªãã¼ãåã追å ã current := $2||name||'/'; END IF; --ç¾å¨ã®ãã¼ãå称ãè¿å´ return next current; --åãã¼ããæ¢ç´¢ãèªåèªèº«ã®ãã¼ãå称ã渡ãã¾ãã sql := 'select composite(unnest(collection), '''||current||''' ) from directory where id = ' ||$1; return QUERY EXECUTE sql; ELSE --ãèããã¼ãæã¯ãã¡ã¤ã«æ å ±ãåºå current := $2||name; EXECUTE 'select size, type from file where id = ' ||$1 into size, type; return next current||type||'('||size||')'; END IF; end; $$ language plpgsql; CREATE FUNCTION
使ç¨ä¾ã
composite=# SELECT composite(id, '') from entity where id = 1; print_composite ------------------------- / /home/ /home/user1/ /home/user1/hoge.txt(3) /home/user1/foo.php(29) /home/user1/bar.txt(10) /home/user2/ /home/user3/ /usr/ /var/ (10 rows)
setof next returnãªã®ã§fromå¥ã§ã使ç¨ã§ãã¾ãã
composite=# select * from composite(1, ''); print_composite ------------------------- / /home/ /home/user1/ /home/user1/hoge.txt(3) /home/user1/foo.php(29) /home/user1/bar.txt(10) /home/user2/ /home/user3/ /usr/ /var/ (10 rows)
home/ 以ä¸ãæ¢ç´¢ã ã¨ããã
composite=# SELECT composite(id, '') from entity where name = 'home'; composite ------------------------ home/ home/user1/ home/user1/hoge.txt(3) home/user1/foo.php(29) home/user1/bar.txt(10) home/user2/ home/user3/ (7 rows)
ãããªãã¾ããã
以ä¸ãpostgreSQLã®ç¶æ¿ãé
ååãå©ç¨ããcompositeãã¿ã¼ã³ã®ãç´¹ä»ã§ããã
(ãã¼ã¿ã®insert, updateãã¤ã³ã¿ã¼ãã§ã¼ã¹ã¨ãªãentity tableã使ç¨ããã¹ãã§ããããã)
â» ç¶æ¿ãé
ååã¯ä»RDBMSã«ã¯ç§»æ¤ãè¾ãæ©æ§ãªã®ã§ãå®åã§å©ç¨ããã«ã¯åå注æãã¦ä¸ããï¼ç¬ï¼
ææ¥ã®PostgreSQL Advent Calendarã¯@maropuããã§ããå®ãããé¡ããã¾ãã