<?xml version="1.0"?>
<?xml-stylesheet type="text/css" href="http://wiki.postgresql.org/skins/common/feed.css?207"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
		<id>http://wiki.postgresql.org/index.php?title=Special:Contributions&amp;feed=atom&amp;target=Ziga</id>
		<title>PostgreSQL wiki - User contributions [en]</title>
		<link rel="self" type="application/atom+xml" href="http://wiki.postgresql.org/index.php?title=Special:Contributions&amp;feed=atom&amp;target=Ziga"/>
		<link rel="alternate" type="text/html" href="http://wiki.postgresql.org/wiki/Special:Contributions/Ziga"/>
		<updated>2013-05-22T12:16:22Z</updated>
		<subtitle>From PostgreSQL wiki</subtitle>
		<generator>MediaWiki 1.15.5-2squeeze5</generator>

	<entry>
		<id>http://wiki.postgresql.org/wiki/Talk:PGXN</id>
		<title>Talk:PGXN</title>
		<link rel="alternate" type="text/html" href="http://wiki.postgresql.org/wiki/Talk:PGXN"/>
				<updated>2010-05-27T18:24:05Z</updated>
		
		<summary type="html">&lt;p&gt;Ziga:&amp;#32;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Possible FAQ Addition ==&lt;br /&gt;
&lt;br /&gt;
How to pronounce PGAN? (P-G-An, P-Gan?)&lt;br /&gt;
&lt;br /&gt;
== PgFoundry considered useful ==&lt;br /&gt;
&lt;br /&gt;
Why not use PgFoundry as a place for uploading extensions?&lt;br /&gt;
&lt;br /&gt;
It already provides many facilities needed for development&lt;br /&gt;
and is being quite used. Developers can already neatly package&lt;br /&gt;
and upload their stuff. It already supports versioned file distribution.&lt;br /&gt;
It is just not well enough integrated with actual running database one&lt;br /&gt;
is using in practice.&lt;br /&gt;
&lt;br /&gt;
PgDEX could periodically (say once a day)  download all changed&lt;br /&gt;
published .tar.gz files (but not stuff in SCM) and compile&lt;br /&gt;
them into installable packages. These would be installed by&lt;br /&gt;
special command line utility, as suggested.&lt;br /&gt;
&lt;br /&gt;
What seems to be needed with this is a way to specify meta-information&lt;br /&gt;
in packages; this could be in a form of a required file (say control,&lt;br /&gt;
control.xml or pg_package.xml), which would contain the required data.&lt;br /&gt;
Perhaps XML and/or RDF would be a good choice for this?&lt;br /&gt;
&lt;br /&gt;
At the very least, it would seem sensible to have some kind of correspondence&lt;br /&gt;
between extension names and PgFoundry projects.&lt;br /&gt;
&lt;br /&gt;
--[[User:Ziga|Ziga]] 18:11, 27 May 2010 (UTC)&lt;/div&gt;</summary>
		<author><name>Ziga</name></author>	</entry>

	<entry>
		<id>http://wiki.postgresql.org/wiki/Talk:PGXN</id>
		<title>Talk:PGXN</title>
		<link rel="alternate" type="text/html" href="http://wiki.postgresql.org/wiki/Talk:PGXN"/>
				<updated>2010-05-27T18:11:42Z</updated>
		
		<summary type="html">&lt;p&gt;Ziga:&amp;#32;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Possible FAQ Addition ==&lt;br /&gt;
&lt;br /&gt;
How to pronounce PGAN? (P-G-An, P-Gan?)&lt;br /&gt;
&lt;br /&gt;
== PgFoundry considered useful ==&lt;br /&gt;
&lt;br /&gt;
Why not use PgFoundry as a place for uploading extensions?&lt;br /&gt;
&lt;br /&gt;
It already provides many facilities needed for development&lt;br /&gt;
and is being quite used. It already supports versioned file distribution.&lt;br /&gt;
It is just not well enough integrated with actual running database one&lt;br /&gt;
is using in practice.&lt;br /&gt;
&lt;br /&gt;
PgDEX could periodically (say once a day)  download all changed&lt;br /&gt;
published .tar.gz files (but not stuff in SCM) and compile&lt;br /&gt;
them into installable packages. These would be installed by&lt;br /&gt;
special command line utility, as suggested.&lt;br /&gt;
&lt;br /&gt;
What seems to be needed with this is a way to specify meta-information&lt;br /&gt;
in packages; this could be in a form of a required file (say control,&lt;br /&gt;
control.xml or pg_package.xml), which would contain the required data.&lt;br /&gt;
Perhaps XML and/or RDF would be a good choice for this?&lt;br /&gt;
&lt;br /&gt;
--[[User:Ziga|Ziga]] 18:11, 27 May 2010 (UTC)&lt;/div&gt;</summary>
		<author><name>Ziga</name></author>	</entry>

	<entry>
		<id>http://wiki.postgresql.org/wiki/Talk:PGXN</id>
		<title>Talk:PGXN</title>
		<link rel="alternate" type="text/html" href="http://wiki.postgresql.org/wiki/Talk:PGXN"/>
				<updated>2010-05-27T18:11:05Z</updated>
		
		<summary type="html">&lt;p&gt;Ziga:&amp;#32;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Possible FAQ Addition ==&lt;br /&gt;
&lt;br /&gt;
How to pronounce PGAN? (P-G-An, P-Gan?)&lt;br /&gt;
&lt;br /&gt;
Why not use PgFoundry as a place for uploading extensions?&lt;br /&gt;
&lt;br /&gt;
It already provides many facilities needed for development&lt;br /&gt;
and is being quite used. It already supports versioned file distribution.&lt;br /&gt;
It is just not well enough integrated with actual running database one&lt;br /&gt;
is using in practice.&lt;br /&gt;
&lt;br /&gt;
PgDEX could periodically (say once a day)  download all changed&lt;br /&gt;
published .tar.gz files (but not stuff in SCM) and compile&lt;br /&gt;
them into installable packages. These would be installed by&lt;br /&gt;
special command line utility, as suggested.&lt;br /&gt;
&lt;br /&gt;
What seems to be needed with this is a way to specify meta-information&lt;br /&gt;
in packages; this could be in a form of a required file (say control,&lt;br /&gt;
control.xml or pg_package.xml), which would contain the required data.&lt;br /&gt;
Perhaps XML and/or RDF would be a good choice for this?&lt;br /&gt;
&lt;br /&gt;
--[[User:Ziga|Ziga]] 18:11, 27 May 2010 (UTC)&lt;/div&gt;</summary>
		<author><name>Ziga</name></author>	</entry>

	<entry>
		<id>http://wiki.postgresql.org/wiki/User:Ziga</id>
		<title>User:Ziga</title>
		<link rel="alternate" type="text/html" href="http://wiki.postgresql.org/wiki/User:Ziga"/>
				<updated>2010-04-20T18:30:29Z</updated>
		
		<summary type="html">&lt;p&gt;Ziga:&amp;#32;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Žiga Kranjec&lt;br /&gt;
&lt;br /&gt;
software developer&lt;br /&gt;
&lt;br /&gt;
Mail: ziga ⓐ ljudmila.org&lt;br /&gt;
&lt;br /&gt;
===areas of interest===&lt;br /&gt;
&lt;br /&gt;
* User interfaces &amp;amp; User experience&lt;br /&gt;
* Perl&lt;br /&gt;
* Web development&lt;br /&gt;
* Semantic Web&lt;br /&gt;
&lt;br /&gt;
===PostgreSQL areas of interest===&lt;br /&gt;
* [[DDL Functions]] - SQL-callable functions capable of generating DDL scripts for objects within the database&lt;br /&gt;
* [[Module Manager]] - automating installation of PostgreSQL extensions&lt;br /&gt;
** [[User:Ziga/xpg_package|xpg_package]] - easily manage PostgreSQL extensions&lt;br /&gt;
* [[User:Ziga/xpg_diff|xpg_diff]] - schema comparator/updater&lt;br /&gt;
* [[DATALINK]] - SQL/MED DATALINK type&lt;/div&gt;</summary>
		<author><name>Ziga</name></author>	</entry>

	<entry>
		<id>http://wiki.postgresql.org/wiki/Free_disk_space</id>
		<title>Free disk space</title>
		<link rel="alternate" type="text/html" href="http://wiki.postgresql.org/wiki/Free_disk_space"/>
				<updated>2010-04-20T18:24:49Z</updated>
		
		<summary type="html">&lt;p&gt;Ziga:&amp;#32;/* Example */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{SnippetInfo|Free disk space|lang=plperlu|version=8.3|depends=Linux|category=Administrative}}&lt;br /&gt;
Author: [[User:Ziga|Žiga Kranjec]]&lt;br /&gt;
&lt;br /&gt;
This function returns file system information provided by unix utilities '''df(1)''' and '''mount(8)'''&lt;br /&gt;
&lt;br /&gt;
You can use it to get this information in SQL instead of shell, which can sometimes be inconvenient.&lt;br /&gt;
&lt;br /&gt;
It tested on Linux only; it might work on some other unices but not on Windows.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
CREATE OR REPLACE FUNCTION disk_free(&lt;br /&gt;
 OUT dev integer, OUT filesystem text, OUT fstype text, OUT mountpoint text, &lt;br /&gt;
 OUT size numeric, OUT used numeric, OUT avail numeric, &lt;br /&gt;
 OUT use double precision, OUT options text)&lt;br /&gt;
  RETURNS SETOF record AS&lt;br /&gt;
$BODY$&lt;br /&gt;
# Get UNIX file system information&lt;br /&gt;
# this uses UNIX df(1) and mount(1) commands&lt;br /&gt;
&lt;br /&gt;
my %d=();&lt;br /&gt;
&lt;br /&gt;
# reported by df(1)&lt;br /&gt;
my $df=`df -B1 -a -P`; my @df=split(/[\n\r]+/,$df); shift @df;&lt;br /&gt;
for my $l (@df) { &lt;br /&gt;
	my @a=split(/\s+/,$l); my $i=$a[0];&lt;br /&gt;
	$d{$i}={&lt;br /&gt;
		'filesystem'=&amp;gt;$i,'size'=&amp;gt;$a[1],'used'=&amp;gt;$a[2],&lt;br /&gt;
		'avail'=&amp;gt;$a[3],'use'=&amp;gt;$a[4],'mountpoint'=&amp;gt;$a[5]&lt;br /&gt;
	};&lt;br /&gt;
	if( $d{$i}{'use'}eq'-') { $d{$i}{'use'}=undef; } &lt;br /&gt;
	else { $d{$i}{'use'}=~s/%//; }&lt;br /&gt;
	my @stat=stat($d{$i}{'mountpoint'});&lt;br /&gt;
	$d{$i}{'dev'}=$stat[0];&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# reported by mount(8)&lt;br /&gt;
my $mt=`mount`; my @mt=split(/[\n\r]+/,$mt);&lt;br /&gt;
for my $l (@mt) {&lt;br /&gt;
	my @a=split(/\s+/,$l);&lt;br /&gt;
	$d{$a[0]}{'fstype'}=$a[4];&lt;br /&gt;
	$d{$a[0]}{'options'}=$a[5];&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
for my $i (keys(%d)) { return_next($d{$i}); }&lt;br /&gt;
&lt;br /&gt;
return undef;&lt;br /&gt;
$BODY$&lt;br /&gt;
  LANGUAGE 'plperlu' VOLATILE&lt;br /&gt;
  COST 1000&lt;br /&gt;
  ROWS 10;&lt;br /&gt;
ALTER FUNCTION disk_free() OWNER TO postgres;&lt;br /&gt;
COMMENT ON FUNCTION disk_free() IS 'Get UNIX file system information';&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Example==&lt;br /&gt;
&amp;lt;source lang='SQL'&amp;gt;&lt;br /&gt;
select * from disk_free();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 dev  | filesystem  |   fstype    |        mountpoint        |     size      |     used     |     avail     | use  |              options              &lt;br /&gt;
------+-------------+-------------+--------------------------+---------------+--------------+---------------+------+-----------------------------------&lt;br /&gt;
 2054 | /dev/sda6   | ext3        | /tmp                     |    1476407296 |     53538816 |    1347870720 |    4 | (rw)&lt;br /&gt;
   16 | tmpfs       | tmpfs       | /dev/shm                 |    4254875648 |            0 |    4254875648 |    0 | (rw,nosuid,nodev)&lt;br /&gt;
 2051 | /dev/sda3   | ext3        | /var                     |   78742790144 |  16139456512 |   58603335680 |   22 | (rw)&lt;br /&gt;
 2055 | /dev/sda7   | ext3        | /home                    | 2837008560128 | 207753547776 | 2485143212032 |    8 | (rw)&lt;br /&gt;
   10 | devpts      | devpts      | /dev/pts                 |             0 |            0 |             0 |      | (rw,noexec,nosuid,gid=5,mode=620)&lt;br /&gt;
 2050 | /dev/sda2   | ext3        | /                        |    2952847360 |    599957504 |    2202890240 |   22 | (rw,errors=remount-ro)&lt;br /&gt;
 2052 | /dev/sda4   | ext3        | /usr                     |   29529182208 |   2355245056 |   25673940992 |    9 | (rw)&lt;br /&gt;
 2049 | /dev/sda1   | ext3        | /boot                    |     484179968 |    121042944 |     338137088 |   27 | (rw)&lt;br /&gt;
    3 | proc        | proc        | /proc                    |             0 |            0 |             0 |      | (rw,noexec,nosuid,nodev)&lt;br /&gt;
   17 | binfmt_misc | binfmt_misc | /proc/sys/fs/binfmt_misc |             0 |            0 |             0 |      | (rw,noexec,nosuid,nodev)&lt;br /&gt;
    0 | sysfs       | sysfs       | /sys                     |             0 |            0 |             0 |      | (rw,noexec,nosuid,nodev)&lt;br /&gt;
   13 | udev        | tmpfs       | /dev                     |      10485760 |       159744 |      10326016 |    2 | (rw,mode=0755)&lt;br /&gt;
(12 rows)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ziga</name></author>	</entry>

	<entry>
		<id>http://wiki.postgresql.org/wiki/Free_disk_space</id>
		<title>Free disk space</title>
		<link rel="alternate" type="text/html" href="http://wiki.postgresql.org/wiki/Free_disk_space"/>
				<updated>2010-04-20T18:23:22Z</updated>
		
		<summary type="html">&lt;p&gt;Ziga:&amp;#32;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{SnippetInfo|Free disk space|lang=plperlu|version=8.3|depends=Linux|category=Administrative}}&lt;br /&gt;
Author: [[User:Ziga|Žiga Kranjec]]&lt;br /&gt;
&lt;br /&gt;
This function returns file system information provided by unix utilities '''df(1)''' and '''mount(8)'''&lt;br /&gt;
&lt;br /&gt;
You can use it to get this information in SQL instead of shell, which can sometimes be inconvenient.&lt;br /&gt;
&lt;br /&gt;
It tested on Linux only; it might work on some other unices but not on Windows.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
CREATE OR REPLACE FUNCTION disk_free(&lt;br /&gt;
 OUT dev integer, OUT filesystem text, OUT fstype text, OUT mountpoint text, &lt;br /&gt;
 OUT size numeric, OUT used numeric, OUT avail numeric, &lt;br /&gt;
 OUT use double precision, OUT options text)&lt;br /&gt;
  RETURNS SETOF record AS&lt;br /&gt;
$BODY$&lt;br /&gt;
# Get UNIX file system information&lt;br /&gt;
# this uses UNIX df(1) and mount(1) commands&lt;br /&gt;
&lt;br /&gt;
my %d=();&lt;br /&gt;
&lt;br /&gt;
# reported by df(1)&lt;br /&gt;
my $df=`df -B1 -a -P`; my @df=split(/[\n\r]+/,$df); shift @df;&lt;br /&gt;
for my $l (@df) { &lt;br /&gt;
	my @a=split(/\s+/,$l); my $i=$a[0];&lt;br /&gt;
	$d{$i}={&lt;br /&gt;
		'filesystem'=&amp;gt;$i,'size'=&amp;gt;$a[1],'used'=&amp;gt;$a[2],&lt;br /&gt;
		'avail'=&amp;gt;$a[3],'use'=&amp;gt;$a[4],'mountpoint'=&amp;gt;$a[5]&lt;br /&gt;
	};&lt;br /&gt;
	if( $d{$i}{'use'}eq'-') { $d{$i}{'use'}=undef; } &lt;br /&gt;
	else { $d{$i}{'use'}=~s/%//; }&lt;br /&gt;
	my @stat=stat($d{$i}{'mountpoint'});&lt;br /&gt;
	$d{$i}{'dev'}=$stat[0];&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# reported by mount(8)&lt;br /&gt;
my $mt=`mount`; my @mt=split(/[\n\r]+/,$mt);&lt;br /&gt;
for my $l (@mt) {&lt;br /&gt;
	my @a=split(/\s+/,$l);&lt;br /&gt;
	$d{$a[0]}{'fstype'}=$a[4];&lt;br /&gt;
	$d{$a[0]}{'options'}=$a[5];&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
for my $i (keys(%d)) { return_next($d{$i}); }&lt;br /&gt;
&lt;br /&gt;
return undef;&lt;br /&gt;
$BODY$&lt;br /&gt;
  LANGUAGE 'plperlu' VOLATILE&lt;br /&gt;
  COST 1000&lt;br /&gt;
  ROWS 10;&lt;br /&gt;
ALTER FUNCTION disk_free() OWNER TO postgres;&lt;br /&gt;
COMMENT ON FUNCTION disk_free() IS 'Get UNIX file system information';&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Example==&lt;br /&gt;
&amp;lt;source lang='SQL'&amp;gt;&lt;br /&gt;
select * from disk_free();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 dev  | filesystem  |   fstype    |        mountpoint        |     size      |     used     |     avail     | %use |              options              &lt;br /&gt;
------+-------------+-------------+--------------------------+---------------+--------------+---------------+------+-----------------------------------&lt;br /&gt;
 2054 | /dev/sda6   | ext3        | /tmp                     |    1476407296 |     53538816 |    1347870720 |    4 | (rw)&lt;br /&gt;
   16 | tmpfs       | tmpfs       | /dev/shm                 |    4254875648 |            0 |    4254875648 |    0 | (rw,nosuid,nodev)&lt;br /&gt;
 2051 | /dev/sda3   | ext3        | /var                     |   78742790144 |  16139456512 |   58603335680 |   22 | (rw)&lt;br /&gt;
 2055 | /dev/sda7   | ext3        | /home                    | 2837008560128 | 207753547776 | 2485143212032 |    8 | (rw)&lt;br /&gt;
   10 | devpts      | devpts      | /dev/pts                 |             0 |            0 |             0 |      | (rw,noexec,nosuid,gid=5,mode=620)&lt;br /&gt;
 2050 | /dev/sda2   | ext3        | /                        |    2952847360 |    599957504 |    2202890240 |   22 | (rw,errors=remount-ro)&lt;br /&gt;
 2052 | /dev/sda4   | ext3        | /usr                     |   29529182208 |   2355245056 |   25673940992 |    9 | (rw)&lt;br /&gt;
 2049 | /dev/sda1   | ext3        | /boot                    |     484179968 |    121042944 |     338137088 |   27 | (rw)&lt;br /&gt;
    3 | proc        | proc        | /proc                    |             0 |            0 |             0 |      | (rw,noexec,nosuid,nodev)&lt;br /&gt;
   17 | binfmt_misc | binfmt_misc | /proc/sys/fs/binfmt_misc |             0 |            0 |             0 |      | (rw,noexec,nosuid,nodev)&lt;br /&gt;
    0 | sysfs       | sysfs       | /sys                     |             0 |            0 |             0 |      | (rw,noexec,nosuid,nodev)&lt;br /&gt;
   13 | udev        | tmpfs       | /dev                     |      10485760 |       159744 |      10326016 |    2 | (rw,mode=0755)&lt;br /&gt;
(12 rows)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ziga</name></author>	</entry>

	<entry>
		<id>http://wiki.postgresql.org/wiki/Free_disk_space</id>
		<title>Free disk space</title>
		<link rel="alternate" type="text/html" href="http://wiki.postgresql.org/wiki/Free_disk_space"/>
				<updated>2010-04-20T18:22:55Z</updated>
		
		<summary type="html">&lt;p&gt;Ziga:&amp;#32;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{SnippetInfo|Free disk space|lang=plperlu|version=8.3|depends=Linux|category=Administrative}}&lt;br /&gt;
Author: [[User:Ziga|Žiga Kranjec]]&lt;br /&gt;
&lt;br /&gt;
This function returns file system information provided by unix utilities '''df(1)''' and '''mount(8)'''&lt;br /&gt;
&lt;br /&gt;
You can use it to get this information in SQL instead of shell, which can sometimes be inconvenient.&lt;br /&gt;
&lt;br /&gt;
It tested on Linux only; it might work on some other unices but not on Windows.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
CREATE OR REPLACE FUNCTION disk_free(&lt;br /&gt;
 OUT dev integer, OUT filesystem text, OUT fstype text, OUT mountpoint text, &lt;br /&gt;
 OUT size numeric, OUT used numeric, OUT avail numeric, &lt;br /&gt;
 OUT use double precision, OUT options text)&lt;br /&gt;
  RETURNS SETOF record AS&lt;br /&gt;
$BODY$&lt;br /&gt;
# Get UNIX file system information&lt;br /&gt;
# this uses UNIX df(1) and mount(1) commands&lt;br /&gt;
&lt;br /&gt;
my %d=();&lt;br /&gt;
&lt;br /&gt;
# reported by df(1)&lt;br /&gt;
my $df=`df -B1 -a -P`; my @df=split(/[\n\r]+/,$df); shift @df;&lt;br /&gt;
for my $l (@df) { &lt;br /&gt;
	my @a=split(/\s+/,$l); my $i=$a[0];&lt;br /&gt;
	$d{$i}={&lt;br /&gt;
		'filesystem'=&amp;gt;$i,'size'=&amp;gt;$a[1],'used'=&amp;gt;$a[2],&lt;br /&gt;
		'avail'=&amp;gt;$a[3],'use'=&amp;gt;$a[4],'mountpoint'=&amp;gt;$a[5]&lt;br /&gt;
	};&lt;br /&gt;
	if( $d{$i}{'use'}eq'-') { $d{$i}{'use'}=undef; } &lt;br /&gt;
	else { $d{$i}{'use'}=~s/%//; }&lt;br /&gt;
	my @stat=stat($d{$i}{'mountpoint'});&lt;br /&gt;
	$d{$i}{'dev'}=$stat[0];&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# reported by mount(8)&lt;br /&gt;
my $mt=`mount`; my @mt=split(/[\n\r]+/,$mt);&lt;br /&gt;
for my $l (@mt) {&lt;br /&gt;
	my @a=split(/\s+/,$l);&lt;br /&gt;
	$d{$a[0]}{'fstype'}=$a[4];&lt;br /&gt;
	$d{$a[0]}{'options'}=$a[5];&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
for my $i (keys(%d)) { return_next($d{$i}); }&lt;br /&gt;
&lt;br /&gt;
return undef;&lt;br /&gt;
$BODY$&lt;br /&gt;
  LANGUAGE 'plperlu' VOLATILE&lt;br /&gt;
  COST 1000&lt;br /&gt;
  ROWS 10;&lt;br /&gt;
ALTER FUNCTION os.disk_free() OWNER TO postgres;&lt;br /&gt;
COMMENT ON FUNCTION disk_free() IS 'Get UNIX file system information';&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Example==&lt;br /&gt;
&amp;lt;source lang='SQL'&amp;gt;&lt;br /&gt;
select * from disk_free();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 dev  | filesystem  |   fstype    |        mountpoint        |     size      |     used     |     avail     | %use |              options              &lt;br /&gt;
------+-------------+-------------+--------------------------+---------------+--------------+---------------+------+-----------------------------------&lt;br /&gt;
 2054 | /dev/sda6   | ext3        | /tmp                     |    1476407296 |     53538816 |    1347870720 |    4 | (rw)&lt;br /&gt;
   16 | tmpfs       | tmpfs       | /dev/shm                 |    4254875648 |            0 |    4254875648 |    0 | (rw,nosuid,nodev)&lt;br /&gt;
 2051 | /dev/sda3   | ext3        | /var                     |   78742790144 |  16139456512 |   58603335680 |   22 | (rw)&lt;br /&gt;
 2055 | /dev/sda7   | ext3        | /home                    | 2837008560128 | 207753547776 | 2485143212032 |    8 | (rw)&lt;br /&gt;
   10 | devpts      | devpts      | /dev/pts                 |             0 |            0 |             0 |      | (rw,noexec,nosuid,gid=5,mode=620)&lt;br /&gt;
 2050 | /dev/sda2   | ext3        | /                        |    2952847360 |    599957504 |    2202890240 |   22 | (rw,errors=remount-ro)&lt;br /&gt;
 2052 | /dev/sda4   | ext3        | /usr                     |   29529182208 |   2355245056 |   25673940992 |    9 | (rw)&lt;br /&gt;
 2049 | /dev/sda1   | ext3        | /boot                    |     484179968 |    121042944 |     338137088 |   27 | (rw)&lt;br /&gt;
    3 | proc        | proc        | /proc                    |             0 |            0 |             0 |      | (rw,noexec,nosuid,nodev)&lt;br /&gt;
   17 | binfmt_misc | binfmt_misc | /proc/sys/fs/binfmt_misc |             0 |            0 |             0 |      | (rw,noexec,nosuid,nodev)&lt;br /&gt;
    0 | sysfs       | sysfs       | /sys                     |             0 |            0 |             0 |      | (rw,noexec,nosuid,nodev)&lt;br /&gt;
   13 | udev        | tmpfs       | /dev                     |      10485760 |       159744 |      10326016 |    2 | (rw,mode=0755)&lt;br /&gt;
(12 rows)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ziga</name></author>	</entry>

	<entry>
		<id>http://wiki.postgresql.org/wiki/Free_disk_space</id>
		<title>Free disk space</title>
		<link rel="alternate" type="text/html" href="http://wiki.postgresql.org/wiki/Free_disk_space"/>
				<updated>2010-04-20T18:22:13Z</updated>
		
		<summary type="html">&lt;p&gt;Ziga:&amp;#32;New page: {{SnippetInfo|Free disk space|lang=plperlu|version=8.3|depends=Linux|category=Administrative}} Author: Žiga Kranjec  This function returns file system information provided b...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{SnippetInfo|Free disk space|lang=plperlu|version=8.3|depends=Linux|category=Administrative}}&lt;br /&gt;
Author: [[User:Ziga|Žiga Kranjec]]&lt;br /&gt;
&lt;br /&gt;
This function returns file system information provided by unix utilities '''df(1)''' and '''mount(8)'''&lt;br /&gt;
&lt;br /&gt;
You can use it to get this information in SQL instead of shell, which can sometimes be inconvenient.&lt;br /&gt;
&lt;br /&gt;
It tested on Linux only; it might work on some other unices but not on Windows.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
CREATE OR REPLACE FUNCTION disk_free(&lt;br /&gt;
 OUT dev integer, OUT filesystem text, OUT fstype text, OUT mountpoint text, &lt;br /&gt;
 OUT size numeric, OUT used numeric, OUT avail numeric, &lt;br /&gt;
 OUT use double precision, OUT options text)&lt;br /&gt;
  RETURNS SETOF record AS&lt;br /&gt;
$BODY$&lt;br /&gt;
# Get UNIX file system information&lt;br /&gt;
# this uses UNIX df(1) and mount(1) commands&lt;br /&gt;
&lt;br /&gt;
my %d=();&lt;br /&gt;
&lt;br /&gt;
# reported by df(1)&lt;br /&gt;
my $df=`df -B1 -a -P`;my @df=split(/[\n\r]+/,$df); shift @df;&lt;br /&gt;
for my $l (@df) { &lt;br /&gt;
	my @a=split(/\s+/,$l); my $i=$a[0];&lt;br /&gt;
	$d{$i}={&lt;br /&gt;
		'filesystem'=&amp;gt;$i,'size'=&amp;gt;$a[1],'used'=&amp;gt;$a[2],&lt;br /&gt;
		'avail'=&amp;gt;$a[3],'use'=&amp;gt;$a[4],'mountpoint'=&amp;gt;$a[5]&lt;br /&gt;
	};&lt;br /&gt;
	if( $d{$i}{'use'}eq'-') { $d{$i}{'use'}=undef; } &lt;br /&gt;
	else { $d{$i}{'use'}=~s/%//; }&lt;br /&gt;
	my @stat=stat($d{$i}{'mountpoint'});&lt;br /&gt;
	$d{$i}{'dev'}=$stat[0];&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# reported by mount(1)&lt;br /&gt;
my $mt=`mount`; my @mt=split(/[\n\r]+/,$mt);&lt;br /&gt;
for my $l (@mt) {&lt;br /&gt;
	my @a=split(/\s+/,$l);&lt;br /&gt;
	$d{$a[0]}{'fstype'}=$a[4];&lt;br /&gt;
	$d{$a[0]}{'options'}=$a[5];&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
for my $i (keys(%d)) { return_next($d{$i}); }&lt;br /&gt;
&lt;br /&gt;
return undef;&lt;br /&gt;
$BODY$&lt;br /&gt;
  LANGUAGE 'plperlu' VOLATILE&lt;br /&gt;
  COST 1000&lt;br /&gt;
  ROWS 10;&lt;br /&gt;
ALTER FUNCTION os.disk_free() OWNER TO postgres;&lt;br /&gt;
COMMENT ON FUNCTION disk_free() IS 'Get UNIX file system information';&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Example==&lt;br /&gt;
&amp;lt;source lang='SQL'&amp;gt;&lt;br /&gt;
select * from disk_free();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 dev  | filesystem  |   fstype    |        mountpoint        |     size      |     used     |     avail     | %use |              options              &lt;br /&gt;
------+-------------+-------------+--------------------------+---------------+--------------+---------------+------+-----------------------------------&lt;br /&gt;
 2054 | /dev/sda6   | ext3        | /tmp                     |    1476407296 |     53538816 |    1347870720 |    4 | (rw)&lt;br /&gt;
   16 | tmpfs       | tmpfs       | /dev/shm                 |    4254875648 |            0 |    4254875648 |    0 | (rw,nosuid,nodev)&lt;br /&gt;
 2051 | /dev/sda3   | ext3        | /var                     |   78742790144 |  16139456512 |   58603335680 |   22 | (rw)&lt;br /&gt;
 2055 | /dev/sda7   | ext3        | /home                    | 2837008560128 | 207753547776 | 2485143212032 |    8 | (rw)&lt;br /&gt;
   10 | devpts      | devpts      | /dev/pts                 |             0 |            0 |             0 |      | (rw,noexec,nosuid,gid=5,mode=620)&lt;br /&gt;
 2050 | /dev/sda2   | ext3        | /                        |    2952847360 |    599957504 |    2202890240 |   22 | (rw,errors=remount-ro)&lt;br /&gt;
 2052 | /dev/sda4   | ext3        | /usr                     |   29529182208 |   2355245056 |   25673940992 |    9 | (rw)&lt;br /&gt;
 2049 | /dev/sda1   | ext3        | /boot                    |     484179968 |    121042944 |     338137088 |   27 | (rw)&lt;br /&gt;
    3 | proc        | proc        | /proc                    |             0 |            0 |             0 |      | (rw,noexec,nosuid,nodev)&lt;br /&gt;
   17 | binfmt_misc | binfmt_misc | /proc/sys/fs/binfmt_misc |             0 |            0 |             0 |      | (rw,noexec,nosuid,nodev)&lt;br /&gt;
    0 | sysfs       | sysfs       | /sys                     |             0 |            0 |             0 |      | (rw,noexec,nosuid,nodev)&lt;br /&gt;
   13 | udev        | tmpfs       | /dev                     |      10485760 |       159744 |      10326016 |    2 | (rw,mode=0755)&lt;br /&gt;
(12 rows)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ziga</name></author>	</entry>

	<entry>
		<id>http://wiki.postgresql.org/wiki/DATALINK</id>
		<title>DATALINK</title>
		<link rel="alternate" type="text/html" href="http://wiki.postgresql.org/wiki/DATALINK"/>
				<updated>2010-04-16T14:16:03Z</updated>
		
		<summary type="html">&lt;p&gt;Ziga:&amp;#32;/* Implementation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
SQL Datalinks are a part of SQL/MED ISO/IEC 9075-9:2003 specification.&lt;br /&gt;
Note that this is distinct from and complements efforts described [[SQL/MED|here]].&lt;br /&gt;
&lt;br /&gt;
Datalink is a special SQL type intended to store URLs in database columns,&lt;br /&gt;
and a number of functions, which can be used in SQL queries.&lt;br /&gt;
&lt;br /&gt;
There aren't many RDBMSs which implement SQL/MED datalinks. &lt;br /&gt;
IBM DB2 does. A lot of it is defined by the SQL standard to be &amp;quot;implementation specific&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Values of DATALINK type are opaque, constructed by using function DLVALUE.&lt;br /&gt;
There are several functions available for converting DATALINK back to text, &lt;br /&gt;
for example DLURLCOMPLETE.&lt;br /&gt;
&lt;br /&gt;
There is not much software, which demands SQL/MED datalinks.&lt;br /&gt;
However, there is functionality concerning files, URLs and web, which is often &lt;br /&gt;
needed in modern applications. Often, it is awkward to use these together &lt;br /&gt;
with RDBMS data. SQL/MED standardizes some of this.&lt;br /&gt;
&lt;br /&gt;
===Features===&lt;br /&gt;
A '''column''' containing a value of type DATALINK can optionally have some special semantics:&lt;br /&gt;
# referential integrity - file pointed to by a datalink cannot be renamed or deleted&lt;br /&gt;
# access control - either SQL or file system mediated&lt;br /&gt;
# point in time recovery of file changes&lt;br /&gt;
&lt;br /&gt;
Only references to external files are stored in the database, not the&lt;br /&gt;
content of the files themselves.&lt;br /&gt;
&lt;br /&gt;
Datalinks as defined by SQL/MED should provide:&lt;br /&gt;
* transactional semantics&lt;br /&gt;
* checking if file exists&lt;br /&gt;
* protection of linked file against renaming or deletion&lt;br /&gt;
* read access control through database&lt;br /&gt;
* write access control through database&lt;br /&gt;
* point-in-time recovery&lt;br /&gt;
* deletion of files no longer referenced&lt;br /&gt;
* access to files on different servers&lt;br /&gt;
&lt;br /&gt;
The following is not specified by SQL/MED, but is often needed in practice (and probably needed to implement datalink):&lt;br /&gt;
* compact URL storage for lots and lots of URLs (say int instead of string; sort-of like enum, but for URLs)&lt;br /&gt;
* URL to filesystem mapping, access control to file system hierarchies&lt;br /&gt;
* local server file access (read, write)&lt;br /&gt;
* remote server file access (get, put)&lt;br /&gt;
* extended file system attributes (get,set)&lt;br /&gt;
* file meta data (list,get,set)&lt;br /&gt;
&lt;br /&gt;
===Use cases===&lt;br /&gt;
Common use cases include:&lt;br /&gt;
* website content management - ensuring that linked-to URLs exist&lt;br /&gt;
* workflow management - providing for locking and versioning of files&lt;br /&gt;
* configuration - managing configuration files, ie have a change in database recreate text configuration file. This file should be locked and writeable only from database.&lt;br /&gt;
* web server log storage (many referer URLs)&lt;br /&gt;
* RDF databases (many URLs)&lt;br /&gt;
&lt;br /&gt;
Datalinks should enable you to:&lt;br /&gt;
* efficiently store URLs (datalinks are stored as integers, not strings)&lt;br /&gt;
* conveniently map between URLs and file system paths&lt;br /&gt;
* safely read and write files from SQL (SQL/MED does not specify functions for this)&lt;br /&gt;
* keep backups of changed files&lt;br /&gt;
* manage files on different servers&lt;br /&gt;
* manage datalink metadata (unified interface to extended filesystem attributes)&lt;br /&gt;
&lt;br /&gt;
==Specification==&lt;br /&gt;
===Synopsys===&lt;br /&gt;
&lt;br /&gt;
 create table my_files (&lt;br /&gt;
   ...,&lt;br /&gt;
   link datalink,&lt;br /&gt;
   ....&lt;br /&gt;
 )&lt;br /&gt;
 &lt;br /&gt;
 insert into my_files (link) select dlvalue('file:///etc/passwd');&lt;br /&gt;
  &lt;br /&gt;
 select into url dlurlcomplete(link) from my_files;&lt;br /&gt;
 &lt;br /&gt;
 update my_files set link=dlnewcopy(url,0);&lt;br /&gt;
 &lt;br /&gt;
 update my_files set link=dlpreviouscopy(url,0);&lt;br /&gt;
&lt;br /&gt;
=== Datalink support functions ===&lt;br /&gt;
&lt;br /&gt;
Constructors for values of type datalink:&lt;br /&gt;
&lt;br /&gt;
* DLVALUE(url)  →  datalink (INSERT only)&lt;br /&gt;
* DLNEWCOPY(url,tokenp)  →  datalink (UPDATE only)&lt;br /&gt;
* DLPREVIOUSCOPY(url,tokenp)  →  datalink (UPDATE only)&lt;br /&gt;
&lt;br /&gt;
Functions for extracting information from datalink type:&lt;br /&gt;
&lt;br /&gt;
* DLURLCOMPLETE(datalink)  →  url&lt;br /&gt;
* DLURLCOMPLETEONLY(datalink)  →  url&lt;br /&gt;
* DLURLCOMPLETEWRITE(datalink)  →  url&lt;br /&gt;
* DLURLPATH(datalink)  →  file path&lt;br /&gt;
* DLURLPATHONLY(datalink)  →  file path&lt;br /&gt;
* DLURLPATHWRITE(datalink)  →  file path&lt;br /&gt;
&lt;br /&gt;
* DLURLSCHEME(datalink)  →  URL scheme ('HTTP' or 'FILE')&lt;br /&gt;
* DLURLSERVER(datalink)  →  server address&lt;br /&gt;
&lt;br /&gt;
* DLREPLACECONTENT(url, url, comment) → datalink (new in SQL 2008)&lt;br /&gt;
&lt;br /&gt;
Additional functions in another well known RDBMS&lt;br /&gt;
&lt;br /&gt;
* DLVALUE(address,linktype [,comment]) → datalink&lt;br /&gt;
* DLCOMMENT(datalink) → text&lt;br /&gt;
* DLLINKTYPE(datalink) → link type ('FILE' or 'URL')&lt;br /&gt;
&lt;br /&gt;
=== Datalink attributes per SQL spec ===&lt;br /&gt;
&lt;br /&gt;
These are refered to as ''link control options'' by SQL spec. They are insanely verbose as text, but can be stored in a typmod. They are specified '''per column''' and thus apply to all URLs stored.&lt;br /&gt;
&lt;br /&gt;
'''LINK CONTROL'''&lt;br /&gt;
* NO&lt;br /&gt;
** just store the datalink&lt;br /&gt;
** file is not &amp;quot;linked&amp;quot;, no further control&lt;br /&gt;
* FILE&lt;br /&gt;
** file is &amp;quot;linked&amp;quot;&lt;br /&gt;
** file has to exist&lt;br /&gt;
** level of control can be specified with further options&lt;br /&gt;
&lt;br /&gt;
'''INTEGRITY'''&lt;br /&gt;
* ALL - linked files cannot be deleted or renamed&lt;br /&gt;
* SELECTIVE  - linked files can only be deleted or modified using file manager operations, if no datalinker is installed&lt;br /&gt;
* NONE - referenced files can be deleted or modified using file manager operations, not compatible with FILE LINK CONTROL&lt;br /&gt;
&lt;br /&gt;
'''READ ACCESS'''&lt;br /&gt;
* DB&lt;br /&gt;
** read access is controlled by SQL server, based on access privileges to the datalink value&lt;br /&gt;
** involves read access tokens&lt;br /&gt;
*** encoded into the URL by the SQL server&lt;br /&gt;
*** verified by external file manager/data linker&lt;br /&gt;
* FS&lt;br /&gt;
** read access is determined by file manager&lt;br /&gt;
&lt;br /&gt;
'''WRITE ACCESS'''&lt;br /&gt;
* ADMIN REQUIRING TOKEN FOR UPDATE&lt;br /&gt;
** write access governed by SQL server (and datalinker)&lt;br /&gt;
** involves write access token for modifying file content&lt;br /&gt;
* ADMIN NOT REQUIRING TOKEN FOR UPDATE&lt;br /&gt;
** write access governed by SQL server (and datalinker)&lt;br /&gt;
* BLOCKED&lt;br /&gt;
** linked files cannot be modified&lt;br /&gt;
* FS&lt;br /&gt;
** write access controlled by file manager&lt;br /&gt;
&lt;br /&gt;
'''RECOVERY'''&lt;br /&gt;
* YES&lt;br /&gt;
* NO&lt;br /&gt;
&lt;br /&gt;
'''ON UNLINK'''&lt;br /&gt;
* DELETE&lt;br /&gt;
** file is deleted when unlinked&lt;br /&gt;
* RESTORE&lt;br /&gt;
** original properties (ownership, permissions) restored as well&lt;br /&gt;
* NONE&lt;br /&gt;
** ownership and permissions are not restored&lt;br /&gt;
&lt;br /&gt;
==Implementation==&lt;br /&gt;
&lt;br /&gt;
Implementation of SQL/MED requires a lot of hocus-pocus and is probably even impossible to do properly on plain unix. Many parts, however seem to be implementable.&lt;br /&gt;
&lt;br /&gt;
System should support at least http: and file: URL schemes. These two require quite different implementations. Perhaps a support for pluggable URL schemes could be useful - consider for example RDF namespaces.&lt;br /&gt;
&lt;br /&gt;
When storing many URLs, it should be possible to greatly reduce space requirements by storing URLs only once in a master URL table and using an int4 or int8 as an actual DATALINK type. This greatly reduces storage requirements needed for many URLs, provided for the use case mentioned. It should be possible to partition the master URL table according to several criteria.&lt;br /&gt;
&lt;br /&gt;
Datalink software is divided in several parts:&lt;br /&gt;
* datalink database schema. Master URL table is stored here.&lt;br /&gt;
* external process ''datalinker''. It uses datalink schema. It manages files on behalf of postgresql server. It uses postgresql for implementing transactional semantics.&lt;br /&gt;
&lt;br /&gt;
QUESTION: what to do for multiple databases on same server?&lt;br /&gt;
&lt;br /&gt;
===Parts===&lt;br /&gt;
* DL - DATALINK SQL/MED + support functions&lt;br /&gt;
* FILEIO - local file access functions&lt;br /&gt;
* URL -  parsing and manipulation - one often needs to get and set various parts of URLs and filenames&lt;br /&gt;
&lt;br /&gt;
Some sort of inter-server communication is needed (to support remote files). Accessing datalinker api in a remote postgresql instance over libpq (say dblink) could maybe work.&lt;br /&gt;
&lt;br /&gt;
===Misc notes===&lt;br /&gt;
&lt;br /&gt;
On ext3 filesystem, files can be locked with 'chattr +i' command, but only by root. This prevents file from beeing changed, no matter what unix file permissions say, even for root user. &lt;br /&gt;
&lt;br /&gt;
By changing file owner/group to postgres and setting unix file permissions, file can be made effectively owned by postgresql server (which can than use normal unix functions to use them).&lt;br /&gt;
&lt;br /&gt;
PL/PerlU seems the right choice for this, with Perl for external datalinker. Proper security and safety will be hard to get right!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:SQL/MED]]&lt;/div&gt;</summary>
		<author><name>Ziga</name></author>	</entry>

	<entry>
		<id>http://wiki.postgresql.org/wiki/DATALINK</id>
		<title>DATALINK</title>
		<link rel="alternate" type="text/html" href="http://wiki.postgresql.org/wiki/DATALINK"/>
				<updated>2010-04-16T14:13:29Z</updated>
		
		<summary type="html">&lt;p&gt;Ziga:&amp;#32;/* Datalink support functions */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
SQL Datalinks are a part of SQL/MED ISO/IEC 9075-9:2003 specification.&lt;br /&gt;
Note that this is distinct from and complements efforts described [[SQL/MED|here]].&lt;br /&gt;
&lt;br /&gt;
Datalink is a special SQL type intended to store URLs in database columns,&lt;br /&gt;
and a number of functions, which can be used in SQL queries.&lt;br /&gt;
&lt;br /&gt;
There aren't many RDBMSs which implement SQL/MED datalinks. &lt;br /&gt;
IBM DB2 does. A lot of it is defined by the SQL standard to be &amp;quot;implementation specific&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Values of DATALINK type are opaque, constructed by using function DLVALUE.&lt;br /&gt;
There are several functions available for converting DATALINK back to text, &lt;br /&gt;
for example DLURLCOMPLETE.&lt;br /&gt;
&lt;br /&gt;
There is not much software, which demands SQL/MED datalinks.&lt;br /&gt;
However, there is functionality concerning files, URLs and web, which is often &lt;br /&gt;
needed in modern applications. Often, it is awkward to use these together &lt;br /&gt;
with RDBMS data. SQL/MED standardizes some of this.&lt;br /&gt;
&lt;br /&gt;
===Features===&lt;br /&gt;
A '''column''' containing a value of type DATALINK can optionally have some special semantics:&lt;br /&gt;
# referential integrity - file pointed to by a datalink cannot be renamed or deleted&lt;br /&gt;
# access control - either SQL or file system mediated&lt;br /&gt;
# point in time recovery of file changes&lt;br /&gt;
&lt;br /&gt;
Only references to external files are stored in the database, not the&lt;br /&gt;
content of the files themselves.&lt;br /&gt;
&lt;br /&gt;
Datalinks as defined by SQL/MED should provide:&lt;br /&gt;
* transactional semantics&lt;br /&gt;
* checking if file exists&lt;br /&gt;
* protection of linked file against renaming or deletion&lt;br /&gt;
* read access control through database&lt;br /&gt;
* write access control through database&lt;br /&gt;
* point-in-time recovery&lt;br /&gt;
* deletion of files no longer referenced&lt;br /&gt;
* access to files on different servers&lt;br /&gt;
&lt;br /&gt;
The following is not specified by SQL/MED, but is often needed in practice (and probably needed to implement datalink):&lt;br /&gt;
* compact URL storage for lots and lots of URLs (say int instead of string; sort-of like enum, but for URLs)&lt;br /&gt;
* URL to filesystem mapping, access control to file system hierarchies&lt;br /&gt;
* local server file access (read, write)&lt;br /&gt;
* remote server file access (get, put)&lt;br /&gt;
* extended file system attributes (get,set)&lt;br /&gt;
* file meta data (list,get,set)&lt;br /&gt;
&lt;br /&gt;
===Use cases===&lt;br /&gt;
Common use cases include:&lt;br /&gt;
* website content management - ensuring that linked-to URLs exist&lt;br /&gt;
* workflow management - providing for locking and versioning of files&lt;br /&gt;
* configuration - managing configuration files, ie have a change in database recreate text configuration file. This file should be locked and writeable only from database.&lt;br /&gt;
* web server log storage (many referer URLs)&lt;br /&gt;
* RDF databases (many URLs)&lt;br /&gt;
&lt;br /&gt;
Datalinks should enable you to:&lt;br /&gt;
* efficiently store URLs (datalinks are stored as integers, not strings)&lt;br /&gt;
* conveniently map between URLs and file system paths&lt;br /&gt;
* safely read and write files from SQL (SQL/MED does not specify functions for this)&lt;br /&gt;
* keep backups of changed files&lt;br /&gt;
* manage files on different servers&lt;br /&gt;
* manage datalink metadata (unified interface to extended filesystem attributes)&lt;br /&gt;
&lt;br /&gt;
==Specification==&lt;br /&gt;
===Synopsys===&lt;br /&gt;
&lt;br /&gt;
 create table my_files (&lt;br /&gt;
   ...,&lt;br /&gt;
   link datalink,&lt;br /&gt;
   ....&lt;br /&gt;
 )&lt;br /&gt;
 &lt;br /&gt;
 insert into my_files (link) select dlvalue('file:///etc/passwd');&lt;br /&gt;
  &lt;br /&gt;
 select into url dlurlcomplete(link) from my_files;&lt;br /&gt;
 &lt;br /&gt;
 update my_files set link=dlnewcopy(url,0);&lt;br /&gt;
 &lt;br /&gt;
 update my_files set link=dlpreviouscopy(url,0);&lt;br /&gt;
&lt;br /&gt;
=== Datalink support functions ===&lt;br /&gt;
&lt;br /&gt;
Constructors for values of type datalink:&lt;br /&gt;
&lt;br /&gt;
* DLVALUE(url)  →  datalink (INSERT only)&lt;br /&gt;
* DLNEWCOPY(url,tokenp)  →  datalink (UPDATE only)&lt;br /&gt;
* DLPREVIOUSCOPY(url,tokenp)  →  datalink (UPDATE only)&lt;br /&gt;
&lt;br /&gt;
Functions for extracting information from datalink type:&lt;br /&gt;
&lt;br /&gt;
* DLURLCOMPLETE(datalink)  →  url&lt;br /&gt;
* DLURLCOMPLETEONLY(datalink)  →  url&lt;br /&gt;
* DLURLCOMPLETEWRITE(datalink)  →  url&lt;br /&gt;
* DLURLPATH(datalink)  →  file path&lt;br /&gt;
* DLURLPATHONLY(datalink)  →  file path&lt;br /&gt;
* DLURLPATHWRITE(datalink)  →  file path&lt;br /&gt;
&lt;br /&gt;
* DLURLSCHEME(datalink)  →  URL scheme ('HTTP' or 'FILE')&lt;br /&gt;
* DLURLSERVER(datalink)  →  server address&lt;br /&gt;
&lt;br /&gt;
* DLREPLACECONTENT(url, url, comment) → datalink (new in SQL 2008)&lt;br /&gt;
&lt;br /&gt;
Additional functions in another well known RDBMS&lt;br /&gt;
&lt;br /&gt;
* DLVALUE(address,linktype [,comment]) → datalink&lt;br /&gt;
* DLCOMMENT(datalink) → text&lt;br /&gt;
* DLLINKTYPE(datalink) → link type ('FILE' or 'URL')&lt;br /&gt;
&lt;br /&gt;
=== Datalink attributes per SQL spec ===&lt;br /&gt;
&lt;br /&gt;
These are refered to as ''link control options'' by SQL spec. They are insanely verbose as text, but can be stored in a typmod. They are specified '''per column''' and thus apply to all URLs stored.&lt;br /&gt;
&lt;br /&gt;
'''LINK CONTROL'''&lt;br /&gt;
* NO&lt;br /&gt;
** just store the datalink&lt;br /&gt;
** file is not &amp;quot;linked&amp;quot;, no further control&lt;br /&gt;
* FILE&lt;br /&gt;
** file is &amp;quot;linked&amp;quot;&lt;br /&gt;
** file has to exist&lt;br /&gt;
** level of control can be specified with further options&lt;br /&gt;
&lt;br /&gt;
'''INTEGRITY'''&lt;br /&gt;
* ALL - linked files cannot be deleted or renamed&lt;br /&gt;
* SELECTIVE  - linked files can only be deleted or modified using file manager operations, if no datalinker is installed&lt;br /&gt;
* NONE - referenced files can be deleted or modified using file manager operations, not compatible with FILE LINK CONTROL&lt;br /&gt;
&lt;br /&gt;
'''READ ACCESS'''&lt;br /&gt;
* DB&lt;br /&gt;
** read access is controlled by SQL server, based on access privileges to the datalink value&lt;br /&gt;
** involves read access tokens&lt;br /&gt;
*** encoded into the URL by the SQL server&lt;br /&gt;
*** verified by external file manager/data linker&lt;br /&gt;
* FS&lt;br /&gt;
** read access is determined by file manager&lt;br /&gt;
&lt;br /&gt;
'''WRITE ACCESS'''&lt;br /&gt;
* ADMIN REQUIRING TOKEN FOR UPDATE&lt;br /&gt;
** write access governed by SQL server (and datalinker)&lt;br /&gt;
** involves write access token for modifying file content&lt;br /&gt;
* ADMIN NOT REQUIRING TOKEN FOR UPDATE&lt;br /&gt;
** write access governed by SQL server (and datalinker)&lt;br /&gt;
* BLOCKED&lt;br /&gt;
** linked files cannot be modified&lt;br /&gt;
* FS&lt;br /&gt;
** write access controlled by file manager&lt;br /&gt;
&lt;br /&gt;
'''RECOVERY'''&lt;br /&gt;
* YES&lt;br /&gt;
* NO&lt;br /&gt;
&lt;br /&gt;
'''ON UNLINK'''&lt;br /&gt;
* DELETE&lt;br /&gt;
** file is deleted when unlinked&lt;br /&gt;
* RESTORE&lt;br /&gt;
** original properties (ownership, permissions) restored as well&lt;br /&gt;
* NONE&lt;br /&gt;
** ownership and permissions are not restored&lt;br /&gt;
&lt;br /&gt;
==Implementation==&lt;br /&gt;
&lt;br /&gt;
Implementation of SQL/MED requires a lot of hocus-pocus and is probably event impossible to do properly on plain unix. Many parts, however seem to be implementable.&lt;br /&gt;
&lt;br /&gt;
System should support at least http: and file: URL schemes. These two require quite different implementations. Perhaps a support for pluggable URL schemes could be useful - consider for example RDF namespaces.&lt;br /&gt;
&lt;br /&gt;
When storing many URLs, it should be possible to greatly reduce space requirements by storing URLs only once in a master URL table and using an int4 or int8 as an actual DATALINK type. This greatly reduces storage requirements needed for many URLs, provided for the use case mentioned. It should be possible to partition the master URL table according to several criteria.&lt;br /&gt;
&lt;br /&gt;
Datalink software is divided in several parts:&lt;br /&gt;
* datalink database schema. Master URL table is stored here.&lt;br /&gt;
* external process ''datalinker''. It uses datalink schema. It manages files on behalf of postgresql server. It uses postgresql for implementing transactional semantics.&lt;br /&gt;
&lt;br /&gt;
QUESTION: what to do for multiple databases on same server?&lt;br /&gt;
&lt;br /&gt;
===Parts===&lt;br /&gt;
* DL - DATALINK SQL/MED + support functions&lt;br /&gt;
* FILEIO - local file access functions&lt;br /&gt;
* URL -  parsing and manipulation - one often needs to get and set various parts of URLs and filenames&lt;br /&gt;
&lt;br /&gt;
Some sort of inter-server communication is needed (to support remote files). Accessing datalinker api in a remote postgresql instance over libpq (say dblink) could maybe work.&lt;br /&gt;
&lt;br /&gt;
===Misc notes===&lt;br /&gt;
&lt;br /&gt;
On ext3 filesystem, files can be locked with 'chattr +i' command, but only by root. This prevents file from beeing changed, no matter what unix file permissions say.&lt;br /&gt;
&lt;br /&gt;
By changing file owner/group to postgres and setting unix file permissions, file can be made effectively owned by postgresql server (which can than use normal unix functions to use them).&lt;br /&gt;
&lt;br /&gt;
PL/PerlU seems the right choice for this, with Perl for external datalinker. Proper security and safety will be hard to get right!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:SQL/MED]]&lt;/div&gt;</summary>
		<author><name>Ziga</name></author>	</entry>

	<entry>
		<id>http://wiki.postgresql.org/wiki/DATALINK</id>
		<title>DATALINK</title>
		<link rel="alternate" type="text/html" href="http://wiki.postgresql.org/wiki/DATALINK"/>
				<updated>2010-04-08T18:29:51Z</updated>
		
		<summary type="html">&lt;p&gt;Ziga:&amp;#32;/* Introduction */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
SQL Datalinks are a part of SQL/MED ISO/IEC 9075-9:2003 specification.&lt;br /&gt;
Note that this is distinct from and complements efforts described [[SQL/MED|here]].&lt;br /&gt;
&lt;br /&gt;
Datalink is a special SQL type intended to store URLs in database columns,&lt;br /&gt;
and a number of functions, which can be used in SQL queries.&lt;br /&gt;
&lt;br /&gt;
There aren't many RDBMSs which implement SQL/MED datalinks. &lt;br /&gt;
IBM DB2 does. A lot of it is defined by the SQL standard to be &amp;quot;implementation specific&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Values of DATALINK type are opaque, constructed by using function DLVALUE.&lt;br /&gt;
There are several functions available for converting DATALINK back to text, &lt;br /&gt;
for example DLURLCOMPLETE.&lt;br /&gt;
&lt;br /&gt;
There is not much software, which demands SQL/MED datalinks.&lt;br /&gt;
However, there is functionality concerning files, URLs and web, which is often &lt;br /&gt;
needed in modern applications. Often, it is awkward to use these together &lt;br /&gt;
with RDBMS data. SQL/MED standardizes some of this.&lt;br /&gt;
&lt;br /&gt;
===Features===&lt;br /&gt;
A '''column''' containing a value of type DATALINK can optionally have some special semantics:&lt;br /&gt;
# referential integrity - file pointed to by a datalink cannot be renamed or deleted&lt;br /&gt;
# access control - either SQL or file system mediated&lt;br /&gt;
# point in time recovery of file changes&lt;br /&gt;
&lt;br /&gt;
Only references to external files are stored in the database, not the&lt;br /&gt;
content of the files themselves.&lt;br /&gt;
&lt;br /&gt;
Datalinks as defined by SQL/MED should provide:&lt;br /&gt;
* transactional semantics&lt;br /&gt;
* checking if file exists&lt;br /&gt;
* protection of linked file against renaming or deletion&lt;br /&gt;
* read access control through database&lt;br /&gt;
* write access control through database&lt;br /&gt;
* point-in-time recovery&lt;br /&gt;
* deletion of files no longer referenced&lt;br /&gt;
* access to files on different servers&lt;br /&gt;
&lt;br /&gt;
The following is not specified by SQL/MED, but is often needed in practice (and probably needed to implement datalink):&lt;br /&gt;
* compact URL storage for lots and lots of URLs (say int instead of string; sort-of like enum, but for URLs)&lt;br /&gt;
* URL to filesystem mapping, access control to file system hierarchies&lt;br /&gt;
* local server file access (read, write)&lt;br /&gt;
* remote server file access (get, put)&lt;br /&gt;
* extended file system attributes (get,set)&lt;br /&gt;
* file meta data (list,get,set)&lt;br /&gt;
&lt;br /&gt;
===Use cases===&lt;br /&gt;
Common use cases include:&lt;br /&gt;
* website content management - ensuring that linked-to URLs exist&lt;br /&gt;
* workflow management - providing for locking and versioning of files&lt;br /&gt;
* configuration - managing configuration files, ie have a change in database recreate text configuration file. This file should be locked and writeable only from database.&lt;br /&gt;
* web server log storage (many referer URLs)&lt;br /&gt;
* RDF databases (many URLs)&lt;br /&gt;
&lt;br /&gt;
Datalinks should enable you to:&lt;br /&gt;
* efficiently store URLs (datalinks are stored as integers, not strings)&lt;br /&gt;
* conveniently map between URLs and file system paths&lt;br /&gt;
* safely read and write files from SQL (SQL/MED does not specify functions for this)&lt;br /&gt;
* keep backups of changed files&lt;br /&gt;
* manage files on different servers&lt;br /&gt;
* manage datalink metadata (unified interface to extended filesystem attributes)&lt;br /&gt;
&lt;br /&gt;
==Specification==&lt;br /&gt;
===Synopsys===&lt;br /&gt;
&lt;br /&gt;
 create table my_files (&lt;br /&gt;
   ...,&lt;br /&gt;
   link datalink,&lt;br /&gt;
   ....&lt;br /&gt;
 )&lt;br /&gt;
 &lt;br /&gt;
 insert into my_files (link) select dlvalue('file:///etc/passwd');&lt;br /&gt;
  &lt;br /&gt;
 select into url dlurlcomplete(link) from my_files;&lt;br /&gt;
 &lt;br /&gt;
 update my_files set link=dlnewcopy(url,0);&lt;br /&gt;
 &lt;br /&gt;
 update my_files set link=dlpreviouscopy(url,0);&lt;br /&gt;
&lt;br /&gt;
=== Datalink support functions ===&lt;br /&gt;
&lt;br /&gt;
Constructors for values of type datalink:&lt;br /&gt;
&lt;br /&gt;
* DLVALUE(url) -&amp;gt; datalink (INSERT only)&lt;br /&gt;
* DLNEWCOPY(url,tokenp) -&amp;gt; datalink (UPDATE only)&lt;br /&gt;
* DLPREVIOUSCOPY(url,tokenp) -&amp;gt; datalink (UPDATE only)&lt;br /&gt;
&lt;br /&gt;
Functions for extracting information from datalink type:&lt;br /&gt;
&lt;br /&gt;
* DLURLCOMPLETE(datalink) -&amp;gt; url&lt;br /&gt;
* DLURLCOMPLETEONLY(datalink) -&amp;gt; url&lt;br /&gt;
* DLURLCOMPLETEWRITE(datalink) -&amp;gt; url&lt;br /&gt;
* DLURLPATH(datalink) -&amp;gt; fpath&lt;br /&gt;
* DLURLPATHONLY(datalink) -&amp;gt; fpath&lt;br /&gt;
* DLURLPATHWRITE(datalink) -&amp;gt; fpath&lt;br /&gt;
&lt;br /&gt;
* DLURLSCHEME(datalink) -&amp;gt; URL scheme (HTTP or FILE)&lt;br /&gt;
* DLURLSERVER(datalink) -&amp;gt; server address&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Datalink attributes per SQL spec ===&lt;br /&gt;
&lt;br /&gt;
These are refered to as ''link control options'' by SQL spec. They are insanely verbose as text, but can be stored in a typmod. They are specified '''per column''' and thus apply to all URLs stored.&lt;br /&gt;
&lt;br /&gt;
'''LINK CONTROL'''&lt;br /&gt;
* NO&lt;br /&gt;
** just store the datalink&lt;br /&gt;
** file is not &amp;quot;linked&amp;quot;, no further control&lt;br /&gt;
* FILE&lt;br /&gt;
** file is &amp;quot;linked&amp;quot;&lt;br /&gt;
** file has to exist&lt;br /&gt;
** level of control can be specified with further options&lt;br /&gt;
&lt;br /&gt;
'''INTEGRITY'''&lt;br /&gt;
* ALL - linked files cannot be deleted or renamed&lt;br /&gt;
* SELECTIVE  - linked files can only be deleted or modified using file manager operations, if no datalinker is installed&lt;br /&gt;
* NONE - referenced files can be deleted or modified using file manager operations, not compatible with FILE LINK CONTROL&lt;br /&gt;
&lt;br /&gt;
'''READ ACCESS'''&lt;br /&gt;
* DB&lt;br /&gt;
** read access is controlled by SQL server, based on access privileges to the datalink value&lt;br /&gt;
** involves read access tokens&lt;br /&gt;
*** encoded into the URL by the SQL server&lt;br /&gt;
*** verified by external file manager/data linker&lt;br /&gt;
* FS&lt;br /&gt;
** read access is determined by file manager&lt;br /&gt;
&lt;br /&gt;
'''WRITE ACCESS'''&lt;br /&gt;
* ADMIN REQUIRING TOKEN FOR UPDATE&lt;br /&gt;
** write access governed by SQL server (and datalinker)&lt;br /&gt;
** involves write access token for modifying file content&lt;br /&gt;
* ADMIN NOT REQUIRING TOKEN FOR UPDATE&lt;br /&gt;
** write access governed by SQL server (and datalinker)&lt;br /&gt;
* BLOCKED&lt;br /&gt;
** linked files cannot be modified&lt;br /&gt;
* FS&lt;br /&gt;
** write access controlled by file manager&lt;br /&gt;
&lt;br /&gt;
'''RECOVERY'''&lt;br /&gt;
* YES&lt;br /&gt;
* NO&lt;br /&gt;
&lt;br /&gt;
'''ON UNLINK'''&lt;br /&gt;
* DELETE&lt;br /&gt;
** file is deleted when unlinked&lt;br /&gt;
* RESTORE&lt;br /&gt;
** original properties (ownership, permissions) restored as well&lt;br /&gt;
* NONE&lt;br /&gt;
** ownership and permissions are not restored&lt;br /&gt;
&lt;br /&gt;
==Implementation==&lt;br /&gt;
&lt;br /&gt;
Implementation of SQL/MED requires a lot of hocus-pocus and is probably event impossible to do properly on plain unix. Many parts, however seem to be implementable.&lt;br /&gt;
&lt;br /&gt;
System should support at least http: and file: URL schemes. These two require quite different implementations. Perhaps a support for pluggable URL schemes could be useful - consider for example RDF namespaces.&lt;br /&gt;
&lt;br /&gt;
When storing many URLs, it should be possible to greatly reduce space requirements by storing URLs only once in a master URL table and using an int4 or int8 as an actual DATALINK type. This greatly reduces storage requirements needed for many URLs, provided for the use case mentioned. It should be possible to partition the master URL table according to several criteria.&lt;br /&gt;
&lt;br /&gt;
Datalink software is divided in several parts:&lt;br /&gt;
* datalink database schema. Master URL table is stored here.&lt;br /&gt;
* external process ''datalinker''. It uses datalink schema. It manages files on behalf of postgresql server. It uses postgresql for implementing transactional semantics.&lt;br /&gt;
&lt;br /&gt;
QUESTION: what to do for multiple databases on same server?&lt;br /&gt;
&lt;br /&gt;
===Parts===&lt;br /&gt;
* DL - DATALINK SQL/MED + support functions&lt;br /&gt;
* FILEIO - local file access functions&lt;br /&gt;
* URL -  parsing and manipulation - one often needs to get and set various parts of URLs and filenames&lt;br /&gt;
&lt;br /&gt;
Some sort of inter-server communication is needed (to support remote files). Accessing datalinker api in a remote postgresql instance over libpq (say dblink) could maybe work.&lt;br /&gt;
&lt;br /&gt;
===Misc notes===&lt;br /&gt;
&lt;br /&gt;
On ext3 filesystem, files can be locked with 'chattr +i' command, but only by root. This prevents file from beeing changed, no matter what unix file permissions say.&lt;br /&gt;
&lt;br /&gt;
By changing file owner/group to postgres and setting unix file permissions, file can be made effectively owned by postgresql server (which can than use normal unix functions to use them).&lt;br /&gt;
&lt;br /&gt;
PL/PerlU seems the right choice for this, with Perl for external datalinker. Proper security and safety will be hard to get right!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:SQL/MED]]&lt;/div&gt;</summary>
		<author><name>Ziga</name></author>	</entry>

	<entry>
		<id>http://wiki.postgresql.org/wiki/DATALINK</id>
		<title>DATALINK</title>
		<link rel="alternate" type="text/html" href="http://wiki.postgresql.org/wiki/DATALINK"/>
				<updated>2010-04-06T05:49:48Z</updated>
		
		<summary type="html">&lt;p&gt;Ziga:&amp;#32;/* Implementation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
SQL Datalinks are a part of SQL/MED ISO/IEC 9075-9:2003 specification.&lt;br /&gt;
&lt;br /&gt;
It is a special SQL type intended to store URLs in database columns,&lt;br /&gt;
and a number of functions, which can be used in SQL queries.&lt;br /&gt;
&lt;br /&gt;
There aren't many RDBMSs which implement SQL/MED datalinks. &lt;br /&gt;
IBM DB2 implements it. A lot of it is defined to be &amp;quot;implementation specific&amp;quot; &lt;br /&gt;
by the SQL standard.&lt;br /&gt;
&lt;br /&gt;
Values of DATALINK type are opaque, constructed by using function DLVALUE.&lt;br /&gt;
There are several functions available for converting DATALINK back to text, &lt;br /&gt;
for example DLURLCOMPLETE.&lt;br /&gt;
&lt;br /&gt;
There is not much software, which demands SQL/MED datalinks.&lt;br /&gt;
There is functionality concerning files, URLs and web, which is often &lt;br /&gt;
needed in modern applications. Often, it is awkward to use these together &lt;br /&gt;
with RDBMS data. SQL/MED standardizes some of this.&lt;br /&gt;
&lt;br /&gt;
===Features===&lt;br /&gt;
A '''column''' containing a value of type DATALINK can optionally have some special semantics:&lt;br /&gt;
# referential integrity - file pointed to by a datalink cannot be renamed or deleted&lt;br /&gt;
# access control - either SQL or file system mediated&lt;br /&gt;
# point in time recovery of file changes&lt;br /&gt;
&lt;br /&gt;
Only references to external files are stored in the database, not the&lt;br /&gt;
content of the files themselves.&lt;br /&gt;
&lt;br /&gt;
Datalinks as defined by SQL/MED should provide:&lt;br /&gt;
* transactional semantics&lt;br /&gt;
* checking if file exists&lt;br /&gt;
* protection of linked file against renaming or deletion&lt;br /&gt;
* read access control through database&lt;br /&gt;
* write access control through database&lt;br /&gt;
* point-in-time recovery&lt;br /&gt;
* deletion of files no longer referenced&lt;br /&gt;
* access to files on different servers&lt;br /&gt;
&lt;br /&gt;
The following is not specified by SQL/MED, but is often needed in practice (and probably needed to implement datalink):&lt;br /&gt;
* compact URL storage for lots and lots of URLs (say int instead of string; sort-of like enum, but for URLs)&lt;br /&gt;
* URL to filesystem mapping, access control to file system hierarchies&lt;br /&gt;
* local server file access (read, write)&lt;br /&gt;
* remote server file access (get, put)&lt;br /&gt;
* extended file system attributes (get,set)&lt;br /&gt;
* file meta data (list,get,set)&lt;br /&gt;
&lt;br /&gt;
===Use cases===&lt;br /&gt;
Common use cases include:&lt;br /&gt;
* website content management - ensuring that linked-to URLs exist&lt;br /&gt;
* workflow management - providing for locking and versioning of files&lt;br /&gt;
* configuration - managing configuration files, ie have a change in database recreate text configuration file. This file should be locked and writeable only from database.&lt;br /&gt;
* web server log storage (many referer URLs)&lt;br /&gt;
* RDF databases (many URLs)&lt;br /&gt;
&lt;br /&gt;
Datalinks should enable you to:&lt;br /&gt;
* efficiently store URLs (datalinks are stored as integers, not strings)&lt;br /&gt;
* conveniently map between URLs and file system paths&lt;br /&gt;
* safely read and write files from SQL (SQL/MED does not specify functions for this)&lt;br /&gt;
* keep backups of changed files&lt;br /&gt;
* manage files on different servers&lt;br /&gt;
* manage datalink metadata (unified interface to extended filesystem attributes)&lt;br /&gt;
&lt;br /&gt;
==Specification==&lt;br /&gt;
===Synopsys===&lt;br /&gt;
&lt;br /&gt;
 create table my_files (&lt;br /&gt;
   ...,&lt;br /&gt;
   link datalink,&lt;br /&gt;
   ....&lt;br /&gt;
 )&lt;br /&gt;
 &lt;br /&gt;
 insert into my_files (link) select dlvalue('file:///etc/passwd');&lt;br /&gt;
  &lt;br /&gt;
 select into url dlurlcomplete(link) from my_files;&lt;br /&gt;
 &lt;br /&gt;
 update my_files set link=dlnewcopy(url,0);&lt;br /&gt;
 &lt;br /&gt;
 update my_files set link=dlpreviouscopy(url,0);&lt;br /&gt;
&lt;br /&gt;
=== Datalink support functions ===&lt;br /&gt;
&lt;br /&gt;
Constructors for values of type datalink:&lt;br /&gt;
&lt;br /&gt;
* DLVALUE(url) -&amp;gt; datalink (INSERT only)&lt;br /&gt;
* DLNEWCOPY(url,tokenp) -&amp;gt; datalink (UPDATE only)&lt;br /&gt;
* DLPREVIOUSCOPY(url,tokenp) -&amp;gt; datalink (UPDATE only)&lt;br /&gt;
&lt;br /&gt;
Functions for extracting information from datalink type:&lt;br /&gt;
&lt;br /&gt;
* DLURLCOMPLETE(datalink) -&amp;gt; url&lt;br /&gt;
* DLURLCOMPLETEONLY(datalink) -&amp;gt; url&lt;br /&gt;
* DLURLCOMPLETEWRITE(datalink) -&amp;gt; url&lt;br /&gt;
* DLURLPATH(datalink) -&amp;gt; fpath&lt;br /&gt;
* DLURLPATHONLY(datalink) -&amp;gt; fpath&lt;br /&gt;
* DLURLPATHWRITE(datalink) -&amp;gt; fpath&lt;br /&gt;
&lt;br /&gt;
* DLURLSCHEME(datalink) -&amp;gt; URL scheme (HTTP or FILE)&lt;br /&gt;
* DLURLSERVER(datalink) -&amp;gt; server address&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Datalink attributes per SQL spec ===&lt;br /&gt;
&lt;br /&gt;
These are refered to as ''link control options'' by SQL spec. They are insanely verbose as text, but can be stored in a typmod. They are specified '''per column''' and thus apply to all URLs stored.&lt;br /&gt;
&lt;br /&gt;
'''LINK CONTROL'''&lt;br /&gt;
* NO&lt;br /&gt;
** just store the datalink&lt;br /&gt;
** file is not &amp;quot;linked&amp;quot;, no further control&lt;br /&gt;
* FILE&lt;br /&gt;
** file is &amp;quot;linked&amp;quot;&lt;br /&gt;
** file has to exist&lt;br /&gt;
** level of control can be specified with further options&lt;br /&gt;
&lt;br /&gt;
'''INTEGRITY'''&lt;br /&gt;
* ALL - linked files cannot be deleted or renamed&lt;br /&gt;
* SELECTIVE  - linked files can only be deleted or modified using file manager operations, if no datalinker is installed&lt;br /&gt;
* NONE - referenced files can be deleted or modified using file manager operations, not compatible with FILE LINK CONTROL&lt;br /&gt;
&lt;br /&gt;
'''READ ACCESS'''&lt;br /&gt;
* DB&lt;br /&gt;
** read access is controlled by SQL server, based on access privileges to the datalink value&lt;br /&gt;
** involves read access tokens&lt;br /&gt;
*** encoded into the URL by the SQL server&lt;br /&gt;
*** verified by external file manager/data linker&lt;br /&gt;
* FS&lt;br /&gt;
** read access is determined by file manager&lt;br /&gt;
&lt;br /&gt;
'''WRITE ACCESS'''&lt;br /&gt;
* ADMIN REQUIRING TOKEN FOR UPDATE&lt;br /&gt;
** write access governed by SQL server (and datalinker)&lt;br /&gt;
** involves write access token for modifying file content&lt;br /&gt;
* ADMIN NOT REQUIRING TOKEN FOR UPDATE&lt;br /&gt;
** write access governed by SQL server (and datalinker)&lt;br /&gt;
* BLOCKED&lt;br /&gt;
** linked files cannot be modified&lt;br /&gt;
* FS&lt;br /&gt;
** write access controlled by file manager&lt;br /&gt;
&lt;br /&gt;
'''RECOVERY'''&lt;br /&gt;
* YES&lt;br /&gt;
* NO&lt;br /&gt;
&lt;br /&gt;
'''ON UNLINK'''&lt;br /&gt;
* DELETE&lt;br /&gt;
** file is deleted when unlinked&lt;br /&gt;
* RESTORE&lt;br /&gt;
** original properties (ownership, permissions) restored as well&lt;br /&gt;
* NONE&lt;br /&gt;
** ownership and permissions are not restored&lt;br /&gt;
&lt;br /&gt;
==Implementation==&lt;br /&gt;
&lt;br /&gt;
Implementation of SQL/MED requires a lot of hocus-pocus and is probably event impossible to do properly on plain unix. Many parts, however seem to be implementable.&lt;br /&gt;
&lt;br /&gt;
System should support at least http: and file: URL schemes. These two require quite different implementations. Perhaps a support for pluggable URL schemes could be useful - consider for example RDF namespaces.&lt;br /&gt;
&lt;br /&gt;
When storing many URLs, it should be possible to greatly reduce space requirements by storing URLs only once in a master URL table and using an int4 or int8 as an actual DATALINK type. This greatly reduces storage requirements needed for many URLs, provided for the use case mentioned. It should be possible to partition the master URL table according to several criteria.&lt;br /&gt;
&lt;br /&gt;
Datalink software is divided in several parts:&lt;br /&gt;
* datalink database schema. Master URL table is stored here.&lt;br /&gt;
* external process ''datalinker''. It uses datalink schema. It manages files on behalf of postgresql server. It uses postgresql for implementing transactional semantics.&lt;br /&gt;
&lt;br /&gt;
QUESTION: what to do for multiple databases on same server?&lt;br /&gt;
&lt;br /&gt;
===Parts===&lt;br /&gt;
* DL - DATALINK SQL/MED + support functions&lt;br /&gt;
* FILEIO - local file access functions&lt;br /&gt;
* URL -  parsing and manipulation - one often needs to get and set various parts of URLs and filenames&lt;br /&gt;
&lt;br /&gt;
Some sort of inter-server communication is needed (to support remote files). Accessing datalinker api in a remote postgresql instance over libpq (say dblink) could maybe work.&lt;br /&gt;
&lt;br /&gt;
===Misc notes===&lt;br /&gt;
&lt;br /&gt;
On ext3 filesystem, files can be locked with 'chattr +i' command, but only by root. This prevents file from beeing changed, no matter what unix file permissions say.&lt;br /&gt;
&lt;br /&gt;
By changing file owner/group to postgres and setting unix file permissions, file can be made effectively owned by postgresql server (which can than use normal unix functions to use them).&lt;br /&gt;
&lt;br /&gt;
PL/PerlU seems the right choice for this, with Perl for external datalinker. Proper security and safety will be hard to get right!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:SQL/MED]]&lt;/div&gt;</summary>
		<author><name>Ziga</name></author>	</entry>

	<entry>
		<id>http://wiki.postgresql.org/wiki/DATALINK</id>
		<title>DATALINK</title>
		<link rel="alternate" type="text/html" href="http://wiki.postgresql.org/wiki/DATALINK"/>
				<updated>2010-04-06T05:46:15Z</updated>
		
		<summary type="html">&lt;p&gt;Ziga:&amp;#32;/* Datalink attributes per SQL spec */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
SQL Datalinks are a part of SQL/MED ISO/IEC 9075-9:2003 specification.&lt;br /&gt;
&lt;br /&gt;
It is a special SQL type intended to store URLs in database columns,&lt;br /&gt;
and a number of functions, which can be used in SQL queries.&lt;br /&gt;
&lt;br /&gt;
There aren't many RDBMSs which implement SQL/MED datalinks. &lt;br /&gt;
IBM DB2 implements it. A lot of it is defined to be &amp;quot;implementation specific&amp;quot; &lt;br /&gt;
by the SQL standard.&lt;br /&gt;
&lt;br /&gt;
Values of DATALINK type are opaque, constructed by using function DLVALUE.&lt;br /&gt;
There are several functions available for converting DATALINK back to text, &lt;br /&gt;
for example DLURLCOMPLETE.&lt;br /&gt;
&lt;br /&gt;
There is not much software, which demands SQL/MED datalinks.&lt;br /&gt;
There is functionality concerning files, URLs and web, which is often &lt;br /&gt;
needed in modern applications. Often, it is awkward to use these together &lt;br /&gt;
with RDBMS data. SQL/MED standardizes some of this.&lt;br /&gt;
&lt;br /&gt;
===Features===&lt;br /&gt;
A '''column''' containing a value of type DATALINK can optionally have some special semantics:&lt;br /&gt;
# referential integrity - file pointed to by a datalink cannot be renamed or deleted&lt;br /&gt;
# access control - either SQL or file system mediated&lt;br /&gt;
# point in time recovery of file changes&lt;br /&gt;
&lt;br /&gt;
Only references to external files are stored in the database, not the&lt;br /&gt;
content of the files themselves.&lt;br /&gt;
&lt;br /&gt;
Datalinks as defined by SQL/MED should provide:&lt;br /&gt;
* transactional semantics&lt;br /&gt;
* checking if file exists&lt;br /&gt;
* protection of linked file against renaming or deletion&lt;br /&gt;
* read access control through database&lt;br /&gt;
* write access control through database&lt;br /&gt;
* point-in-time recovery&lt;br /&gt;
* deletion of files no longer referenced&lt;br /&gt;
* access to files on different servers&lt;br /&gt;
&lt;br /&gt;
The following is not specified by SQL/MED, but is often needed in practice (and probably needed to implement datalink):&lt;br /&gt;
* compact URL storage for lots and lots of URLs (say int instead of string; sort-of like enum, but for URLs)&lt;br /&gt;
* URL to filesystem mapping, access control to file system hierarchies&lt;br /&gt;
* local server file access (read, write)&lt;br /&gt;
* remote server file access (get, put)&lt;br /&gt;
* extended file system attributes (get,set)&lt;br /&gt;
* file meta data (list,get,set)&lt;br /&gt;
&lt;br /&gt;
===Use cases===&lt;br /&gt;
Common use cases include:&lt;br /&gt;
* website content management - ensuring that linked-to URLs exist&lt;br /&gt;
* workflow management - providing for locking and versioning of files&lt;br /&gt;
* configuration - managing configuration files, ie have a change in database recreate text configuration file. This file should be locked and writeable only from database.&lt;br /&gt;
* web server log storage (many referer URLs)&lt;br /&gt;
* RDF databases (many URLs)&lt;br /&gt;
&lt;br /&gt;
Datalinks should enable you to:&lt;br /&gt;
* efficiently store URLs (datalinks are stored as integers, not strings)&lt;br /&gt;
* conveniently map between URLs and file system paths&lt;br /&gt;
* safely read and write files from SQL (SQL/MED does not specify functions for this)&lt;br /&gt;
* keep backups of changed files&lt;br /&gt;
* manage files on different servers&lt;br /&gt;
* manage datalink metadata (unified interface to extended filesystem attributes)&lt;br /&gt;
&lt;br /&gt;
==Specification==&lt;br /&gt;
===Synopsys===&lt;br /&gt;
&lt;br /&gt;
 create table my_files (&lt;br /&gt;
   ...,&lt;br /&gt;
   link datalink,&lt;br /&gt;
   ....&lt;br /&gt;
 )&lt;br /&gt;
 &lt;br /&gt;
 insert into my_files (link) select dlvalue('file:///etc/passwd');&lt;br /&gt;
  &lt;br /&gt;
 select into url dlurlcomplete(link) from my_files;&lt;br /&gt;
 &lt;br /&gt;
 update my_files set link=dlnewcopy(url,0);&lt;br /&gt;
 &lt;br /&gt;
 update my_files set link=dlpreviouscopy(url,0);&lt;br /&gt;
&lt;br /&gt;
=== Datalink support functions ===&lt;br /&gt;
&lt;br /&gt;
Constructors for values of type datalink:&lt;br /&gt;
&lt;br /&gt;
* DLVALUE(url) -&amp;gt; datalink (INSERT only)&lt;br /&gt;
* DLNEWCOPY(url,tokenp) -&amp;gt; datalink (UPDATE only)&lt;br /&gt;
* DLPREVIOUSCOPY(url,tokenp) -&amp;gt; datalink (UPDATE only)&lt;br /&gt;
&lt;br /&gt;
Functions for extracting information from datalink type:&lt;br /&gt;
&lt;br /&gt;
* DLURLCOMPLETE(datalink) -&amp;gt; url&lt;br /&gt;
* DLURLCOMPLETEONLY(datalink) -&amp;gt; url&lt;br /&gt;
* DLURLCOMPLETEWRITE(datalink) -&amp;gt; url&lt;br /&gt;
* DLURLPATH(datalink) -&amp;gt; fpath&lt;br /&gt;
* DLURLPATHONLY(datalink) -&amp;gt; fpath&lt;br /&gt;
* DLURLPATHWRITE(datalink) -&amp;gt; fpath&lt;br /&gt;
&lt;br /&gt;
* DLURLSCHEME(datalink) -&amp;gt; URL scheme (HTTP or FILE)&lt;br /&gt;
* DLURLSERVER(datalink) -&amp;gt; server address&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Datalink attributes per SQL spec ===&lt;br /&gt;
&lt;br /&gt;
These are refered to as ''link control options'' by SQL spec. They are insanely verbose as text, but can be stored in a typmod. They are specified '''per column''' and thus apply to all URLs stored.&lt;br /&gt;
&lt;br /&gt;
'''LINK CONTROL'''&lt;br /&gt;
* NO&lt;br /&gt;
** just store the datalink&lt;br /&gt;
** file is not &amp;quot;linked&amp;quot;, no further control&lt;br /&gt;
* FILE&lt;br /&gt;
** file is &amp;quot;linked&amp;quot;&lt;br /&gt;
** file has to exist&lt;br /&gt;
** level of control can be specified with further options&lt;br /&gt;
&lt;br /&gt;
'''INTEGRITY'''&lt;br /&gt;
* ALL - linked files cannot be deleted or renamed&lt;br /&gt;
* SELECTIVE  - linked files can only be deleted or modified using file manager operations, if no datalinker is installed&lt;br /&gt;
* NONE - referenced files can be deleted or modified using file manager operations, not compatible with FILE LINK CONTROL&lt;br /&gt;
&lt;br /&gt;
'''READ ACCESS'''&lt;br /&gt;
* DB&lt;br /&gt;
** read access is controlled by SQL server, based on access privileges to the datalink value&lt;br /&gt;
** involves read access tokens&lt;br /&gt;
*** encoded into the URL by the SQL server&lt;br /&gt;
*** verified by external file manager/data linker&lt;br /&gt;
* FS&lt;br /&gt;
** read access is determined by file manager&lt;br /&gt;
&lt;br /&gt;
'''WRITE ACCESS'''&lt;br /&gt;
* ADMIN REQUIRING TOKEN FOR UPDATE&lt;br /&gt;
** write access governed by SQL server (and datalinker)&lt;br /&gt;
** involves write access token for modifying file content&lt;br /&gt;
* ADMIN NOT REQUIRING TOKEN FOR UPDATE&lt;br /&gt;
** write access governed by SQL server (and datalinker)&lt;br /&gt;
* BLOCKED&lt;br /&gt;
** linked files cannot be modified&lt;br /&gt;
* FS&lt;br /&gt;
** write access controlled by file manager&lt;br /&gt;
&lt;br /&gt;
'''RECOVERY'''&lt;br /&gt;
* YES&lt;br /&gt;
* NO&lt;br /&gt;
&lt;br /&gt;
'''ON UNLINK'''&lt;br /&gt;
* DELETE&lt;br /&gt;
** file is deleted when unlinked&lt;br /&gt;
* RESTORE&lt;br /&gt;
** original properties (ownership, permissions) restored as well&lt;br /&gt;
* NONE&lt;br /&gt;
** ownership and permissions are not restored&lt;br /&gt;
&lt;br /&gt;
==Implementation==&lt;br /&gt;
&lt;br /&gt;
Implementation of SQL/MED requires a lot of hocus-pocus and is probably event impossible to do properly on plain unix. Many parts however seem to be implementable.&lt;br /&gt;
&lt;br /&gt;
System should support at least http: and file: URL schemes. These two require quite different implementations. Perhaps a support for pluggable URL schemes could be useful - consider for example RDF namespaces.&lt;br /&gt;
&lt;br /&gt;
When storing many URLs, it should be possible to greatly reduce space requirements by storing URLs only once in a master URL table and using an int4 or int8 as an actual DATALINK type. This greatly reduces storage requirements needed for many URLs, provided for the use case mentioned. It should be possible to partition the master URL table according to several criteria.&lt;br /&gt;
&lt;br /&gt;
Datalink software is divided in several parts:&lt;br /&gt;
* datalink database schema. Master URL table is stored here.&lt;br /&gt;
* external process ''datalinker''. It uses datalink schema. It manages files on behalf of postgresql server. It uses postgresql for implementing transactional semantics.&lt;br /&gt;
&lt;br /&gt;
QUESTION: what to do for multiple databases on same server?&lt;br /&gt;
&lt;br /&gt;
===Parts===&lt;br /&gt;
* DL - DATALINK SQL/MED + support functions&lt;br /&gt;
* FILEIO - local file access functions&lt;br /&gt;
* URL -  parsing and manipulation - one often needs to get and set various parts of URLs and filenames&lt;br /&gt;
&lt;br /&gt;
+ some sort of inter-server communication&lt;br /&gt;
&lt;br /&gt;
===Misc notes===&lt;br /&gt;
&lt;br /&gt;
On ext3 filesystem, files can be locked with 'chattr +i' command, but only by root. This prevents file from beeing changed, no matter what unix file permissions say.&lt;br /&gt;
&lt;br /&gt;
By changing file owner/group to postgres and setting unix file permissions, file can be made effectively owned by postgresql server (which can than use normal unix functions to use them).&lt;br /&gt;
&lt;br /&gt;
PL/PerlU seems the right choice for this, with Perl for external datalinker. Proper security and safety will be hard to get right!&lt;br /&gt;
&lt;br /&gt;
[[Category:SQL/MED]]&lt;/div&gt;</summary>
		<author><name>Ziga</name></author>	</entry>

	<entry>
		<id>http://wiki.postgresql.org/wiki/DATALINK</id>
		<title>DATALINK</title>
		<link rel="alternate" type="text/html" href="http://wiki.postgresql.org/wiki/DATALINK"/>
				<updated>2010-04-06T05:45:48Z</updated>
		
		<summary type="html">&lt;p&gt;Ziga:&amp;#32;/* Datalink attributes per SQL spec */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
SQL Datalinks are a part of SQL/MED ISO/IEC 9075-9:2003 specification.&lt;br /&gt;
&lt;br /&gt;
It is a special SQL type intended to store URLs in database columns,&lt;br /&gt;
and a number of functions, which can be used in SQL queries.&lt;br /&gt;
&lt;br /&gt;
There aren't many RDBMSs which implement SQL/MED datalinks. &lt;br /&gt;
IBM DB2 implements it. A lot of it is defined to be &amp;quot;implementation specific&amp;quot; &lt;br /&gt;
by the SQL standard.&lt;br /&gt;
&lt;br /&gt;
Values of DATALINK type are opaque, constructed by using function DLVALUE.&lt;br /&gt;
There are several functions available for converting DATALINK back to text, &lt;br /&gt;
for example DLURLCOMPLETE.&lt;br /&gt;
&lt;br /&gt;
There is not much software, which demands SQL/MED datalinks.&lt;br /&gt;
There is functionality concerning files, URLs and web, which is often &lt;br /&gt;
needed in modern applications. Often, it is awkward to use these together &lt;br /&gt;
with RDBMS data. SQL/MED standardizes some of this.&lt;br /&gt;
&lt;br /&gt;
===Features===&lt;br /&gt;
A '''column''' containing a value of type DATALINK can optionally have some special semantics:&lt;br /&gt;
# referential integrity - file pointed to by a datalink cannot be renamed or deleted&lt;br /&gt;
# access control - either SQL or file system mediated&lt;br /&gt;
# point in time recovery of file changes&lt;br /&gt;
&lt;br /&gt;
Only references to external files are stored in the database, not the&lt;br /&gt;
content of the files themselves.&lt;br /&gt;
&lt;br /&gt;
Datalinks as defined by SQL/MED should provide:&lt;br /&gt;
* transactional semantics&lt;br /&gt;
* checking if file exists&lt;br /&gt;
* protection of linked file against renaming or deletion&lt;br /&gt;
* read access control through database&lt;br /&gt;
* write access control through database&lt;br /&gt;
* point-in-time recovery&lt;br /&gt;
* deletion of files no longer referenced&lt;br /&gt;
* access to files on different servers&lt;br /&gt;
&lt;br /&gt;
The following is not specified by SQL/MED, but is often needed in practice (and probably needed to implement datalink):&lt;br /&gt;
* compact URL storage for lots and lots of URLs (say int instead of string; sort-of like enum, but for URLs)&lt;br /&gt;
* URL to filesystem mapping, access control to file system hierarchies&lt;br /&gt;
* local server file access (read, write)&lt;br /&gt;
* remote server file access (get, put)&lt;br /&gt;
* extended file system attributes (get,set)&lt;br /&gt;
* file meta data (list,get,set)&lt;br /&gt;
&lt;br /&gt;
===Use cases===&lt;br /&gt;
Common use cases include:&lt;br /&gt;
* website content management - ensuring that linked-to URLs exist&lt;br /&gt;
* workflow management - providing for locking and versioning of files&lt;br /&gt;
* configuration - managing configuration files, ie have a change in database recreate text configuration file. This file should be locked and writeable only from database.&lt;br /&gt;
* web server log storage (many referer URLs)&lt;br /&gt;
* RDF databases (many URLs)&lt;br /&gt;
&lt;br /&gt;
Datalinks should enable you to:&lt;br /&gt;
* efficiently store URLs (datalinks are stored as integers, not strings)&lt;br /&gt;
* conveniently map between URLs and file system paths&lt;br /&gt;
* safely read and write files from SQL (SQL/MED does not specify functions for this)&lt;br /&gt;
* keep backups of changed files&lt;br /&gt;
* manage files on different servers&lt;br /&gt;
* manage datalink metadata (unified interface to extended filesystem attributes)&lt;br /&gt;
&lt;br /&gt;
==Specification==&lt;br /&gt;
===Synopsys===&lt;br /&gt;
&lt;br /&gt;
 create table my_files (&lt;br /&gt;
   ...,&lt;br /&gt;
   link datalink,&lt;br /&gt;
   ....&lt;br /&gt;
 )&lt;br /&gt;
 &lt;br /&gt;
 insert into my_files (link) select dlvalue('file:///etc/passwd');&lt;br /&gt;
  &lt;br /&gt;
 select into url dlurlcomplete(link) from my_files;&lt;br /&gt;
 &lt;br /&gt;
 update my_files set link=dlnewcopy(url,0);&lt;br /&gt;
 &lt;br /&gt;
 update my_files set link=dlpreviouscopy(url,0);&lt;br /&gt;
&lt;br /&gt;
=== Datalink support functions ===&lt;br /&gt;
&lt;br /&gt;
Constructors for values of type datalink:&lt;br /&gt;
&lt;br /&gt;
* DLVALUE(url) -&amp;gt; datalink (INSERT only)&lt;br /&gt;
* DLNEWCOPY(url,tokenp) -&amp;gt; datalink (UPDATE only)&lt;br /&gt;
* DLPREVIOUSCOPY(url,tokenp) -&amp;gt; datalink (UPDATE only)&lt;br /&gt;
&lt;br /&gt;
Functions for extracting information from datalink type:&lt;br /&gt;
&lt;br /&gt;
* DLURLCOMPLETE(datalink) -&amp;gt; url&lt;br /&gt;
* DLURLCOMPLETEONLY(datalink) -&amp;gt; url&lt;br /&gt;
* DLURLCOMPLETEWRITE(datalink) -&amp;gt; url&lt;br /&gt;
* DLURLPATH(datalink) -&amp;gt; fpath&lt;br /&gt;
* DLURLPATHONLY(datalink) -&amp;gt; fpath&lt;br /&gt;
* DLURLPATHWRITE(datalink) -&amp;gt; fpath&lt;br /&gt;
&lt;br /&gt;
* DLURLSCHEME(datalink) -&amp;gt; URL scheme (HTTP or FILE)&lt;br /&gt;
* DLURLSERVER(datalink) -&amp;gt; server address&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Datalink attributes per SQL spec ===&lt;br /&gt;
&lt;br /&gt;
These are refered to as ''link control options'' by SQL spec. They are insanely verbose as text, but can be stored in a typmod. They are specified '''per column''' and thus apply to all URLs stored.&lt;br /&gt;
&lt;br /&gt;
'''LINK CONTROL'''&lt;br /&gt;
* NO&lt;br /&gt;
** just store the datalink&lt;br /&gt;
** file is not &amp;quot;linked&amp;quot;, no further control&lt;br /&gt;
* FILE&lt;br /&gt;
** file is &amp;quot;linked&amp;quot;&lt;br /&gt;
** file has to exist&lt;br /&gt;
** level of control can be specified with further options&lt;br /&gt;
&lt;br /&gt;
'''INTEGRITY'''&lt;br /&gt;
* ALL - linked files cannot be deleted or renamed&lt;br /&gt;
* SELECTIVE  - linked files can only be deleted or modified using file manager operations, if no datalinker is installed&lt;br /&gt;
* NONE - referenced files can be deleted or modified using file manager operations, not compatible with FILE LINK CONTROL&lt;br /&gt;
&lt;br /&gt;
'''READ ACCESS'''&lt;br /&gt;
* DB&lt;br /&gt;
** read access is controlled by SQL server, based on access privileges to the datalink value&lt;br /&gt;
** involves read access tokens&lt;br /&gt;
*** encoded into the URL by the SQL server&lt;br /&gt;
*** verified by external file manager/data linker&lt;br /&gt;
* FS&lt;br /&gt;
** read access is determined by file manager&lt;br /&gt;
&lt;br /&gt;
'''WRITE ACCESS'''&lt;br /&gt;
* ADMIN REQUIRING TOKEN FOR UPDATE&lt;br /&gt;
** write access governed by SQL server (and datalinker)&lt;br /&gt;
** involves write access token for modifying file content&lt;br /&gt;
* ADMIN NOT REQUIRING TOKEN FOR UPDATE&lt;br /&gt;
** write access governed by SQL server (and datalinker)&lt;br /&gt;
* BLOCKED&lt;br /&gt;
** linked files cannot be modified&lt;br /&gt;
* FS&lt;br /&gt;
** write access controlled by file manager&lt;br /&gt;
&lt;br /&gt;
'''RECOVERY'''&lt;br /&gt;
* YES&lt;br /&gt;
* NO&lt;br /&gt;
&lt;br /&gt;
'''UNLINK'''&lt;br /&gt;
* DELETE&lt;br /&gt;
** file is deleted when unlinked&lt;br /&gt;
* RESTORE&lt;br /&gt;
** original properties (ownership, permissions) restored as well&lt;br /&gt;
* NONE&lt;br /&gt;
** ownership and permissions are not restored&lt;br /&gt;
&lt;br /&gt;
==Implementation==&lt;br /&gt;
&lt;br /&gt;
Implementation of SQL/MED requires a lot of hocus-pocus and is probably event impossible to do properly on plain unix. Many parts however seem to be implementable.&lt;br /&gt;
&lt;br /&gt;
System should support at least http: and file: URL schemes. These two require quite different implementations. Perhaps a support for pluggable URL schemes could be useful - consider for example RDF namespaces.&lt;br /&gt;
&lt;br /&gt;
When storing many URLs, it should be possible to greatly reduce space requirements by storing URLs only once in a master URL table and using an int4 or int8 as an actual DATALINK type. This greatly reduces storage requirements needed for many URLs, provided for the use case mentioned. It should be possible to partition the master URL table according to several criteria.&lt;br /&gt;
&lt;br /&gt;
Datalink software is divided in several parts:&lt;br /&gt;
* datalink database schema. Master URL table is stored here.&lt;br /&gt;
* external process ''datalinker''. It uses datalink schema. It manages files on behalf of postgresql server. It uses postgresql for implementing transactional semantics.&lt;br /&gt;
&lt;br /&gt;
QUESTION: what to do for multiple databases on same server?&lt;br /&gt;
&lt;br /&gt;
===Parts===&lt;br /&gt;
* DL - DATALINK SQL/MED + support functions&lt;br /&gt;
* FILEIO - local file access functions&lt;br /&gt;
* URL -  parsing and manipulation - one often needs to get and set various parts of URLs and filenames&lt;br /&gt;
&lt;br /&gt;
+ some sort of inter-server communication&lt;br /&gt;
&lt;br /&gt;
===Misc notes===&lt;br /&gt;
&lt;br /&gt;
On ext3 filesystem, files can be locked with 'chattr +i' command, but only by root. This prevents file from beeing changed, no matter what unix file permissions say.&lt;br /&gt;
&lt;br /&gt;
By changing file owner/group to postgres and setting unix file permissions, file can be made effectively owned by postgresql server (which can than use normal unix functions to use them).&lt;br /&gt;
&lt;br /&gt;
PL/PerlU seems the right choice for this, with Perl for external datalinker. Proper security and safety will be hard to get right!&lt;br /&gt;
&lt;br /&gt;
[[Category:SQL/MED]]&lt;/div&gt;</summary>
		<author><name>Ziga</name></author>	</entry>

	<entry>
		<id>http://wiki.postgresql.org/wiki/DATALINK</id>
		<title>DATALINK</title>
		<link rel="alternate" type="text/html" href="http://wiki.postgresql.org/wiki/DATALINK"/>
				<updated>2010-04-06T05:41:41Z</updated>
		
		<summary type="html">&lt;p&gt;Ziga:&amp;#32;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
SQL Datalinks are a part of SQL/MED ISO/IEC 9075-9:2003 specification.&lt;br /&gt;
&lt;br /&gt;
It is a special SQL type intended to store URLs in database columns,&lt;br /&gt;
and a number of functions, which can be used in SQL queries.&lt;br /&gt;
&lt;br /&gt;
There aren't many RDBMSs which implement SQL/MED datalinks. &lt;br /&gt;
IBM DB2 implements it. A lot of it is defined to be &amp;quot;implementation specific&amp;quot; &lt;br /&gt;
by the SQL standard.&lt;br /&gt;
&lt;br /&gt;
Values of DATALINK type are opaque, constructed by using function DLVALUE.&lt;br /&gt;
There are several functions available for converting DATALINK back to text, &lt;br /&gt;
for example DLURLCOMPLETE.&lt;br /&gt;
&lt;br /&gt;
There is not much software, which demands SQL/MED datalinks.&lt;br /&gt;
There is functionality concerning files, URLs and web, which is often &lt;br /&gt;
needed in modern applications. Often, it is awkward to use these together &lt;br /&gt;
with RDBMS data. SQL/MED standardizes some of this.&lt;br /&gt;
&lt;br /&gt;
===Features===&lt;br /&gt;
A '''column''' containing a value of type DATALINK can optionally have some special semantics:&lt;br /&gt;
# referential integrity - file pointed to by a datalink cannot be renamed or deleted&lt;br /&gt;
# access control - either SQL or file system mediated&lt;br /&gt;
# point in time recovery of file changes&lt;br /&gt;
&lt;br /&gt;
Only references to external files are stored in the database, not the&lt;br /&gt;
content of the files themselves.&lt;br /&gt;
&lt;br /&gt;
Datalinks as defined by SQL/MED should provide:&lt;br /&gt;
* transactional semantics&lt;br /&gt;
* checking if file exists&lt;br /&gt;
* protection of linked file against renaming or deletion&lt;br /&gt;
* read access control through database&lt;br /&gt;
* write access control through database&lt;br /&gt;
* point-in-time recovery&lt;br /&gt;
* deletion of files no longer referenced&lt;br /&gt;
* access to files on different servers&lt;br /&gt;
&lt;br /&gt;
The following is not specified by SQL/MED, but is often needed in practice (and probably needed to implement datalink):&lt;br /&gt;
* compact URL storage for lots and lots of URLs (say int instead of string; sort-of like enum, but for URLs)&lt;br /&gt;
* URL to filesystem mapping, access control to file system hierarchies&lt;br /&gt;
* local server file access (read, write)&lt;br /&gt;
* remote server file access (get, put)&lt;br /&gt;
* extended file system attributes (get,set)&lt;br /&gt;
* file meta data (list,get,set)&lt;br /&gt;
&lt;br /&gt;
===Use cases===&lt;br /&gt;
Common use cases include:&lt;br /&gt;
* website content management - ensuring that linked-to URLs exist&lt;br /&gt;
* workflow management - providing for locking and versioning of files&lt;br /&gt;
* configuration - managing configuration files, ie have a change in database recreate text configuration file. This file should be locked and writeable only from database.&lt;br /&gt;
* web server log storage (many referer URLs)&lt;br /&gt;
* RDF databases (many URLs)&lt;br /&gt;
&lt;br /&gt;
Datalinks should enable you to:&lt;br /&gt;
* efficiently store URLs (datalinks are stored as integers, not strings)&lt;br /&gt;
* conveniently map between URLs and file system paths&lt;br /&gt;
* safely read and write files from SQL (SQL/MED does not specify functions for this)&lt;br /&gt;
* keep backups of changed files&lt;br /&gt;
* manage files on different servers&lt;br /&gt;
* manage datalink metadata (unified interface to extended filesystem attributes)&lt;br /&gt;
&lt;br /&gt;
==Specification==&lt;br /&gt;
===Synopsys===&lt;br /&gt;
&lt;br /&gt;
 create table my_files (&lt;br /&gt;
   ...,&lt;br /&gt;
   link datalink,&lt;br /&gt;
   ....&lt;br /&gt;
 )&lt;br /&gt;
 &lt;br /&gt;
 insert into my_files (link) select dlvalue('file:///etc/passwd');&lt;br /&gt;
  &lt;br /&gt;
 select into url dlurlcomplete(link) from my_files;&lt;br /&gt;
 &lt;br /&gt;
 update my_files set link=dlnewcopy(url,0);&lt;br /&gt;
 &lt;br /&gt;
 update my_files set link=dlpreviouscopy(url,0);&lt;br /&gt;
&lt;br /&gt;
=== Datalink support functions ===&lt;br /&gt;
&lt;br /&gt;
Constructors for values of type datalink:&lt;br /&gt;
&lt;br /&gt;
* DLVALUE(url) -&amp;gt; datalink (INSERT only)&lt;br /&gt;
* DLNEWCOPY(url,tokenp) -&amp;gt; datalink (UPDATE only)&lt;br /&gt;
* DLPREVIOUSCOPY(url,tokenp) -&amp;gt; datalink (UPDATE only)&lt;br /&gt;
&lt;br /&gt;
Functions for extracting information from datalink type:&lt;br /&gt;
&lt;br /&gt;
* DLURLCOMPLETE(datalink) -&amp;gt; url&lt;br /&gt;
* DLURLCOMPLETEONLY(datalink) -&amp;gt; url&lt;br /&gt;
* DLURLCOMPLETEWRITE(datalink) -&amp;gt; url&lt;br /&gt;
* DLURLPATH(datalink) -&amp;gt; fpath&lt;br /&gt;
* DLURLPATHONLY(datalink) -&amp;gt; fpath&lt;br /&gt;
* DLURLPATHWRITE(datalink) -&amp;gt; fpath&lt;br /&gt;
&lt;br /&gt;
* DLURLSCHEME(datalink) -&amp;gt; URL scheme (HTTP or FILE)&lt;br /&gt;
* DLURLSERVER(datalink) -&amp;gt; server address&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Datalink attributes per SQL spec ===&lt;br /&gt;
&lt;br /&gt;
These are refered to as ''link control options'' by SQL spec&lt;br /&gt;
&lt;br /&gt;
'''LINK CONTROL'''&lt;br /&gt;
* NO (0/n)&lt;br /&gt;
** just store the datalink&lt;br /&gt;
** file is not &amp;quot;linked&amp;quot;, no further control&lt;br /&gt;
* FILE (f)&lt;br /&gt;
** file is &amp;quot;linked&amp;quot;&lt;br /&gt;
** file has to exist&lt;br /&gt;
** level of control can be specified with further options&lt;br /&gt;
&lt;br /&gt;
'''INTEGRITY'''&lt;br /&gt;
* ALL (a) - linked files cannot be deleted or renamed&lt;br /&gt;
* SELECTIVE (c/s) - linked files can only be deleted or modified using file manager operations, if no datalinker is installed&lt;br /&gt;
* NONE (0/n) - referenced files can be deleted or modified using file manager operations, not compatible with FILE LINK CONTROL&lt;br /&gt;
&lt;br /&gt;
'''READ ACCESS'''&lt;br /&gt;
* DB (d)&lt;br /&gt;
** read access is controlled by SQL server, based on access privileges to the datalink value&lt;br /&gt;
** involves read access tokens&lt;br /&gt;
*** encoded into the URL by the SQL server&lt;br /&gt;
*** verified by external file manager/data linker&lt;br /&gt;
* FS (f)&lt;br /&gt;
** read access is determined by file manager&lt;br /&gt;
&lt;br /&gt;
'''WRITE ACCESS'''&lt;br /&gt;
* ADMIN REQUIRING TOKEN FOR UPDATE (e/t)&lt;br /&gt;
** write access governed by SQL server (and datalinker)&lt;br /&gt;
** involves write access token for modifying file content&lt;br /&gt;
* ADMIN NOT REQUIRING TOKEN FOR UPDATE (a)&lt;br /&gt;
** write access governed by SQL server (and datalinker)&lt;br /&gt;
* BLOCKED (b)&lt;br /&gt;
** linked files cannot be modified&lt;br /&gt;
* FS (f)&lt;br /&gt;
** write access controlled by file manager&lt;br /&gt;
&lt;br /&gt;
'''RECOVERY'''&lt;br /&gt;
* YES (1/y)&lt;br /&gt;
* NO (0/n)&lt;br /&gt;
&lt;br /&gt;
'''UNLINK'''&lt;br /&gt;
* DELETE (d)&lt;br /&gt;
** file is deleted when unlinked&lt;br /&gt;
* RESTORE (1/r)&lt;br /&gt;
** original properties (ownership, permissions) restored as well&lt;br /&gt;
* NONE (0/n)&lt;br /&gt;
** ownership and permissions are not restored&lt;br /&gt;
&lt;br /&gt;
==Implementation==&lt;br /&gt;
&lt;br /&gt;
Implementation of SQL/MED requires a lot of hocus-pocus and is probably event impossible to do properly on plain unix. Many parts however seem to be implementable.&lt;br /&gt;
&lt;br /&gt;
System should support at least http: and file: URL schemes. These two require quite different implementations. Perhaps a support for pluggable URL schemes could be useful - consider for example RDF namespaces.&lt;br /&gt;
&lt;br /&gt;
When storing many URLs, it should be possible to greatly reduce space requirements by storing URLs only once in a master URL table and using an int4 or int8 as an actual DATALINK type. This greatly reduces storage requirements needed for many URLs, provided for the use case mentioned. It should be possible to partition the master URL table according to several criteria.&lt;br /&gt;
&lt;br /&gt;
Datalink software is divided in several parts:&lt;br /&gt;
* datalink database schema. Master URL table is stored here.&lt;br /&gt;
* external process ''datalinker''. It uses datalink schema. It manages files on behalf of postgresql server. It uses postgresql for implementing transactional semantics.&lt;br /&gt;
&lt;br /&gt;
QUESTION: what to do for multiple databases on same server?&lt;br /&gt;
&lt;br /&gt;
===Parts===&lt;br /&gt;
* DL - DATALINK SQL/MED + support functions&lt;br /&gt;
* FILEIO - local file access functions&lt;br /&gt;
* URL -  parsing and manipulation - one often needs to get and set various parts of URLs and filenames&lt;br /&gt;
&lt;br /&gt;
+ some sort of inter-server communication&lt;br /&gt;
&lt;br /&gt;
===Misc notes===&lt;br /&gt;
&lt;br /&gt;
On ext3 filesystem, files can be locked with 'chattr +i' command, but only by root. This prevents file from beeing changed, no matter what unix file permissions say.&lt;br /&gt;
&lt;br /&gt;
By changing file owner/group to postgres and setting unix file permissions, file can be made effectively owned by postgresql server (which can than use normal unix functions to use them).&lt;br /&gt;
&lt;br /&gt;
PL/PerlU seems the right choice for this, with Perl for external datalinker. Proper security and safety will be hard to get right!&lt;br /&gt;
&lt;br /&gt;
[[Category:SQL/MED]]&lt;/div&gt;</summary>
		<author><name>Ziga</name></author>	</entry>

	<entry>
		<id>http://wiki.postgresql.org/wiki/DATALINK</id>
		<title>DATALINK</title>
		<link rel="alternate" type="text/html" href="http://wiki.postgresql.org/wiki/DATALINK"/>
				<updated>2010-04-06T05:39:21Z</updated>
		
		<summary type="html">&lt;p&gt;Ziga:&amp;#32;/* Features */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
SQL Datalinks are a part of SQL/MED ISO/IEC 9075-9:2003 specification.&lt;br /&gt;
&lt;br /&gt;
It is a special SQL type intended to store URLs in database columns,&lt;br /&gt;
and a number of functions, which can be used in SQL queries.&lt;br /&gt;
&lt;br /&gt;
There aren't many RDBMSs which implement SQL/MED datalinks. &lt;br /&gt;
IBM DB2 implements it. A lot of it is defined to be &amp;quot;implementation specific&amp;quot; &lt;br /&gt;
by the SQL standard.&lt;br /&gt;
&lt;br /&gt;
Values of DATALINK type are opaque, constructed by using function DLVALUE.&lt;br /&gt;
There are several functions available for converting DATALINK back to text, &lt;br /&gt;
for example DLURLCOMPLETE.&lt;br /&gt;
&lt;br /&gt;
There is not much software, which demands SQL/MED datalinks.&lt;br /&gt;
There is functionality concerning files, URLs and web, which is often &lt;br /&gt;
needed in modern applications. Often, it is awkward to use these together &lt;br /&gt;
with RDBMS data. SQL/MED standardizes some of this.&lt;br /&gt;
&lt;br /&gt;
===Features===&lt;br /&gt;
A '''column''' containing a value of type DATALINK can optionally have some special semantics:&lt;br /&gt;
# referential integrity - file pointed to by a datalink cannot be renamed or deleted&lt;br /&gt;
# access control - either SQL or file system mediated&lt;br /&gt;
# point in time recovery of file changes&lt;br /&gt;
&lt;br /&gt;
Only references to external files are stored in the database, not the&lt;br /&gt;
content of the files themselves.&lt;br /&gt;
&lt;br /&gt;
Datalinks as defined by SQL/MED should provide:&lt;br /&gt;
* transactional semantics&lt;br /&gt;
* checking if file exists&lt;br /&gt;
* protection of linked file against renaming or deletion&lt;br /&gt;
* read access control through database&lt;br /&gt;
* write access control through database&lt;br /&gt;
* point-in-time recovery&lt;br /&gt;
* deletion of files no longer referenced&lt;br /&gt;
* access to files on different servers&lt;br /&gt;
&lt;br /&gt;
The following is not specified by SQL/MED, but is often needed in practice:&lt;br /&gt;
* compact URL storage for lots and lots of URLs (say int instead of string; sort-of like enum, but for URLs)&lt;br /&gt;
* URL to filesystem mapping, access control to file system hierarchies&lt;br /&gt;
* local server file access (read, write)&lt;br /&gt;
* remote server file access (get, put)&lt;br /&gt;
* extended file system attributes (get,set)&lt;br /&gt;
* file meta data (list,get,set)&lt;br /&gt;
&lt;br /&gt;
===Use cases===&lt;br /&gt;
Common use cases include:&lt;br /&gt;
* website content management - ensuring that linked-to URLs exist&lt;br /&gt;
* workflow management - providing for locking and versioning of files&lt;br /&gt;
* configuration - managing configuration files, ie have a change in database recreate text configuration file. This file should be locked and writeable only from database.&lt;br /&gt;
* web server log storage (many referer URLs)&lt;br /&gt;
* RDF databases (many URLs)&lt;br /&gt;
&lt;br /&gt;
Datalinks should enable you to:&lt;br /&gt;
* efficiently store URLs (datalinks are stored as integers, not strings)&lt;br /&gt;
* conveniently map between URLs and file system paths&lt;br /&gt;
* safely read and write files from SQL (SQL/MED does not specify functions for this)&lt;br /&gt;
* keep backups of changed files&lt;br /&gt;
* manage files on different servers&lt;br /&gt;
* manage datalink metadata (unified interface to extended filesystem attributes)&lt;br /&gt;
&lt;br /&gt;
==Specification==&lt;br /&gt;
===Synopsys===&lt;br /&gt;
&lt;br /&gt;
 create table my_files (&lt;br /&gt;
   ...,&lt;br /&gt;
   link datalink,&lt;br /&gt;
   ....&lt;br /&gt;
 )&lt;br /&gt;
 &lt;br /&gt;
 insert into my_files (link) select dlvalue('file:///etc/passwd');&lt;br /&gt;
  &lt;br /&gt;
 select into url dlurlcomplete(link) from my_files;&lt;br /&gt;
 &lt;br /&gt;
 update my_files set link=dlnewcopy(url,0);&lt;br /&gt;
 &lt;br /&gt;
 update my_files set link=dlpreviouscopy(url,0);&lt;br /&gt;
&lt;br /&gt;
=== Datalink support functions ===&lt;br /&gt;
&lt;br /&gt;
Constructors for values of type datalink:&lt;br /&gt;
&lt;br /&gt;
* DLVALUE(url) -&amp;gt; datalink (INSERT only)&lt;br /&gt;
* DLNEWCOPY(url,tokenp) -&amp;gt; datalink (UPDATE only)&lt;br /&gt;
* DLPREVIOUSCOPY(url,tokenp) -&amp;gt; datalink (UPDATE only)&lt;br /&gt;
&lt;br /&gt;
Functions for extracting information from datalink type:&lt;br /&gt;
&lt;br /&gt;
* DLURLCOMPLETE(datalink) -&amp;gt; url&lt;br /&gt;
* DLURLCOMPLETEONLY(datalink) -&amp;gt; url&lt;br /&gt;
* DLURLCOMPLETEWRITE(datalink) -&amp;gt; url&lt;br /&gt;
* DLURLPATH(datalink) -&amp;gt; fpath&lt;br /&gt;
* DLURLPATHONLY(datalink) -&amp;gt; fpath&lt;br /&gt;
* DLURLPATHWRITE(datalink) -&amp;gt; fpath&lt;br /&gt;
&lt;br /&gt;
* DLURLSCHEME(datalink) -&amp;gt; URL scheme (HTTP or FILE)&lt;br /&gt;
* DLURLSERVER(datalink) -&amp;gt; server address&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Datalink attributes per SQL spec ===&lt;br /&gt;
&lt;br /&gt;
These are refered to as ''link control options'' by SQL spec&lt;br /&gt;
&lt;br /&gt;
'''LINK CONTROL'''&lt;br /&gt;
* NO (0/n)&lt;br /&gt;
** just store the datalink&lt;br /&gt;
** file is not &amp;quot;linked&amp;quot;, no further control&lt;br /&gt;
* FILE (f)&lt;br /&gt;
** file is &amp;quot;linked&amp;quot;&lt;br /&gt;
** file has to exist&lt;br /&gt;
** level of control can be specified with further options&lt;br /&gt;
&lt;br /&gt;
'''INTEGRITY'''&lt;br /&gt;
* ALL (a) - linked files cannot be deleted or renamed&lt;br /&gt;
* SELECTIVE (c/s) - linked files can only be deleted or modified using file manager operations, if no datalinker is installed&lt;br /&gt;
* NONE (0/n) - referenced files can be deleted or modified using file manager operations, not compatible with FILE LINK CONTROL&lt;br /&gt;
&lt;br /&gt;
'''READ ACCESS'''&lt;br /&gt;
* DB (d)&lt;br /&gt;
** read access is controlled by SQL server, based on access privileges to the datalink value&lt;br /&gt;
** involves read access tokens&lt;br /&gt;
*** encoded into the URL by the SQL server&lt;br /&gt;
*** verified by external file manager/data linker&lt;br /&gt;
* FS (f)&lt;br /&gt;
** read access is determined by file manager&lt;br /&gt;
&lt;br /&gt;
'''WRITE ACCESS'''&lt;br /&gt;
* ADMIN REQUIRING TOKEN FOR UPDATE (e/t)&lt;br /&gt;
** write access governed by SQL server (and datalinker)&lt;br /&gt;
** involves write access token for modifying file content&lt;br /&gt;
* ADMIN NOT REQUIRING TOKEN FOR UPDATE (a)&lt;br /&gt;
** write access governed by SQL server (and datalinker)&lt;br /&gt;
* BLOCKED (b)&lt;br /&gt;
** linked files cannot be modified&lt;br /&gt;
* FS (f)&lt;br /&gt;
** write access controlled by file manager&lt;br /&gt;
&lt;br /&gt;
'''RECOVERY'''&lt;br /&gt;
* YES (1/y)&lt;br /&gt;
* NO (0/n)&lt;br /&gt;
&lt;br /&gt;
'''UNLINK'''&lt;br /&gt;
* DELETE (d)&lt;br /&gt;
** file is deleted when unlinked&lt;br /&gt;
* RESTORE (1/r)&lt;br /&gt;
** original properties (ownership, permissions) restored as well&lt;br /&gt;
* NONE (0/n)&lt;br /&gt;
** ownership and permissions are not restored&lt;br /&gt;
&lt;br /&gt;
==Implementation==&lt;br /&gt;
&lt;br /&gt;
Implementation of SQL/MED requires a lot of hocus-pocus and is probably event impossible to do properly on plain unix. Many parts however seem to be implementable.&lt;br /&gt;
&lt;br /&gt;
System should support at least http: and file: URL schemes. These two require quite different implementations. Perhaps a support for pluggable URL schemes could be useful - consider for example RDF namespaces.&lt;br /&gt;
&lt;br /&gt;
When storing many URLs, it should be possible to greatly reduce space requirements by storing URLs only once in a master URL table and using an int4 or int8 as an actual DATALINK type. This greatly reduces storage requirements needed for many URLs, provided for the use case mentioned. It should be possible to partition the master URL table according to several criteria.&lt;br /&gt;
&lt;br /&gt;
Datalink software is divided in several parts:&lt;br /&gt;
* datalink database schema. Master URL table is stored here.&lt;br /&gt;
* external process ''datalinker''. It uses datalink schema. It manages files on behalf of postgresql server. It uses postgresql for implementing transactional semantics.&lt;br /&gt;
&lt;br /&gt;
QUESTION: what to do for multiple databases on same server?&lt;br /&gt;
&lt;br /&gt;
===Parts===&lt;br /&gt;
* DL - DATALINK SQL/MED + support functions&lt;br /&gt;
* FILEIO - local file access functions&lt;br /&gt;
* URL -  parsing and manipulation - one often needs to get and set various parts of URLs and filenames&lt;br /&gt;
&lt;br /&gt;
+ some sort of inter-server communication&lt;br /&gt;
&lt;br /&gt;
===Misc notes===&lt;br /&gt;
&lt;br /&gt;
On ext3 filesystem, files can be locked with 'chattr +i' command, but only by root. This prevents file from beeing changed, no matter what unix file permissions say.&lt;br /&gt;
&lt;br /&gt;
By changing file owner/group to postgres and setting unix file permissions, file can be made effectively owned by postgresql server (which can than use normal unix functions to use them).&lt;br /&gt;
&lt;br /&gt;
PL/PerlU seems the right choice for this, with Perl for external datalinker. Proper security and safety will be hard to get right!&lt;br /&gt;
&lt;br /&gt;
[[Category:SQL/MED]]&lt;/div&gt;</summary>
		<author><name>Ziga</name></author>	</entry>

	<entry>
		<id>http://wiki.postgresql.org/wiki/DATALINK</id>
		<title>DATALINK</title>
		<link rel="alternate" type="text/html" href="http://wiki.postgresql.org/wiki/DATALINK"/>
				<updated>2010-04-06T05:37:10Z</updated>
		
		<summary type="html">&lt;p&gt;Ziga:&amp;#32;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
SQL Datalinks are a part of SQL/MED ISO/IEC 9075-9:2003 specification.&lt;br /&gt;
&lt;br /&gt;
It is a special SQL type intended to store URLs in database columns,&lt;br /&gt;
and a number of functions, which can be used in SQL queries.&lt;br /&gt;
&lt;br /&gt;
There aren't many RDBMSs which implement SQL/MED datalinks. &lt;br /&gt;
IBM DB2 implements it. A lot of it is defined to be &amp;quot;implementation specific&amp;quot; &lt;br /&gt;
by the SQL standard.&lt;br /&gt;
&lt;br /&gt;
Values of DATALINK type are opaque, constructed by using function DLVALUE.&lt;br /&gt;
There are several functions available for converting DATALINK back to text, &lt;br /&gt;
for example DLURLCOMPLETE.&lt;br /&gt;
&lt;br /&gt;
There is not much software, which demands SQL/MED datalinks.&lt;br /&gt;
There is functionality concerning files, URLs and web, which is often &lt;br /&gt;
needed in modern applications. Often, it is awkward to use these together &lt;br /&gt;
with RDBMS data. SQL/MED standardizes some of this.&lt;br /&gt;
&lt;br /&gt;
===Features===&lt;br /&gt;
The DATALINK type can have some special semantics:&lt;br /&gt;
# referential integrity - file pointed to by a datalink column cannot be renamed or deleted&lt;br /&gt;
# access control - either SQL or file system mediated&lt;br /&gt;
# point in time recovery of file changes&lt;br /&gt;
&lt;br /&gt;
Only references to external files are stored in the database, not the&lt;br /&gt;
content of the files themselves.&lt;br /&gt;
&lt;br /&gt;
Datalinks as defined by SQL/MED should provide:&lt;br /&gt;
* transactional semantics&lt;br /&gt;
* checking if file exists&lt;br /&gt;
* protection of linked file against renaming or deletion&lt;br /&gt;
* read access control through database&lt;br /&gt;
* write access control through database&lt;br /&gt;
* point-in-time recovery&lt;br /&gt;
* deletion of files no longer referenced&lt;br /&gt;
* access to files on different servers&lt;br /&gt;
&lt;br /&gt;
The following is not specified by SQL/MED, but is often needed in practice:&lt;br /&gt;
* compact URL storage for lots and lots of URLs (say int instead of string; sort-of like enum, but for URLs)&lt;br /&gt;
* URL to filesystem mapping, access control to file system hierarchies&lt;br /&gt;
* local server file access (read, write)&lt;br /&gt;
* remote server file access (get, put)&lt;br /&gt;
* extended file system attributes (get,set)&lt;br /&gt;
* file meta data (list,get,set)&lt;br /&gt;
&lt;br /&gt;
===Use cases===&lt;br /&gt;
Common use cases include:&lt;br /&gt;
* website content management - ensuring that linked-to URLs exist&lt;br /&gt;
* workflow management - providing for locking and versioning of files&lt;br /&gt;
* configuration - managing configuration files, ie have a change in database recreate text configuration file. This file should be locked and writeable only from database.&lt;br /&gt;
* web server log storage (many referer URLs)&lt;br /&gt;
* RDF databases (many URLs)&lt;br /&gt;
&lt;br /&gt;
Datalinks should enable you to:&lt;br /&gt;
* efficiently store URLs (datalinks are stored as integers, not strings)&lt;br /&gt;
* conveniently map between URLs and file system paths&lt;br /&gt;
* safely read and write files from SQL (SQL/MED does not specify functions for this)&lt;br /&gt;
* keep backups of changed files&lt;br /&gt;
* manage files on different servers&lt;br /&gt;
* manage datalink metadata (unified interface to extended filesystem attributes)&lt;br /&gt;
&lt;br /&gt;
==Specification==&lt;br /&gt;
===Synopsys===&lt;br /&gt;
&lt;br /&gt;
 create table my_files (&lt;br /&gt;
   ...,&lt;br /&gt;
   link datalink,&lt;br /&gt;
   ....&lt;br /&gt;
 )&lt;br /&gt;
 &lt;br /&gt;
 insert into my_files (link) select dlvalue('file:///etc/passwd');&lt;br /&gt;
  &lt;br /&gt;
 select into url dlurlcomplete(link) from my_files;&lt;br /&gt;
 &lt;br /&gt;
 update my_files set link=dlnewcopy(url,0);&lt;br /&gt;
 &lt;br /&gt;
 update my_files set link=dlpreviouscopy(url,0);&lt;br /&gt;
&lt;br /&gt;
=== Datalink support functions ===&lt;br /&gt;
&lt;br /&gt;
Constructors for values of type datalink:&lt;br /&gt;
&lt;br /&gt;
* DLVALUE(url) -&amp;gt; datalink (INSERT only)&lt;br /&gt;
* DLNEWCOPY(url,tokenp) -&amp;gt; datalink (UPDATE only)&lt;br /&gt;
* DLPREVIOUSCOPY(url,tokenp) -&amp;gt; datalink (UPDATE only)&lt;br /&gt;
&lt;br /&gt;
Functions for extracting information from datalink type:&lt;br /&gt;
&lt;br /&gt;
* DLURLCOMPLETE(datalink) -&amp;gt; url&lt;br /&gt;
* DLURLCOMPLETEONLY(datalink) -&amp;gt; url&lt;br /&gt;
* DLURLCOMPLETEWRITE(datalink) -&amp;gt; url&lt;br /&gt;
* DLURLPATH(datalink) -&amp;gt; fpath&lt;br /&gt;
* DLURLPATHONLY(datalink) -&amp;gt; fpath&lt;br /&gt;
* DLURLPATHWRITE(datalink) -&amp;gt; fpath&lt;br /&gt;
&lt;br /&gt;
* DLURLSCHEME(datalink) -&amp;gt; URL scheme (HTTP or FILE)&lt;br /&gt;
* DLURLSERVER(datalink) -&amp;gt; server address&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Datalink attributes per SQL spec ===&lt;br /&gt;
&lt;br /&gt;
These are refered to as ''link control options'' by SQL spec&lt;br /&gt;
&lt;br /&gt;
'''LINK CONTROL'''&lt;br /&gt;
* NO (0/n)&lt;br /&gt;
** just store the datalink&lt;br /&gt;
** file is not &amp;quot;linked&amp;quot;, no further control&lt;br /&gt;
* FILE (f)&lt;br /&gt;
** file is &amp;quot;linked&amp;quot;&lt;br /&gt;
** file has to exist&lt;br /&gt;
** level of control can be specified with further options&lt;br /&gt;
&lt;br /&gt;
'''INTEGRITY'''&lt;br /&gt;
* ALL (a) - linked files cannot be deleted or renamed&lt;br /&gt;
* SELECTIVE (c/s) - linked files can only be deleted or modified using file manager operations, if no datalinker is installed&lt;br /&gt;
* NONE (0/n) - referenced files can be deleted or modified using file manager operations, not compatible with FILE LINK CONTROL&lt;br /&gt;
&lt;br /&gt;
'''READ ACCESS'''&lt;br /&gt;
* DB (d)&lt;br /&gt;
** read access is controlled by SQL server, based on access privileges to the datalink value&lt;br /&gt;
** involves read access tokens&lt;br /&gt;
*** encoded into the URL by the SQL server&lt;br /&gt;
*** verified by external file manager/data linker&lt;br /&gt;
* FS (f)&lt;br /&gt;
** read access is determined by file manager&lt;br /&gt;
&lt;br /&gt;
'''WRITE ACCESS'''&lt;br /&gt;
* ADMIN REQUIRING TOKEN FOR UPDATE (e/t)&lt;br /&gt;
** write access governed by SQL server (and datalinker)&lt;br /&gt;
** involves write access token for modifying file content&lt;br /&gt;
* ADMIN NOT REQUIRING TOKEN FOR UPDATE (a)&lt;br /&gt;
** write access governed by SQL server (and datalinker)&lt;br /&gt;
* BLOCKED (b)&lt;br /&gt;
** linked files cannot be modified&lt;br /&gt;
* FS (f)&lt;br /&gt;
** write access controlled by file manager&lt;br /&gt;
&lt;br /&gt;
'''RECOVERY'''&lt;br /&gt;
* YES (1/y)&lt;br /&gt;
* NO (0/n)&lt;br /&gt;
&lt;br /&gt;
'''UNLINK'''&lt;br /&gt;
* DELETE (d)&lt;br /&gt;
** file is deleted when unlinked&lt;br /&gt;
* RESTORE (1/r)&lt;br /&gt;
** original properties (ownership, permissions) restored as well&lt;br /&gt;
* NONE (0/n)&lt;br /&gt;
** ownership and permissions are not restored&lt;br /&gt;
&lt;br /&gt;
==Implementation==&lt;br /&gt;
&lt;br /&gt;
Implementation of SQL/MED requires a lot of hocus-pocus and is probably event impossible to do properly on plain unix. Many parts however seem to be implementable.&lt;br /&gt;
&lt;br /&gt;
System should support at least http: and file: URL schemes. These two require quite different implementations. Perhaps a support for pluggable URL schemes could be useful - consider for example RDF namespaces.&lt;br /&gt;
&lt;br /&gt;
When storing many URLs, it should be possible to greatly reduce space requirements by storing URLs only once in a master URL table and using an int4 or int8 as an actual DATALINK type. This greatly reduces storage requirements needed for many URLs, provided for the use case mentioned. It should be possible to partition the master URL table according to several criteria.&lt;br /&gt;
&lt;br /&gt;
Datalink software is divided in several parts:&lt;br /&gt;
* datalink database schema. Master URL table is stored here.&lt;br /&gt;
* external process ''datalinker''. It uses datalink schema. It manages files on behalf of postgresql server. It uses postgresql for implementing transactional semantics.&lt;br /&gt;
&lt;br /&gt;
QUESTION: what to do for multiple databases on same server?&lt;br /&gt;
&lt;br /&gt;
===Parts===&lt;br /&gt;
* DL - DATALINK SQL/MED + support functions&lt;br /&gt;
* FILEIO - local file access functions&lt;br /&gt;
* URL -  parsing and manipulation - one often needs to get and set various parts of URLs and filenames&lt;br /&gt;
&lt;br /&gt;
+ some sort of inter-server communication&lt;br /&gt;
&lt;br /&gt;
===Misc notes===&lt;br /&gt;
&lt;br /&gt;
On ext3 filesystem, files can be locked with 'chattr +i' command, but only by root. This prevents file from beeing changed, no matter what unix file permissions say.&lt;br /&gt;
&lt;br /&gt;
By changing file owner/group to postgres and setting unix file permissions, file can be made effectively owned by postgresql server (which can than use normal unix functions to use them).&lt;br /&gt;
&lt;br /&gt;
PL/PerlU seems the right choice for this, with Perl for external datalinker. Proper security and safety will be hard to get right!&lt;br /&gt;
&lt;br /&gt;
[[Category:SQL/MED]]&lt;/div&gt;</summary>
		<author><name>Ziga</name></author>	</entry>

	<entry>
		<id>http://wiki.postgresql.org/wiki/DATALINK</id>
		<title>DATALINK</title>
		<link rel="alternate" type="text/html" href="http://wiki.postgresql.org/wiki/DATALINK"/>
				<updated>2010-04-06T05:09:56Z</updated>
		
		<summary type="html">&lt;p&gt;Ziga:&amp;#32;/* Features */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
SQL Datalinks are a part of SQL/MED ISO/IEC 9075-9:2003 specification.&lt;br /&gt;
&lt;br /&gt;
It is a special SQL type intended to store URLs in database columns,&lt;br /&gt;
and a number of functions, which can be used in SQL queries.&lt;br /&gt;
&lt;br /&gt;
There aren't many RDBMSs which implement SQL/MED datalinks. &lt;br /&gt;
IBM DB2 implements it. A lot of it is defined to be &amp;quot;implementation specific&amp;quot; &lt;br /&gt;
by the SQL standard.&lt;br /&gt;
&lt;br /&gt;
Values of DATALINK type are opaque, constructed by using function DLVALUE.&lt;br /&gt;
There are several functions available for converting DATALINK back to text, &lt;br /&gt;
for example DLURLCOMPLETE.&lt;br /&gt;
&lt;br /&gt;
There is not much software, which demands SQL/MED datalinks.&lt;br /&gt;
There is functionality concerning files, URLs and web, which is often &lt;br /&gt;
needed in modern applications. Often, it is awkward to use these together &lt;br /&gt;
with RDBMS data. SQL/MED standardizes some of this.&lt;br /&gt;
&lt;br /&gt;
===Features===&lt;br /&gt;
The DATALINK type can have some special semantics:&lt;br /&gt;
# referential integrity - file pointed to by a datalink column cannot be renamed or deleted&lt;br /&gt;
# access control - either SQL or file system mediated&lt;br /&gt;
# point in time recovery of file changes&lt;br /&gt;
&lt;br /&gt;
Only references to external files are stored in the database, not the&lt;br /&gt;
content of the files themselves.&lt;br /&gt;
&lt;br /&gt;
Datalinks as defined by SQL/MED should provide:&lt;br /&gt;
* transactional semantics&lt;br /&gt;
* checking if file exists&lt;br /&gt;
* protection of linked file against renaming or deletion&lt;br /&gt;
* read access control through database&lt;br /&gt;
* write access control through database&lt;br /&gt;
* point-in-time recovery&lt;br /&gt;
* deletion of files no longer referenced&lt;br /&gt;
* access to files on different servers&lt;br /&gt;
&lt;br /&gt;
The following is not specified in SQL/MED, but is often needed in practice&lt;br /&gt;
* compact URL storage for lots and lots of URLs&lt;br /&gt;
* URL to filesystem mapping, access control to file system hierarchies&lt;br /&gt;
* local server file access (read, write)&lt;br /&gt;
* remote server file access (get, put)&lt;br /&gt;
* extended file system attributes (get,set)&lt;br /&gt;
* file meta data (list,get,set)&lt;br /&gt;
&lt;br /&gt;
===Use cases===&lt;br /&gt;
Common use cases include:&lt;br /&gt;
* website content management - ensuring that linked-to URLs exist&lt;br /&gt;
* workflow management - providing for locking and versioning of files&lt;br /&gt;
* configuration - managing configuration files, ie have a change in database recreate text configuration file. This file should be locked and writeable only from database.&lt;br /&gt;
* web server log storage (many referer URLs)&lt;br /&gt;
* RDF databases (many URLs)&lt;br /&gt;
&lt;br /&gt;
==Implementation==&lt;br /&gt;
&lt;br /&gt;
Implementation of SQL/MED requires a lot of hocus-pocus and is probably event impossible to do properly on plain unix. Many parts however seem to be implementable.&lt;br /&gt;
&lt;br /&gt;
When storing many URLs, it should be possible to greatly reduce space requirements by storing URLs only once in a master URL table and using an int4 or int8 as an actual DATALINK type. This greatly reduces storage requirements needed for many URLs. It should be possible to partition the master URL table according to several criteria.&lt;br /&gt;
&lt;br /&gt;
Datalink software is divided in several parts:&lt;br /&gt;
* datalink database schema. URL dictionary &lt;br /&gt;
* external process ''datalinker''. It uses datalink schema. It manages files on behalf of postgresql server. It uses postgresql for implementing transactional semantics on file modifications.&lt;br /&gt;
QUESTION: what to do for multiple databases on same server?&lt;br /&gt;
&lt;br /&gt;
Parts:&lt;br /&gt;
* DL - DATALINK SQL/MED + support functions&lt;br /&gt;
* FILEIO - local file access functions&lt;br /&gt;
* URL -  parsing and manipulation - one often needs to get and set various parts of URLs and filenames&lt;br /&gt;
&lt;br /&gt;
+ some sort of inter-server communication&lt;br /&gt;
&lt;br /&gt;
[[Category:SQL/MED]]&lt;/div&gt;</summary>
		<author><name>Ziga</name></author>	</entry>

	<entry>
		<id>http://wiki.postgresql.org/wiki/DATALINK</id>
		<title>DATALINK</title>
		<link rel="alternate" type="text/html" href="http://wiki.postgresql.org/wiki/DATALINK"/>
				<updated>2010-04-06T05:08:40Z</updated>
		
		<summary type="html">&lt;p&gt;Ziga:&amp;#32;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
SQL Datalinks are a part of SQL/MED ISO/IEC 9075-9:2003 specification.&lt;br /&gt;
&lt;br /&gt;
It is a special SQL type intended to store URLs in database columns,&lt;br /&gt;
and a number of functions, which can be used in SQL queries.&lt;br /&gt;
&lt;br /&gt;
There aren't many RDBMSs which implement SQL/MED datalinks. &lt;br /&gt;
IBM DB2 implements it. A lot of it is defined to be &amp;quot;implementation specific&amp;quot; &lt;br /&gt;
by the SQL standard.&lt;br /&gt;
&lt;br /&gt;
Values of DATALINK type are opaque, constructed by using function DLVALUE.&lt;br /&gt;
There are several functions available for converting DATALINK back to text, &lt;br /&gt;
for example DLURLCOMPLETE.&lt;br /&gt;
&lt;br /&gt;
There is not much software, which demands SQL/MED datalinks.&lt;br /&gt;
There is functionality concerning files, URLs and web, which is often &lt;br /&gt;
needed in modern applications. Often, it is awkward to use these together &lt;br /&gt;
with RDBMS data. SQL/MED standardizes some of this.&lt;br /&gt;
&lt;br /&gt;
===Features===&lt;br /&gt;
The DATALINK type can have some special semantics:&lt;br /&gt;
# referential integrity - file pointed to by a datalink column cannot be renamed or deleted&lt;br /&gt;
# access control - either SQL or file system mediated&lt;br /&gt;
# point in time recovery of file changes&lt;br /&gt;
&lt;br /&gt;
Only references to external files are stored in the database, not the&lt;br /&gt;
content of the files themselves.&lt;br /&gt;
&lt;br /&gt;
Datalinks as defined by SQL/MED should provide:&lt;br /&gt;
* transactional semantics&lt;br /&gt;
* checking if file exists&lt;br /&gt;
* protection of linked file against renaming or deletion&lt;br /&gt;
* read access through database&lt;br /&gt;
* write access through database&lt;br /&gt;
* point-in-time recovery&lt;br /&gt;
* deletion of files no longer referenced&lt;br /&gt;
* access to files on different servers&lt;br /&gt;
&lt;br /&gt;
The following is not specified in SQL/MED, but is often needed in practice&lt;br /&gt;
* compact URL storage for lots and lots of URLs&lt;br /&gt;
* URL to filesystem mapping, access control to file system hierarchies&lt;br /&gt;
* local server file access (read, write)&lt;br /&gt;
* remote server file access (get, put)&lt;br /&gt;
* extended file system attributes (get,set)&lt;br /&gt;
* file meta data (list,get,set)&lt;br /&gt;
&lt;br /&gt;
===Use cases===&lt;br /&gt;
Common use cases include:&lt;br /&gt;
* website content management - ensuring that linked-to URLs exist&lt;br /&gt;
* workflow management - providing for locking and versioning of files&lt;br /&gt;
* configuration - managing configuration files, ie have a change in database recreate text configuration file. This file should be locked and writeable only from database.&lt;br /&gt;
* web server log storage (many referer URLs)&lt;br /&gt;
* RDF databases (many URLs)&lt;br /&gt;
&lt;br /&gt;
==Implementation==&lt;br /&gt;
&lt;br /&gt;
Implementation of SQL/MED requires a lot of hocus-pocus and is probably event impossible to do properly on plain unix. Many parts however seem to be implementable.&lt;br /&gt;
&lt;br /&gt;
When storing many URLs, it should be possible to greatly reduce space requirements by storing URLs only once in a master URL table and using an int4 or int8 as an actual DATALINK type. This greatly reduces storage requirements needed for many URLs. It should be possible to partition the master URL table according to several criteria.&lt;br /&gt;
&lt;br /&gt;
Datalink software is divided in several parts:&lt;br /&gt;
* datalink database schema. URL dictionary &lt;br /&gt;
* external process ''datalinker''. It uses datalink schema. It manages files on behalf of postgresql server. It uses postgresql for implementing transactional semantics on file modifications.&lt;br /&gt;
QUESTION: what to do for multiple databases on same server?&lt;br /&gt;
&lt;br /&gt;
Parts:&lt;br /&gt;
* DL - DATALINK SQL/MED + support functions&lt;br /&gt;
* FILEIO - local file access functions&lt;br /&gt;
* URL -  parsing and manipulation - one often needs to get and set various parts of URLs and filenames&lt;br /&gt;
&lt;br /&gt;
+ some sort of inter-server communication&lt;br /&gt;
&lt;br /&gt;
[[Category:SQL/MED]]&lt;/div&gt;</summary>
		<author><name>Ziga</name></author>	</entry>

	<entry>
		<id>http://wiki.postgresql.org/wiki/DATALINK</id>
		<title>DATALINK</title>
		<link rel="alternate" type="text/html" href="http://wiki.postgresql.org/wiki/DATALINK"/>
				<updated>2010-04-06T05:04:24Z</updated>
		
		<summary type="html">&lt;p&gt;Ziga:&amp;#32;New page: ==Introduction==  SQL Datalinks are a part of SQL/MED ISO/IEC 9075-9:2003 specification.  It is a special SQL type intended to store URLs in database columns, and a number of functions, wh...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
SQL Datalinks are a part of SQL/MED ISO/IEC 9075-9:2003 specification.&lt;br /&gt;
&lt;br /&gt;
It is a special SQL type intended to store URLs in database columns,&lt;br /&gt;
and a number of functions, which can be used in SQL queries.&lt;br /&gt;
&lt;br /&gt;
There aren't many RDBMSs which implement SQL/MED datalinks. &lt;br /&gt;
IBM DB2 implements it. A lot of it is defined to be &amp;quot;implementation specific&amp;quot; &lt;br /&gt;
by the SQL standard.&lt;br /&gt;
&lt;br /&gt;
Values of DATALINK type are opaque, constructed by using function DLVALUE.&lt;br /&gt;
There are several functions available for converting DATALINK back to text, &lt;br /&gt;
for example DLURLCOMPLETE.&lt;br /&gt;
&lt;br /&gt;
Only references to external files are stored in the database, not the&lt;br /&gt;
content of the files themselves.&lt;br /&gt;
&lt;br /&gt;
The DATALINK type can have some special semantics:&lt;br /&gt;
# referential integrity - file pointed to by a datalink column cannot be renamed or deleted&lt;br /&gt;
# access control - either SQL or file system mediated&lt;br /&gt;
# point in time recovery of file changes&lt;br /&gt;
&lt;br /&gt;
There is not much software, which demands SQL/MED datalinks.&lt;br /&gt;
There is functionality concerning files, URLs and web, which is often &lt;br /&gt;
needed in modern applications. Often, it is awkward to use these together &lt;br /&gt;
with RDBMS data. SQL/MED standardizes some of this.&lt;br /&gt;
&lt;br /&gt;
Common use cases include:&lt;br /&gt;
* website content management - ensuring that linked-to URLs exist&lt;br /&gt;
* workflow management - providing for locking and versioning of files&lt;br /&gt;
* configuration - managing configuration files, ie have a change in database recreate text configuration file. This file should be locked and writeable only from database.&lt;br /&gt;
* web server log storage (many referer URLs)&lt;br /&gt;
* RDF databases (many URLs)&lt;br /&gt;
&lt;br /&gt;
Datalinks as defined by SQL/MED should provide:&lt;br /&gt;
* transactional semantics&lt;br /&gt;
* checking if file exists&lt;br /&gt;
* protection of linked file against renaming or deletion&lt;br /&gt;
* read access through database&lt;br /&gt;
* write access through database&lt;br /&gt;
* point-in-time recovery&lt;br /&gt;
* deletion of files no longer referenced&lt;br /&gt;
* access to files on different servers&lt;br /&gt;
&lt;br /&gt;
In addition, we would also like&lt;br /&gt;
* compact URL storage for lots and lots of URLs&lt;br /&gt;
* URL : filesystem mapping&lt;br /&gt;
* remote server access&lt;br /&gt;
* extended file system attributes&lt;br /&gt;
* file meta data&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Implementation==&lt;br /&gt;
&lt;br /&gt;
Implementation of SQL/MED requires a lot of hocus-pocus and is probably event impossible to do properly on plain unix. Many parts however seem to be implementable.&lt;br /&gt;
&lt;br /&gt;
When storing many URLs, it should be possible to greatly reduce space requirements by storing URLs only once in a master URL table and using an int4 or int8 as an actual DATALINK type. This greatly reduces storage requirements needed for many URLs. It should be possible to partition the master URL table according to several criteria.&lt;br /&gt;
&lt;br /&gt;
Datalink software is divided in several parts:&lt;br /&gt;
* datalink database schema. URL dictionary &lt;br /&gt;
* external process ''datalinker''. It uses datalink schema. It manages files on behalf of postgresql server. It uses postgresql for implementing transactional semantics on file modifications.&lt;br /&gt;
QUESTION: what to do for multiple databases on same server?&lt;br /&gt;
&lt;br /&gt;
Parts:&lt;br /&gt;
* DL - DATALINK SQL/MED + support functions&lt;br /&gt;
* FILEIO - local file access functions&lt;br /&gt;
* URL -  parsing and manipulation - one often needs to get and set various parts of URLs and filenames&lt;br /&gt;
&lt;br /&gt;
+ some sort of inter-server communication&lt;br /&gt;
&lt;br /&gt;
[[Category:SQL/MED]]&lt;/div&gt;</summary>
		<author><name>Ziga</name></author>	</entry>

	<entry>
		<id>http://wiki.postgresql.org/wiki/Module_Manager</id>
		<title>Module Manager</title>
		<link rel="alternate" type="text/html" href="http://wiki.postgresql.org/wiki/Module_Manager"/>
				<updated>2008-10-17T20:30:57Z</updated>
		
		<summary type="html">&lt;p&gt;Ziga:&amp;#32;/* As a database user */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;There has been some interest PostgreSQL extension/package/module manager.&lt;br /&gt;
&lt;br /&gt;
We would like some software to make it easier for users and developers to install and manage&lt;br /&gt;
various add-on features available for PostgreSQL.&lt;br /&gt;
&lt;br /&gt;
Currently the process of installing add-ons is rather manual and cumbersome. &lt;br /&gt;
It usually requires command-line interface and/or superuser access.&lt;br /&gt;
It would be great, if modules could be used through SQL alone.&lt;br /&gt;
&lt;br /&gt;
Recently, this topic has reappeared on pgsql-hackers mailing list:&lt;br /&gt;
* [http://archives.postgresql.org/pgsql-hackers/2008-04/msg00132.php 2008-04 pgsql-hackers thread]&lt;br /&gt;
* [http://archives.postgresql.org/pgsql-hackers/2007-10/msg01281.php 2007-10 pgsql-hackers thread]&lt;br /&gt;
* [http://archives.postgresql.org/pgsql-patches/2006-05/msg00327.php 2006-05 pgsql-hackers thread]&lt;br /&gt;
* [http://archives.postgresql.org/message-id/ca33c0a30804061349s41b4d8fcsa9c579454b27ecd2@mail.gmail.com Database owner installable modules patch by Tom Dunstan]&lt;br /&gt;
* [http://archives.postgresql.org/pgsql-hackers/2008-07/msg01098.php PostgreSQL extensions packaging proposal by Dimitri Fontaine]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Perhaps a difference among terms ''extension'', ''package'' and ''module'' should be clarified?&lt;br /&gt;
Here the term ''module'' is used, due to popular demand.&lt;br /&gt;
&lt;br /&gt;
==Synopsis==&lt;br /&gt;
&lt;br /&gt;
===As a database user===&lt;br /&gt;
&lt;br /&gt;
====Using modules====&lt;br /&gt;
Import desired module with '''contrib.import()''' function.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ljudmila=&amp;gt; select contrib.import('hstore');&lt;br /&gt;
... stuff ...&lt;br /&gt;
    import     &lt;br /&gt;
---------------&lt;br /&gt;
 INSTALL hstore&lt;br /&gt;
(1 row)&lt;br /&gt;
&lt;br /&gt;
ljudmila=&amp;gt; select 'a=&amp;gt;3'::hstore;&lt;br /&gt;
  hstore  &lt;br /&gt;
----------&lt;br /&gt;
 &amp;quot;a&amp;quot;=&amp;gt;&amp;quot;3&amp;quot;&lt;br /&gt;
(1 row)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When user calls '''import()''' for the first time, module is installed into current schema.&lt;br /&gt;
&lt;br /&gt;
===As a database administrator===&lt;br /&gt;
&lt;br /&gt;
====Install the module manager and contrib modules====&lt;br /&gt;
&lt;br /&gt;
By default, this goes into schema '''contrib'''.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
postgres@mama:$ pg_module all &amp;gt;pg_module.sql&lt;br /&gt;
postgres@mama:$ psql&lt;br /&gt;
ljudmila=# \i pg_module.sql&lt;br /&gt;
BEGIN&lt;br /&gt;
... stuff ...&lt;br /&gt;
COMMIT&lt;br /&gt;
ljudmila=# set search_path=contrib; \d+&lt;br /&gt;
SET&lt;br /&gt;
                                      List of relations&lt;br /&gt;
 Schema  |        Name        | Type  |   Owner    |               Description               &lt;br /&gt;
---------+--------------------+-------+------------+-----------------------------------------&lt;br /&gt;
 contrib | pg_module          | table | pg_modules | modules, which can imported or deported&lt;br /&gt;
 contrib | pg_module_contents | table | pg_modules | module contents&lt;br /&gt;
 contrib | pg_module_usage    | view  | pg_modules | modules imported into schemas&lt;br /&gt;
(3 rows)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====List available modules====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ljudmila=# select * from modules.pg_module;&lt;br /&gt;
       modname       |               modimport               |            moddeport            &lt;br /&gt;
---------------------+---------------------------------------+---------------------------------&lt;br /&gt;
 pg_buffercache      | module_pg_buffercache_import()        | module_pg_buffercache_deport()&lt;br /&gt;
 pgrowlocks          | module_pgrowlocks_import()            | module_pgrowlocks_deport()&lt;br /&gt;
 tsearch2            | module_tsearch2_import()              | module_tsearch2_deport()&lt;br /&gt;
 moddatetime         | module_moddatetime_import()           | &lt;br /&gt;
 pgcrypto            | module_pgcrypto_import()              | module_pgcrypto_deport()&lt;br /&gt;
 lo                  | module_lo_import()                    | module_lo_deport()&lt;br /&gt;
 seg                 | module_seg_import()                   | module_seg_deport()&lt;br /&gt;
 pgxml               | module_pgxml_import()                 | module_pgxml_deport()&lt;br /&gt;
 test_parser         | module_test_parser_import()           | module_test_parser_deport()&lt;br /&gt;
 tablefunc           | module_tablefunc_import()             | module_tablefunc_deport()&lt;br /&gt;
 cube                | module_cube_import()                  | module_cube_deport()&lt;br /&gt;
 timetravel          | module_timetravel_import()            | &lt;br /&gt;
 chkpass             | module_chkpass_import()               | module_chkpass_deport()&lt;br /&gt;
 _int                | module__int_import()                  | module__int_deport()&lt;br /&gt;
 refint              | module_refint_import()                | &lt;br /&gt;
 int_aggregate       | module_int_aggregate_import()         | module_int_aggregate_deport()&lt;br /&gt;
 pgstattuple         | module_pgstattuple_import()           | module_pgstattuple_deport()&lt;br /&gt;
 fuzzystrmatch       | module_fuzzystrmatch_import()         | module_fuzzystrmatch_deport()&lt;br /&gt;
 pg_freespacemap     | module_pg_freespacemap_import()       | module_pg_freespacemap_deport()&lt;br /&gt;
 dblink              | module_dblink_import()                | module_dblink_deport()&lt;br /&gt;
 isn                 | module_isn_import()                   | module_isn_deport()&lt;br /&gt;
 pageinspect         | module_pageinspect_import()           | module_pageinspect_deport()&lt;br /&gt;
 insert_username     | module_insert_username_import()       | &lt;br /&gt;
 adminpack           | module_adminpack_import()             | module_adminpack_deport()&lt;br /&gt;
 ltree               | module_ltree_import()                 | module_ltree_deport()&lt;br /&gt;
 dict_int            | module_dict_int_import()              | module_dict_int_deport()&lt;br /&gt;
 autoinc             | module_autoinc_import()               | &lt;br /&gt;
 btree_gist          | module_btree_gist_import()            | module_btree_gist_deport()&lt;br /&gt;
 dict_xsyn           | module_dict_xsyn_import()             | module_dict_xsyn_deport()&lt;br /&gt;
 pg_trgm             | module_pg_trgm_import()               | module_pg_trgm_deport()&lt;br /&gt;
 hstore              | module_hstore_import()                | module_hstore_deport()&lt;br /&gt;
 earthdistance       | module_earthdistance_import()         | module_earthdistance_deport()&lt;br /&gt;
 sslinfo             | module_sslinfo_import()               | module_sslinfo_deport()&lt;br /&gt;
(35 rows)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====List module contents====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ljudmila=# select * from modules.pg_module_contents where modname='tablefunc';&lt;br /&gt;
  modname  | sql_type |                     sql_identifier                     |  objid  | objsubid &lt;br /&gt;
-----------+----------+--------------------------------------------------------+---------+----------&lt;br /&gt;
 tablefunc | FUNCTION | normal_rand(integer,double precision,double precision) | 6542867 |        0&lt;br /&gt;
 tablefunc | FUNCTION | crosstab(text)                                         | 6542868 |        0&lt;br /&gt;
 tablefunc | TYPE     | tablefunc_crosstab_2                                   | 6542871 |        0&lt;br /&gt;
 tablefunc | TYPE     | tablefunc_crosstab_3                                   | 6542874 |        0&lt;br /&gt;
 tablefunc | TYPE     | tablefunc_crosstab_4                                   | 6542877 |        0&lt;br /&gt;
 tablefunc | FUNCTION | crosstab2(text)                                        | 6542878 |        0&lt;br /&gt;
 tablefunc | FUNCTION | crosstab3(text)                                        | 6542879 |        0&lt;br /&gt;
 tablefunc | FUNCTION | crosstab4(text)                                        | 6542880 |        0&lt;br /&gt;
 tablefunc | FUNCTION | crosstab(text,integer)                                 | 6542881 |        0&lt;br /&gt;
 tablefunc | FUNCTION | crosstab(text,text)                                    | 6542882 |        0&lt;br /&gt;
 tablefunc | FUNCTION | connectby(text,text,text,text,integer,text)            | 6542883 |        0&lt;br /&gt;
 tablefunc | FUNCTION | connectby(text,text,text,text,integer)                 | 6542884 |        0&lt;br /&gt;
 tablefunc | FUNCTION | connectby(text,text,text,text,text,integer,text)       | 6542885 |        0&lt;br /&gt;
 tablefunc | FUNCTION | connectby(text,text,text,text,text,integer)            | 6542886 |        0&lt;br /&gt;
(14 rows)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Show module usage by schema====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ljudmila=#  select * from modules.pg_module_usage;&lt;br /&gt;
 schema_name | module_name | module_order &lt;br /&gt;
-------------+-------------+--------------&lt;br /&gt;
(0 rows)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Grant module usage privilege to user====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ljudmila=# grant usage on schema modules to atom;&lt;br /&gt;
GRANT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Elaboration==&lt;br /&gt;
&lt;br /&gt;
===Use Cases===&lt;br /&gt;
* Installing stuff from ''contrib''&lt;br /&gt;
* Installing stuff from [http://pgfoundry.org/ PgFoundry]&lt;br /&gt;
* Installing user's own stuff&lt;br /&gt;
* Convincing ISPs that modules are cool and can be easily installed and used safely&lt;br /&gt;
&lt;br /&gt;
===Wishes/Requirements===&lt;br /&gt;
&lt;br /&gt;
✓ = done,&lt;br /&gt;
❤ = work in progress&lt;br /&gt;
&lt;br /&gt;
====✓ enable regular users to install modules====&lt;br /&gt;
Done through use of SECURITY DEFINER functions. &lt;br /&gt;
Basically, module import/deport functions run as superuser and can do anything.&lt;br /&gt;
USAGE privilege on module manager schema must be granted to roles to enable them to use modules.&lt;br /&gt;
&lt;br /&gt;
====install modules by name (and optionally version)====&lt;br /&gt;
====❤ command line interface, in spirit of apt-get or CPAN====&lt;br /&gt;
====✓ transactional installation (module either gets installed ok or not at all)====&lt;br /&gt;
====✓ you should be able to tell what is installed====&lt;br /&gt;
====✓ should manage current contrib stuff too====&lt;br /&gt;
====support multiple versions of databases and extensions====&lt;br /&gt;
====create and drop (and alter) extensions in user-specified databases/schemas====&lt;br /&gt;
====auto-get and compile and install extensions from sources from internet====&lt;br /&gt;
====module sources: contrib, pgfoundry, user====&lt;br /&gt;
====dependencies management (install dependencies as well)====&lt;br /&gt;
====uninstall should use dependancies, not hand-written SQL scripts====&lt;br /&gt;
====support for/integration with pg_dump/pg_restore; should dump import() statements insted of objects====&lt;br /&gt;
&lt;br /&gt;
==Construction==&lt;br /&gt;
&lt;br /&gt;
===Current status===&lt;br /&gt;
There is a prototype implementation of user level module manager in PL/PgSQL in form of SQL schema.&lt;br /&gt;
The name of the schema defaults to '''modules''', but can be configured at module manager installation time.&lt;br /&gt;
&lt;br /&gt;
There is a prototype implementation of command-line tool in Perl, which help with module creation.&lt;br /&gt;
This is not needed by normal SQL users.&lt;br /&gt;
&lt;br /&gt;
===Concepts===&lt;br /&gt;
A ''module'' is a collection of SQL objects, &lt;br /&gt;
which can be created or dropped at once.&lt;br /&gt;
&lt;br /&gt;
''Module manager'' is a tool, which is specific to PostgreSQL, &lt;br /&gt;
not a specific operating system. It should handle all tasks&lt;br /&gt;
related to module management&lt;br /&gt;
&lt;br /&gt;
There are two aspect to module manager:&lt;br /&gt;
# user level access for normal database users: functions '''import(modulename)''', '''install(modulename)''' and '''uninstall(modulename)'''&lt;br /&gt;
# admin level access for database administrators: functions '''create_module()''', '''drop_module()''' and '''analyze_module()'''&lt;br /&gt;
&lt;br /&gt;
Modules are installed on local system (eg Debian Linux), per&lt;br /&gt;
specific PostgreSQL version.&lt;br /&gt;
&lt;br /&gt;
Modules are installed each in it's own directory, like:&lt;br /&gt;
&lt;br /&gt;
 /usr/share/posteresql/8.3/modules/tablefunc-8.3.0/&lt;br /&gt;
&lt;br /&gt;
path structure:&lt;br /&gt;
&lt;br /&gt;
 $base/postgresql/&amp;lt;i&amp;gt;pg_version&amp;lt;/i&amp;gt;/modules/&amp;lt;i&amp;gt;modulename&amp;lt;/i&amp;gt;-&amp;lt;i&amp;gt;moduleversion&amp;lt;/i&amp;gt;/&lt;br /&gt;
&lt;br /&gt;
where:&lt;br /&gt;
* pg_version - postgresql version number (so multiple installations are supported)&lt;br /&gt;
* modulename - unique module name, (ex. hstore, tablefunc, newsysviews)&lt;br /&gt;
* moduleversion - debian-like version numbers. For contrib, this should probably match PostgreSQL version.&lt;br /&gt;
&lt;br /&gt;
module directory should contain at least:&lt;br /&gt;
* SQL install instructions (file install.sql)&lt;br /&gt;
* SQL uninstall instructions (file uninstall.sql)&lt;br /&gt;
* Module information (file module.xml) - contents of this should be elaborated&lt;br /&gt;
&lt;br /&gt;
This would make it easier for utilities to enumerate installed modules.&lt;br /&gt;
&lt;br /&gt;
Once installed, extensions can be:&lt;br /&gt;
* ''loaded'' (installed in particular database/schema)&lt;br /&gt;
* ''unloaded'' (removed from particular database/schema)&lt;br /&gt;
* ''upgraded'' (to a new version)&lt;br /&gt;
&lt;br /&gt;
Perhaps words CREATE, DROP and ALTER should be used?&lt;br /&gt;
&lt;br /&gt;
===Current ''contrib'' problems===&lt;br /&gt;
* everything in one directory; it is clumsy to match install and uninstall files and even see, what is available&lt;br /&gt;
* no module versions specified (or any metadata for that matter)&lt;br /&gt;
* many files explicitly set schema to public:&lt;br /&gt;
** this is the default anyway&lt;br /&gt;
** it requires user to edit SQL file to change this&lt;br /&gt;
** this should be set by module manager, if it is to support module installation in any schema&lt;br /&gt;
&lt;br /&gt;
Recommendations: &lt;br /&gt;
* Move everything from contrib to appropriate dirs/files in modules directory&lt;br /&gt;
* Add missing module.xml files&lt;br /&gt;
* Make symlinks from contrib&lt;br /&gt;
&lt;br /&gt;
===See Also===&lt;br /&gt;
* [[User:Ziga/xpg_package]] - somewhat older document of a similar nature&lt;/div&gt;</summary>
		<author><name>Ziga</name></author>	</entry>

	<entry>
		<id>http://wiki.postgresql.org/wiki/Module_Manager</id>
		<title>Module Manager</title>
		<link rel="alternate" type="text/html" href="http://wiki.postgresql.org/wiki/Module_Manager"/>
				<updated>2008-10-17T20:28:58Z</updated>
		
		<summary type="html">&lt;p&gt;Ziga:&amp;#32;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;There has been some interest PostgreSQL extension/package/module manager.&lt;br /&gt;
&lt;br /&gt;
We would like some software to make it easier for users and developers to install and manage&lt;br /&gt;
various add-on features available for PostgreSQL.&lt;br /&gt;
&lt;br /&gt;
Currently the process of installing add-ons is rather manual and cumbersome. &lt;br /&gt;
It usually requires command-line interface and/or superuser access.&lt;br /&gt;
It would be great, if modules could be used through SQL alone.&lt;br /&gt;
&lt;br /&gt;
Recently, this topic has reappeared on pgsql-hackers mailing list:&lt;br /&gt;
* [http://archives.postgresql.org/pgsql-hackers/2008-04/msg00132.php 2008-04 pgsql-hackers thread]&lt;br /&gt;
* [http://archives.postgresql.org/pgsql-hackers/2007-10/msg01281.php 2007-10 pgsql-hackers thread]&lt;br /&gt;
* [http://archives.postgresql.org/pgsql-patches/2006-05/msg00327.php 2006-05 pgsql-hackers thread]&lt;br /&gt;
* [http://archives.postgresql.org/message-id/ca33c0a30804061349s41b4d8fcsa9c579454b27ecd2@mail.gmail.com Database owner installable modules patch by Tom Dunstan]&lt;br /&gt;
* [http://archives.postgresql.org/pgsql-hackers/2008-07/msg01098.php PostgreSQL extensions packaging proposal by Dimitri Fontaine]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Perhaps a difference among terms ''extension'', ''package'' and ''module'' should be clarified?&lt;br /&gt;
Here the term ''module'' is used, due to popular demand.&lt;br /&gt;
&lt;br /&gt;
==Synopsis==&lt;br /&gt;
&lt;br /&gt;
===As a database user===&lt;br /&gt;
&lt;br /&gt;
====Using modules====&lt;br /&gt;
Import desired module with '''contrib.import()''' function.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ljudmila=&amp;gt; select contrib.import('hstore');&lt;br /&gt;
... stuff ...&lt;br /&gt;
    import     &lt;br /&gt;
---------------&lt;br /&gt;
 IMPORT DEFINE hstore&lt;br /&gt;
(1 row)&lt;br /&gt;
&lt;br /&gt;
ljudmila=&amp;gt; select 'a=&amp;gt;3'::hstore;&lt;br /&gt;
  hstore  &lt;br /&gt;
----------&lt;br /&gt;
 &amp;quot;a&amp;quot;=&amp;gt;&amp;quot;3&amp;quot;&lt;br /&gt;
(1 row)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===As a database administrator===&lt;br /&gt;
&lt;br /&gt;
====Install the module manager and contrib modules====&lt;br /&gt;
&lt;br /&gt;
By default, this goes into schema '''contrib'''.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
postgres@mama:$ pg_module all &amp;gt;pg_module.sql&lt;br /&gt;
postgres@mama:$ psql&lt;br /&gt;
ljudmila=# \i pg_module.sql&lt;br /&gt;
BEGIN&lt;br /&gt;
... stuff ...&lt;br /&gt;
COMMIT&lt;br /&gt;
ljudmila=# set search_path=contrib; \d+&lt;br /&gt;
SET&lt;br /&gt;
                                      List of relations&lt;br /&gt;
 Schema  |        Name        | Type  |   Owner    |               Description               &lt;br /&gt;
---------+--------------------+-------+------------+-----------------------------------------&lt;br /&gt;
 contrib | pg_module          | table | pg_modules | modules, which can imported or deported&lt;br /&gt;
 contrib | pg_module_contents | table | pg_modules | module contents&lt;br /&gt;
 contrib | pg_module_usage    | view  | pg_modules | modules imported into schemas&lt;br /&gt;
(3 rows)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====List available modules====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ljudmila=# select * from modules.pg_module;&lt;br /&gt;
       modname       |               modimport               |            moddeport            &lt;br /&gt;
---------------------+---------------------------------------+---------------------------------&lt;br /&gt;
 pg_buffercache      | module_pg_buffercache_import()        | module_pg_buffercache_deport()&lt;br /&gt;
 pgrowlocks          | module_pgrowlocks_import()            | module_pgrowlocks_deport()&lt;br /&gt;
 tsearch2            | module_tsearch2_import()              | module_tsearch2_deport()&lt;br /&gt;
 moddatetime         | module_moddatetime_import()           | &lt;br /&gt;
 pgcrypto            | module_pgcrypto_import()              | module_pgcrypto_deport()&lt;br /&gt;
 lo                  | module_lo_import()                    | module_lo_deport()&lt;br /&gt;
 seg                 | module_seg_import()                   | module_seg_deport()&lt;br /&gt;
 pgxml               | module_pgxml_import()                 | module_pgxml_deport()&lt;br /&gt;
 test_parser         | module_test_parser_import()           | module_test_parser_deport()&lt;br /&gt;
 tablefunc           | module_tablefunc_import()             | module_tablefunc_deport()&lt;br /&gt;
 cube                | module_cube_import()                  | module_cube_deport()&lt;br /&gt;
 timetravel          | module_timetravel_import()            | &lt;br /&gt;
 chkpass             | module_chkpass_import()               | module_chkpass_deport()&lt;br /&gt;
 _int                | module__int_import()                  | module__int_deport()&lt;br /&gt;
 refint              | module_refint_import()                | &lt;br /&gt;
 int_aggregate       | module_int_aggregate_import()         | module_int_aggregate_deport()&lt;br /&gt;
 pgstattuple         | module_pgstattuple_import()           | module_pgstattuple_deport()&lt;br /&gt;
 fuzzystrmatch       | module_fuzzystrmatch_import()         | module_fuzzystrmatch_deport()&lt;br /&gt;
 pg_freespacemap     | module_pg_freespacemap_import()       | module_pg_freespacemap_deport()&lt;br /&gt;
 dblink              | module_dblink_import()                | module_dblink_deport()&lt;br /&gt;
 isn                 | module_isn_import()                   | module_isn_deport()&lt;br /&gt;
 pageinspect         | module_pageinspect_import()           | module_pageinspect_deport()&lt;br /&gt;
 insert_username     | module_insert_username_import()       | &lt;br /&gt;
 adminpack           | module_adminpack_import()             | module_adminpack_deport()&lt;br /&gt;
 ltree               | module_ltree_import()                 | module_ltree_deport()&lt;br /&gt;
 dict_int            | module_dict_int_import()              | module_dict_int_deport()&lt;br /&gt;
 autoinc             | module_autoinc_import()               | &lt;br /&gt;
 btree_gist          | module_btree_gist_import()            | module_btree_gist_deport()&lt;br /&gt;
 dict_xsyn           | module_dict_xsyn_import()             | module_dict_xsyn_deport()&lt;br /&gt;
 pg_trgm             | module_pg_trgm_import()               | module_pg_trgm_deport()&lt;br /&gt;
 hstore              | module_hstore_import()                | module_hstore_deport()&lt;br /&gt;
 earthdistance       | module_earthdistance_import()         | module_earthdistance_deport()&lt;br /&gt;
 sslinfo             | module_sslinfo_import()               | module_sslinfo_deport()&lt;br /&gt;
(35 rows)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====List module contents====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ljudmila=# select * from modules.pg_module_contents where modname='tablefunc';&lt;br /&gt;
  modname  | sql_type |                     sql_identifier                     |  objid  | objsubid &lt;br /&gt;
-----------+----------+--------------------------------------------------------+---------+----------&lt;br /&gt;
 tablefunc | FUNCTION | normal_rand(integer,double precision,double precision) | 6542867 |        0&lt;br /&gt;
 tablefunc | FUNCTION | crosstab(text)                                         | 6542868 |        0&lt;br /&gt;
 tablefunc | TYPE     | tablefunc_crosstab_2                                   | 6542871 |        0&lt;br /&gt;
 tablefunc | TYPE     | tablefunc_crosstab_3                                   | 6542874 |        0&lt;br /&gt;
 tablefunc | TYPE     | tablefunc_crosstab_4                                   | 6542877 |        0&lt;br /&gt;
 tablefunc | FUNCTION | crosstab2(text)                                        | 6542878 |        0&lt;br /&gt;
 tablefunc | FUNCTION | crosstab3(text)                                        | 6542879 |        0&lt;br /&gt;
 tablefunc | FUNCTION | crosstab4(text)                                        | 6542880 |        0&lt;br /&gt;
 tablefunc | FUNCTION | crosstab(text,integer)                                 | 6542881 |        0&lt;br /&gt;
 tablefunc | FUNCTION | crosstab(text,text)                                    | 6542882 |        0&lt;br /&gt;
 tablefunc | FUNCTION | connectby(text,text,text,text,integer,text)            | 6542883 |        0&lt;br /&gt;
 tablefunc | FUNCTION | connectby(text,text,text,text,integer)                 | 6542884 |        0&lt;br /&gt;
 tablefunc | FUNCTION | connectby(text,text,text,text,text,integer,text)       | 6542885 |        0&lt;br /&gt;
 tablefunc | FUNCTION | connectby(text,text,text,text,text,integer)            | 6542886 |        0&lt;br /&gt;
(14 rows)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Show module usage by schema====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ljudmila=#  select * from modules.pg_module_usage;&lt;br /&gt;
 schema_name | module_name | module_order &lt;br /&gt;
-------------+-------------+--------------&lt;br /&gt;
(0 rows)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Grant module usage privilege to user====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ljudmila=# grant usage on schema modules to atom;&lt;br /&gt;
GRANT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Elaboration==&lt;br /&gt;
&lt;br /&gt;
===Use Cases===&lt;br /&gt;
* Installing stuff from ''contrib''&lt;br /&gt;
* Installing stuff from [http://pgfoundry.org/ PgFoundry]&lt;br /&gt;
* Installing user's own stuff&lt;br /&gt;
* Convincing ISPs that modules are cool and can be easily installed and used safely&lt;br /&gt;
&lt;br /&gt;
===Wishes/Requirements===&lt;br /&gt;
&lt;br /&gt;
✓ = done,&lt;br /&gt;
❤ = work in progress&lt;br /&gt;
&lt;br /&gt;
====✓ enable regular users to install modules====&lt;br /&gt;
Done through use of SECURITY DEFINER functions. &lt;br /&gt;
Basically, module import/deport functions run as superuser and can do anything.&lt;br /&gt;
USAGE privilege on module manager schema must be granted to roles to enable them to use modules.&lt;br /&gt;
&lt;br /&gt;
====install modules by name (and optionally version)====&lt;br /&gt;
====❤ command line interface, in spirit of apt-get or CPAN====&lt;br /&gt;
====✓ transactional installation (module either gets installed ok or not at all)====&lt;br /&gt;
====✓ you should be able to tell what is installed====&lt;br /&gt;
====✓ should manage current contrib stuff too====&lt;br /&gt;
====support multiple versions of databases and extensions====&lt;br /&gt;
====create and drop (and alter) extensions in user-specified databases/schemas====&lt;br /&gt;
====auto-get and compile and install extensions from sources from internet====&lt;br /&gt;
====module sources: contrib, pgfoundry, user====&lt;br /&gt;
====dependencies management (install dependencies as well)====&lt;br /&gt;
====uninstall should use dependancies, not hand-written SQL scripts====&lt;br /&gt;
====support for/integration with pg_dump/pg_restore; should dump import() statements insted of objects====&lt;br /&gt;
&lt;br /&gt;
==Construction==&lt;br /&gt;
&lt;br /&gt;
===Current status===&lt;br /&gt;
There is a prototype implementation of user level module manager in PL/PgSQL in form of SQL schema.&lt;br /&gt;
The name of the schema defaults to '''modules''', but can be configured at module manager installation time.&lt;br /&gt;
&lt;br /&gt;
There is a prototype implementation of command-line tool in Perl, which help with module creation.&lt;br /&gt;
This is not needed by normal SQL users.&lt;br /&gt;
&lt;br /&gt;
===Concepts===&lt;br /&gt;
A ''module'' is a collection of SQL objects, &lt;br /&gt;
which can be created or dropped at once.&lt;br /&gt;
&lt;br /&gt;
''Module manager'' is a tool, which is specific to PostgreSQL, &lt;br /&gt;
not a specific operating system. It should handle all tasks&lt;br /&gt;
related to module management&lt;br /&gt;
&lt;br /&gt;
There are two aspect to module manager:&lt;br /&gt;
# user level access for normal database users: functions '''import(modulename)''', '''install(modulename)''' and '''uninstall(modulename)'''&lt;br /&gt;
# admin level access for database administrators: functions '''create_module()''', '''drop_module()''' and '''analyze_module()'''&lt;br /&gt;
&lt;br /&gt;
Modules are installed on local system (eg Debian Linux), per&lt;br /&gt;
specific PostgreSQL version.&lt;br /&gt;
&lt;br /&gt;
Modules are installed each in it's own directory, like:&lt;br /&gt;
&lt;br /&gt;
 /usr/share/posteresql/8.3/modules/tablefunc-8.3.0/&lt;br /&gt;
&lt;br /&gt;
path structure:&lt;br /&gt;
&lt;br /&gt;
 $base/postgresql/&amp;lt;i&amp;gt;pg_version&amp;lt;/i&amp;gt;/modules/&amp;lt;i&amp;gt;modulename&amp;lt;/i&amp;gt;-&amp;lt;i&amp;gt;moduleversion&amp;lt;/i&amp;gt;/&lt;br /&gt;
&lt;br /&gt;
where:&lt;br /&gt;
* pg_version - postgresql version number (so multiple installations are supported)&lt;br /&gt;
* modulename - unique module name, (ex. hstore, tablefunc, newsysviews)&lt;br /&gt;
* moduleversion - debian-like version numbers. For contrib, this should probably match PostgreSQL version.&lt;br /&gt;
&lt;br /&gt;
module directory should contain at least:&lt;br /&gt;
* SQL install instructions (file install.sql)&lt;br /&gt;
* SQL uninstall instructions (file uninstall.sql)&lt;br /&gt;
* Module information (file module.xml) - contents of this should be elaborated&lt;br /&gt;
&lt;br /&gt;
This would make it easier for utilities to enumerate installed modules.&lt;br /&gt;
&lt;br /&gt;
Once installed, extensions can be:&lt;br /&gt;
* ''loaded'' (installed in particular database/schema)&lt;br /&gt;
* ''unloaded'' (removed from particular database/schema)&lt;br /&gt;
* ''upgraded'' (to a new version)&lt;br /&gt;
&lt;br /&gt;
Perhaps words CREATE, DROP and ALTER should be used?&lt;br /&gt;
&lt;br /&gt;
===Current ''contrib'' problems===&lt;br /&gt;
* everything in one directory; it is clumsy to match install and uninstall files and even see, what is available&lt;br /&gt;
* no module versions specified (or any metadata for that matter)&lt;br /&gt;
* many files explicitly set schema to public:&lt;br /&gt;
** this is the default anyway&lt;br /&gt;
** it requires user to edit SQL file to change this&lt;br /&gt;
** this should be set by module manager, if it is to support module installation in any schema&lt;br /&gt;
&lt;br /&gt;
Recommendations: &lt;br /&gt;
* Move everything from contrib to appropriate dirs/files in modules directory&lt;br /&gt;
* Add missing module.xml files&lt;br /&gt;
* Make symlinks from contrib&lt;br /&gt;
&lt;br /&gt;
===See Also===&lt;br /&gt;
* [[User:Ziga/xpg_package]] - somewhat older document of a similar nature&lt;/div&gt;</summary>
		<author><name>Ziga</name></author>	</entry>

	<entry>
		<id>http://wiki.postgresql.org/wiki/Module_Manager</id>
		<title>Module Manager</title>
		<link rel="alternate" type="text/html" href="http://wiki.postgresql.org/wiki/Module_Manager"/>
				<updated>2008-10-17T20:28:02Z</updated>
		
		<summary type="html">&lt;p&gt;Ziga:&amp;#32;/* As a database user */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;There has been some interest PostgreSQL extension/package/module manager.&lt;br /&gt;
&lt;br /&gt;
We would like some software to make it easier for users and developers to install and manage&lt;br /&gt;
various add-on features available for PostgreSQL.&lt;br /&gt;
&lt;br /&gt;
Currently the process of installing add-ons is rather manual and cumbersome. &lt;br /&gt;
It usually requires command-line interface and/or superuser access.&lt;br /&gt;
It would be great, if modules could be used through SQL alone.&lt;br /&gt;
&lt;br /&gt;
Recently, this topic has reappeared on pgsql-hackers mailing list:&lt;br /&gt;
* [http://archives.postgresql.org/pgsql-hackers/2008-04/msg00132.php 2008-04 pgsql-hackers thread]&lt;br /&gt;
* [http://archives.postgresql.org/pgsql-hackers/2007-10/msg01281.php 2007-10 pgsql-hackers thread]&lt;br /&gt;
* [http://archives.postgresql.org/pgsql-patches/2006-05/msg00327.php 2006-05 pgsql-hackers thread]&lt;br /&gt;
* [http://archives.postgresql.org/message-id/ca33c0a30804061349s41b4d8fcsa9c579454b27ecd2@mail.gmail.com Database owner installable modules patch by Tom Dunstan]&lt;br /&gt;
* [http://archives.postgresql.org/pgsql-hackers/2008-07/msg01098.php PostgreSQL extensions packaging proposal by Dimitri Fontaine]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Perhaps a difference among terms ''extension'', ''package'' and ''module'' should be clarified?&lt;br /&gt;
Here the term ''module'' is used, due to popular demand.&lt;br /&gt;
&lt;br /&gt;
==Synopsis==&lt;br /&gt;
&lt;br /&gt;
===As a database user===&lt;br /&gt;
&lt;br /&gt;
====Using modules====&lt;br /&gt;
Import desired module with '''contrib.import()''' function.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ljudmila=&amp;gt; select contrib.import('hstore');&lt;br /&gt;
... stuff ...&lt;br /&gt;
    import     &lt;br /&gt;
---------------&lt;br /&gt;
 IMPORT DEFINE hstore&lt;br /&gt;
(1 row)&lt;br /&gt;
&lt;br /&gt;
ljudmila=&amp;gt; select 'a=&amp;gt;3'::hstore;&lt;br /&gt;
  hstore  &lt;br /&gt;
----------&lt;br /&gt;
 &amp;quot;a&amp;quot;=&amp;gt;&amp;quot;3&amp;quot;&lt;br /&gt;
(1 row)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===As a database administrator===&lt;br /&gt;
&lt;br /&gt;
====Install the module manager and contrib modules====&lt;br /&gt;
&lt;br /&gt;
By default, this goes into schema '''modules'''.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
postgres@mama:$ pg_module all &amp;gt;pg_module.sql&lt;br /&gt;
postgres@mama:$ psql&lt;br /&gt;
ljudmila=# \i pg_module.sql&lt;br /&gt;
BEGIN&lt;br /&gt;
... stuff ...&lt;br /&gt;
COMMIT&lt;br /&gt;
ljudmila=# set search_path=modules; \d+&lt;br /&gt;
SET&lt;br /&gt;
                                      List of relations&lt;br /&gt;
 Schema  |        Name        | Type  |   Owner    |               Description               &lt;br /&gt;
---------+--------------------+-------+------------+-----------------------------------------&lt;br /&gt;
 modules | pg_module          | table | pg_modules | modules, which can imported or deported&lt;br /&gt;
 modules | pg_module_contents | table | pg_modules | module contents&lt;br /&gt;
 modules | pg_module_usage    | view  | pg_modules | modules imported into schemas&lt;br /&gt;
(3 rows)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====List available modules====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ljudmila=# select * from modules.pg_module;&lt;br /&gt;
       modname       |               modimport               |            moddeport            &lt;br /&gt;
---------------------+---------------------------------------+---------------------------------&lt;br /&gt;
 pg_buffercache      | module_pg_buffercache_import()        | module_pg_buffercache_deport()&lt;br /&gt;
 pgrowlocks          | module_pgrowlocks_import()            | module_pgrowlocks_deport()&lt;br /&gt;
 tsearch2            | module_tsearch2_import()              | module_tsearch2_deport()&lt;br /&gt;
 moddatetime         | module_moddatetime_import()           | &lt;br /&gt;
 pgcrypto            | module_pgcrypto_import()              | module_pgcrypto_deport()&lt;br /&gt;
 lo                  | module_lo_import()                    | module_lo_deport()&lt;br /&gt;
 seg                 | module_seg_import()                   | module_seg_deport()&lt;br /&gt;
 pgxml               | module_pgxml_import()                 | module_pgxml_deport()&lt;br /&gt;
 test_parser         | module_test_parser_import()           | module_test_parser_deport()&lt;br /&gt;
 tablefunc           | module_tablefunc_import()             | module_tablefunc_deport()&lt;br /&gt;
 cube                | module_cube_import()                  | module_cube_deport()&lt;br /&gt;
 timetravel          | module_timetravel_import()            | &lt;br /&gt;
 chkpass             | module_chkpass_import()               | module_chkpass_deport()&lt;br /&gt;
 _int                | module__int_import()                  | module__int_deport()&lt;br /&gt;
 refint              | module_refint_import()                | &lt;br /&gt;
 int_aggregate       | module_int_aggregate_import()         | module_int_aggregate_deport()&lt;br /&gt;
 pgstattuple         | module_pgstattuple_import()           | module_pgstattuple_deport()&lt;br /&gt;
 fuzzystrmatch       | module_fuzzystrmatch_import()         | module_fuzzystrmatch_deport()&lt;br /&gt;
 pg_freespacemap     | module_pg_freespacemap_import()       | module_pg_freespacemap_deport()&lt;br /&gt;
 dblink              | module_dblink_import()                | module_dblink_deport()&lt;br /&gt;
 isn                 | module_isn_import()                   | module_isn_deport()&lt;br /&gt;
 pageinspect         | module_pageinspect_import()           | module_pageinspect_deport()&lt;br /&gt;
 insert_username     | module_insert_username_import()       | &lt;br /&gt;
 adminpack           | module_adminpack_import()             | module_adminpack_deport()&lt;br /&gt;
 ltree               | module_ltree_import()                 | module_ltree_deport()&lt;br /&gt;
 dict_int            | module_dict_int_import()              | module_dict_int_deport()&lt;br /&gt;
 autoinc             | module_autoinc_import()               | &lt;br /&gt;
 btree_gist          | module_btree_gist_import()            | module_btree_gist_deport()&lt;br /&gt;
 dict_xsyn           | module_dict_xsyn_import()             | module_dict_xsyn_deport()&lt;br /&gt;
 pg_trgm             | module_pg_trgm_import()               | module_pg_trgm_deport()&lt;br /&gt;
 hstore              | module_hstore_import()                | module_hstore_deport()&lt;br /&gt;
 earthdistance       | module_earthdistance_import()         | module_earthdistance_deport()&lt;br /&gt;
 sslinfo             | module_sslinfo_import()               | module_sslinfo_deport()&lt;br /&gt;
(35 rows)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====List module contents====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ljudmila=# select * from modules.pg_module_contents where modname='tablefunc';&lt;br /&gt;
  modname  | sql_type |                     sql_identifier                     |  objid  | objsubid &lt;br /&gt;
-----------+----------+--------------------------------------------------------+---------+----------&lt;br /&gt;
 tablefunc | FUNCTION | normal_rand(integer,double precision,double precision) | 6542867 |        0&lt;br /&gt;
 tablefunc | FUNCTION | crosstab(text)                                         | 6542868 |        0&lt;br /&gt;
 tablefunc | TYPE     | tablefunc_crosstab_2                                   | 6542871 |        0&lt;br /&gt;
 tablefunc | TYPE     | tablefunc_crosstab_3                                   | 6542874 |        0&lt;br /&gt;
 tablefunc | TYPE     | tablefunc_crosstab_4                                   | 6542877 |        0&lt;br /&gt;
 tablefunc | FUNCTION | crosstab2(text)                                        | 6542878 |        0&lt;br /&gt;
 tablefunc | FUNCTION | crosstab3(text)                                        | 6542879 |        0&lt;br /&gt;
 tablefunc | FUNCTION | crosstab4(text)                                        | 6542880 |        0&lt;br /&gt;
 tablefunc | FUNCTION | crosstab(text,integer)                                 | 6542881 |        0&lt;br /&gt;
 tablefunc | FUNCTION | crosstab(text,text)                                    | 6542882 |        0&lt;br /&gt;
 tablefunc | FUNCTION | connectby(text,text,text,text,integer,text)            | 6542883 |        0&lt;br /&gt;
 tablefunc | FUNCTION | connectby(text,text,text,text,integer)                 | 6542884 |        0&lt;br /&gt;
 tablefunc | FUNCTION | connectby(text,text,text,text,text,integer,text)       | 6542885 |        0&lt;br /&gt;
 tablefunc | FUNCTION | connectby(text,text,text,text,text,integer)            | 6542886 |        0&lt;br /&gt;
(14 rows)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Show module usage by schema====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ljudmila=#  select * from modules.pg_module_usage;&lt;br /&gt;
 schema_name | module_name | module_order &lt;br /&gt;
-------------+-------------+--------------&lt;br /&gt;
(0 rows)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Grant module usage privilege to user====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ljudmila=# grant usage on schema modules to atom;&lt;br /&gt;
GRANT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Elaboration==&lt;br /&gt;
&lt;br /&gt;
===Use Cases===&lt;br /&gt;
* Installing stuff from ''contrib''&lt;br /&gt;
* Installing stuff from [http://pgfoundry.org/ PgFoundry]&lt;br /&gt;
* Installing user's own stuff&lt;br /&gt;
* Convincing ISPs that modules are cool and can be easily installed and used safely&lt;br /&gt;
&lt;br /&gt;
===Wishes/Requirements===&lt;br /&gt;
&lt;br /&gt;
✓ = done,&lt;br /&gt;
❤ = work in progress&lt;br /&gt;
&lt;br /&gt;
====✓ enable regular users to install modules====&lt;br /&gt;
Done through use of SECURITY DEFINER functions. &lt;br /&gt;
Basically, module import/deport functions run as superuser and can do anything.&lt;br /&gt;
USAGE privilege on module manager schema must be granted to roles to enable them to use modules.&lt;br /&gt;
&lt;br /&gt;
====install modules by name (and optionally version)====&lt;br /&gt;
====❤ command line interface, in spirit of apt-get or CPAN====&lt;br /&gt;
====✓ transactional installation (module either gets installed ok or not at all)====&lt;br /&gt;
====✓ you should be able to tell what is installed====&lt;br /&gt;
====✓ should manage current contrib stuff too====&lt;br /&gt;
====support multiple versions of databases and extensions====&lt;br /&gt;
====create and drop (and alter) extensions in user-specified databases/schemas====&lt;br /&gt;
====auto-get and compile and install extensions from sources from internet====&lt;br /&gt;
====module sources: contrib, pgfoundry, user====&lt;br /&gt;
====dependencies management (install dependencies as well)====&lt;br /&gt;
====uninstall should use dependancies, not hand-written SQL scripts====&lt;br /&gt;
====support for/integration with pg_dump/pg_restore; should dump import() statements insted of objects====&lt;br /&gt;
&lt;br /&gt;
==Construction==&lt;br /&gt;
&lt;br /&gt;
===Current status===&lt;br /&gt;
There is a prototype implementation of user level module manager in PL/PgSQL in form of SQL schema.&lt;br /&gt;
The name of the schema defaults to '''modules''', but can be configured at module manager installation time.&lt;br /&gt;
&lt;br /&gt;
There is a prototype implementation of command-line tool in Perl, which help with module creation.&lt;br /&gt;
This is not needed by normal SQL users.&lt;br /&gt;
&lt;br /&gt;
===Concepts===&lt;br /&gt;
A ''module'' is a collection of SQL objects, &lt;br /&gt;
which can be created or dropped at once.&lt;br /&gt;
&lt;br /&gt;
''Module manager'' is a tool, which is specific to PostgreSQL, &lt;br /&gt;
not a specific operating system. It should handle all tasks&lt;br /&gt;
related to module management&lt;br /&gt;
&lt;br /&gt;
There are two aspect to module manager:&lt;br /&gt;
# user level access for normal database users: functions '''import(modulename)''', '''install(modulename)''' and '''uninstall(modulename)'''&lt;br /&gt;
# admin level access for database administrators: functions '''create_module()''', '''drop_module()''' and '''analyze_module()'''&lt;br /&gt;
&lt;br /&gt;
Modules are installed on local system (eg Debian Linux), per&lt;br /&gt;
specific PostgreSQL version.&lt;br /&gt;
&lt;br /&gt;
Modules are installed each in it's own directory, like:&lt;br /&gt;
&lt;br /&gt;
 /usr/share/posteresql/8.3/modules/tablefunc-8.3.0/&lt;br /&gt;
&lt;br /&gt;
path structure:&lt;br /&gt;
&lt;br /&gt;
 $base/postgresql/&amp;lt;i&amp;gt;pg_version&amp;lt;/i&amp;gt;/modules/&amp;lt;i&amp;gt;modulename&amp;lt;/i&amp;gt;-&amp;lt;i&amp;gt;moduleversion&amp;lt;/i&amp;gt;/&lt;br /&gt;
&lt;br /&gt;
where:&lt;br /&gt;
* pg_version - postgresql version number (so multiple installations are supported)&lt;br /&gt;
* modulename - unique module name, (ex. hstore, tablefunc, newsysviews)&lt;br /&gt;
* moduleversion - debian-like version numbers. For contrib, this should probably match PostgreSQL version.&lt;br /&gt;
&lt;br /&gt;
module directory should contain at least:&lt;br /&gt;
* SQL install instructions (file install.sql)&lt;br /&gt;
* SQL uninstall instructions (file uninstall.sql)&lt;br /&gt;
* Module information (file module.xml) - contents of this should be elaborated&lt;br /&gt;
&lt;br /&gt;
This would make it easier for utilities to enumerate installed modules.&lt;br /&gt;
&lt;br /&gt;
Once installed, extensions can be:&lt;br /&gt;
* ''loaded'' (installed in particular database/schema)&lt;br /&gt;
* ''unloaded'' (removed from particular database/schema)&lt;br /&gt;
* ''upgraded'' (to a new version)&lt;br /&gt;
&lt;br /&gt;
Perhaps words CREATE, DROP and ALTER should be used?&lt;br /&gt;
&lt;br /&gt;
===Current ''contrib'' problems===&lt;br /&gt;
* everything in one directory; it is clumsy to match install and uninstall files and even see, what is available&lt;br /&gt;
* no module versions specified (or any metadata for that matter)&lt;br /&gt;
* many files explicitly set schema to public:&lt;br /&gt;
** this is the default anyway&lt;br /&gt;
** it requires user to edit SQL file to change this&lt;br /&gt;
** this should be set by module manager, if it is to support module installation in any schema&lt;br /&gt;
&lt;br /&gt;
Recommendations: &lt;br /&gt;
* Move everything from contrib to appropriate dirs/files in modules directory&lt;br /&gt;
* Add missing module.xml files&lt;br /&gt;
* Make symlinks from contrib&lt;br /&gt;
&lt;br /&gt;
===See Also===&lt;br /&gt;
* [[User:Ziga/xpg_package]] - somewhat older document of a similar nature&lt;/div&gt;</summary>
		<author><name>Ziga</name></author>	</entry>

	<entry>
		<id>http://wiki.postgresql.org/wiki/Module_Manager</id>
		<title>Module Manager</title>
		<link rel="alternate" type="text/html" href="http://wiki.postgresql.org/wiki/Module_Manager"/>
				<updated>2008-10-17T20:27:07Z</updated>
		
		<summary type="html">&lt;p&gt;Ziga:&amp;#32;/* Concepts */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;There has been some interest PostgreSQL extension/package/module manager.&lt;br /&gt;
&lt;br /&gt;
We would like some software to make it easier for users and developers to install and manage&lt;br /&gt;
various add-on features available for PostgreSQL.&lt;br /&gt;
&lt;br /&gt;
Currently the process of installing add-ons is rather manual and cumbersome. &lt;br /&gt;
It usually requires command-line interface and/or superuser access.&lt;br /&gt;
It would be great, if modules could be used through SQL alone.&lt;br /&gt;
&lt;br /&gt;
Recently, this topic has reappeared on pgsql-hackers mailing list:&lt;br /&gt;
* [http://archives.postgresql.org/pgsql-hackers/2008-04/msg00132.php 2008-04 pgsql-hackers thread]&lt;br /&gt;
* [http://archives.postgresql.org/pgsql-hackers/2007-10/msg01281.php 2007-10 pgsql-hackers thread]&lt;br /&gt;
* [http://archives.postgresql.org/pgsql-patches/2006-05/msg00327.php 2006-05 pgsql-hackers thread]&lt;br /&gt;
* [http://archives.postgresql.org/message-id/ca33c0a30804061349s41b4d8fcsa9c579454b27ecd2@mail.gmail.com Database owner installable modules patch by Tom Dunstan]&lt;br /&gt;
* [http://archives.postgresql.org/pgsql-hackers/2008-07/msg01098.php PostgreSQL extensions packaging proposal by Dimitri Fontaine]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Perhaps a difference among terms ''extension'', ''package'' and ''module'' should be clarified?&lt;br /&gt;
Here the term ''module'' is used, due to popular demand.&lt;br /&gt;
&lt;br /&gt;
==Synopsis==&lt;br /&gt;
&lt;br /&gt;
===As a database user===&lt;br /&gt;
&lt;br /&gt;
====Using modules====&lt;br /&gt;
Simply import desired module with '''modules.import()''' function.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ljudmila=&amp;gt; select modules.import('hstore');&lt;br /&gt;
... stuff ...&lt;br /&gt;
    import     &lt;br /&gt;
---------------&lt;br /&gt;
 IMPORT DEFINE hstore&lt;br /&gt;
(1 row)&lt;br /&gt;
&lt;br /&gt;
ljudmila=&amp;gt; select 'a=&amp;gt;3'::hstore;&lt;br /&gt;
  hstore  &lt;br /&gt;
----------&lt;br /&gt;
 &amp;quot;a&amp;quot;=&amp;gt;&amp;quot;3&amp;quot;&lt;br /&gt;
(1 row)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If module is already imported, IMPORT is returned instead of IMPORT DEFINE.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===As a database administrator===&lt;br /&gt;
&lt;br /&gt;
====Install the module manager and contrib modules====&lt;br /&gt;
&lt;br /&gt;
By default, this goes into schema '''modules'''.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
postgres@mama:$ pg_module all &amp;gt;pg_module.sql&lt;br /&gt;
postgres@mama:$ psql&lt;br /&gt;
ljudmila=# \i pg_module.sql&lt;br /&gt;
BEGIN&lt;br /&gt;
... stuff ...&lt;br /&gt;
COMMIT&lt;br /&gt;
ljudmila=# set search_path=modules; \d+&lt;br /&gt;
SET&lt;br /&gt;
                                      List of relations&lt;br /&gt;
 Schema  |        Name        | Type  |   Owner    |               Description               &lt;br /&gt;
---------+--------------------+-------+------------+-----------------------------------------&lt;br /&gt;
 modules | pg_module          | table | pg_modules | modules, which can imported or deported&lt;br /&gt;
 modules | pg_module_contents | table | pg_modules | module contents&lt;br /&gt;
 modules | pg_module_usage    | view  | pg_modules | modules imported into schemas&lt;br /&gt;
(3 rows)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====List available modules====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ljudmila=# select * from modules.pg_module;&lt;br /&gt;
       modname       |               modimport               |            moddeport            &lt;br /&gt;
---------------------+---------------------------------------+---------------------------------&lt;br /&gt;
 pg_buffercache      | module_pg_buffercache_import()        | module_pg_buffercache_deport()&lt;br /&gt;
 pgrowlocks          | module_pgrowlocks_import()            | module_pgrowlocks_deport()&lt;br /&gt;
 tsearch2            | module_tsearch2_import()              | module_tsearch2_deport()&lt;br /&gt;
 moddatetime         | module_moddatetime_import()           | &lt;br /&gt;
 pgcrypto            | module_pgcrypto_import()              | module_pgcrypto_deport()&lt;br /&gt;
 lo                  | module_lo_import()                    | module_lo_deport()&lt;br /&gt;
 seg                 | module_seg_import()                   | module_seg_deport()&lt;br /&gt;
 pgxml               | module_pgxml_import()                 | module_pgxml_deport()&lt;br /&gt;
 test_parser         | module_test_parser_import()           | module_test_parser_deport()&lt;br /&gt;
 tablefunc           | module_tablefunc_import()             | module_tablefunc_deport()&lt;br /&gt;
 cube                | module_cube_import()                  | module_cube_deport()&lt;br /&gt;
 timetravel          | module_timetravel_import()            | &lt;br /&gt;
 chkpass             | module_chkpass_import()               | module_chkpass_deport()&lt;br /&gt;
 _int                | module__int_import()                  | module__int_deport()&lt;br /&gt;
 refint              | module_refint_import()                | &lt;br /&gt;
 int_aggregate       | module_int_aggregate_import()         | module_int_aggregate_deport()&lt;br /&gt;
 pgstattuple         | module_pgstattuple_import()           | module_pgstattuple_deport()&lt;br /&gt;
 fuzzystrmatch       | module_fuzzystrmatch_import()         | module_fuzzystrmatch_deport()&lt;br /&gt;
 pg_freespacemap     | module_pg_freespacemap_import()       | module_pg_freespacemap_deport()&lt;br /&gt;
 dblink              | module_dblink_import()                | module_dblink_deport()&lt;br /&gt;
 isn                 | module_isn_import()                   | module_isn_deport()&lt;br /&gt;
 pageinspect         | module_pageinspect_import()           | module_pageinspect_deport()&lt;br /&gt;
 insert_username     | module_insert_username_import()       | &lt;br /&gt;
 adminpack           | module_adminpack_import()             | module_adminpack_deport()&lt;br /&gt;
 ltree               | module_ltree_import()                 | module_ltree_deport()&lt;br /&gt;
 dict_int            | module_dict_int_import()              | module_dict_int_deport()&lt;br /&gt;
 autoinc             | module_autoinc_import()               | &lt;br /&gt;
 btree_gist          | module_btree_gist_import()            | module_btree_gist_deport()&lt;br /&gt;
 dict_xsyn           | module_dict_xsyn_import()             | module_dict_xsyn_deport()&lt;br /&gt;
 pg_trgm             | module_pg_trgm_import()               | module_pg_trgm_deport()&lt;br /&gt;
 hstore              | module_hstore_import()                | module_hstore_deport()&lt;br /&gt;
 earthdistance       | module_earthdistance_import()         | module_earthdistance_deport()&lt;br /&gt;
 sslinfo             | module_sslinfo_import()               | module_sslinfo_deport()&lt;br /&gt;
(35 rows)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====List module contents====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ljudmila=# select * from modules.pg_module_contents where modname='tablefunc';&lt;br /&gt;
  modname  | sql_type |                     sql_identifier                     |  objid  | objsubid &lt;br /&gt;
-----------+----------+--------------------------------------------------------+---------+----------&lt;br /&gt;
 tablefunc | FUNCTION | normal_rand(integer,double precision,double precision) | 6542867 |        0&lt;br /&gt;
 tablefunc | FUNCTION | crosstab(text)                                         | 6542868 |        0&lt;br /&gt;
 tablefunc | TYPE     | tablefunc_crosstab_2                                   | 6542871 |        0&lt;br /&gt;
 tablefunc | TYPE     | tablefunc_crosstab_3                                   | 6542874 |        0&lt;br /&gt;
 tablefunc | TYPE     | tablefunc_crosstab_4                                   | 6542877 |        0&lt;br /&gt;
 tablefunc | FUNCTION | crosstab2(text)                                        | 6542878 |        0&lt;br /&gt;
 tablefunc | FUNCTION | crosstab3(text)                                        | 6542879 |        0&lt;br /&gt;
 tablefunc | FUNCTION | crosstab4(text)                                        | 6542880 |        0&lt;br /&gt;
 tablefunc | FUNCTION | crosstab(text,integer)                                 | 6542881 |        0&lt;br /&gt;
 tablefunc | FUNCTION | crosstab(text,text)                                    | 6542882 |        0&lt;br /&gt;
 tablefunc | FUNCTION | connectby(text,text,text,text,integer,text)            | 6542883 |        0&lt;br /&gt;
 tablefunc | FUNCTION | connectby(text,text,text,text,integer)                 | 6542884 |        0&lt;br /&gt;
 tablefunc | FUNCTION | connectby(text,text,text,text,text,integer,text)       | 6542885 |        0&lt;br /&gt;
 tablefunc | FUNCTION | connectby(text,text,text,text,text,integer)            | 6542886 |        0&lt;br /&gt;
(14 rows)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Show module usage by schema====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ljudmila=#  select * from modules.pg_module_usage;&lt;br /&gt;
 schema_name | module_name | module_order &lt;br /&gt;
-------------+-------------+--------------&lt;br /&gt;
(0 rows)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Grant module usage privilege to user====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ljudmila=# grant usage on schema modules to atom;&lt;br /&gt;
GRANT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Elaboration==&lt;br /&gt;
&lt;br /&gt;
===Use Cases===&lt;br /&gt;
* Installing stuff from ''contrib''&lt;br /&gt;
* Installing stuff from [http://pgfoundry.org/ PgFoundry]&lt;br /&gt;
* Installing user's own stuff&lt;br /&gt;
* Convincing ISPs that modules are cool and can be easily installed and used safely&lt;br /&gt;
&lt;br /&gt;
===Wishes/Requirements===&lt;br /&gt;
&lt;br /&gt;
✓ = done,&lt;br /&gt;
❤ = work in progress&lt;br /&gt;
&lt;br /&gt;
====✓ enable regular users to install modules====&lt;br /&gt;
Done through use of SECURITY DEFINER functions. &lt;br /&gt;
Basically, module import/deport functions run as superuser and can do anything.&lt;br /&gt;
USAGE privilege on module manager schema must be granted to roles to enable them to use modules.&lt;br /&gt;
&lt;br /&gt;
====install modules by name (and optionally version)====&lt;br /&gt;
====❤ command line interface, in spirit of apt-get or CPAN====&lt;br /&gt;
====✓ transactional installation (module either gets installed ok or not at all)====&lt;br /&gt;
====✓ you should be able to tell what is installed====&lt;br /&gt;
====✓ should manage current contrib stuff too====&lt;br /&gt;
====support multiple versions of databases and extensions====&lt;br /&gt;
====create and drop (and alter) extensions in user-specified databases/schemas====&lt;br /&gt;
====auto-get and compile and install extensions from sources from internet====&lt;br /&gt;
====module sources: contrib, pgfoundry, user====&lt;br /&gt;
====dependencies management (install dependencies as well)====&lt;br /&gt;
====uninstall should use dependancies, not hand-written SQL scripts====&lt;br /&gt;
====support for/integration with pg_dump/pg_restore; should dump import() statements insted of objects====&lt;br /&gt;
&lt;br /&gt;
==Construction==&lt;br /&gt;
&lt;br /&gt;
===Current status===&lt;br /&gt;
There is a prototype implementation of user level module manager in PL/PgSQL in form of SQL schema.&lt;br /&gt;
The name of the schema defaults to '''modules''', but can be configured at module manager installation time.&lt;br /&gt;
&lt;br /&gt;
There is a prototype implementation of command-line tool in Perl, which help with module creation.&lt;br /&gt;
This is not needed by normal SQL users.&lt;br /&gt;
&lt;br /&gt;
===Concepts===&lt;br /&gt;
A ''module'' is a collection of SQL objects, &lt;br /&gt;
which can be created or dropped at once.&lt;br /&gt;
&lt;br /&gt;
''Module manager'' is a tool, which is specific to PostgreSQL, &lt;br /&gt;
not a specific operating system. It should handle all tasks&lt;br /&gt;
related to module management&lt;br /&gt;
&lt;br /&gt;
There are two aspect to module manager:&lt;br /&gt;
# user level access for normal database users: functions '''import(modulename)''', '''install(modulename)''' and '''uninstall(modulename)'''&lt;br /&gt;
# admin level access for database administrators: functions '''create_module()''', '''drop_module()''' and '''analyze_module()'''&lt;br /&gt;
&lt;br /&gt;
Modules are installed on local system (eg Debian Linux), per&lt;br /&gt;
specific PostgreSQL version.&lt;br /&gt;
&lt;br /&gt;
Modules are installed each in it's own directory, like:&lt;br /&gt;
&lt;br /&gt;
 /usr/share/posteresql/8.3/modules/tablefunc-8.3.0/&lt;br /&gt;
&lt;br /&gt;
path structure:&lt;br /&gt;
&lt;br /&gt;
 $base/postgresql/&amp;lt;i&amp;gt;pg_version&amp;lt;/i&amp;gt;/modules/&amp;lt;i&amp;gt;modulename&amp;lt;/i&amp;gt;-&amp;lt;i&amp;gt;moduleversion&amp;lt;/i&amp;gt;/&lt;br /&gt;
&lt;br /&gt;
where:&lt;br /&gt;
* pg_version - postgresql version number (so multiple installations are supported)&lt;br /&gt;
* modulename - unique module name, (ex. hstore, tablefunc, newsysviews)&lt;br /&gt;
* moduleversion - debian-like version numbers. For contrib, this should probably match PostgreSQL version.&lt;br /&gt;
&lt;br /&gt;
module directory should contain at least:&lt;br /&gt;
* SQL install instructions (file install.sql)&lt;br /&gt;
* SQL uninstall instructions (file uninstall.sql)&lt;br /&gt;
* Module information (file module.xml) - contents of this should be elaborated&lt;br /&gt;
&lt;br /&gt;
This would make it easier for utilities to enumerate installed modules.&lt;br /&gt;
&lt;br /&gt;
Once installed, extensions can be:&lt;br /&gt;
* ''loaded'' (installed in particular database/schema)&lt;br /&gt;
* ''unloaded'' (removed from particular database/schema)&lt;br /&gt;
* ''upgraded'' (to a new version)&lt;br /&gt;
&lt;br /&gt;
Perhaps words CREATE, DROP and ALTER should be used?&lt;br /&gt;
&lt;br /&gt;
===Current ''contrib'' problems===&lt;br /&gt;
* everything in one directory; it is clumsy to match install and uninstall files and even see, what is available&lt;br /&gt;
* no module versions specified (or any metadata for that matter)&lt;br /&gt;
* many files explicitly set schema to public:&lt;br /&gt;
** this is the default anyway&lt;br /&gt;
** it requires user to edit SQL file to change this&lt;br /&gt;
** this should be set by module manager, if it is to support module installation in any schema&lt;br /&gt;
&lt;br /&gt;
Recommendations: &lt;br /&gt;
* Move everything from contrib to appropriate dirs/files in modules directory&lt;br /&gt;
* Add missing module.xml files&lt;br /&gt;
* Make symlinks from contrib&lt;br /&gt;
&lt;br /&gt;
===See Also===&lt;br /&gt;
* [[User:Ziga/xpg_package]] - somewhat older document of a similar nature&lt;/div&gt;</summary>
		<author><name>Ziga</name></author>	</entry>

	<entry>
		<id>http://wiki.postgresql.org/wiki/Module_Manager</id>
		<title>Module Manager</title>
		<link rel="alternate" type="text/html" href="http://wiki.postgresql.org/wiki/Module_Manager"/>
				<updated>2008-10-17T14:36:32Z</updated>
		
		<summary type="html">&lt;p&gt;Ziga:&amp;#32;/* Wishes/Requirements */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;There has been some interest PostgreSQL extension/package/module manager.&lt;br /&gt;
&lt;br /&gt;
We would like some software to make it easier for users and developers to install and manage&lt;br /&gt;
various add-on features available for PostgreSQL.&lt;br /&gt;
&lt;br /&gt;
Currently the process of installing add-ons is rather manual and cumbersome. &lt;br /&gt;
It usually requires command-line interface and/or superuser access.&lt;br /&gt;
It would be great, if modules could be used through SQL alone.&lt;br /&gt;
&lt;br /&gt;
Recently, this topic has reappeared on pgsql-hackers mailing list:&lt;br /&gt;
* [http://archives.postgresql.org/pgsql-hackers/2008-04/msg00132.php 2008-04 pgsql-hackers thread]&lt;br /&gt;
* [http://archives.postgresql.org/pgsql-hackers/2007-10/msg01281.php 2007-10 pgsql-hackers thread]&lt;br /&gt;
* [http://archives.postgresql.org/pgsql-patches/2006-05/msg00327.php 2006-05 pgsql-hackers thread]&lt;br /&gt;
* [http://archives.postgresql.org/message-id/ca33c0a30804061349s41b4d8fcsa9c579454b27ecd2@mail.gmail.com Database owner installable modules patch by Tom Dunstan]&lt;br /&gt;
* [http://archives.postgresql.org/pgsql-hackers/2008-07/msg01098.php PostgreSQL extensions packaging proposal by Dimitri Fontaine]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Perhaps a difference among terms ''extension'', ''package'' and ''module'' should be clarified?&lt;br /&gt;
Here the term ''module'' is used, due to popular demand.&lt;br /&gt;
&lt;br /&gt;
==Synopsis==&lt;br /&gt;
&lt;br /&gt;
===As a database user===&lt;br /&gt;
&lt;br /&gt;
====Using modules====&lt;br /&gt;
Simply import desired module with '''modules.import()''' function.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ljudmila=&amp;gt; select modules.import('hstore');&lt;br /&gt;
... stuff ...&lt;br /&gt;
    import     &lt;br /&gt;
---------------&lt;br /&gt;
 IMPORT DEFINE hstore&lt;br /&gt;
(1 row)&lt;br /&gt;
&lt;br /&gt;
ljudmila=&amp;gt; select 'a=&amp;gt;3'::hstore;&lt;br /&gt;
  hstore  &lt;br /&gt;
----------&lt;br /&gt;
 &amp;quot;a&amp;quot;=&amp;gt;&amp;quot;3&amp;quot;&lt;br /&gt;
(1 row)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If module is already imported, IMPORT is returned instead of IMPORT DEFINE.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===As a database administrator===&lt;br /&gt;
&lt;br /&gt;
====Install the module manager and contrib modules====&lt;br /&gt;
&lt;br /&gt;
By default, this goes into schema '''modules'''.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
postgres@mama:$ pg_module all &amp;gt;pg_module.sql&lt;br /&gt;
postgres@mama:$ psql&lt;br /&gt;
ljudmila=# \i pg_module.sql&lt;br /&gt;
BEGIN&lt;br /&gt;
... stuff ...&lt;br /&gt;
COMMIT&lt;br /&gt;
ljudmila=# set search_path=modules; \d+&lt;br /&gt;
SET&lt;br /&gt;
                                      List of relations&lt;br /&gt;
 Schema  |        Name        | Type  |   Owner    |               Description               &lt;br /&gt;
---------+--------------------+-------+------------+-----------------------------------------&lt;br /&gt;
 modules | pg_module          | table | pg_modules | modules, which can imported or deported&lt;br /&gt;
 modules | pg_module_contents | table | pg_modules | module contents&lt;br /&gt;
 modules | pg_module_usage    | view  | pg_modules | modules imported into schemas&lt;br /&gt;
(3 rows)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====List available modules====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ljudmila=# select * from modules.pg_module;&lt;br /&gt;
       modname       |               modimport               |            moddeport            &lt;br /&gt;
---------------------+---------------------------------------+---------------------------------&lt;br /&gt;
 pg_buffercache      | module_pg_buffercache_import()        | module_pg_buffercache_deport()&lt;br /&gt;
 pgrowlocks          | module_pgrowlocks_import()            | module_pgrowlocks_deport()&lt;br /&gt;
 tsearch2            | module_tsearch2_import()              | module_tsearch2_deport()&lt;br /&gt;
 moddatetime         | module_moddatetime_import()           | &lt;br /&gt;
 pgcrypto            | module_pgcrypto_import()              | module_pgcrypto_deport()&lt;br /&gt;
 lo                  | module_lo_import()                    | module_lo_deport()&lt;br /&gt;
 seg                 | module_seg_import()                   | module_seg_deport()&lt;br /&gt;
 pgxml               | module_pgxml_import()                 | module_pgxml_deport()&lt;br /&gt;
 test_parser         | module_test_parser_import()           | module_test_parser_deport()&lt;br /&gt;
 tablefunc           | module_tablefunc_import()             | module_tablefunc_deport()&lt;br /&gt;
 cube                | module_cube_import()                  | module_cube_deport()&lt;br /&gt;
 timetravel          | module_timetravel_import()            | &lt;br /&gt;
 chkpass             | module_chkpass_import()               | module_chkpass_deport()&lt;br /&gt;
 _int                | module__int_import()                  | module__int_deport()&lt;br /&gt;
 refint              | module_refint_import()                | &lt;br /&gt;
 int_aggregate       | module_int_aggregate_import()         | module_int_aggregate_deport()&lt;br /&gt;
 pgstattuple         | module_pgstattuple_import()           | module_pgstattuple_deport()&lt;br /&gt;
 fuzzystrmatch       | module_fuzzystrmatch_import()         | module_fuzzystrmatch_deport()&lt;br /&gt;
 pg_freespacemap     | module_pg_freespacemap_import()       | module_pg_freespacemap_deport()&lt;br /&gt;
 dblink              | module_dblink_import()                | module_dblink_deport()&lt;br /&gt;
 isn                 | module_isn_import()                   | module_isn_deport()&lt;br /&gt;
 pageinspect         | module_pageinspect_import()           | module_pageinspect_deport()&lt;br /&gt;
 insert_username     | module_insert_username_import()       | &lt;br /&gt;
 adminpack           | module_adminpack_import()             | module_adminpack_deport()&lt;br /&gt;
 ltree               | module_ltree_import()                 | module_ltree_deport()&lt;br /&gt;
 dict_int            | module_dict_int_import()              | module_dict_int_deport()&lt;br /&gt;
 autoinc             | module_autoinc_import()               | &lt;br /&gt;
 btree_gist          | module_btree_gist_import()            | module_btree_gist_deport()&lt;br /&gt;
 dict_xsyn           | module_dict_xsyn_import()             | module_dict_xsyn_deport()&lt;br /&gt;
 pg_trgm             | module_pg_trgm_import()               | module_pg_trgm_deport()&lt;br /&gt;
 hstore              | module_hstore_import()                | module_hstore_deport()&lt;br /&gt;
 earthdistance       | module_earthdistance_import()         | module_earthdistance_deport()&lt;br /&gt;
 sslinfo             | module_sslinfo_import()               | module_sslinfo_deport()&lt;br /&gt;
(35 rows)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====List module contents====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ljudmila=# select * from modules.pg_module_contents where modname='tablefunc';&lt;br /&gt;
  modname  | sql_type |                     sql_identifier                     |  objid  | objsubid &lt;br /&gt;
-----------+----------+--------------------------------------------------------+---------+----------&lt;br /&gt;
 tablefunc | FUNCTION | normal_rand(integer,double precision,double precision) | 6542867 |        0&lt;br /&gt;
 tablefunc | FUNCTION | crosstab(text)                                         | 6542868 |        0&lt;br /&gt;
 tablefunc | TYPE     | tablefunc_crosstab_2                                   | 6542871 |        0&lt;br /&gt;
 tablefunc | TYPE     | tablefunc_crosstab_3                                   | 6542874 |        0&lt;br /&gt;
 tablefunc | TYPE     | tablefunc_crosstab_4                                   | 6542877 |        0&lt;br /&gt;
 tablefunc | FUNCTION | crosstab2(text)                                        | 6542878 |        0&lt;br /&gt;
 tablefunc | FUNCTION | crosstab3(text)                                        | 6542879 |        0&lt;br /&gt;
 tablefunc | FUNCTION | crosstab4(text)                                        | 6542880 |        0&lt;br /&gt;
 tablefunc | FUNCTION | crosstab(text,integer)                                 | 6542881 |        0&lt;br /&gt;
 tablefunc | FUNCTION | crosstab(text,text)                                    | 6542882 |        0&lt;br /&gt;
 tablefunc | FUNCTION | connectby(text,text,text,text,integer,text)            | 6542883 |        0&lt;br /&gt;
 tablefunc | FUNCTION | connectby(text,text,text,text,integer)                 | 6542884 |        0&lt;br /&gt;
 tablefunc | FUNCTION | connectby(text,text,text,text,text,integer,text)       | 6542885 |        0&lt;br /&gt;
 tablefunc | FUNCTION | connectby(text,text,text,text,text,integer)            | 6542886 |        0&lt;br /&gt;
(14 rows)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Show module usage by schema====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ljudmila=#  select * from modules.pg_module_usage;&lt;br /&gt;
 schema_name | module_name | module_order &lt;br /&gt;
-------------+-------------+--------------&lt;br /&gt;
(0 rows)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Grant module usage privilege to user====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ljudmila=# grant usage on schema modules to atom;&lt;br /&gt;
GRANT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Elaboration==&lt;br /&gt;
&lt;br /&gt;
===Use Cases===&lt;br /&gt;
* Installing stuff from ''contrib''&lt;br /&gt;
* Installing stuff from [http://pgfoundry.org/ PgFoundry]&lt;br /&gt;
* Installing user's own stuff&lt;br /&gt;
* Convincing ISPs that modules are cool and can be easily installed and used safely&lt;br /&gt;
&lt;br /&gt;
===Wishes/Requirements===&lt;br /&gt;
&lt;br /&gt;
✓ = done,&lt;br /&gt;
❤ = work in progress&lt;br /&gt;
&lt;br /&gt;
====✓ enable regular users to install modules====&lt;br /&gt;
Done through use of SECURITY DEFINER functions. &lt;br /&gt;
Basically, module import/deport functions run as superuser and can do anything.&lt;br /&gt;
USAGE privilege on module manager schema must be granted to roles to enable them to use modules.&lt;br /&gt;
&lt;br /&gt;
====install modules by name (and optionally version)====&lt;br /&gt;
====❤ command line interface, in spirit of apt-get or CPAN====&lt;br /&gt;
====✓ transactional installation (module either gets installed ok or not at all)====&lt;br /&gt;
====✓ you should be able to tell what is installed====&lt;br /&gt;
====✓ should manage current contrib stuff too====&lt;br /&gt;
====support multiple versions of databases and extensions====&lt;br /&gt;
====create and drop (and alter) extensions in user-specified databases/schemas====&lt;br /&gt;
====auto-get and compile and install extensions from sources from internet====&lt;br /&gt;
====module sources: contrib, pgfoundry, user====&lt;br /&gt;
====dependencies management (install dependencies as well)====&lt;br /&gt;
====uninstall should use dependancies, not hand-written SQL scripts====&lt;br /&gt;
====support for/integration with pg_dump/pg_restore; should dump import() statements insted of objects====&lt;br /&gt;
&lt;br /&gt;
==Construction==&lt;br /&gt;
&lt;br /&gt;
===Current status===&lt;br /&gt;
There is a prototype implementation of user level module manager in PL/PgSQL in form of SQL schema.&lt;br /&gt;
The name of the schema defaults to '''modules''', but can be configured at module manager installation time.&lt;br /&gt;
&lt;br /&gt;
There is a prototype implementation of command-line tool in Perl, which help with module creation.&lt;br /&gt;
This is not needed by normal SQL users.&lt;br /&gt;
&lt;br /&gt;
===Concepts===&lt;br /&gt;
A ''module'' is a collection of SQL objects, &lt;br /&gt;
which can be created or droped at once.&lt;br /&gt;
&lt;br /&gt;
''Module manager'' is a tool, which is specific to PostgreSQL, &lt;br /&gt;
not a specific operating system. It should handle all tasks&lt;br /&gt;
related to module management.&lt;br /&gt;
&lt;br /&gt;
There are two aspect to module manager:&lt;br /&gt;
# user level access for normal database users: functions '''import(modulename)''' and '''deport(modulename)'''&lt;br /&gt;
# admin level access for database administrators: functions '''create_module()''', '''drop_module()''' and '''analyze_module()'''&lt;br /&gt;
&lt;br /&gt;
Mo&lt;br /&gt;
&lt;br /&gt;
Modules are installed on local system (eg Debian Linux), per&lt;br /&gt;
specific PostgreSQL version.&lt;br /&gt;
&lt;br /&gt;
Modules are installed each in it's own directory, like:&lt;br /&gt;
&lt;br /&gt;
 /usr/share/posteresql/8.3/modules/tablefunc-8.3.0/&lt;br /&gt;
&lt;br /&gt;
path structure:&lt;br /&gt;
&lt;br /&gt;
 $base/postgresql/&amp;lt;i&amp;gt;pg_version&amp;lt;/i&amp;gt;/modules/&amp;lt;i&amp;gt;modulename&amp;lt;/i&amp;gt;-&amp;lt;i&amp;gt;moduleversion&amp;lt;/i&amp;gt;/&lt;br /&gt;
&lt;br /&gt;
where:&lt;br /&gt;
* pg_version - postgresql version number (so multiple installations are supported)&lt;br /&gt;
* modulename - unique module name, (ex. hstore, tablefunc, newsysviews)&lt;br /&gt;
* moduleversion - debian-like version numbers. For contrib, this should probably match PostgreSQL version.&lt;br /&gt;
&lt;br /&gt;
module directory should contain at least:&lt;br /&gt;
* SQL install instructions (file install.sql)&lt;br /&gt;
* SQL uninstall instructions (file uninstall.sql)&lt;br /&gt;
* Module information (file module.xml) - contents of this should be elaborated&lt;br /&gt;
&lt;br /&gt;
This would make it easier for utilities to enumerate installed modules.&lt;br /&gt;
&lt;br /&gt;
Once installed, extensions can be:&lt;br /&gt;
* ''loaded'' (installed in particular database/schema)&lt;br /&gt;
* ''unloaded'' (removed from particular database/schema)&lt;br /&gt;
* ''upgraded'' (to a new version)&lt;br /&gt;
&lt;br /&gt;
Perhaps words CREATE, DROP and ALTER should be used?&lt;br /&gt;
&lt;br /&gt;
===Current ''contrib'' problems===&lt;br /&gt;
* everything in one directory; it is clumsy to match install and uninstall files and even see, what is available&lt;br /&gt;
* no module versions specified (or any metadata for that matter)&lt;br /&gt;
* many files explicitly set schema to public:&lt;br /&gt;
** this is the default anyway&lt;br /&gt;
** it requires user to edit SQL file to change this&lt;br /&gt;
** this should be set by module manager, if it is to support module installation in any schema&lt;br /&gt;
&lt;br /&gt;
Recommendations: &lt;br /&gt;
* Move everything from contrib to appropriate dirs/files in modules directory&lt;br /&gt;
* Add missing module.xml files&lt;br /&gt;
* Make symlinks from contrib&lt;br /&gt;
&lt;br /&gt;
===See Also===&lt;br /&gt;
* [[User:Ziga/xpg_package]] - somewhat older document of a similar nature&lt;/div&gt;</summary>
		<author><name>Ziga</name></author>	</entry>

	<entry>
		<id>http://wiki.postgresql.org/wiki/Module_Manager</id>
		<title>Module Manager</title>
		<link rel="alternate" type="text/html" href="http://wiki.postgresql.org/wiki/Module_Manager"/>
				<updated>2008-10-17T14:31:28Z</updated>
		
		<summary type="html">&lt;p&gt;Ziga:&amp;#32;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;There has been some interest PostgreSQL extension/package/module manager.&lt;br /&gt;
&lt;br /&gt;
We would like some software to make it easier for users and developers to install and manage&lt;br /&gt;
various add-on features available for PostgreSQL.&lt;br /&gt;
&lt;br /&gt;
Currently the process of installing add-ons is rather manual and cumbersome. &lt;br /&gt;
It usually requires command-line interface and/or superuser access.&lt;br /&gt;
It would be great, if modules could be used through SQL alone.&lt;br /&gt;
&lt;br /&gt;
Recently, this topic has reappeared on pgsql-hackers mailing list:&lt;br /&gt;
* [http://archives.postgresql.org/pgsql-hackers/2008-04/msg00132.php 2008-04 pgsql-hackers thread]&lt;br /&gt;
* [http://archives.postgresql.org/pgsql-hackers/2007-10/msg01281.php 2007-10 pgsql-hackers thread]&lt;br /&gt;
* [http://archives.postgresql.org/pgsql-patches/2006-05/msg00327.php 2006-05 pgsql-hackers thread]&lt;br /&gt;
* [http://archives.postgresql.org/message-id/ca33c0a30804061349s41b4d8fcsa9c579454b27ecd2@mail.gmail.com Database owner installable modules patch by Tom Dunstan]&lt;br /&gt;
* [http://archives.postgresql.org/pgsql-hackers/2008-07/msg01098.php PostgreSQL extensions packaging proposal by Dimitri Fontaine]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Perhaps a difference among terms ''extension'', ''package'' and ''module'' should be clarified?&lt;br /&gt;
Here the term ''module'' is used, due to popular demand.&lt;br /&gt;
&lt;br /&gt;
==Synopsis==&lt;br /&gt;
&lt;br /&gt;
===As a database user===&lt;br /&gt;
&lt;br /&gt;
====Using modules====&lt;br /&gt;
Simply import desired module with '''modules.import()''' function.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ljudmila=&amp;gt; select modules.import('hstore');&lt;br /&gt;
... stuff ...&lt;br /&gt;
    import     &lt;br /&gt;
---------------&lt;br /&gt;
 IMPORT DEFINE hstore&lt;br /&gt;
(1 row)&lt;br /&gt;
&lt;br /&gt;
ljudmila=&amp;gt; select 'a=&amp;gt;3'::hstore;&lt;br /&gt;
  hstore  &lt;br /&gt;
----------&lt;br /&gt;
 &amp;quot;a&amp;quot;=&amp;gt;&amp;quot;3&amp;quot;&lt;br /&gt;
(1 row)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If module is already imported, IMPORT is returned instead of IMPORT DEFINE.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===As a database administrator===&lt;br /&gt;
&lt;br /&gt;
====Install the module manager and contrib modules====&lt;br /&gt;
&lt;br /&gt;
By default, this goes into schema '''modules'''.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
postgres@mama:$ pg_module all &amp;gt;pg_module.sql&lt;br /&gt;
postgres@mama:$ psql&lt;br /&gt;
ljudmila=# \i pg_module.sql&lt;br /&gt;
BEGIN&lt;br /&gt;
... stuff ...&lt;br /&gt;
COMMIT&lt;br /&gt;
ljudmila=# set search_path=modules; \d+&lt;br /&gt;
SET&lt;br /&gt;
                                      List of relations&lt;br /&gt;
 Schema  |        Name        | Type  |   Owner    |               Description               &lt;br /&gt;
---------+--------------------+-------+------------+-----------------------------------------&lt;br /&gt;
 modules | pg_module          | table | pg_modules | modules, which can imported or deported&lt;br /&gt;
 modules | pg_module_contents | table | pg_modules | module contents&lt;br /&gt;
 modules | pg_module_usage    | view  | pg_modules | modules imported into schemas&lt;br /&gt;
(3 rows)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====List available modules====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ljudmila=# select * from modules.pg_module;&lt;br /&gt;
       modname       |               modimport               |            moddeport            &lt;br /&gt;
---------------------+---------------------------------------+---------------------------------&lt;br /&gt;
 pg_buffercache      | module_pg_buffercache_import()        | module_pg_buffercache_deport()&lt;br /&gt;
 pgrowlocks          | module_pgrowlocks_import()            | module_pgrowlocks_deport()&lt;br /&gt;
 tsearch2            | module_tsearch2_import()              | module_tsearch2_deport()&lt;br /&gt;
 moddatetime         | module_moddatetime_import()           | &lt;br /&gt;
 pgcrypto            | module_pgcrypto_import()              | module_pgcrypto_deport()&lt;br /&gt;
 lo                  | module_lo_import()                    | module_lo_deport()&lt;br /&gt;
 seg                 | module_seg_import()                   | module_seg_deport()&lt;br /&gt;
 pgxml               | module_pgxml_import()                 | module_pgxml_deport()&lt;br /&gt;
 test_parser         | module_test_parser_import()           | module_test_parser_deport()&lt;br /&gt;
 tablefunc           | module_tablefunc_import()             | module_tablefunc_deport()&lt;br /&gt;
 cube                | module_cube_import()                  | module_cube_deport()&lt;br /&gt;
 timetravel          | module_timetravel_import()            | &lt;br /&gt;
 chkpass             | module_chkpass_import()               | module_chkpass_deport()&lt;br /&gt;
 _int                | module__int_import()                  | module__int_deport()&lt;br /&gt;
 refint              | module_refint_import()                | &lt;br /&gt;
 int_aggregate       | module_int_aggregate_import()         | module_int_aggregate_deport()&lt;br /&gt;
 pgstattuple         | module_pgstattuple_import()           | module_pgstattuple_deport()&lt;br /&gt;
 fuzzystrmatch       | module_fuzzystrmatch_import()         | module_fuzzystrmatch_deport()&lt;br /&gt;
 pg_freespacemap     | module_pg_freespacemap_import()       | module_pg_freespacemap_deport()&lt;br /&gt;
 dblink              | module_dblink_import()                | module_dblink_deport()&lt;br /&gt;
 isn                 | module_isn_import()                   | module_isn_deport()&lt;br /&gt;
 pageinspect         | module_pageinspect_import()           | module_pageinspect_deport()&lt;br /&gt;
 insert_username     | module_insert_username_import()       | &lt;br /&gt;
 adminpack           | module_adminpack_import()             | module_adminpack_deport()&lt;br /&gt;
 ltree               | module_ltree_import()                 | module_ltree_deport()&lt;br /&gt;
 dict_int            | module_dict_int_import()              | module_dict_int_deport()&lt;br /&gt;
 autoinc             | module_autoinc_import()               | &lt;br /&gt;
 btree_gist          | module_btree_gist_import()            | module_btree_gist_deport()&lt;br /&gt;
 dict_xsyn           | module_dict_xsyn_import()             | module_dict_xsyn_deport()&lt;br /&gt;
 pg_trgm             | module_pg_trgm_import()               | module_pg_trgm_deport()&lt;br /&gt;
 hstore              | module_hstore_import()                | module_hstore_deport()&lt;br /&gt;
 earthdistance       | module_earthdistance_import()         | module_earthdistance_deport()&lt;br /&gt;
 sslinfo             | module_sslinfo_import()               | module_sslinfo_deport()&lt;br /&gt;
(35 rows)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====List module contents====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ljudmila=# select * from modules.pg_module_contents where modname='tablefunc';&lt;br /&gt;
  modname  | sql_type |                     sql_identifier                     |  objid  | objsubid &lt;br /&gt;
-----------+----------+--------------------------------------------------------+---------+----------&lt;br /&gt;
 tablefunc | FUNCTION | normal_rand(integer,double precision,double precision) | 6542867 |        0&lt;br /&gt;
 tablefunc | FUNCTION | crosstab(text)                                         | 6542868 |        0&lt;br /&gt;
 tablefunc | TYPE     | tablefunc_crosstab_2                                   | 6542871 |        0&lt;br /&gt;
 tablefunc | TYPE     | tablefunc_crosstab_3                                   | 6542874 |        0&lt;br /&gt;
 tablefunc | TYPE     | tablefunc_crosstab_4                                   | 6542877 |        0&lt;br /&gt;
 tablefunc | FUNCTION | crosstab2(text)                                        | 6542878 |        0&lt;br /&gt;
 tablefunc | FUNCTION | crosstab3(text)                                        | 6542879 |        0&lt;br /&gt;
 tablefunc | FUNCTION | crosstab4(text)                                        | 6542880 |        0&lt;br /&gt;
 tablefunc | FUNCTION | crosstab(text,integer)                                 | 6542881 |        0&lt;br /&gt;
 tablefunc | FUNCTION | crosstab(text,text)                                    | 6542882 |        0&lt;br /&gt;
 tablefunc | FUNCTION | connectby(text,text,text,text,integer,text)            | 6542883 |        0&lt;br /&gt;
 tablefunc | FUNCTION | connectby(text,text,text,text,integer)                 | 6542884 |        0&lt;br /&gt;
 tablefunc | FUNCTION | connectby(text,text,text,text,text,integer,text)       | 6542885 |        0&lt;br /&gt;
 tablefunc | FUNCTION | connectby(text,text,text,text,text,integer)            | 6542886 |        0&lt;br /&gt;
(14 rows)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Show module usage by schema====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ljudmila=#  select * from modules.pg_module_usage;&lt;br /&gt;
 schema_name | module_name | module_order &lt;br /&gt;
-------------+-------------+--------------&lt;br /&gt;
(0 rows)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Grant module usage privilege to user====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ljudmila=# grant usage on schema modules to atom;&lt;br /&gt;
GRANT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Elaboration==&lt;br /&gt;
&lt;br /&gt;
===Use Cases===&lt;br /&gt;
* Installing stuff from ''contrib''&lt;br /&gt;
* Installing stuff from [http://pgfoundry.org/ PgFoundry]&lt;br /&gt;
* Installing user's own stuff&lt;br /&gt;
* Convincing ISPs that modules are cool and can be easily installed and used safely&lt;br /&gt;
&lt;br /&gt;
===Wishes/Requirements===&lt;br /&gt;
* ✓ enable regular users to install modules&lt;br /&gt;
* install modules by name (and optionally version)&lt;br /&gt;
* ❤ command line interface, in spirit of apt-get or CPAN&lt;br /&gt;
* ✓ transactional installation (module either gets installed ok or not at all)&lt;br /&gt;
* ✓ you should be able to tell what is installed&lt;br /&gt;
* ✓ should manage current contrib stuff too &lt;br /&gt;
* support multiple versions of databases and extensions&lt;br /&gt;
* create and drop (and alter) extensions in user-specified databases/schemas&lt;br /&gt;
* auto-get and compile and install extensions from sources from internet&lt;br /&gt;
* module sources: contrib, pgfoundry, user&lt;br /&gt;
* dependencies management (install dependencies as well)&lt;br /&gt;
* uninstall should use dependancies, not hand-written SQL scripts&lt;br /&gt;
* support for/integration with pg_dump/pg_restore&lt;br /&gt;
&lt;br /&gt;
✓ = done,&lt;br /&gt;
❤ = work in progress&lt;br /&gt;
&lt;br /&gt;
==Construction==&lt;br /&gt;
&lt;br /&gt;
===Current status===&lt;br /&gt;
There is a prototype implementation of user level module manager in PL/PgSQL in form of SQL schema.&lt;br /&gt;
The name of the schema defaults to '''modules''', but can be configured at module manager installation time.&lt;br /&gt;
&lt;br /&gt;
There is a prototype implementation of command-line tool in Perl, which help with module creation.&lt;br /&gt;
This is not needed by normal SQL users.&lt;br /&gt;
&lt;br /&gt;
===Concepts===&lt;br /&gt;
A ''module'' is a collection of SQL objects, &lt;br /&gt;
which can be created or droped at once.&lt;br /&gt;
&lt;br /&gt;
''Module manager'' is a tool, which is specific to PostgreSQL, &lt;br /&gt;
not a specific operating system. It should handle all tasks&lt;br /&gt;
related to module management.&lt;br /&gt;
&lt;br /&gt;
There are two aspect to module manager:&lt;br /&gt;
# user level access for normal database users: functions '''import(modulename)''' and '''deport(modulename)'''&lt;br /&gt;
# admin level access for database administrators: functions '''create_module()''', '''drop_module()''' and '''analyze_module()'''&lt;br /&gt;
&lt;br /&gt;
Mo&lt;br /&gt;
&lt;br /&gt;
Modules are installed on local system (eg Debian Linux), per&lt;br /&gt;
specific PostgreSQL version.&lt;br /&gt;
&lt;br /&gt;
Modules are installed each in it's own directory, like:&lt;br /&gt;
&lt;br /&gt;
 /usr/share/posteresql/8.3/modules/tablefunc-8.3.0/&lt;br /&gt;
&lt;br /&gt;
path structure:&lt;br /&gt;
&lt;br /&gt;
 $base/postgresql/&amp;lt;i&amp;gt;pg_version&amp;lt;/i&amp;gt;/modules/&amp;lt;i&amp;gt;modulename&amp;lt;/i&amp;gt;-&amp;lt;i&amp;gt;moduleversion&amp;lt;/i&amp;gt;/&lt;br /&gt;
&lt;br /&gt;
where:&lt;br /&gt;
* pg_version - postgresql version number (so multiple installations are supported)&lt;br /&gt;
* modulename - unique module name, (ex. hstore, tablefunc, newsysviews)&lt;br /&gt;
* moduleversion - debian-like version numbers. For contrib, this should probably match PostgreSQL version.&lt;br /&gt;
&lt;br /&gt;
module directory should contain at least:&lt;br /&gt;
* SQL install instructions (file install.sql)&lt;br /&gt;
* SQL uninstall instructions (file uninstall.sql)&lt;br /&gt;
* Module information (file module.xml) - contents of this should be elaborated&lt;br /&gt;
&lt;br /&gt;
This would make it easier for utilities to enumerate installed modules.&lt;br /&gt;
&lt;br /&gt;
Once installed, extensions can be:&lt;br /&gt;
* ''loaded'' (installed in particular database/schema)&lt;br /&gt;
* ''unloaded'' (removed from particular database/schema)&lt;br /&gt;
* ''upgraded'' (to a new version)&lt;br /&gt;
&lt;br /&gt;
Perhaps words CREATE, DROP and ALTER should be used?&lt;br /&gt;
&lt;br /&gt;
===Current ''contrib'' problems===&lt;br /&gt;
* everything in one directory; it is clumsy to match install and uninstall files and even see, what is available&lt;br /&gt;
* no module versions specified (or any metadata for that matter)&lt;br /&gt;
* many files explicitly set schema to public:&lt;br /&gt;
** this is the default anyway&lt;br /&gt;
** it requires user to edit SQL file to change this&lt;br /&gt;
** this should be set by module manager, if it is to support module installation in any schema&lt;br /&gt;
&lt;br /&gt;
Recommendations: &lt;br /&gt;
* Move everything from contrib to appropriate dirs/files in modules directory&lt;br /&gt;
* Add missing module.xml files&lt;br /&gt;
* Make symlinks from contrib&lt;br /&gt;
&lt;br /&gt;
===See Also===&lt;br /&gt;
* [[User:Ziga/xpg_package]] - somewhat older document of a similar nature&lt;/div&gt;</summary>
		<author><name>Ziga</name></author>	</entry>

	<entry>
		<id>http://wiki.postgresql.org/wiki/Module_Manager</id>
		<title>Module Manager</title>
		<link rel="alternate" type="text/html" href="http://wiki.postgresql.org/wiki/Module_Manager"/>
				<updated>2008-10-17T14:13:01Z</updated>
		
		<summary type="html">&lt;p&gt;Ziga:&amp;#32;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;There has been some interest PostgreSQL extension/package/module manager.&lt;br /&gt;
&lt;br /&gt;
We would like some software to make it easier for users and developers to install and manage&lt;br /&gt;
various add-on features available for PostgreSQL.&lt;br /&gt;
&lt;br /&gt;
Currently the process of installing add-ons is rather manual and cumbersome. &lt;br /&gt;
It usually requires command-line interface and/or superuser access.&lt;br /&gt;
It would be great, if modules could be used through SQL alone.&lt;br /&gt;
&lt;br /&gt;
Recently, this topic has reappeared on pgsql-hackers mailing list:&lt;br /&gt;
* [http://archives.postgresql.org/pgsql-hackers/2008-04/msg00132.php 2008-04 pgsql-hackers thread]&lt;br /&gt;
* [http://archives.postgresql.org/pgsql-hackers/2007-10/msg01281.php 2007-10 pgsql-hackers thread]&lt;br /&gt;
* [http://archives.postgresql.org/pgsql-patches/2006-05/msg00327.php 2006-05 pgsql-hackers thread]&lt;br /&gt;
* [http://archives.postgresql.org/message-id/ca33c0a30804061349s41b4d8fcsa9c579454b27ecd2@mail.gmail.com Database owner installable modules patch by Tom Dunstan]&lt;br /&gt;
* [http://archives.postgresql.org/pgsql-hackers/2008-07/msg01098.php PostgreSQL extensions packaging proposal by Dimitri Fontaine]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Perhaps a difference among terms ''extension'', ''package'' and ''module'' should be clarified?&lt;br /&gt;
Here the term ''module'' is used, due to popular demand.&lt;br /&gt;
&lt;br /&gt;
A ''module'' is a collection of SQL objects.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Synopsis==&lt;br /&gt;
&lt;br /&gt;
===As a database user===&lt;br /&gt;
&lt;br /&gt;
====Using modules====&lt;br /&gt;
Simply import desired module with '''modules.import()''' function.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ljudmila=&amp;gt; select modules.import('hstore');&lt;br /&gt;
... stuff ...&lt;br /&gt;
    import     &lt;br /&gt;
---------------&lt;br /&gt;
 IMPORT DEFINE hstore&lt;br /&gt;
(1 row)&lt;br /&gt;
&lt;br /&gt;
ljudmila=&amp;gt; select 'a=&amp;gt;3'::hstore;&lt;br /&gt;
  hstore  &lt;br /&gt;
----------&lt;br /&gt;
 &amp;quot;a&amp;quot;=&amp;gt;&amp;quot;3&amp;quot;&lt;br /&gt;
(1 row)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If module is already imported, IMPORT is returned instead of IMPORT DEFINE.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===As a database administrator===&lt;br /&gt;
&lt;br /&gt;
====Install the module manager and contrib modules====&lt;br /&gt;
&lt;br /&gt;
By default, this goes into schema '''modules'''.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
postgres@mama:$ pg_module all &amp;gt;pg_module.sql&lt;br /&gt;
postgres@mama:$ psql&lt;br /&gt;
ljudmila=# \i pg_module.sql&lt;br /&gt;
BEGIN&lt;br /&gt;
... stuff ...&lt;br /&gt;
COMMIT&lt;br /&gt;
ljudmila=# set search_path=modules; \d+&lt;br /&gt;
SET&lt;br /&gt;
                                      List of relations&lt;br /&gt;
 Schema  |        Name        | Type  |   Owner    |               Description               &lt;br /&gt;
---------+--------------------+-------+------------+-----------------------------------------&lt;br /&gt;
 modules | pg_module          | table | pg_modules | modules, which can imported or deported&lt;br /&gt;
 modules | pg_module_contents | table | pg_modules | module contents&lt;br /&gt;
 modules | pg_module_usage    | view  | pg_modules | modules imported into schemas&lt;br /&gt;
(3 rows)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====List available modules====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ljudmila=# select * from modules.pg_module;&lt;br /&gt;
       modname       |               modimport               |            moddeport            &lt;br /&gt;
---------------------+---------------------------------------+---------------------------------&lt;br /&gt;
 pg_buffercache      | module_pg_buffercache_import()        | module_pg_buffercache_deport()&lt;br /&gt;
 pgrowlocks          | module_pgrowlocks_import()            | module_pgrowlocks_deport()&lt;br /&gt;
 tsearch2            | module_tsearch2_import()              | module_tsearch2_deport()&lt;br /&gt;
 moddatetime         | module_moddatetime_import()           | &lt;br /&gt;
 pgcrypto            | module_pgcrypto_import()              | module_pgcrypto_deport()&lt;br /&gt;
 lo                  | module_lo_import()                    | module_lo_deport()&lt;br /&gt;
 seg                 | module_seg_import()                   | module_seg_deport()&lt;br /&gt;
 pgxml               | module_pgxml_import()                 | module_pgxml_deport()&lt;br /&gt;
 test_parser         | module_test_parser_import()           | module_test_parser_deport()&lt;br /&gt;
 tablefunc           | module_tablefunc_import()             | module_tablefunc_deport()&lt;br /&gt;
 cube                | module_cube_import()                  | module_cube_deport()&lt;br /&gt;
 timetravel          | module_timetravel_import()            | &lt;br /&gt;
 chkpass             | module_chkpass_import()               | module_chkpass_deport()&lt;br /&gt;
 _int                | module__int_import()                  | module__int_deport()&lt;br /&gt;
 refint              | module_refint_import()                | &lt;br /&gt;
 int_aggregate       | module_int_aggregate_import()         | module_int_aggregate_deport()&lt;br /&gt;
 pgstattuple         | module_pgstattuple_import()           | module_pgstattuple_deport()&lt;br /&gt;
 fuzzystrmatch       | module_fuzzystrmatch_import()         | module_fuzzystrmatch_deport()&lt;br /&gt;
 pg_freespacemap     | module_pg_freespacemap_import()       | module_pg_freespacemap_deport()&lt;br /&gt;
 dblink              | module_dblink_import()                | module_dblink_deport()&lt;br /&gt;
 isn                 | module_isn_import()                   | module_isn_deport()&lt;br /&gt;
 pageinspect         | module_pageinspect_import()           | module_pageinspect_deport()&lt;br /&gt;
 insert_username     | module_insert_username_import()       | &lt;br /&gt;
 adminpack           | module_adminpack_import()             | module_adminpack_deport()&lt;br /&gt;
 ltree               | module_ltree_import()                 | module_ltree_deport()&lt;br /&gt;
 dict_int            | module_dict_int_import()              | module_dict_int_deport()&lt;br /&gt;
 autoinc             | module_autoinc_import()               | &lt;br /&gt;
 btree_gist          | module_btree_gist_import()            | module_btree_gist_deport()&lt;br /&gt;
 dict_xsyn           | module_dict_xsyn_import()             | module_dict_xsyn_deport()&lt;br /&gt;
 pg_trgm             | module_pg_trgm_import()               | module_pg_trgm_deport()&lt;br /&gt;
 hstore              | module_hstore_import()                | module_hstore_deport()&lt;br /&gt;
 earthdistance       | module_earthdistance_import()         | module_earthdistance_deport()&lt;br /&gt;
 sslinfo             | module_sslinfo_import()               | module_sslinfo_deport()&lt;br /&gt;
(35 rows)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====List module contents====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ljudmila=# select * from modules.pg_module_contents where modname='tablefunc';&lt;br /&gt;
  modname  | sql_type |                     sql_identifier                     |  objid  | objsubid &lt;br /&gt;
-----------+----------+--------------------------------------------------------+---------+----------&lt;br /&gt;
 tablefunc | FUNCTION | normal_rand(integer,double precision,double precision) | 6542867 |        0&lt;br /&gt;
 tablefunc | FUNCTION | crosstab(text)                                         | 6542868 |        0&lt;br /&gt;
 tablefunc | TYPE     | tablefunc_crosstab_2                                   | 6542871 |        0&lt;br /&gt;
 tablefunc | TYPE     | tablefunc_crosstab_3                                   | 6542874 |        0&lt;br /&gt;
 tablefunc | TYPE     | tablefunc_crosstab_4                                   | 6542877 |        0&lt;br /&gt;
 tablefunc | FUNCTION | crosstab2(text)                                        | 6542878 |        0&lt;br /&gt;
 tablefunc | FUNCTION | crosstab3(text)                                        | 6542879 |        0&lt;br /&gt;
 tablefunc | FUNCTION | crosstab4(text)                                        | 6542880 |        0&lt;br /&gt;
 tablefunc | FUNCTION | crosstab(text,integer)                                 | 6542881 |        0&lt;br /&gt;
 tablefunc | FUNCTION | crosstab(text,text)                                    | 6542882 |        0&lt;br /&gt;
 tablefunc | FUNCTION | connectby(text,text,text,text,integer,text)            | 6542883 |        0&lt;br /&gt;
 tablefunc | FUNCTION | connectby(text,text,text,text,integer)                 | 6542884 |        0&lt;br /&gt;
 tablefunc | FUNCTION | connectby(text,text,text,text,text,integer,text)       | 6542885 |        0&lt;br /&gt;
 tablefunc | FUNCTION | connectby(text,text,text,text,text,integer)            | 6542886 |        0&lt;br /&gt;
(14 rows)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Show module usage by schema====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ljudmila=#  select * from modules.pg_module_usage;&lt;br /&gt;
 schema_name | module_name | module_order &lt;br /&gt;
-------------+-------------+--------------&lt;br /&gt;
(0 rows)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Grant module usage privilege to user====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ljudmila=# grant usage on schema modules to atom;&lt;br /&gt;
GRANT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Elaboration==&lt;br /&gt;
===Use Cases===&lt;br /&gt;
* Installing stuff from ''contrib''&lt;br /&gt;
* Installing stuff from [http://pgfoundry.org/ PgFoundry]&lt;br /&gt;
* Installing user's own stuff&lt;br /&gt;
* Convincing ISPs that modules are cool and can be easily installed and used safely&lt;br /&gt;
&lt;br /&gt;
===Wishes/Requirements===&lt;br /&gt;
* ✓ enable regular users to install modules&lt;br /&gt;
* install modules by name (and optionally version)&lt;br /&gt;
* ❤ command line interface, in spirit of apt-get or CPAN&lt;br /&gt;
* ✓ transactional installation (module either gets installed ok or not at all)&lt;br /&gt;
* ✓ you should be able to tell what is installed&lt;br /&gt;
* ✓ should manage current contrib stuff too &lt;br /&gt;
* support multiple versions of databases and extensions&lt;br /&gt;
* create and drop (and alter) extensions in user-specified databases/schemas&lt;br /&gt;
* auto-get and compile and install extensions from sources from internet&lt;br /&gt;
* module sources: contrib, pgfoundry, user&lt;br /&gt;
* dependencies management (install dependencies as well)&lt;br /&gt;
* uninstall should use dependancies, not hand-written SQL scripts&lt;br /&gt;
* support for/integration with pg_dump/pg_restore&lt;br /&gt;
&lt;br /&gt;
✓ = done,&lt;br /&gt;
❤ = work in progress&lt;br /&gt;
&lt;br /&gt;
==Construction==&lt;br /&gt;
&lt;br /&gt;
===Concepts===&lt;br /&gt;
''Module manager'' is a tool, which is specific to PostgreSQL, &lt;br /&gt;
not a specific operating system. It should handle all tasks&lt;br /&gt;
related to module management.&lt;br /&gt;
&lt;br /&gt;
Modules are installed on local system (eg Debian Linux), per&lt;br /&gt;
specific PostgreSQL version.&lt;br /&gt;
&lt;br /&gt;
Modules are installed each in it's own directory, like:&lt;br /&gt;
&lt;br /&gt;
 /usr/share/posteresql/8.3/modules/tablefunc-8.3.0/&lt;br /&gt;
&lt;br /&gt;
path structure:&lt;br /&gt;
&lt;br /&gt;
 $base/postgresql/&amp;lt;i&amp;gt;pg_version&amp;lt;/i&amp;gt;/modules/&amp;lt;i&amp;gt;modulename&amp;lt;/i&amp;gt;-&amp;lt;i&amp;gt;moduleversion&amp;lt;/i&amp;gt;/&lt;br /&gt;
&lt;br /&gt;
where:&lt;br /&gt;
* pg_version - postgresql version number (so multiple installations are supported)&lt;br /&gt;
* modulename - unique module name, (ex. hstore, tablefunc, newsysviews)&lt;br /&gt;
* moduleversion - debian-like version numbers. For contrib, this should probably match PostgreSQL version.&lt;br /&gt;
&lt;br /&gt;
module directory should contain at least:&lt;br /&gt;
* SQL install instructions (file install.sql)&lt;br /&gt;
* SQL uninstall instructions (file uninstall.sql)&lt;br /&gt;
* Module information (file module.xml) - contents of this should be elaborated&lt;br /&gt;
&lt;br /&gt;
This would make it easier for utilities to enumerate installed modules.&lt;br /&gt;
&lt;br /&gt;
Once installed, extensions can be:&lt;br /&gt;
* ''loaded'' (installed in particular database/schema)&lt;br /&gt;
* ''unloaded'' (removed from particular database/schema)&lt;br /&gt;
* ''upgraded'' (to a new version)&lt;br /&gt;
&lt;br /&gt;
Perhaps words CREATE, DROP and ALTER should be used?&lt;br /&gt;
&lt;br /&gt;
===Current ''contrib'' problems===&lt;br /&gt;
* everything in one directory; it is clumsy to match install and uninstall files and even see, what is available&lt;br /&gt;
* no module versions specified (or any metadata for that matter)&lt;br /&gt;
* many files explicitly set schema to public:&lt;br /&gt;
** this is the default anyway&lt;br /&gt;
** it requires user to edit SQL file to change this&lt;br /&gt;
** this should be set by module manager, if it is to support module installation in any schema&lt;br /&gt;
&lt;br /&gt;
Recommendations: &lt;br /&gt;
* Move everything from contrib to appropriate dirs/files in modules directory&lt;br /&gt;
* Add missing module.xml files&lt;br /&gt;
* Make symlinks from contrib&lt;br /&gt;
&lt;br /&gt;
===See Also===&lt;br /&gt;
* [[User:Ziga/xpg_package]] - somewhat older document of a similar nature&lt;/div&gt;</summary>
		<author><name>Ziga</name></author>	</entry>

	<entry>
		<id>http://wiki.postgresql.org/wiki/Module_Manager</id>
		<title>Module Manager</title>
		<link rel="alternate" type="text/html" href="http://wiki.postgresql.org/wiki/Module_Manager"/>
				<updated>2008-10-17T14:03:46Z</updated>
		
		<summary type="html">&lt;p&gt;Ziga:&amp;#32;/* Wishes/Requirements */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;There has been some interest PostgreSQL extension/package/module manager.&lt;br /&gt;
&lt;br /&gt;
We would like some software to make it easier for users and developers to install and manage&lt;br /&gt;
various add-on features available for PostgreSQL.&lt;br /&gt;
&lt;br /&gt;
Currently the process of installing add-ons is rather manual and cumbersome.&lt;br /&gt;
&lt;br /&gt;
Recently, this topic has reappeared on pgsql-hackers mailing list:&lt;br /&gt;
* [http://archives.postgresql.org/pgsql-hackers/2008-04/msg00132.php 2008-04 pgsql-hackers thread]&lt;br /&gt;
* [http://archives.postgresql.org/pgsql-hackers/2007-10/msg01281.php 2007-10 pgsql-hackers thread]&lt;br /&gt;
* [http://archives.postgresql.org/pgsql-patches/2006-05/msg00327.php 2006-05 pgsql-hackers thread]&lt;br /&gt;
* [http://archives.postgresql.org/message-id/ca33c0a30804061349s41b4d8fcsa9c579454b27ecd2@mail.gmail.com Database owner installable modules patch by Tom Dunstan]&lt;br /&gt;
* [http://archives.postgresql.org/pgsql-hackers/2008-07/msg01098.php PostgreSQL extensions packaging proposal by Dimitri Fontaine]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Perhaps a difference among terms ''extension'', ''package'' and ''module'' should be clarified?&lt;br /&gt;
Here the term ''module'' is used, due to popular demand.&lt;br /&gt;
&lt;br /&gt;
==Synopsis==&lt;br /&gt;
&lt;br /&gt;
===As a database user===&lt;br /&gt;
&lt;br /&gt;
====Using modules====&lt;br /&gt;
Simply import desired module with '''modules.import()''' function.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ljudmila=&amp;gt; select modules.import('hstore');&lt;br /&gt;
... stuff ...&lt;br /&gt;
    import     &lt;br /&gt;
---------------&lt;br /&gt;
 IMPORT DEFINE hstore&lt;br /&gt;
(1 row)&lt;br /&gt;
&lt;br /&gt;
ljudmila=&amp;gt; select 'a=&amp;gt;3'::hstore;&lt;br /&gt;
  hstore  &lt;br /&gt;
----------&lt;br /&gt;
 &amp;quot;a&amp;quot;=&amp;gt;&amp;quot;3&amp;quot;&lt;br /&gt;
(1 row)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If module is already imported, IMPORT is returned instead of IMPORT DEFINE.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===As a database administrator===&lt;br /&gt;
&lt;br /&gt;
====Install the module manager and contrib modules====&lt;br /&gt;
&lt;br /&gt;
By default, this goes into schema '''modules'''.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
postgres@mama:$ pg_module all &amp;gt;pg_module.sql&lt;br /&gt;
postgres@mama:$ psql&lt;br /&gt;
ljudmila=# \i pg_module.sql&lt;br /&gt;
BEGIN&lt;br /&gt;
... stuff ...&lt;br /&gt;
COMMIT&lt;br /&gt;
ljudmila=# set search_path=modules; \d+&lt;br /&gt;
SET&lt;br /&gt;
                                      List of relations&lt;br /&gt;
 Schema  |        Name        | Type  |   Owner    |               Description               &lt;br /&gt;
---------+--------------------+-------+------------+-----------------------------------------&lt;br /&gt;
 modules | pg_module          | table | pg_modules | modules, which can imported or deported&lt;br /&gt;
 modules | pg_module_contents | table | pg_modules | module contents&lt;br /&gt;
 modules | pg_module_usage    | view  | pg_modules | modules imported into schemas&lt;br /&gt;
(3 rows)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====List available modules====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ljudmila=# select * from modules.pg_module;&lt;br /&gt;
       modname       |               modimport               |            moddeport            &lt;br /&gt;
---------------------+---------------------------------------+---------------------------------&lt;br /&gt;
 pg_buffercache      | module_pg_buffercache_import()        | module_pg_buffercache_deport()&lt;br /&gt;
 pgrowlocks          | module_pgrowlocks_import()            | module_pgrowlocks_deport()&lt;br /&gt;
 tsearch2            | module_tsearch2_import()              | module_tsearch2_deport()&lt;br /&gt;
 moddatetime         | module_moddatetime_import()           | &lt;br /&gt;
 pgcrypto            | module_pgcrypto_import()              | module_pgcrypto_deport()&lt;br /&gt;
 lo                  | module_lo_import()                    | module_lo_deport()&lt;br /&gt;
 seg                 | module_seg_import()                   | module_seg_deport()&lt;br /&gt;
 pgxml               | module_pgxml_import()                 | module_pgxml_deport()&lt;br /&gt;
 test_parser         | module_test_parser_import()           | module_test_parser_deport()&lt;br /&gt;
 tablefunc           | module_tablefunc_import()             | module_tablefunc_deport()&lt;br /&gt;
 cube                | module_cube_import()                  | module_cube_deport()&lt;br /&gt;
 timetravel          | module_timetravel_import()            | &lt;br /&gt;
 chkpass             | module_chkpass_import()               | module_chkpass_deport()&lt;br /&gt;
 _int                | module__int_import()                  | module__int_deport()&lt;br /&gt;
 refint              | module_refint_import()                | &lt;br /&gt;
 int_aggregate       | module_int_aggregate_import()         | module_int_aggregate_deport()&lt;br /&gt;
 pgstattuple         | module_pgstattuple_import()           | module_pgstattuple_deport()&lt;br /&gt;
 fuzzystrmatch       | module_fuzzystrmatch_import()         | module_fuzzystrmatch_deport()&lt;br /&gt;
 pg_freespacemap     | module_pg_freespacemap_import()       | module_pg_freespacemap_deport()&lt;br /&gt;
 dblink              | module_dblink_import()                | module_dblink_deport()&lt;br /&gt;
 isn                 | module_isn_import()                   | module_isn_deport()&lt;br /&gt;
 pageinspect         | module_pageinspect_import()           | module_pageinspect_deport()&lt;br /&gt;
 insert_username     | module_insert_username_import()       | &lt;br /&gt;
 adminpack           | module_adminpack_import()             | module_adminpack_deport()&lt;br /&gt;
 ltree               | module_ltree_import()                 | module_ltree_deport()&lt;br /&gt;
 dict_int            | module_dict_int_import()              | module_dict_int_deport()&lt;br /&gt;
 autoinc             | module_autoinc_import()               | &lt;br /&gt;
 btree_gist          | module_btree_gist_import()            | module_btree_gist_deport()&lt;br /&gt;
 dict_xsyn           | module_dict_xsyn_import()             | module_dict_xsyn_deport()&lt;br /&gt;
 pg_trgm             | module_pg_trgm_import()               | module_pg_trgm_deport()&lt;br /&gt;
 hstore              | module_hstore_import()                | module_hstore_deport()&lt;br /&gt;
 earthdistance       | module_earthdistance_import()         | module_earthdistance_deport()&lt;br /&gt;
 sslinfo             | module_sslinfo_import()               | module_sslinfo_deport()&lt;br /&gt;
(35 rows)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====List module contents====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ljudmila=# select * from modules.pg_module_contents where modname='tablefunc';&lt;br /&gt;
  modname  | sql_type |                     sql_identifier                     |  objid  | objsubid &lt;br /&gt;
-----------+----------+--------------------------------------------------------+---------+----------&lt;br /&gt;
 tablefunc | FUNCTION | normal_rand(integer,double precision,double precision) | 6542867 |        0&lt;br /&gt;
 tablefunc | FUNCTION | crosstab(text)                                         | 6542868 |        0&lt;br /&gt;
 tablefunc | TYPE     | tablefunc_crosstab_2                                   | 6542871 |        0&lt;br /&gt;
 tablefunc | TYPE     | tablefunc_crosstab_3                                   | 6542874 |        0&lt;br /&gt;
 tablefunc | TYPE     | tablefunc_crosstab_4                                   | 6542877 |        0&lt;br /&gt;
 tablefunc | FUNCTION | crosstab2(text)                                        | 6542878 |        0&lt;br /&gt;
 tablefunc | FUNCTION | crosstab3(text)                                        | 6542879 |        0&lt;br /&gt;
 tablefunc | FUNCTION | crosstab4(text)                                        | 6542880 |        0&lt;br /&gt;
 tablefunc | FUNCTION | crosstab(text,integer)                                 | 6542881 |        0&lt;br /&gt;
 tablefunc | FUNCTION | crosstab(text,text)                                    | 6542882 |        0&lt;br /&gt;
 tablefunc | FUNCTION | connectby(text,text,text,text,integer,text)            | 6542883 |        0&lt;br /&gt;
 tablefunc | FUNCTION | connectby(text,text,text,text,integer)                 | 6542884 |        0&lt;br /&gt;
 tablefunc | FUNCTION | connectby(text,text,text,text,text,integer,text)       | 6542885 |        0&lt;br /&gt;
 tablefunc | FUNCTION | connectby(text,text,text,text,text,integer)            | 6542886 |        0&lt;br /&gt;
(14 rows)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Show module usage by schema====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ljudmila=#  select * from modules.pg_module_usage;&lt;br /&gt;
 schema_name | module_name | module_order &lt;br /&gt;
-------------+-------------+--------------&lt;br /&gt;
(0 rows)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Grant module usage privilege to user====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ljudmila=# grant usage on schema modules to atom;&lt;br /&gt;
GRANT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Elaboration==&lt;br /&gt;
===Use Cases===&lt;br /&gt;
* Installing stuff from ''contrib''&lt;br /&gt;
* Installing stuff from [http://pgfoundry.org/ PgFoundry]&lt;br /&gt;
* Installing user's own stuff&lt;br /&gt;
* Convincing ISPs that modules are cool and can be easily installed and used safely&lt;br /&gt;
&lt;br /&gt;
===Wishes/Requirements===&lt;br /&gt;
* ✓ enable regular users to install modules&lt;br /&gt;
* install modules by name (and optionally version)&lt;br /&gt;
* ❤ command line interface, in spirit of apt-get or CPAN&lt;br /&gt;
* ✓ transactional installation (module either gets installed ok or not at all)&lt;br /&gt;
* ✓ you should be able to tell what is installed&lt;br /&gt;
* ✓ should manage current contrib stuff too &lt;br /&gt;
* support multiple versions of databases and extensions&lt;br /&gt;
* create and drop (and alter) extensions in user-specified databases/schemas&lt;br /&gt;
* auto-get and compile and install extensions from sources from internet&lt;br /&gt;
* module sources: contrib, pgfoundry, user&lt;br /&gt;
* dependencies management (install dependencies as well)&lt;br /&gt;
* uninstall should use dependancies, not hand-written SQL scripts&lt;br /&gt;
* support for/integration with pg_dump/pg_restore&lt;br /&gt;
&lt;br /&gt;
✓ = done,&lt;br /&gt;
❤ = work in progress&lt;br /&gt;
&lt;br /&gt;
==Construction==&lt;br /&gt;
&lt;br /&gt;
===Concepts===&lt;br /&gt;
''Module manager'' is a tool, which is specific to PostgreSQL, &lt;br /&gt;
not a specific operating system. It should handle all tasks&lt;br /&gt;
related to module management.&lt;br /&gt;
&lt;br /&gt;
Modules are installed on local system (eg Debian Linux), per&lt;br /&gt;
specific PostgreSQL version.&lt;br /&gt;
&lt;br /&gt;
Modules are installed each in it's own directory, like:&lt;br /&gt;
&lt;br /&gt;
 /usr/share/posteresql/8.3/modules/tablefunc-8.3.0/&lt;br /&gt;
&lt;br /&gt;
path structure:&lt;br /&gt;
&lt;br /&gt;
 $base/postgresql/&amp;lt;i&amp;gt;pg_version&amp;lt;/i&amp;gt;/modules/&amp;lt;i&amp;gt;modulename&amp;lt;/i&amp;gt;-&amp;lt;i&amp;gt;moduleversion&amp;lt;/i&amp;gt;/&lt;br /&gt;
&lt;br /&gt;
where:&lt;br /&gt;
* pg_version - postgresql version number (so multiple installations are supported)&lt;br /&gt;
* modulename - unique module name, (ex. hstore, tablefunc, newsysviews)&lt;br /&gt;
* moduleversion - debian-like version numbers. For contrib, this should probably match PostgreSQL version.&lt;br /&gt;
&lt;br /&gt;
module directory should contain at least:&lt;br /&gt;
* SQL install instructions (file install.sql)&lt;br /&gt;
* SQL uninstall instructions (file uninstall.sql)&lt;br /&gt;
* Module information (file module.xml) - contents of this should be elaborated&lt;br /&gt;
&lt;br /&gt;
This would make it easier for utilities to enumerate installed modules.&lt;br /&gt;
&lt;br /&gt;
Once installed, extensions can be:&lt;br /&gt;
* ''loaded'' (installed in particular database/schema)&lt;br /&gt;
* ''unloaded'' (removed from particular database/schema)&lt;br /&gt;
* ''upgraded'' (to a new version)&lt;br /&gt;
&lt;br /&gt;
Perhaps words CREATE, DROP and ALTER should be used?&lt;br /&gt;
&lt;br /&gt;
===Current ''contrib'' problems===&lt;br /&gt;
* everything in one directory; it is clumsy to match install and uninstall files and even see, what is available&lt;br /&gt;
* no module versions specified (or any metadata for that matter)&lt;br /&gt;
* many files explicitly set schema to public:&lt;br /&gt;
** this is the default anyway&lt;br /&gt;
** it requires user to edit SQL file to change this&lt;br /&gt;
** this should be set by module manager, if it is to support module installation in any schema&lt;br /&gt;
&lt;br /&gt;
Recommendations: &lt;br /&gt;
* Move everything from contrib to appropriate dirs/files in modules directory&lt;br /&gt;
* Add missing module.xml files&lt;br /&gt;
* Make symlinks from contrib&lt;br /&gt;
&lt;br /&gt;
===See Also===&lt;br /&gt;
* [[User:Ziga/xpg_package]] - somewhat older document of a similar nature&lt;/div&gt;</summary>
		<author><name>Ziga</name></author>	</entry>

	<entry>
		<id>http://wiki.postgresql.org/wiki/Module_Manager</id>
		<title>Module Manager</title>
		<link rel="alternate" type="text/html" href="http://wiki.postgresql.org/wiki/Module_Manager"/>
				<updated>2008-10-17T03:26:39Z</updated>
		
		<summary type="html">&lt;p&gt;Ziga:&amp;#32;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;There has been some interest PostgreSQL extension/package/module manager.&lt;br /&gt;
&lt;br /&gt;
We would like some software to make it easier for users and developers to install and manage&lt;br /&gt;
various add-on features available for PostgreSQL.&lt;br /&gt;
&lt;br /&gt;
Currently the process of installing add-ons is rather manual and cumbersome.&lt;br /&gt;
&lt;br /&gt;
Recently, this topic has reappeared on pgsql-hackers mailing list:&lt;br /&gt;
* [http://archives.postgresql.org/pgsql-hackers/2008-04/msg00132.php 2008-04 pgsql-hackers thread]&lt;br /&gt;
* [http://archives.postgresql.org/pgsql-hackers/2007-10/msg01281.php 2007-10 pgsql-hackers thread]&lt;br /&gt;
* [http://archives.postgresql.org/pgsql-patches/2006-05/msg00327.php 2006-05 pgsql-hackers thread]&lt;br /&gt;
* [http://archives.postgresql.org/message-id/ca33c0a30804061349s41b4d8fcsa9c579454b27ecd2@mail.gmail.com Database owner installable modules patch by Tom Dunstan]&lt;br /&gt;
* [http://archives.postgresql.org/pgsql-hackers/2008-07/msg01098.php PostgreSQL extensions packaging proposal by Dimitri Fontaine]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Perhaps a difference among terms ''extension'', ''package'' and ''module'' should be clarified?&lt;br /&gt;
Here the term ''module'' is used, due to popular demand.&lt;br /&gt;
&lt;br /&gt;
==Synopsis==&lt;br /&gt;
&lt;br /&gt;
===As a database user===&lt;br /&gt;
&lt;br /&gt;
====Using modules====&lt;br /&gt;
Simply import desired module with '''modules.import()''' function.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ljudmila=&amp;gt; select modules.import('hstore');&lt;br /&gt;
... stuff ...&lt;br /&gt;
    import     &lt;br /&gt;
---------------&lt;br /&gt;
 IMPORT DEFINE hstore&lt;br /&gt;
(1 row)&lt;br /&gt;
&lt;br /&gt;
ljudmila=&amp;gt; select 'a=&amp;gt;3'::hstore;&lt;br /&gt;
  hstore  &lt;br /&gt;
----------&lt;br /&gt;
 &amp;quot;a&amp;quot;=&amp;gt;&amp;quot;3&amp;quot;&lt;br /&gt;
(1 row)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If module is already imported, IMPORT is returned instead of IMPORT DEFINE.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===As a database administrator===&lt;br /&gt;
&lt;br /&gt;
====Install the module manager and contrib modules====&lt;br /&gt;
&lt;br /&gt;
By default, this goes into schema '''modules'''.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
postgres@mama:$ pg_module all &amp;gt;pg_module.sql&lt;br /&gt;
postgres@mama:$ psql&lt;br /&gt;
ljudmila=# \i pg_module.sql&lt;br /&gt;
BEGIN&lt;br /&gt;
... stuff ...&lt;br /&gt;
COMMIT&lt;br /&gt;
ljudmila=# set search_path=modules; \d+&lt;br /&gt;
SET&lt;br /&gt;
                                      List of relations&lt;br /&gt;
 Schema  |        Name        | Type  |   Owner    |               Description               &lt;br /&gt;
---------+--------------------+-------+------------+-----------------------------------------&lt;br /&gt;
 modules | pg_module          | table | pg_modules | modules, which can imported or deported&lt;br /&gt;
 modules | pg_module_contents | table | pg_modules | module contents&lt;br /&gt;
 modules | pg_module_usage    | view  | pg_modules | modules imported into schemas&lt;br /&gt;
(3 rows)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====List available modules====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ljudmila=# select * from modules.pg_module;&lt;br /&gt;
       modname       |               modimport               |            moddeport            &lt;br /&gt;
---------------------+---------------------------------------+---------------------------------&lt;br /&gt;
 pg_buffercache      | module_pg_buffercache_import()        | module_pg_buffercache_deport()&lt;br /&gt;
 pgrowlocks          | module_pgrowlocks_import()            | module_pgrowlocks_deport()&lt;br /&gt;
 tsearch2            | module_tsearch2_import()              | module_tsearch2_deport()&lt;br /&gt;
 moddatetime         | module_moddatetime_import()           | &lt;br /&gt;
 pgcrypto            | module_pgcrypto_import()              | module_pgcrypto_deport()&lt;br /&gt;
 lo                  | module_lo_import()                    | module_lo_deport()&lt;br /&gt;
 seg                 | module_seg_import()                   | module_seg_deport()&lt;br /&gt;
 pgxml               | module_pgxml_import()                 | module_pgxml_deport()&lt;br /&gt;
 test_parser         | module_test_parser_import()           | module_test_parser_deport()&lt;br /&gt;
 tablefunc           | module_tablefunc_import()             | module_tablefunc_deport()&lt;br /&gt;
 cube                | module_cube_import()                  | module_cube_deport()&lt;br /&gt;
 timetravel          | module_timetravel_import()            | &lt;br /&gt;
 chkpass             | module_chkpass_import()               | module_chkpass_deport()&lt;br /&gt;
 _int                | module__int_import()                  | module__int_deport()&lt;br /&gt;
 refint              | module_refint_import()                | &lt;br /&gt;
 int_aggregate       | module_int_aggregate_import()         | module_int_aggregate_deport()&lt;br /&gt;
 pgstattuple         | module_pgstattuple_import()           | module_pgstattuple_deport()&lt;br /&gt;
 fuzzystrmatch       | module_fuzzystrmatch_import()         | module_fuzzystrmatch_deport()&lt;br /&gt;
 pg_freespacemap     | module_pg_freespacemap_import()       | module_pg_freespacemap_deport()&lt;br /&gt;
 dblink              | module_dblink_import()                | module_dblink_deport()&lt;br /&gt;
 isn                 | module_isn_import()                   | module_isn_deport()&lt;br /&gt;
 pageinspect         | module_pageinspect_import()           | module_pageinspect_deport()&lt;br /&gt;
 insert_username     | module_insert_username_import()       | &lt;br /&gt;
 adminpack           | module_adminpack_import()             | module_adminpack_deport()&lt;br /&gt;
 ltree               | module_ltree_import()                 | module_ltree_deport()&lt;br /&gt;
 dict_int            | module_dict_int_import()              | module_dict_int_deport()&lt;br /&gt;
 autoinc             | module_autoinc_import()               | &lt;br /&gt;
 btree_gist          | module_btree_gist_import()            | module_btree_gist_deport()&lt;br /&gt;
 dict_xsyn           | module_dict_xsyn_import()             | module_dict_xsyn_deport()&lt;br /&gt;
 pg_trgm             | module_pg_trgm_import()               | module_pg_trgm_deport()&lt;br /&gt;
 hstore              | module_hstore_import()                | module_hstore_deport()&lt;br /&gt;
 earthdistance       | module_earthdistance_import()         | module_earthdistance_deport()&lt;br /&gt;
 sslinfo             | module_sslinfo_import()               | module_sslinfo_deport()&lt;br /&gt;
(35 rows)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====List module contents====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ljudmila=# select * from modules.pg_module_contents where modname='tablefunc';&lt;br /&gt;
  modname  | sql_type |                     sql_identifier                     |  objid  | objsubid &lt;br /&gt;
-----------+----------+--------------------------------------------------------+---------+----------&lt;br /&gt;
 tablefunc | FUNCTION | normal_rand(integer,double precision,double precision) | 6542867 |        0&lt;br /&gt;
 tablefunc | FUNCTION | crosstab(text)                                         | 6542868 |        0&lt;br /&gt;
 tablefunc | TYPE     | tablefunc_crosstab_2                                   | 6542871 |        0&lt;br /&gt;
 tablefunc | TYPE     | tablefunc_crosstab_3                                   | 6542874 |        0&lt;br /&gt;
 tablefunc | TYPE     | tablefunc_crosstab_4                                   | 6542877 |        0&lt;br /&gt;
 tablefunc | FUNCTION | crosstab2(text)                                        | 6542878 |        0&lt;br /&gt;
 tablefunc | FUNCTION | crosstab3(text)                                        | 6542879 |        0&lt;br /&gt;
 tablefunc | FUNCTION | crosstab4(text)                                        | 6542880 |        0&lt;br /&gt;
 tablefunc | FUNCTION | crosstab(text,integer)                                 | 6542881 |        0&lt;br /&gt;
 tablefunc | FUNCTION | crosstab(text,text)                                    | 6542882 |        0&lt;br /&gt;
 tablefunc | FUNCTION | connectby(text,text,text,text,integer,text)            | 6542883 |        0&lt;br /&gt;
 tablefunc | FUNCTION | connectby(text,text,text,text,integer)                 | 6542884 |        0&lt;br /&gt;
 tablefunc | FUNCTION | connectby(text,text,text,text,text,integer,text)       | 6542885 |        0&lt;br /&gt;
 tablefunc | FUNCTION | connectby(text,text,text,text,text,integer)            | 6542886 |        0&lt;br /&gt;
(14 rows)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Show module usage by schema====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ljudmila=#  select * from modules.pg_module_usage;&lt;br /&gt;
 schema_name | module_name | module_order &lt;br /&gt;
-------------+-------------+--------------&lt;br /&gt;
(0 rows)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Grant module usage privilege to user====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ljudmila=# grant usage on schema modules to atom;&lt;br /&gt;
GRANT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Elaboration==&lt;br /&gt;
===Use Cases===&lt;br /&gt;
* Installing stuff from ''contrib''&lt;br /&gt;
* Installing stuff from [http://pgfoundry.org/ PgFoundry]&lt;br /&gt;
* Installing user's own stuff&lt;br /&gt;
* Convincing ISPs that modules are cool and can be easily installed and used safely&lt;br /&gt;
&lt;br /&gt;
===Wishes/Requirements===&lt;br /&gt;
* simple apt-get or CPAN like interface, install by name&lt;br /&gt;
* transactional installation (module either gets installed ok or not at all)&lt;br /&gt;
* you should be able to tell what is installed&lt;br /&gt;
* should manage current contrib stuff too&lt;br /&gt;
* support multiple versions of databases and extensions&lt;br /&gt;
* create and drop (and alter) extensions in user-specified databases/schemas&lt;br /&gt;
* auto-get and compile and install extensions from sources from internet&lt;br /&gt;
* module sources: contrib, pgfoundry, user&lt;br /&gt;
* dependencies management (install dependencies as well)&lt;br /&gt;
* uninstall should use dependancies, not hand-written SQL scripts&lt;br /&gt;
* support for/integration with pg_dump/pg_restore&lt;br /&gt;
&lt;br /&gt;
==Construction==&lt;br /&gt;
&lt;br /&gt;
===Concepts===&lt;br /&gt;
''Module manager'' is a tool, which is specific to PostgreSQL, &lt;br /&gt;
not a specific operating system. It should handle all tasks&lt;br /&gt;
related to module management.&lt;br /&gt;
&lt;br /&gt;
Modules are installed on local system (eg Debian Linux), per&lt;br /&gt;
specific PostgreSQL version.&lt;br /&gt;
&lt;br /&gt;
Modules are installed each in it's own directory, like:&lt;br /&gt;
&lt;br /&gt;
 /usr/share/posteresql/8.3/modules/tablefunc-8.3.0/&lt;br /&gt;
&lt;br /&gt;
path structure:&lt;br /&gt;
&lt;br /&gt;
 $base/postgresql/&amp;lt;i&amp;gt;pg_version&amp;lt;/i&amp;gt;/modules/&amp;lt;i&amp;gt;modulename&amp;lt;/i&amp;gt;-&amp;lt;i&amp;gt;moduleversion&amp;lt;/i&amp;gt;/&lt;br /&gt;
&lt;br /&gt;
where:&lt;br /&gt;
* pg_version - postgresql version number (so multiple installations are supported)&lt;br /&gt;
* modulename - unique module name, (ex. hstore, tablefunc, newsysviews)&lt;br /&gt;
* moduleversion - debian-like version numbers. For contrib, this should probably match PostgreSQL version.&lt;br /&gt;
&lt;br /&gt;
module directory should contain at least:&lt;br /&gt;
* SQL install instructions (file install.sql)&lt;br /&gt;
* SQL uninstall instructions (file uninstall.sql)&lt;br /&gt;
* Module information (file module.xml) - contents of this should be elaborated&lt;br /&gt;
&lt;br /&gt;
This would make it easier for utilities to enumerate installed modules.&lt;br /&gt;
&lt;br /&gt;
Once installed, extensions can be:&lt;br /&gt;
* ''loaded'' (installed in particular database/schema)&lt;br /&gt;
* ''unloaded'' (removed from particular database/schema)&lt;br /&gt;
* ''upgraded'' (to a new version)&lt;br /&gt;
&lt;br /&gt;
Perhaps words CREATE, DROP and ALTER should be used?&lt;br /&gt;
&lt;br /&gt;
===Current ''contrib'' problems===&lt;br /&gt;
* everything in one directory; it is clumsy to match install and uninstall files and even see, what is available&lt;br /&gt;
* no module versions specified (or any metadata for that matter)&lt;br /&gt;
* many files explicitly set schema to public:&lt;br /&gt;
** this is the default anyway&lt;br /&gt;
** it requires user to edit SQL file to change this&lt;br /&gt;
** this should be set by module manager, if it is to support module installation in any schema&lt;br /&gt;
&lt;br /&gt;
Recommendations: &lt;br /&gt;
* Move everything from contrib to appropriate dirs/files in modules directory&lt;br /&gt;
* Add missing module.xml files&lt;br /&gt;
* Make symlinks from contrib&lt;br /&gt;
&lt;br /&gt;
===See Also===&lt;br /&gt;
* [[User:Ziga/xpg_package]] - somewhat older document of a similar nature&lt;/div&gt;</summary>
		<author><name>Ziga</name></author>	</entry>

	<entry>
		<id>http://wiki.postgresql.org/wiki/Module_Manager</id>
		<title>Module Manager</title>
		<link rel="alternate" type="text/html" href="http://wiki.postgresql.org/wiki/Module_Manager"/>
				<updated>2008-10-17T03:08:11Z</updated>
		
		<summary type="html">&lt;p&gt;Ziga:&amp;#32;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;There has been some interest PostgreSQL extension/package/module manager.&lt;br /&gt;
&lt;br /&gt;
We would like some software to make it easier for users and developers to install and manage&lt;br /&gt;
various add-on features available for PostgreSQL.&lt;br /&gt;
&lt;br /&gt;
Currently the process of installing add-ons is rather manual and cumbersome.&lt;br /&gt;
&lt;br /&gt;
Recently, this topic has reappeared on pgsql-hackers mailing list:&lt;br /&gt;
* [http://archives.postgresql.org/pgsql-hackers/2008-04/msg00132.php 2008-04 pgsql-hackers thread]&lt;br /&gt;
* [http://archives.postgresql.org/pgsql-hackers/2007-10/msg01281.php 2007-10 pgsql-hackers thread]&lt;br /&gt;
* [http://archives.postgresql.org/pgsql-patches/2006-05/msg00327.php 2006-05 pgsql-hackers thread]&lt;br /&gt;
* [http://archives.postgresql.org/message-id/ca33c0a30804061349s41b4d8fcsa9c579454b27ecd2@mail.gmail.com Database owner installable modules patch by Tom Dunstan]&lt;br /&gt;
* [http://archives.postgresql.org/pgsql-hackers/2008-07/msg01098.php PostgreSQL extensions packaging proposal by Dimitri Fontaine]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Perhaps a difference among terms ''extension'', ''package'' and ''module'' should be clarified?&lt;br /&gt;
Here the term ''module'' is used, due to popular demand.&lt;br /&gt;
&lt;br /&gt;
==Synopsis==&lt;br /&gt;
&lt;br /&gt;
===As database administrator===&lt;br /&gt;
&lt;br /&gt;
====Install the module manager and contrib modules:====&lt;br /&gt;
&lt;br /&gt;
By default, this goes into schema '''modules'''.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
postgres@mama:$ pg_module all &amp;gt;pg_module.sql&lt;br /&gt;
postgres@mama:$ psql&lt;br /&gt;
ljudmila=# \i pg_module.sql&lt;br /&gt;
BEGIN&lt;br /&gt;
... stuff ...&lt;br /&gt;
COMMIT&lt;br /&gt;
ljudmila=# set search_path=modules; \d+&lt;br /&gt;
SET&lt;br /&gt;
                                      List of relations&lt;br /&gt;
 Schema  |        Name        | Type  |   Owner    |               Description               &lt;br /&gt;
---------+--------------------+-------+------------+-----------------------------------------&lt;br /&gt;
 modules | pg_module          | table | pg_modules | modules, which can imported or deported&lt;br /&gt;
 modules | pg_module_contents | table | pg_modules | module contents&lt;br /&gt;
 modules | pg_module_usage    | view  | pg_modules | modules imported into schemas&lt;br /&gt;
(3 rows)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====List available modules====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ljudmila=# select * from modules.pg_module;&lt;br /&gt;
       modname       |               modimport               |            moddeport            &lt;br /&gt;
---------------------+---------------------------------------+---------------------------------&lt;br /&gt;
 pg_buffercache      | module_pg_buffercache_import()        | module_pg_buffercache_deport()&lt;br /&gt;
 pgrowlocks          | module_pgrowlocks_import()            | module_pgrowlocks_deport()&lt;br /&gt;
 tsearch2            | module_tsearch2_import()              | module_tsearch2_deport()&lt;br /&gt;
 moddatetime         | module_moddatetime_import()           | &lt;br /&gt;
 pgcrypto            | module_pgcrypto_import()              | module_pgcrypto_deport()&lt;br /&gt;
 lo                  | module_lo_import()                    | module_lo_deport()&lt;br /&gt;
 seg                 | module_seg_import()                   | module_seg_deport()&lt;br /&gt;
 pgxml               | module_pgxml_import()                 | module_pgxml_deport()&lt;br /&gt;
 test_parser         | module_test_parser_import()           | module_test_parser_deport()&lt;br /&gt;
 tablefunc           | module_tablefunc_import()             | module_tablefunc_deport()&lt;br /&gt;
 cube                | module_cube_import()                  | module_cube_deport()&lt;br /&gt;
 timetravel          | module_timetravel_import()            | &lt;br /&gt;
 chkpass             | module_chkpass_import()               | module_chkpass_deport()&lt;br /&gt;
 _int                | module__int_import()                  | module__int_deport()&lt;br /&gt;
 refint              | module_refint_import()                | &lt;br /&gt;
 int_aggregate       | module_int_aggregate_import()         | module_int_aggregate_deport()&lt;br /&gt;
 pgstattuple         | module_pgstattuple_import()           | module_pgstattuple_deport()&lt;br /&gt;
 fuzzystrmatch       | module_fuzzystrmatch_import()         | module_fuzzystrmatch_deport()&lt;br /&gt;
 pg_freespacemap     | module_pg_freespacemap_import()       | module_pg_freespacemap_deport()&lt;br /&gt;
 dblink              | module_dblink_import()                | module_dblink_deport()&lt;br /&gt;
 isn                 | module_isn_import()                   | module_isn_deport()&lt;br /&gt;
 pageinspect         | module_pageinspect_import()           | module_pageinspect_deport()&lt;br /&gt;
 insert_username     | module_insert_username_import()       | &lt;br /&gt;
 adminpack           | module_adminpack_import()             | module_adminpack_deport()&lt;br /&gt;
 ltree               | module_ltree_import()                 | module_ltree_deport()&lt;br /&gt;
 dict_int            | module_dict_int_import()              | module_dict_int_deport()&lt;br /&gt;
 autoinc             | module_autoinc_import()               | &lt;br /&gt;
 btree_gist          | module_btree_gist_import()            | module_btree_gist_deport()&lt;br /&gt;
 dict_xsyn           | module_dict_xsyn_import()             | module_dict_xsyn_deport()&lt;br /&gt;
 pg_trgm             | module_pg_trgm_import()               | module_pg_trgm_deport()&lt;br /&gt;
 hstore              | module_hstore_import()                | module_hstore_deport()&lt;br /&gt;
 earthdistance       | module_earthdistance_import()         | module_earthdistance_deport()&lt;br /&gt;
 sslinfo             | module_sslinfo_import()               | module_sslinfo_deport()&lt;br /&gt;
(35 rows)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Show module usage by schema:====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ljudmila=#  select * from pg_module_usage;&lt;br /&gt;
 schema_name | module_name | module_order &lt;br /&gt;
-------------+-------------+--------------&lt;br /&gt;
(0 rows)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Grant module usage privilege to user:====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ljudmila=# grant usage on schema modules to atom;&lt;br /&gt;
GRANT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===As database user, simply import desired module:===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ljudmila=&amp;gt; select modules.import('hstore');&lt;br /&gt;
... stuff ...&lt;br /&gt;
    import     &lt;br /&gt;
---------------&lt;br /&gt;
 IMPORT DEFINE hstore&lt;br /&gt;
(1 row)&lt;br /&gt;
&lt;br /&gt;
Time: 86.935 ms&lt;br /&gt;
ljudmila=&amp;gt; select 'a=&amp;gt;3'::hstore;&lt;br /&gt;
  hstore  &lt;br /&gt;
----------&lt;br /&gt;
 &amp;quot;a&amp;quot;=&amp;gt;&amp;quot;3&amp;quot;&lt;br /&gt;
(1 row)&lt;br /&gt;
&lt;br /&gt;
Time: 0.759 ms&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If module is already imported, IMPORT is returned instead of IMPORT DEFINE.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Elaboration==&lt;br /&gt;
===Use Cases===&lt;br /&gt;
* Installing stuff from ''contrib''&lt;br /&gt;
* Installing stuff from [http://pgfoundry.org/ PgFoundry]&lt;br /&gt;
* Installing user's own stuff&lt;br /&gt;
* Convincing ISPs that modules are cool and can be easily installed and used safely&lt;br /&gt;
&lt;br /&gt;
===Wishes/Requirements===&lt;br /&gt;
* simple apt-get or CPAN like interface, install by name&lt;br /&gt;
* transactional installation (module either gets installed ok or not at all)&lt;br /&gt;
* you should be able to tell what is installed&lt;br /&gt;
* should manage current contrib stuff too&lt;br /&gt;
* support multiple versions of databases and extensions&lt;br /&gt;
* create and drop (and alter) extensions in user-specified databases/schemas&lt;br /&gt;
* auto-get and compile and install extensions from sources from internet&lt;br /&gt;
* module sources: contrib, pgfoundry, user&lt;br /&gt;
* dependencies management (install dependencies as well)&lt;br /&gt;
* uninstall should use dependancies, not hand-written SQL scripts&lt;br /&gt;
* support for/integration with pg_dump/pg_restore&lt;br /&gt;
&lt;br /&gt;
==Construction==&lt;br /&gt;
&lt;br /&gt;
===Concepts===&lt;br /&gt;
''Module manager'' is a tool, which is specific to PostgreSQL, &lt;br /&gt;
not a specific operating system. It should handle all tasks&lt;br /&gt;
related to module management.&lt;br /&gt;
&lt;br /&gt;
Modules are installed on local system (eg Debian Linux), per&lt;br /&gt;
specific PostgreSQL version.&lt;br /&gt;
&lt;br /&gt;
Modules are installed each in it's own directory, like:&lt;br /&gt;
&lt;br /&gt;
 /usr/share/posteresql/8.3/modules/tablefunc-8.3.0/&lt;br /&gt;
&lt;br /&gt;
path structure:&lt;br /&gt;
&lt;br /&gt;
 $base/postgresql/&amp;lt;i&amp;gt;pg_version&amp;lt;/i&amp;gt;/modules/&amp;lt;i&amp;gt;modulename&amp;lt;/i&amp;gt;-&amp;lt;i&amp;gt;moduleversion&amp;lt;/i&amp;gt;/&lt;br /&gt;
&lt;br /&gt;
where:&lt;br /&gt;
* pg_version - postgresql version number (so multiple installations are supported)&lt;br /&gt;
* modulename - unique module name, (ex. hstore, tablefunc, newsysviews)&lt;br /&gt;
* moduleversion - debian-like version numbers. For contrib, this should probably match PostgreSQL version.&lt;br /&gt;
&lt;br /&gt;
module directory should contain at least:&lt;br /&gt;
* SQL install instructions (file install.sql)&lt;br /&gt;
* SQL uninstall instructions (file uninstall.sql)&lt;br /&gt;
* Module information (file module.xml) - contents of this should be elaborated&lt;br /&gt;
&lt;br /&gt;
This would make it easier for utilities to enumerate installed modules.&lt;br /&gt;
&lt;br /&gt;
Once installed, extensions can be:&lt;br /&gt;
* ''loaded'' (installed in particular database/schema)&lt;br /&gt;
* ''unloaded'' (removed from particular database/schema)&lt;br /&gt;
* ''upgraded'' (to a new version)&lt;br /&gt;
&lt;br /&gt;
Perhaps words CREATE, DROP and ALTER should be used?&lt;br /&gt;
&lt;br /&gt;
===Current ''contrib'' problems===&lt;br /&gt;
* everything in one directory; it is clumsy to match install and uninstall files and even see, what is available&lt;br /&gt;
* no module versions specified (or any metadata for that matter)&lt;br /&gt;
* many files explicitly set schema to public:&lt;br /&gt;
** this is the default anyway&lt;br /&gt;
** it requires user to edit SQL file to change this&lt;br /&gt;
** this should be set by module manager, if it is to support module installation in any schema&lt;br /&gt;
&lt;br /&gt;
Recommendations: &lt;br /&gt;
* Move everything from contrib to appropriate dirs/files in modules directory&lt;br /&gt;
* Add missing module.xml files&lt;br /&gt;
* Make symlinks from contrib&lt;br /&gt;
&lt;br /&gt;
===See Also===&lt;br /&gt;
* [[User:Ziga/xpg_package]] - somewhat older document of a similar nature&lt;/div&gt;</summary>
		<author><name>Ziga</name></author>	</entry>

	<entry>
		<id>http://wiki.postgresql.org/wiki/Module_Manager</id>
		<title>Module Manager</title>
		<link rel="alternate" type="text/html" href="http://wiki.postgresql.org/wiki/Module_Manager"/>
				<updated>2008-10-16T17:09:11Z</updated>
		
		<summary type="html">&lt;p&gt;Ziga:&amp;#32;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;There has been some interest PostgreSQL extension/package/module manager.&lt;br /&gt;
&lt;br /&gt;
We would like some software to make it easier for users and developers to install and manage&lt;br /&gt;
various add-on features available for PostgreSQL.&lt;br /&gt;
&lt;br /&gt;
Currently the process of installing add-ons is rather manual and cumbersome.&lt;br /&gt;
&lt;br /&gt;
Recently, this topic has reappeared on pgsql-hackers mailing list:&lt;br /&gt;
* [http://archives.postgresql.org/pgsql-hackers/2008-04/msg00132.php 2008-04 pgsql-hackers thread]&lt;br /&gt;
* [http://archives.postgresql.org/pgsql-hackers/2007-10/msg01281.php 2007-10 pgsql-hackers thread]&lt;br /&gt;
* [http://archives.postgresql.org/pgsql-patches/2006-05/msg00327.php 2006-05 pgsql-hackers thread]&lt;br /&gt;
* [http://archives.postgresql.org/message-id/ca33c0a30804061349s41b4d8fcsa9c579454b27ecd2@mail.gmail.com Database owner installable modules patch by Tom Dunstan]&lt;br /&gt;
* [http://archives.postgresql.org/pgsql-hackers/2008-07/msg01098.php PostgreSQL extensions packaging proposal by Dimitri Fontaine]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Perhaps a difference among terms ''extension'', ''package'' and ''module'' should be clarified?&lt;br /&gt;
Here the term ''module'' is used, due to popular demand.&lt;br /&gt;
&lt;br /&gt;
==Elaboration==&lt;br /&gt;
===Use Cases===&lt;br /&gt;
* Installing stuff from ''contrib''&lt;br /&gt;
* Installing stuff from [http://pgfoundry.org/ PgFoundry]&lt;br /&gt;
* Installing user's own stuff&lt;br /&gt;
* Convincing ISPs that modules are cool and can be easily installed and used safely&lt;br /&gt;
&lt;br /&gt;
===Wishes/Requirements===&lt;br /&gt;
* simple apt-get or CPAN like interface, install by name&lt;br /&gt;
* transactional installation (module either gets installed ok or not at all)&lt;br /&gt;
* you should be able to tell what is installed&lt;br /&gt;
* should manage current contrib stuff too&lt;br /&gt;
* support multiple versions of databases and extensions&lt;br /&gt;
* create and drop (and alter) extensions in user-specified databases/schemas&lt;br /&gt;
* auto-get and compile and install extensions from sources from internet&lt;br /&gt;
* module sources: contrib, pgfoundry, user&lt;br /&gt;
* dependencies management (install dependencies as well)&lt;br /&gt;
* uninstall should use dependancies, not hand-written SQL scripts&lt;br /&gt;
* support for/integration with pg_dump/pg_restore&lt;br /&gt;
&lt;br /&gt;
==Construction==&lt;br /&gt;
&lt;br /&gt;
===Concepts===&lt;br /&gt;
''Module manager'' is a tool, which is specific to PostgreSQL, &lt;br /&gt;
not a specific operating system. It should handle all tasks&lt;br /&gt;
related to module management.&lt;br /&gt;
&lt;br /&gt;
Modules are installed on local system (eg Debian Linux), per&lt;br /&gt;
specific PostgreSQL version.&lt;br /&gt;
&lt;br /&gt;
Modules are installed each in it's own directory, like:&lt;br /&gt;
&lt;br /&gt;
 /usr/share/posteresql/8.3/modules/tablefunc-8.3.0/&lt;br /&gt;
&lt;br /&gt;
path structure:&lt;br /&gt;
&lt;br /&gt;
 $base/postgresql/&amp;lt;i&amp;gt;pg_version&amp;lt;/i&amp;gt;/modules/&amp;lt;i&amp;gt;modulename&amp;lt;/i&amp;gt;-&amp;lt;i&amp;gt;moduleversion&amp;lt;/i&amp;gt;/&lt;br /&gt;
&lt;br /&gt;
where:&lt;br /&gt;
* pg_version - postgresql version number (so multiple installations are supported)&lt;br /&gt;
* modulename - unique module name, (ex. hstore, tablefunc, newsysviews)&lt;br /&gt;
* moduleversion - debian-like version numbers. For contrib, this should probably match PostgreSQL version.&lt;br /&gt;
&lt;br /&gt;
module directory should contain at least:&lt;br /&gt;
* SQL install instructions (file install.sql)&lt;br /&gt;
* SQL uninstall instructions (file uninstall.sql)&lt;br /&gt;
* Module information (file module.xml) - contents of this should be elaborated&lt;br /&gt;
&lt;br /&gt;
This would make it easier for utilities to enumerate installed modules.&lt;br /&gt;
&lt;br /&gt;
Once installed, extensions can be:&lt;br /&gt;
* ''loaded'' (installed in particular database/schema)&lt;br /&gt;
* ''unloaded'' (removed from particular database/schema)&lt;br /&gt;
* ''upgraded'' (to a new version)&lt;br /&gt;
&lt;br /&gt;
Perhaps words CREATE, DROP and ALTER should be used?&lt;br /&gt;
&lt;br /&gt;
===Current ''contrib'' problems===&lt;br /&gt;
* everything in one directory; it is clumsy to match install and uninstall files and even see, what is available&lt;br /&gt;
* no module versions specified (or any metadata for that matter)&lt;br /&gt;
* many files explicitly set schema to public:&lt;br /&gt;
** this is the default anyway&lt;br /&gt;
** it requires user to edit SQL file to change this&lt;br /&gt;
** this should be set by module manager, if it is to support module installation in any schema&lt;br /&gt;
&lt;br /&gt;
Recommendations: &lt;br /&gt;
* Move everything from contrib to appropriate dirs/files in modules directory&lt;br /&gt;
* Add missing module.xml files&lt;br /&gt;
* Make symlinks from contrib&lt;br /&gt;
&lt;br /&gt;
===See Also===&lt;br /&gt;
* [[User:Ziga/xpg_package]] - somewhat older document of a similar nature&lt;/div&gt;</summary>
		<author><name>Ziga</name></author>	</entry>

	<entry>
		<id>http://wiki.postgresql.org/wiki/User:Ziga</id>
		<title>User:Ziga</title>
		<link rel="alternate" type="text/html" href="http://wiki.postgresql.org/wiki/User:Ziga"/>
				<updated>2008-04-14T21:28:20Z</updated>
		
		<summary type="html">&lt;p&gt;Ziga:&amp;#32;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Žiga Kranjec&lt;br /&gt;
&lt;br /&gt;
software developer&lt;br /&gt;
&lt;br /&gt;
Mail: ziga (a) ljudmila.org&lt;br /&gt;
&lt;br /&gt;
===areas of interest===&lt;br /&gt;
&lt;br /&gt;
* User interfaces &amp;amp; User experience&lt;br /&gt;
* Perl&lt;br /&gt;
* web development&lt;br /&gt;
* semantic web&lt;br /&gt;
&lt;br /&gt;
===PostgreSQL areas of interest===&lt;br /&gt;
* [[DDL Functions]] - SQL-callable functions capable of generating DDL scripts for objects within the database&lt;br /&gt;
* [[Module Manager]] - automating installation of PostgreSQL extensions&lt;br /&gt;
** [[User:Ziga/xpg_package|xpg_package]] - easily manage PostgreSQL extensions&lt;br /&gt;
* [[User:Ziga/xpg_diff|xpg_diff]] - schema comparator/updater&lt;br /&gt;
* [[Datalink]] - SQL/MED DATALINK type&lt;/div&gt;</summary>
		<author><name>Ziga</name></author>	</entry>

	<entry>
		<id>http://wiki.postgresql.org/wiki/Module_Manager</id>
		<title>Module Manager</title>
		<link rel="alternate" type="text/html" href="http://wiki.postgresql.org/wiki/Module_Manager"/>
				<updated>2008-04-14T21:26:56Z</updated>
		
		<summary type="html">&lt;p&gt;Ziga:&amp;#32;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;There has been some interest PostgreSQL extension/package/module manager.&lt;br /&gt;
&lt;br /&gt;
We would like some software to make it easier for users and developers to install and manage&lt;br /&gt;
various add-on features available for PostgreSQL.&lt;br /&gt;
&lt;br /&gt;
Currently the process of installing add-ons is rather manual and cumbersome.&lt;br /&gt;
&lt;br /&gt;
Recently, this topic has reappeared on pgsql-hackers mailing list:&lt;br /&gt;
* [http://archives.postgresql.org/pgsql-hackers/2008-04/msg00132.php 2008-04 pgsql-hackers thread]&lt;br /&gt;
* [http://archives.postgresql.org/pgsql-hackers/2007-10/msg01281.php 2007-10 pgsql-hackers thread]&lt;br /&gt;
* [http://archives.postgresql.org/pgsql-patches/2006-05/msg00327.php 2006-05 pgsql-hackers thread]&lt;br /&gt;
&lt;br /&gt;
Perhaps a difference among terms ''extension'', ''package'' and ''module'' should be clarified?&lt;br /&gt;
Here the term ''module'' is used, due to popular demand.&lt;br /&gt;
&lt;br /&gt;
==Elaboration==&lt;br /&gt;
===Use Cases===&lt;br /&gt;
* Installing stuff from ''contrib''&lt;br /&gt;
* Installing stuff from [http://pgfoundry.org/ PgFoundry]&lt;br /&gt;
* Installing user's stuff&lt;br /&gt;
* Convincing ISPs that modules are cool and can be easily installed and used safely&lt;br /&gt;
&lt;br /&gt;
===Wishes/Requirements===&lt;br /&gt;
* simple apt-get or CPAN like interface, install by name&lt;br /&gt;
* transactional installation (module either gets installed ok or not at all)&lt;br /&gt;
* you should be able to tell what is installed&lt;br /&gt;
* should manage current contrib stuff too&lt;br /&gt;
* support multiple versions of databases and extensions&lt;br /&gt;
* create and drop (and alter) extensions in user-specified databases/schemas&lt;br /&gt;
* auto-get and compile and install extensions from sources from internet&lt;br /&gt;
* module sources: contrib, pgfoundry, user&lt;br /&gt;
* dependencies management (install dependencies as well)&lt;br /&gt;
* uninstall should use dependancies, not hand-written SQL scripts&lt;br /&gt;
* support for/integration with pg_dump/pg_restore&lt;br /&gt;
&lt;br /&gt;
==Construction==&lt;br /&gt;
&lt;br /&gt;
===Concepts===&lt;br /&gt;
''Module manager'' is a tool, which is specific to PostgreSQL, &lt;br /&gt;
not a specific operating system. It should handle all tasks&lt;br /&gt;
related to module management.&lt;br /&gt;
&lt;br /&gt;
Modules are installed on local system (eg Debian Linux), per&lt;br /&gt;
specific PostgreSQL version.&lt;br /&gt;
&lt;br /&gt;
Modules are installed each in it's own directory, like:&lt;br /&gt;
&lt;br /&gt;
 /usr/share/posteresql/8.3/modules/tablefunc-8.3.0/&lt;br /&gt;
&lt;br /&gt;
path structure:&lt;br /&gt;
&lt;br /&gt;
 $base/postgresql/&amp;lt;i&amp;gt;pg_version&amp;lt;/i&amp;gt;/modules/&amp;lt;i&amp;gt;modulename&amp;lt;/i&amp;gt;-&amp;lt;i&amp;gt;moduleversion&amp;lt;/i&amp;gt;/&lt;br /&gt;
&lt;br /&gt;
where:&lt;br /&gt;
* pg_version - postgresql version number (so multiple installations are supported)&lt;br /&gt;
* modulename - unique module name, (ex. hstore, tablefunc, newsysviews)&lt;br /&gt;
* moduleversion - debian-like version numbers. For contrib, this should probably match PostgreSQL version.&lt;br /&gt;
&lt;br /&gt;
module directory should contain at least:&lt;br /&gt;
* SQL install instructions (file install.sql)&lt;br /&gt;
* SQL uninstall instructions (file uninstall.sql)&lt;br /&gt;
* Module information (file module.xml) - contents of this should be elaborated&lt;br /&gt;
&lt;br /&gt;
This would make it easier for utilities to enumerate installed modules.&lt;br /&gt;
&lt;br /&gt;
Once installed, extensions can be:&lt;br /&gt;
* ''loaded'' (installed in particular database/schema)&lt;br /&gt;
* ''unloaded'' (removed from particular database/schema)&lt;br /&gt;
* ''upgraded'' (to a new version)&lt;br /&gt;
&lt;br /&gt;
Perhaps words CREATE, DROP and ALTER should be used?&lt;br /&gt;
&lt;br /&gt;
===Current ''contrib'' problems===&lt;br /&gt;
* everything in one directory; it is clumsy to match install and uninstall files and even see, what is available&lt;br /&gt;
* no module versions specified (or any metadata for that matter)&lt;br /&gt;
* many files explicitly set schema to public:&lt;br /&gt;
** this is the default anyway&lt;br /&gt;
** it requires user to edit SQL file to change this&lt;br /&gt;
** this should be set by module manager, if it is to support module installation in any schema&lt;br /&gt;
&lt;br /&gt;
Recommendations: &lt;br /&gt;
* Move everything from contrib to appropriate dirs/files in modules directory&lt;br /&gt;
* Add missing module.xml files&lt;br /&gt;
* Make symlinks from contrib&lt;br /&gt;
&lt;br /&gt;
===See Also===&lt;br /&gt;
* [[User:Ziga/xpg_package]] - somewhat older document of a similar nature&lt;/div&gt;</summary>
		<author><name>Ziga</name></author>	</entry>

	<entry>
		<id>http://wiki.postgresql.org/wiki/Module_Manager</id>
		<title>Module Manager</title>
		<link rel="alternate" type="text/html" href="http://wiki.postgresql.org/wiki/Module_Manager"/>
				<updated>2008-04-14T21:23:07Z</updated>
		
		<summary type="html">&lt;p&gt;Ziga:&amp;#32;Extension Manager moved to Module Manager: term Module seems to be agreed upon&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;There has been some interest PostgreSQL extension/package/module manager.&lt;br /&gt;
&lt;br /&gt;
We would like some software to make it easier for users and developers to install and manage&lt;br /&gt;
various add-on features available for PostgreSQL.&lt;br /&gt;
&lt;br /&gt;
Currently the process of installing add-ons is rather manual and cumbersome.&lt;br /&gt;
&lt;br /&gt;
Recently, this topic has reappeared on pgsql-hackers mailing list:&lt;br /&gt;
* [http://archives.postgresql.org/pgsql-hackers/2008-04/msg00132.php 2008-04 pgsql-hackers thread]&lt;br /&gt;
* [http://archives.postgresql.org/pgsql-hackers/2007-10/msg01281.php 2007-10 pgsql-hackers thread]&lt;br /&gt;
* [http://archives.postgresql.org/pgsql-patches/2006-05/msg00327.php 2006-05 pgsql-hackers thread]&lt;br /&gt;
&lt;br /&gt;
Perhaps a difference among terms ''extension'', ''package'' and ''module'' should be clarified?&lt;br /&gt;
Here the term ''module'' is used, due to popular demand.&lt;br /&gt;
&lt;br /&gt;
==Use Cases==&lt;br /&gt;
* Installing stuff from ''contrib''&lt;br /&gt;
* Installing stuff from [http://pgfoundry.org/ PgFoundry]&lt;br /&gt;
* Installing user's stuff&lt;br /&gt;
* Convincing ISPs that modules are cool and can be easily installed and used safely&lt;br /&gt;
&lt;br /&gt;
==Wishes/Requirements==&lt;br /&gt;
* simple apt-get or CPAN like interface, install by name&lt;br /&gt;
* transactional installation (module either gets installed ok or not at all)&lt;br /&gt;
* you should be able to tell what is installed&lt;br /&gt;
* should manage current contrib stuff too&lt;br /&gt;
* support multiple versions of databases and extensions&lt;br /&gt;
* create and drop (and alter) extensions in user-specified databases/schemas&lt;br /&gt;
* auto-get and compile and install extensions from sources from internet&lt;br /&gt;
* module sources: contrib, pgfoundry, user&lt;br /&gt;
* dependencies management (install dependencies as well)&lt;br /&gt;
* uninstall should use dependancies, not hand-written SQL scripts&lt;br /&gt;
* support for/integration with pg_dump/pg_restore&lt;br /&gt;
&lt;br /&gt;
==Concepts==&lt;br /&gt;
&lt;br /&gt;
''Module manager'' is a tool, which is specific to PostgreSQL, &lt;br /&gt;
not a specific operating system. It should handle all tasks&lt;br /&gt;
related to module management.&lt;br /&gt;
&lt;br /&gt;
Modules are installed on local system (eg Debian Linux), per&lt;br /&gt;
specific PostgreSQL version.&lt;br /&gt;
&lt;br /&gt;
Modules are installed each in it's own directory, like:&lt;br /&gt;
&lt;br /&gt;
 /usr/share/posteresql/8.3/modules/tablefunc-8.3.0/&lt;br /&gt;
&lt;br /&gt;
path structure:&lt;br /&gt;
&lt;br /&gt;
 $base/postgresql/&amp;lt;i&amp;gt;pg_version&amp;lt;/i&amp;gt;/modules/&amp;lt;i&amp;gt;modulename&amp;lt;/i&amp;gt;-&amp;lt;i&amp;gt;moduleversion&amp;lt;/i&amp;gt;/&lt;br /&gt;
&lt;br /&gt;
where:&lt;br /&gt;
* pg_version - postgresql version number (so multiple installations are supported)&lt;br /&gt;
* modulename - unique module name, (ex. hstore, tablefunc, newsysviews)&lt;br /&gt;
* moduleversion - debian-like version numbers. For contrib, this should probably match PostgreSQL version.&lt;br /&gt;
&lt;br /&gt;
module directory should contain at least:&lt;br /&gt;
* SQL install instructions (file install.sql)&lt;br /&gt;
* SQL uninstall instructions (file uninstall.sql)&lt;br /&gt;
* Module information (file module.xml) - contents of this should be elaborated&lt;br /&gt;
&lt;br /&gt;
This would make it easier for utilities to enumerate installed modules.&lt;br /&gt;
&lt;br /&gt;
Once installed, extensions can be:&lt;br /&gt;
* ''loaded'' (installed in particular database/schema)&lt;br /&gt;
* ''unloaded'' (removed from particular database/schema)&lt;br /&gt;
* ''upgraded'' (to a new version)&lt;br /&gt;
&lt;br /&gt;
Perhaps words CREATE, DROP and ALTER should be used?&lt;br /&gt;
&lt;br /&gt;
===Current ''contrib'' problems===&lt;br /&gt;
* everything in one directory; it is clumsy to match install and uninstall files and even see, what is available&lt;br /&gt;
* no module versions specified (or any metadata for that matter)&lt;br /&gt;
* many files explicitly set schema to public:&lt;br /&gt;
** this is the default anyway&lt;br /&gt;
** it requires user to edit SQL file to change this&lt;br /&gt;
** this should be set by module manager, if it is to support module installation in any schema&lt;br /&gt;
&lt;br /&gt;
Recommendations: &lt;br /&gt;
* Move everything from contrib to appropriate dirs/files in modules directory&lt;br /&gt;
* Add missing module.xml files&lt;br /&gt;
* Make symlinks from contrib&lt;br /&gt;
&lt;br /&gt;
See Also: [[User:Ziga/xpg_package]]&lt;/div&gt;</summary>
		<author><name>Ziga</name></author>	</entry>

	<entry>
		<id>http://wiki.postgresql.org/wiki/Extension_Manager</id>
		<title>Extension Manager</title>
		<link rel="alternate" type="text/html" href="http://wiki.postgresql.org/wiki/Extension_Manager"/>
				<updated>2008-04-14T21:23:07Z</updated>
		
		<summary type="html">&lt;p&gt;Ziga:&amp;#32;Extension Manager moved to Module Manager: term Module seems to be agreed upon&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[Module Manager]]&lt;/div&gt;</summary>
		<author><name>Ziga</name></author>	</entry>

	<entry>
		<id>http://wiki.postgresql.org/wiki/Module_Manager</id>
		<title>Module Manager</title>
		<link rel="alternate" type="text/html" href="http://wiki.postgresql.org/wiki/Module_Manager"/>
				<updated>2008-04-14T21:22:32Z</updated>
		
		<summary type="html">&lt;p&gt;Ziga:&amp;#32;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;There has been some interest PostgreSQL extension/package/module manager.&lt;br /&gt;
&lt;br /&gt;
We would like some software to make it easier for users and developers to install and manage&lt;br /&gt;
various add-on features available for PostgreSQL.&lt;br /&gt;
&lt;br /&gt;
Currently the process of installing add-ons is rather manual and cumbersome.&lt;br /&gt;
&lt;br /&gt;
Recently, this topic has reappeared on pgsql-hackers mailing list:&lt;br /&gt;
* [http://archives.postgresql.org/pgsql-hackers/2008-04/msg00132.php 2008-04 pgsql-hackers thread]&lt;br /&gt;
* [http://archives.postgresql.org/pgsql-hackers/2007-10/msg01281.php 2007-10 pgsql-hackers thread]&lt;br /&gt;
* [http://archives.postgresql.org/pgsql-patches/2006-05/msg00327.php 2006-05 pgsql-hackers thread]&lt;br /&gt;
&lt;br /&gt;
Perhaps a difference among terms ''extension'', ''package'' and ''module'' should be clarified?&lt;br /&gt;
Here the term ''module'' is used, due to popular demand.&lt;br /&gt;
&lt;br /&gt;
==Use Cases==&lt;br /&gt;
* Installing stuff from ''contrib''&lt;br /&gt;
* Installing stuff from [http://pgfoundry.org/ PgFoundry]&lt;br /&gt;
* Installing user's stuff&lt;br /&gt;
* Convincing ISPs that modules are cool and can be easily installed and used safely&lt;br /&gt;
&lt;br /&gt;
==Wishes/Requirements==&lt;br /&gt;
* simple apt-get or CPAN like interface, install by name&lt;br /&gt;
* transactional installation (module either gets installed ok or not at all)&lt;br /&gt;
* you should be able to tell what is installed&lt;br /&gt;
* should manage current contrib stuff too&lt;br /&gt;
* support multiple versions of databases and extensions&lt;br /&gt;
* create and drop (and alter) extensions in user-specified databases/schemas&lt;br /&gt;
* auto-get and compile and install extensions from sources from internet&lt;br /&gt;
* module sources: contrib, pgfoundry, user&lt;br /&gt;
* dependencies management (install dependencies as well)&lt;br /&gt;
* uninstall should use dependancies, not hand-written SQL scripts&lt;br /&gt;
* support for/integration with pg_dump/pg_restore&lt;br /&gt;
&lt;br /&gt;
==Concepts==&lt;br /&gt;
&lt;br /&gt;
''Module manager'' is a tool, which is specific to PostgreSQL, &lt;br /&gt;
not a specific operating system. It should handle all tasks&lt;br /&gt;
related to module management.&lt;br /&gt;
&lt;br /&gt;
Modules are installed on local system (eg Debian Linux), per&lt;br /&gt;
specific PostgreSQL version.&lt;br /&gt;
&lt;br /&gt;
Modules are installed each in it's own directory, like:&lt;br /&gt;
&lt;br /&gt;
 /usr/share/posteresql/8.3/modules/tablefunc-8.3.0/&lt;br /&gt;
&lt;br /&gt;
path structure:&lt;br /&gt;
&lt;br /&gt;
 $base/postgresql/&amp;lt;i&amp;gt;pg_version&amp;lt;/i&amp;gt;/modules/&amp;lt;i&amp;gt;modulename&amp;lt;/i&amp;gt;-&amp;lt;i&amp;gt;moduleversion&amp;lt;/i&amp;gt;/&lt;br /&gt;
&lt;br /&gt;
where:&lt;br /&gt;
* pg_version - postgresql version number (so multiple installations are supported)&lt;br /&gt;
* modulename - unique module name, (ex. hstore, tablefunc, newsysviews)&lt;br /&gt;
* moduleversion - debian-like version numbers. For contrib, this should probably match PostgreSQL version.&lt;br /&gt;
&lt;br /&gt;
module directory should contain at least:&lt;br /&gt;
* SQL install instructions (file install.sql)&lt;br /&gt;
* SQL uninstall instructions (file uninstall.sql)&lt;br /&gt;
* Module information (file module.xml) - contents of this should be elaborated&lt;br /&gt;
&lt;br /&gt;
This would make it easier for utilities to enumerate installed modules.&lt;br /&gt;
&lt;br /&gt;
Once installed, extensions can be:&lt;br /&gt;
* ''loaded'' (installed in particular database/schema)&lt;br /&gt;
* ''unloaded'' (removed from particular database/schema)&lt;br /&gt;
* ''upgraded'' (to a new version)&lt;br /&gt;
&lt;br /&gt;
Perhaps words CREATE, DROP and ALTER should be used?&lt;br /&gt;
&lt;br /&gt;
===Current ''contrib'' problems===&lt;br /&gt;
* everything in one directory; it is clumsy to match install and uninstall files and even see, what is available&lt;br /&gt;
* no module versions specified (or any metadata for that matter)&lt;br /&gt;
* many files explicitly set schema to public:&lt;br /&gt;
** this is the default anyway&lt;br /&gt;
** it requires user to edit SQL file to change this&lt;br /&gt;
** this should be set by module manager, if it is to support module installation in any schema&lt;br /&gt;
&lt;br /&gt;
Recommendations: &lt;br /&gt;
* Move everything from contrib to appropriate dirs/files in modules directory&lt;br /&gt;
* Add missing module.xml files&lt;br /&gt;
* Make symlinks from contrib&lt;br /&gt;
&lt;br /&gt;
See Also: [[User:Ziga/xpg_package]]&lt;/div&gt;</summary>
		<author><name>Ziga</name></author>	</entry>

	<entry>
		<id>http://wiki.postgresql.org/wiki/User:Ziga</id>
		<title>User:Ziga</title>
		<link rel="alternate" type="text/html" href="http://wiki.postgresql.org/wiki/User:Ziga"/>
				<updated>2008-04-14T20:35:26Z</updated>
		
		<summary type="html">&lt;p&gt;Ziga:&amp;#32;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Žiga Kranjec&lt;br /&gt;
&lt;br /&gt;
software developer&lt;br /&gt;
&lt;br /&gt;
Mail: ziga (a) ljudmila.org&lt;br /&gt;
&lt;br /&gt;
===areas of interest===&lt;br /&gt;
&lt;br /&gt;
* user interfaces &amp;amp; user experience&lt;br /&gt;
* perl&lt;br /&gt;
* website development&lt;br /&gt;
&lt;br /&gt;
===PostgreSQL areas of interest===&lt;br /&gt;
* [[DDL Functions]] - SQL-callable functions capable of generating DDL scripts for objects within the database&lt;br /&gt;
* [[Module Manager]] - automating installation of PostgreSQL extensions&lt;br /&gt;
** [[User:Ziga/xpg_package|xpg_package]] - easily manage PostgreSQL extensions&lt;br /&gt;
* [[User:Ziga/xpg_diff|xpg_diff]] - schema comparator/updater&lt;br /&gt;
* [[Datalink]] - SQL/MED DATALINK type&lt;/div&gt;</summary>
		<author><name>Ziga</name></author>	</entry>

	<entry>
		<id>http://wiki.postgresql.org/wiki/User:Ziga</id>
		<title>User:Ziga</title>
		<link rel="alternate" type="text/html" href="http://wiki.postgresql.org/wiki/User:Ziga"/>
				<updated>2008-04-14T20:33:35Z</updated>
		
		<summary type="html">&lt;p&gt;Ziga:&amp;#32;New page: Žiga Kranjec  software developer  Mail: ziga (a) ljudmila.org  ===areas of interest===  * user interfaces &amp;amp; user experience * perl * website development  ===PostgreSQL areas of interest==...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Žiga Kranjec&lt;br /&gt;
&lt;br /&gt;
software developer&lt;br /&gt;
&lt;br /&gt;
Mail: ziga (a) ljudmila.org&lt;br /&gt;
&lt;br /&gt;
===areas of interest===&lt;br /&gt;
&lt;br /&gt;
* user interfaces &amp;amp; user experience&lt;br /&gt;
* perl&lt;br /&gt;
* website development&lt;br /&gt;
&lt;br /&gt;
===PostgreSQL areas of interest===&lt;br /&gt;
* [[DDL Functions]] - SQL-callable functions capable of generating DDL scripts for objects within the database&lt;br /&gt;
* [[Package Manager]] - automating installation of PostgreSQL extensions&lt;br /&gt;
** [[User:Ziga/xpg_package|xpg_package]] - easily manage PostgreSQL extensions&lt;br /&gt;
* [[User:Ziga/xpg_diff|xpg_diff]] - schema comparator/updater&lt;/div&gt;</summary>
		<author><name>Ziga</name></author>	</entry>

	</feed>