Robert Haas <[email protected]> writes:
>> Maybe you would want the system to be able to determine the oldest
>> version to start from to reach the current default_version given in the
>> control file, but I guess it would be better to add another property
>> like default_full_version or such (last_stop?).
>
> Possibly that might be a better design, yes. Especially since we
> don't order version numbers intrinsically.
It's quite simple to implement too, see attached. As for the version
number ordering, that's a giant rat hole I don't want to be digging in,
and I think we can bypass that problem entirely.
Regards,
--
Dimitri Fontaine
http://2ndQuadrant.fr PostgreSQL : Expertise, Formation et Support
diff --git a/contrib/hstore/Makefile b/contrib/hstore/Makefile
index e9e5e53..2d624d3 100644
--- a/contrib/hstore/Makefile
+++ b/contrib/hstore/Makefile
@@ -5,7 +5,7 @@ OBJS = hstore_io.o hstore_op.o hstore_gist.o hstore_gin.o hstore_compat.o \
crc32.o
EXTENSION = hstore
-DATA = hstore--1.0.sql hstore--1.1.sql hstore--1.0--1.1.sql \
+DATA = hstore--1.0.sql hstore--1.1.sql.orig hstore--1.0--1.1.sql \
hstore--unpackaged--1.0.sql
REGRESS = hstore
diff --git a/contrib/hstore/hstore--1.1.sql b/contrib/hstore/hstore--1.1.sql
deleted file mode 100644
index e95ad32..0000000
--- a/contrib/hstore/hstore--1.1.sql
+++ /dev/null
@@ -1,524 +0,0 @@
-/* contrib/hstore/hstore--1.1.sql */
-
--- complain if script is sourced in psql, rather than via CREATE EXTENSION
-\echo Use "CREATE EXTENSION hstore" to load this file. \quit
-
-CREATE TYPE hstore;
-
-CREATE FUNCTION hstore_in(cstring)
-RETURNS hstore
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION hstore_out(hstore)
-RETURNS cstring
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION hstore_recv(internal)
-RETURNS hstore
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION hstore_send(hstore)
-RETURNS bytea
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE TYPE hstore (
- INTERNALLENGTH = -1,
- INPUT = hstore_in,
- OUTPUT = hstore_out,
- RECEIVE = hstore_recv,
- SEND = hstore_send,
- STORAGE = extended
-);
-
-CREATE FUNCTION hstore_version_diag(hstore)
-RETURNS integer
-AS 'MODULE_PATHNAME','hstore_version_diag'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION fetchval(hstore,text)
-RETURNS text
-AS 'MODULE_PATHNAME','hstore_fetchval'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE OPERATOR -> (
- LEFTARG = hstore,
- RIGHTARG = text,
- PROCEDURE = fetchval
-);
-
-CREATE FUNCTION slice_array(hstore,text[])
-RETURNS text[]
-AS 'MODULE_PATHNAME','hstore_slice_to_array'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE OPERATOR -> (
- LEFTARG = hstore,
- RIGHTARG = text[],
- PROCEDURE = slice_array
-);
-
-CREATE FUNCTION slice(hstore,text[])
-RETURNS hstore
-AS 'MODULE_PATHNAME','hstore_slice_to_hstore'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION isexists(hstore,text)
-RETURNS bool
-AS 'MODULE_PATHNAME','hstore_exists'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION exist(hstore,text)
-RETURNS bool
-AS 'MODULE_PATHNAME','hstore_exists'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE OPERATOR ? (
- LEFTARG = hstore,
- RIGHTARG = text,
- PROCEDURE = exist,
- RESTRICT = contsel,
- JOIN = contjoinsel
-);
-
-CREATE FUNCTION exists_any(hstore,text[])
-RETURNS bool
-AS 'MODULE_PATHNAME','hstore_exists_any'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE OPERATOR ?| (
- LEFTARG = hstore,
- RIGHTARG = text[],
- PROCEDURE = exists_any,
- RESTRICT = contsel,
- JOIN = contjoinsel
-);
-
-CREATE FUNCTION exists_all(hstore,text[])
-RETURNS bool
-AS 'MODULE_PATHNAME','hstore_exists_all'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE OPERATOR ?& (
- LEFTARG = hstore,
- RIGHTARG = text[],
- PROCEDURE = exists_all,
- RESTRICT = contsel,
- JOIN = contjoinsel
-);
-
-CREATE FUNCTION isdefined(hstore,text)
-RETURNS bool
-AS 'MODULE_PATHNAME','hstore_defined'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION defined(hstore,text)
-RETURNS bool
-AS 'MODULE_PATHNAME','hstore_defined'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION delete(hstore,text)
-RETURNS hstore
-AS 'MODULE_PATHNAME','hstore_delete'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION delete(hstore,text[])
-RETURNS hstore
-AS 'MODULE_PATHNAME','hstore_delete_array'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION delete(hstore,hstore)
-RETURNS hstore
-AS 'MODULE_PATHNAME','hstore_delete_hstore'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE OPERATOR - (
- LEFTARG = hstore,
- RIGHTARG = text,
- PROCEDURE = delete
-);
-
-CREATE OPERATOR - (
- LEFTARG = hstore,
- RIGHTARG = text[],
- PROCEDURE = delete
-);
-
-CREATE OPERATOR - (
- LEFTARG = hstore,
- RIGHTARG = hstore,
- PROCEDURE = delete
-);
-
-CREATE FUNCTION hs_concat(hstore,hstore)
-RETURNS hstore
-AS 'MODULE_PATHNAME','hstore_concat'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE OPERATOR || (
- LEFTARG = hstore,
- RIGHTARG = hstore,
- PROCEDURE = hs_concat
-);
-
-CREATE FUNCTION hs_contains(hstore,hstore)
-RETURNS bool
-AS 'MODULE_PATHNAME','hstore_contains'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION hs_contained(hstore,hstore)
-RETURNS bool
-AS 'MODULE_PATHNAME','hstore_contained'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE OPERATOR @> (
- LEFTARG = hstore,
- RIGHTARG = hstore,
- PROCEDURE = hs_contains,
- COMMUTATOR = '<@',
- RESTRICT = contsel,
- JOIN = contjoinsel
-);
-
-CREATE OPERATOR <@ (
- LEFTARG = hstore,
- RIGHTARG = hstore,
- PROCEDURE = hs_contained,
- COMMUTATOR = '@>',
- RESTRICT = contsel,
- JOIN = contjoinsel
-);
-
--- obsolete:
-CREATE OPERATOR @ (
- LEFTARG = hstore,
- RIGHTARG = hstore,
- PROCEDURE = hs_contains,
- COMMUTATOR = '~',
- RESTRICT = contsel,
- JOIN = contjoinsel
-);
-
-CREATE OPERATOR ~ (
- LEFTARG = hstore,
- RIGHTARG = hstore,
- PROCEDURE = hs_contained,
- COMMUTATOR = '@',
- RESTRICT = contsel,
- JOIN = contjoinsel
-);
-
-CREATE FUNCTION tconvert(text,text)
-RETURNS hstore
-AS 'MODULE_PATHNAME','hstore_from_text'
-LANGUAGE C IMMUTABLE; -- not STRICT; needs to allow (key,NULL)
-
-CREATE FUNCTION hstore(text,text)
-RETURNS hstore
-AS 'MODULE_PATHNAME','hstore_from_text'
-LANGUAGE C IMMUTABLE; -- not STRICT; needs to allow (key,NULL)
-
-CREATE FUNCTION hstore(text[],text[])
-RETURNS hstore
-AS 'MODULE_PATHNAME', 'hstore_from_arrays'
-LANGUAGE C IMMUTABLE; -- not STRICT; allows (keys,null)
-
-CREATE FUNCTION hstore(text[])
-RETURNS hstore
-AS 'MODULE_PATHNAME', 'hstore_from_array'
-LANGUAGE C IMMUTABLE STRICT;
-
-CREATE CAST (text[] AS hstore)
- WITH FUNCTION hstore(text[]);
-
-CREATE FUNCTION hstore(record)
-RETURNS hstore
-AS 'MODULE_PATHNAME', 'hstore_from_record'
-LANGUAGE C IMMUTABLE; -- not STRICT; allows (null::recordtype)
-
-CREATE FUNCTION hstore_to_array(hstore)
-RETURNS text[]
-AS 'MODULE_PATHNAME','hstore_to_array'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE OPERATOR %% (
- RIGHTARG = hstore,
- PROCEDURE = hstore_to_array
-);
-
-CREATE FUNCTION hstore_to_matrix(hstore)
-RETURNS text[]
-AS 'MODULE_PATHNAME','hstore_to_matrix'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE OPERATOR %# (
- RIGHTARG = hstore,
- PROCEDURE = hstore_to_matrix
-);
-
-CREATE FUNCTION akeys(hstore)
-RETURNS text[]
-AS 'MODULE_PATHNAME','hstore_akeys'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION avals(hstore)
-RETURNS text[]
-AS 'MODULE_PATHNAME','hstore_avals'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION skeys(hstore)
-RETURNS setof text
-AS 'MODULE_PATHNAME','hstore_skeys'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION svals(hstore)
-RETURNS setof text
-AS 'MODULE_PATHNAME','hstore_svals'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION each(IN hs hstore,
- OUT key text,
- OUT value text)
-RETURNS SETOF record
-AS 'MODULE_PATHNAME','hstore_each'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION populate_record(anyelement,hstore)
-RETURNS anyelement
-AS 'MODULE_PATHNAME', 'hstore_populate_record'
-LANGUAGE C IMMUTABLE; -- not STRICT; allows (null::rectype,hstore)
-
-CREATE OPERATOR #= (
- LEFTARG = anyelement,
- RIGHTARG = hstore,
- PROCEDURE = populate_record
-);
-
--- btree support
-
-CREATE FUNCTION hstore_eq(hstore,hstore)
-RETURNS boolean
-AS 'MODULE_PATHNAME','hstore_eq'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION hstore_ne(hstore,hstore)
-RETURNS boolean
-AS 'MODULE_PATHNAME','hstore_ne'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION hstore_gt(hstore,hstore)
-RETURNS boolean
-AS 'MODULE_PATHNAME','hstore_gt'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION hstore_ge(hstore,hstore)
-RETURNS boolean
-AS 'MODULE_PATHNAME','hstore_ge'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION hstore_lt(hstore,hstore)
-RETURNS boolean
-AS 'MODULE_PATHNAME','hstore_lt'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION hstore_le(hstore,hstore)
-RETURNS boolean
-AS 'MODULE_PATHNAME','hstore_le'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION hstore_cmp(hstore,hstore)
-RETURNS integer
-AS 'MODULE_PATHNAME','hstore_cmp'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE OPERATOR = (
- LEFTARG = hstore,
- RIGHTARG = hstore,
- PROCEDURE = hstore_eq,
- COMMUTATOR = =,
- NEGATOR = <>,
- RESTRICT = eqsel,
- JOIN = eqjoinsel,
- MERGES,
- HASHES
-);
-CREATE OPERATOR <> (
- LEFTARG = hstore,
- RIGHTARG = hstore,
- PROCEDURE = hstore_ne,
- COMMUTATOR = <>,
- NEGATOR = =,
- RESTRICT = neqsel,
- JOIN = neqjoinsel
-);
-
--- the comparison operators have funky names (and are undocumented)
--- in an attempt to discourage anyone from actually using them. they
--- only exist to support the btree opclass
-
-CREATE OPERATOR #<# (
- LEFTARG = hstore,
- RIGHTARG = hstore,
- PROCEDURE = hstore_lt,
- COMMUTATOR = #>#,
- NEGATOR = #>=#,
- RESTRICT = scalarltsel,
- JOIN = scalarltjoinsel
-);
-CREATE OPERATOR #<=# (
- LEFTARG = hstore,
- RIGHTARG = hstore,
- PROCEDURE = hstore_le,
- COMMUTATOR = #>=#,
- NEGATOR = #>#,
- RESTRICT = scalarltsel,
- JOIN = scalarltjoinsel
-);
-CREATE OPERATOR #># (
- LEFTARG = hstore,
- RIGHTARG = hstore,
- PROCEDURE = hstore_gt,
- COMMUTATOR = #<#,
- NEGATOR = #<=#,
- RESTRICT = scalargtsel,
- JOIN = scalargtjoinsel
-);
-CREATE OPERATOR #>=# (
- LEFTARG = hstore,
- RIGHTARG = hstore,
- PROCEDURE = hstore_ge,
- COMMUTATOR = #<=#,
- NEGATOR = #<#,
- RESTRICT = scalargtsel,
- JOIN = scalargtjoinsel
-);
-
-CREATE OPERATOR CLASS btree_hstore_ops
-DEFAULT FOR TYPE hstore USING btree
-AS
- OPERATOR 1 #<# ,
- OPERATOR 2 #<=# ,
- OPERATOR 3 = ,
- OPERATOR 4 #>=# ,
- OPERATOR 5 #># ,
- FUNCTION 1 hstore_cmp(hstore,hstore);
-
--- hash support
-
-CREATE FUNCTION hstore_hash(hstore)
-RETURNS integer
-AS 'MODULE_PATHNAME','hstore_hash'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE OPERATOR CLASS hash_hstore_ops
-DEFAULT FOR TYPE hstore USING hash
-AS
- OPERATOR 1 = ,
- FUNCTION 1 hstore_hash(hstore);
-
--- GiST support
-
-CREATE TYPE ghstore;
-
-CREATE FUNCTION ghstore_in(cstring)
-RETURNS ghstore
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION ghstore_out(ghstore)
-RETURNS cstring
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE TYPE ghstore (
- INTERNALLENGTH = -1,
- INPUT = ghstore_in,
- OUTPUT = ghstore_out
-);
-
-CREATE FUNCTION ghstore_compress(internal)
-RETURNS internal
-AS 'MODULE_PATHNAME'
-LANGUAGE C IMMUTABLE STRICT;
-
-CREATE FUNCTION ghstore_decompress(internal)
-RETURNS internal
-AS 'MODULE_PATHNAME'
-LANGUAGE C IMMUTABLE STRICT;
-
-CREATE FUNCTION ghstore_penalty(internal,internal,internal)
-RETURNS internal
-AS 'MODULE_PATHNAME'
-LANGUAGE C IMMUTABLE STRICT;
-
-CREATE FUNCTION ghstore_picksplit(internal, internal)
-RETURNS internal
-AS 'MODULE_PATHNAME'
-LANGUAGE C IMMUTABLE STRICT;
-
-CREATE FUNCTION ghstore_union(internal, internal)
-RETURNS internal
-AS 'MODULE_PATHNAME'
-LANGUAGE C IMMUTABLE STRICT;
-
-CREATE FUNCTION ghstore_same(internal, internal, internal)
-RETURNS internal
-AS 'MODULE_PATHNAME'
-LANGUAGE C IMMUTABLE STRICT;
-
-CREATE FUNCTION ghstore_consistent(internal,internal,int,oid,internal)
-RETURNS bool
-AS 'MODULE_PATHNAME'
-LANGUAGE C IMMUTABLE STRICT;
-
-CREATE OPERATOR CLASS gist_hstore_ops
-DEFAULT FOR TYPE hstore USING gist
-AS
- OPERATOR 7 @> ,
- OPERATOR 9 ?(hstore,text) ,
- OPERATOR 10 ?|(hstore,text[]) ,
- OPERATOR 11 ?&(hstore,text[]) ,
- --OPERATOR 8 <@ ,
- OPERATOR 13 @ ,
- --OPERATOR 14 ~ ,
- FUNCTION 1 ghstore_consistent (internal, internal, int, oid, internal),
- FUNCTION 2 ghstore_union (internal, internal),
- FUNCTION 3 ghstore_compress (internal),
- FUNCTION 4 ghstore_decompress (internal),
- FUNCTION 5 ghstore_penalty (internal, internal, internal),
- FUNCTION 6 ghstore_picksplit (internal, internal),
- FUNCTION 7 ghstore_same (internal, internal, internal),
- STORAGE ghstore;
-
--- GIN support
-
-CREATE FUNCTION gin_extract_hstore(internal, internal)
-RETURNS internal
-AS 'MODULE_PATHNAME'
-LANGUAGE C IMMUTABLE STRICT;
-
-CREATE FUNCTION gin_extract_hstore_query(internal, internal, int2, internal, internal)
-RETURNS internal
-AS 'MODULE_PATHNAME'
-LANGUAGE C IMMUTABLE STRICT;
-
-CREATE FUNCTION gin_consistent_hstore(internal, int2, internal, int4, internal, internal)
-RETURNS bool
-AS 'MODULE_PATHNAME'
-LANGUAGE C IMMUTABLE STRICT;
-
-CREATE OPERATOR CLASS gin_hstore_ops
-DEFAULT FOR TYPE hstore USING gin
-AS
- OPERATOR 7 @>,
- OPERATOR 9 ?(hstore,text),
- OPERATOR 10 ?|(hstore,text[]),
- OPERATOR 11 ?&(hstore,text[]),
- FUNCTION 1 bttextcmp(text,text),
- FUNCTION 2 gin_extract_hstore(internal, internal),
- FUNCTION 3 gin_extract_hstore_query(internal, internal, int2, internal, internal),
- FUNCTION 4 gin_consistent_hstore(internal, int2, internal, int4, internal, internal),
- STORAGE text;
diff --git a/contrib/hstore/hstore.control b/contrib/hstore/hstore.control
index 4104e17..0c49ade 100644
--- a/contrib/hstore/hstore.control
+++ b/contrib/hstore/hstore.control
@@ -1,5 +1,6 @@
# hstore extension
comment = 'data type for storing sets of (key, value) pairs'
default_version = '1.1'
+default_full_version = '1.0'
module_pathname = '$libdir/hstore'
relocatable = true
diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c
index 6ecbbc7..2fb1658 100644
--- a/src/backend/commands/extension.c
+++ b/src/backend/commands/extension.c
@@ -66,6 +66,7 @@ typedef struct ExtensionControlFile
char *name; /* name of the extension */
char *directory; /* directory for script files */
char *default_version; /* default install target version, if any */
+ char *default_full_version; /* default install source version, if any */
char *module_pathname; /* string to substitute for MODULE_PATHNAME */
char *comment; /* comment, if any */
char *schema; /* target schema (allowed if !relocatable) */
@@ -505,6 +506,10 @@ parse_extension_control_file(ExtensionControlFile *control,
control->default_version = pstrdup(item->value);
}
+ else if (strcmp(item->name, "default_full_version") == 0)
+ {
+ control->default_full_version = pstrdup(item->value);
+ }
else if (strcmp(item->name, "module_pathname") == 0)
{
control->module_pathname = pstrdup(item->value);
@@ -1288,9 +1293,15 @@ CreateExtension(CreateExtensionStmt *stmt)
* Determine the (unpackaged) version to update from, if any, and then
* figure out what sequence of update scripts we need to apply.
*/
- if (d_old_version && d_old_version->arg)
+ if ((d_old_version && d_old_version->arg) || pcontrol->default_full_version)
{
- oldVersionName = strVal(d_old_version->arg);
+ bool unpackaged = (d_old_version && d_old_version->arg);
+
+ if (unpackaged)
+ oldVersionName = strVal(d_old_version->arg);
+ else
+ oldVersionName = pcontrol->default_full_version;
+
check_valid_version_name(oldVersionName);
if (strcmp(oldVersionName, versionName) == 0)
@@ -1303,24 +1314,28 @@ CreateExtension(CreateExtensionStmt *stmt)
oldVersionName,
versionName);
- if (list_length(updateVersions) == 1)
- {
- /*
- * Simple case where there's just one update script to run. We
- * will not need any follow-on update steps.
- */
- Assert(strcmp((char *) linitial(updateVersions), versionName) == 0);
- updateVersions = NIL;
- }
- else
+ /* in the create from unpackaged case, redude the update list */
+ if (unpackaged)
{
- /*
- * Multi-step sequence. We treat this as installing the version
- * that is the target of the first script, followed by successive
- * updates to the later versions.
- */
- versionName = (char *) linitial(updateVersions);
- updateVersions = list_delete_first(updateVersions);
+ if (list_length(updateVersions) == 1)
+ {
+ /*
+ * Simple case where there's just one update script to run. We
+ * will not need any follow-on update steps.
+ */
+ Assert(strcmp((char *) linitial(updateVersions), versionName) == 0);
+ updateVersions = NIL;
+ }
+ else
+ {
+ /*
+ * Multi-step sequence. We treat this as installing the version
+ * that is the target of the first script, followed by successive
+ * updates to the later versions.
+ */
+ versionName = (char *) linitial(updateVersions);
+ updateVersions = list_delete_first(updateVersions);
+ }
}
}
else
@@ -1455,18 +1470,30 @@ CreateExtension(CreateExtensionStmt *stmt)
/*
* Execute the installation script file
- */
- execute_extension_script(extensionOid, control,
- oldVersionName, versionName,
- requiredSchemas,
- schemaName, schemaOid);
-
- /*
+ *
* If additional update scripts have to be executed, apply the updates as
* though a series of ALTER EXTENSION UPDATE commands were given
*/
- ApplyExtensionUpdates(extensionOid, pcontrol,
- versionName, updateVersions);
+ if (pcontrol->default_full_version)
+ {
+ execute_extension_script(extensionOid, control,
+ NULL, oldVersionName,
+ requiredSchemas,
+ schemaName, schemaOid);
+
+ ApplyExtensionUpdates(extensionOid, pcontrol,
+ oldVersionName, updateVersions);
+ }
+ else
+ {
+ execute_extension_script(extensionOid, control,
+ oldVersionName, versionName,
+ requiredSchemas,
+ schemaName, schemaOid);
+
+ ApplyExtensionUpdates(extensionOid, pcontrol,
+ versionName, updateVersions);
+ }
}
/*
--
Sent via pgsql-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers