Review: create extension default_full_version
Hi,
I looked at the discussion for this patch and the patch itself. Here
are my comments and observations about the patch.
What I got from the discussion is that the patch tries to implement a
mechanism to install extension from series of SQL scripts from
base/full version e.g. if a user wants to create an extension "1.1",
system should run v1.0 script followed by 1.0--1.1 script. In that
case we need to know about the base or full version which in the above
case is v1.0. So the patch added a defualt_full_version option in
extension control file.
Here are my comments about the patch
* Note: Patch does not apply cleanly on latest code base. You probably
need to re-base the code
ibrar@ibrar-laptop:~/work/postgresql$ patch -p1
<extension-default-full-version.v0.patch
patching file contrib/hstore/Makefile
Hunk #1 FAILED at 5.
1 out of 1 hunk FAILED -- saving rejects to file contrib/hstore/Makefile.rej
patching file contrib/hstore/hstore--1.1.sql
patching file contrib/hstore/hstore.control
patching file src/backend/commands/extension.c
Hunk #1 succeeded at 68 (offset 2 lines).
Hunk #2 succeeded at 508 (offset 2 lines).
Hunk #3 succeeded at 1295 (offset 2 lines).
Hunk #4 succeeded at 1316 (offset 2 lines).
Hunk #5 succeeded at 1473 (offset 3 lines).
* This is a user visible change so documentation change is required here.
* Also, You need to update the comment, because this code is now
handling default_full_version as well.
/*
* 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) || pcontrol->default_full_version)
* In case the "default_full_version" and VERSION in SQL are same then
we are getting a misleading error message i.e.
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
postgres=# create EXTENSION hstore version '1.0';
ERROR: FROM version must be different from installation target version "1.0"
Error message is complaining about "FROM" clause which is not used in
the query. I think EXTENSION creation should not be blocked in case
"default_full_version" and VERSION are same. But if we want to block
that; error message should be meaningful.
* I noticed another issue with the patch.
In case we do not specify the default_full_version in control file
then this is the sequence of sql scripts.
postgres=# CREATE EXTENSION hstore version '1.3' from '1.0';
WARNING: /usr/local/pgsql/share/extension/hstore--1.0--1.1.sql
WARNING: /usr/local/pgsql/share/extension/hstore--1.1--1.2.sql
WARNING: /usr/local/pgsql/share/extension/hstore--1.2--1.3.sql
CREATE EXTENSION
But in case default_full_version = 1.0, then we are getting "ERROR:
could not stat file..." error message.
postgres=# CREATE EXTENSION hstore version '1.3' from '1.0';
WARNING: SCRIPT = /usr/local/pgsql/share/extension/hstore--1.0.sql
WARNING: SCRIPT =
/usr/local/pgsql/share/extension/hstore--1.0--1.2.sql
<<--- Why not 1.0--1.1
ERROR: could not stat file
"/usr/local/pgsql/share/extension/hstore--1.0--1.2.sql": No such file
or directory
This is because of missing version number i.e. first we're executing
1.0 followed by 1.0--1.2 not 1.0--1.1 but I think following should be
the right sequence
postgres=# CREATE EXTENSION hstore version '1.3' from '1.0';
WARNING: /usr/local/pgsql/share/extension/hstore--1.0.sql
WARNING: /usr/local/pgsql/share/extension/hstore--1.0--1.1.sql
WARNING: /usr/local/pgsql/share/extension/hstore--1.1--1.2.sql
WARNING: /usr/local/pgsql/share/extension/hstore--1.2--1.3.sql
CREATE EXTENSION
PS: I modified the code to get this result.
- IMHO there should be an SQL option along with the default_full_version; like.
postgres=# create EXTENSION hstore VERSION '1.1' FULL_VERSION '1.0';
- hstore regression is also failing.
-----------
Ibrar Ahmed
Hi,
Thanks for your very good review!
Ibrar Ahmed <ibrar.ahmad@gmail.com> writes:
I looked at the discussion for this patch and the patch itself. Here
are my comments and observations about the patch.
What I got from the discussion is that the patch tries to implement a
mechanism to install extension from series of SQL scripts from
base/full version e.g. if a user wants to create an extension "1.1",
system should run v1.0 script followed by 1.0--1.1 script. In that
case we need to know about the base or full version which in the above
case is v1.0. So the patch added a defualt_full_version option in
extension control file.
Exactly, that was an idea from Robert and I implemented it quite
quickly. Too quickly as we can see from your testing report.
Here are my comments about the patch
* Note: Patch does not apply cleanly on latest code base. You probably
need to re-base the code
Done. The thing is that meanwhile another solution to the main problem
has been found: drop support for installing hstore 1.0. Attached patch
fixes the problem by reinstalling hstore--1.0.sql and re-enabling this
version, and removing the hstore--1.1.sql file now that it's enough to
just have hstore--1.0--1.1.sql to install directly (and by default) the
newer version.
I think we will have to decide about taking only the mechanism or both
the mechanism and the actual change for the hstore contrib.
* This is a user visible change so documentation change is required here.
Added coverage of the new parameter.
* Also, You need to update the comment, because this code is now
handling default_full_version as well./*
* 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) || pcontrol->default_full_version)
Done. I also fixed the bugs you reported here. Here's an edited version
of the new (fixed) output:
dim=# set client_min_messages to debug1;
dim=# create extension hstore version '1.0';
DEBUG: execute_extension_script: '/Users/dim/pgsql/ddl/share/extension/hstore--1.0.sql'
WARNING: => is deprecated as an operator name
CREATE EXTENSION
dim=# create extension hstore version '1.1';
DEBUG: execute_extension_script: '/Users/dim/pgsql/ddl/share/extension/hstore--1.0.sql'
WARNING: => is deprecated as an operator name
DEBUG: execute_extension_script: '/Users/dim/pgsql/ddl/share/extension/hstore--1.0--1.1.sql'
CREATE EXTENSION
dim=# create extension hstore;
DEBUG: execute_extension_script: '/Users/dim/pgsql/ddl/share/extension/hstore--1.0.sql'
WARNING: => is deprecated as an operator name
DETAIL: This name may be disallowed altogether in future versions of PostgreSQL.
DEBUG: execute_extension_script: '/Users/dim/pgsql/ddl/share/extension/hstore--1.0--1.1.sql'
CREATE EXTENSION
postgres=# CREATE EXTENSION hstore version '1.3' from '1.0';
WARNING: /usr/local/pgsql/share/extension/hstore--1.0--1.1.sql
WARNING: /usr/local/pgsql/share/extension/hstore--1.1--1.2.sql
WARNING: /usr/local/pgsql/share/extension/hstore--1.2--1.3.sql
CREATE EXTENSION
I liked your idea of extending the reporting about what files are used,
but of course we can't keep that at the WARNING level, so I made that
logging DEBUG1 in the attached patch.
postgres=# CREATE EXTENSION hstore version '1.3' from '1.0';
Please try that case again, I believe it's fixed in the attached.
- hstore regression is also failing.
That's because it doesn't cope anymore with the operator => warning, and
I left it this way because we have to decide about shipping hstore 1.0
once we have this patch in.
Regards,
--
Dimitri Fontaine
http://2ndQuadrant.fr PostgreSQL : Expertise, Formation et Support
Attachments:
extension-default-full-version.v1.patchtext/x-patchDownload
*** a/contrib/hstore/Makefile
--- b/contrib/hstore/Makefile
***************
*** 5,11 **** OBJS = hstore_io.o hstore_op.o hstore_gist.o hstore_gin.o hstore_compat.o \
crc32.o
EXTENSION = hstore
! DATA = hstore--1.1.sql hstore--1.0--1.1.sql hstore--unpackaged--1.0.sql
REGRESS = hstore
--- 5,11 ----
crc32.o
EXTENSION = hstore
! DATA = hstore--1.0.sql hstore--1.0--1.1.sql hstore--unpackaged--1.0.sql
REGRESS = hstore
*** /dev/null
--- b/contrib/hstore/hstore--1.0.sql
***************
*** 0 ****
--- 1,530 ----
+ /* contrib/hstore/hstore--1.0.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 OPERATOR => (
+ LEFTARG = text,
+ RIGHTARG = text,
+ PROCEDURE = hstore
+ );
+
+ 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;
*** a/contrib/hstore/hstore--1.1.sql
--- /dev/null
***************
*** 1,524 ****
- /* 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;
--- 0 ----
*** 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
*** a/doc/src/sgml/extend.sgml
--- b/doc/src/sgml/extend.sgml
***************
*** 423,428 ****
--- 423,443 ----
</varlistentry>
<varlistentry>
+ <term><varname>default_full_version</varname> (<type>string</type>)</term>
+ <listitem>
+ <para>
+ This option allows an extension author to avoid shiping all versions
+ scripts when shipping an extension. When a version is requested and
+ the matching script does not exist on disk,
+ set <replaceable>default_full_version</replaceable> to the first
+ script you still ship and PostgreSQL will apply the intermediate
+ upgrade script as per the <command>ALTER EXTENSION UPDATE</command>
+ command.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><varname>comment</varname> (<type>string</type>)</term>
<listitem>
<para>
*** a/src/backend/commands/extension.c
--- b/src/backend/commands/extension.c
***************
*** 68,73 **** typedef struct ExtensionControlFile
--- 68,74 ----
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) */
***************
*** 507,512 **** parse_extension_control_file(ExtensionControlFile *control,
--- 508,517 ----
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);
***************
*** 804,809 **** execute_extension_script(Oid extensionOid, ExtensionControlFile *control,
--- 809,816 ----
filename = get_extension_script_filename(control, from_version, version);
+ elog(DEBUG1, "execute_extension_script: '%s'", filename);
+
/*
* Force client_min_messages and log_min_messages to be at least WARNING,
* so that we won't spam the user with useless NOTICE messages from common
***************
*** 1289,1328 **** 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)
{
! oldVersionName = strVal(d_old_version->arg);
! check_valid_version_name(oldVersionName);
! if (strcmp(oldVersionName, versionName) == 0)
! ereport(ERROR,
! (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
! errmsg("FROM version must be different from installation target version \"%s\"",
! versionName)));
! updateVersions = identify_update_path(pcontrol,
! 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
{
! /*
! * 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
--- 1296,1370 ----
/*
* Determine the (unpackaged) version to update from, if any, and then
* figure out what sequence of update scripts we need to apply.
+ *
+ * When we have a default_full_version and the target is different from it,
+ * apply the same algorithm to find a sequence of updates. If the user did
+ * ask for a target version that happens to be the same as the
+ * default_full_version, just install that one directly.
*/
! if ((d_old_version && d_old_version->arg) || pcontrol->default_full_version)
{
! 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)
{
! if (unpackaged)
! {
! ereport(ERROR,
! (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
! errmsg("FROM version must be different from installation target version \"%s\"",
! versionName)));
! }
! else
! {
! /*
! * CREATE EXTENSION ... VERSION = default_full_version, just
! * pretend we don't have a default_full_version for the
! * remaining of the code here, as that's the behavior we want
! * to see happening.
! */
! pcontrol->default_full_version = NULL;
! oldVersionName = NULL;
! updateVersions = NIL;
! }
}
else
{
! /* oldVersionName != versionName */
! updateVersions = identify_update_path(pcontrol,
! oldVersionName,
! versionName);
! }
!
! /* in the create from unpackaged case, reduce the update list */
! if (unpackaged)
! {
! 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
***************
*** 1458,1475 **** 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);
}
/*
--- 1500,1529 ----
/*
* Execute the installation script file
! *
* If additional update scripts have to be executed, apply the updates as
* though a series of ALTER EXTENSION UPDATE commands were given
*/
! 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);
! }
}
/*
On Mon, Dec 3, 2012 at 11:05 PM, Dimitri Fontaine <dimitri@2ndquadrant.fr>wrote:
Hi,
Thanks for your very good review!
Ibrar Ahmed <ibrar.ahmad@gmail.com> writes:
I looked at the discussion for this patch and the patch itself. Here
are my comments and observations about the patch.
What I got from the discussion is that the patch tries to implement a
mechanism to install extension from series of SQL scripts from
base/full version e.g. if a user wants to create an extension "1.1",
system should run v1.0 script followed by 1.0--1.1 script. In that
case we need to know about the base or full version which in the above
case is v1.0. So the patch added a defualt_full_version option in
extension control file.Exactly, that was an idea from Robert and I implemented it quite
quickly. Too quickly as we can see from your testing report.Here are my comments about the patch
* Note: Patch does not apply cleanly on latest code base. You probably
need to re-base the codeDone. The thing is that meanwhile another solution to the main problem
has been found: drop support for installing hstore 1.0. Attached patch
fixes the problem by reinstalling hstore--1.0.sql and re-enabling this
version, and removing the hstore--1.1.sql file now that it's enough to
just have hstore--1.0--1.1.sql to install directly (and by default) the
newer version.I think we will have to decide about taking only the mechanism or both
the mechanism and the actual change for the hstore contrib.* This is a user visible change so documentation change is required here.
Added coverage of the new parameter.
* Also, You need to update the comment, because this code is now
handling default_full_version as well./*
* Determine the (unpackaged) version to update from, if any, andthen
* figure out what sequence of update scripts we need to apply.
*/
if ((d_old_version && d_old_version->arg) ||pcontrol->default_full_version)
Done. I also fixed the bugs you reported here. Here's an edited version
of the new (fixed) output:dim=# set client_min_messages to debug1;
dim=# create extension hstore version '1.0';
DEBUG: execute_extension_script:
'/Users/dim/pgsql/ddl/share/extension/hstore--1.0.sql'
WARNING: => is deprecated as an operator name
CREATE EXTENSIONdim=# create extension hstore version '1.1';
DEBUG: execute_extension_script:
'/Users/dim/pgsql/ddl/share/extension/hstore--1.0.sql'
WARNING: => is deprecated as an operator name
DEBUG: execute_extension_script:
'/Users/dim/pgsql/ddl/share/extension/hstore--1.0--1.1.sql'
CREATE EXTENSIONdim=# create extension hstore;
DEBUG: execute_extension_script:
'/Users/dim/pgsql/ddl/share/extension/hstore--1.0.sql'
WARNING: => is deprecated as an operator name
DETAIL: This name may be disallowed altogether in future versions of
PostgreSQL.
DEBUG: execute_extension_script:
'/Users/dim/pgsql/ddl/share/extension/hstore--1.0--1.1.sql'
CREATE EXTENSIONpostgres=# CREATE EXTENSION hstore version '1.3' from '1.0';
WARNING: /usr/local/pgsql/share/extension/hstore--1.0--1.1.sql
WARNING: /usr/local/pgsql/share/extension/hstore--1.1--1.2.sql
WARNING: /usr/local/pgsql/share/extension/hstore--1.2--1.3.sql
CREATE EXTENSIONI liked your idea of extending the reporting about what files are used,
but of course we can't keep that at the WARNING level, so I made that
logging DEBUG1 in the attached patch.postgres=# CREATE EXTENSION hstore version '1.3' from '1.0';
Please try that case again, I believe it's fixed in the attached.
I am still getting the same error message.
Without default_full_version
----------------------------------------
postgres=# CREATE EXTENSION hstore version '1.3' from '1.1';
DEBUG: execute_extension_script:
'/usr/local/pgsql/share/extension/hstore--1.1--1.2.sql'
DEBUG: execute_extension_script:
'/usr/local/pgsql/share/extension/hstore--1.2--1.3.sql'
CREATE EXTENSION
With default_full_version = '1.1'
--------------------------------------------
postgres=# CREATE EXTENSION hstore version '1.3' from '1.1';
DEBUG: execute_extension_script:
'/usr/local/pgsql/share/extension/hstore--1.1.sql'
DEBUG: execute_extension_script:
'/usr/local/pgsql/share/extension/hstore--1.1--1.3.sql'
*ERROR: could not stat file
"/usr/local/pgsql/share/extension/hstore--1.1--1.3.sql": No such file or
directory*
I think there is an issue in this area of the code
if (pcontrol->default_full_version)
{
execute_extension_script(extensionOid, control,
<<-- 1.1.sql
NULL, oldVersionName,
requiredSchemas,
schemaName, schemaOid);
ApplyExtensionUpdates(extensionOid, pcontrol,
<<-- 1.1--1.3.sql (wrong)
oldVersionName, updateVersions);
The first statement is executing "1.1.sql" because oldVersionName = "1.1".
Keep in mind that versionName = "1.2" and updateVersions list contain only
version name "1.3". So in case of default_full_version you are ignoring *
versionName* which is *"1.2"* that is causing this error message
*
*
*ERROR: could not stat file
"/usr/local/pgsql/share/extension/hstore--1.1--1.3.sql": No such file or
directory*
- hstore regression is also failing.
That's because it doesn't cope anymore with the operator => warning, and
I left it this way because we have to decide about shipping hstore 1.0
once we have this patch in.Regards,
--
Dimitri Fontaine
http://2ndQuadrant.fr PostgreSQL : Expertise, Formation et Support
--
Ibrar Ahmed
EnterpriseDB http://www.enterprisedb.com
Ibrar Ahmed <ibrar.ahmad@gmail.com> writes:
I am still getting the same error message.
With the attached patch (v2), it works well:
create extension hstore version '1.2' from 'unpackaged';
DEBUG: execute_extension_script: '/Users/dim/pgsql/ddl/share/extension/hstore--unpackaged--1.0.sql'
DEBUG: execute_extension_script: '/Users/dim/pgsql/ddl/share/extension/hstore--1.0--1.1.sql'
DEBUG: execute_extension_script: '/Users/dim/pgsql/ddl/share/extension/hstore--1.1--1.2.sql'
CREATE EXTENSION
You have to remember that the spelling FROM 'unpackaged version' really
means that we have previously installed a "loose" version of the
extension (just \i hstore.sql) and want to apply the upgrade path from
there.
We can't have FROM meaning the same thing as default_full_version.
With default_full_version = '1.1'
--------------------------------------------
postgres=# CREATE EXTENSION hstore version '1.3' from '1.1';
DEBUG: execute_extension_script:
'/usr/local/pgsql/share/extension/hstore--1.1.sql'
DEBUG: execute_extension_script:
'/usr/local/pgsql/share/extension/hstore--1.1--1.3.sql'
*ERROR: could not stat file
"/usr/local/pgsql/share/extension/hstore--1.1--1.3.sql": No such file or
directory*
That's nonetheless a bug and is fixed now:
- if (pcontrol->default_full_version)
+ if (pcontrol->default_full_version && !unpackaged)
See attached.
Regards,
--
Dimitri Fontaine
http://2ndQuadrant.fr PostgreSQL : Expertise, Formation et Support
Attachments:
extension-default-full-version.v2.patchtext/x-patchDownload
*** a/contrib/hstore/Makefile
--- b/contrib/hstore/Makefile
***************
*** 5,11 **** OBJS = hstore_io.o hstore_op.o hstore_gist.o hstore_gin.o hstore_compat.o \
crc32.o
EXTENSION = hstore
! DATA = hstore--1.1.sql hstore--1.0--1.1.sql hstore--unpackaged--1.0.sql
REGRESS = hstore
--- 5,11 ----
crc32.o
EXTENSION = hstore
! DATA = hstore--1.0.sql hstore--1.0--1.1.sql hstore--unpackaged--1.0.sql
REGRESS = hstore
*** /dev/null
--- b/contrib/hstore/hstore--1.0.sql
***************
*** 0 ****
--- 1,530 ----
+ /* contrib/hstore/hstore--1.0.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 OPERATOR => (
+ LEFTARG = text,
+ RIGHTARG = text,
+ PROCEDURE = hstore
+ );
+
+ 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;
*** a/contrib/hstore/hstore--1.1.sql
--- /dev/null
***************
*** 1,524 ****
- /* 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;
--- 0 ----
*** 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
*** a/doc/src/sgml/extend.sgml
--- b/doc/src/sgml/extend.sgml
***************
*** 423,428 ****
--- 423,443 ----
</varlistentry>
<varlistentry>
+ <term><varname>default_full_version</varname> (<type>string</type>)</term>
+ <listitem>
+ <para>
+ This option allows an extension author to avoid shiping all versions
+ scripts when shipping an extension. When a version is requested and
+ the matching script does not exist on disk,
+ set <replaceable>default_full_version</replaceable> to the first
+ script you still ship and PostgreSQL will apply the intermediate
+ upgrade script as per the <command>ALTER EXTENSION UPDATE</command>
+ command.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><varname>comment</varname> (<type>string</type>)</term>
<listitem>
<para>
*** a/src/backend/commands/extension.c
--- b/src/backend/commands/extension.c
***************
*** 68,73 **** typedef struct ExtensionControlFile
--- 68,74 ----
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) */
***************
*** 507,512 **** parse_extension_control_file(ExtensionControlFile *control,
--- 508,517 ----
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);
***************
*** 804,809 **** execute_extension_script(Oid extensionOid, ExtensionControlFile *control,
--- 809,816 ----
filename = get_extension_script_filename(control, from_version, version);
+ elog(DEBUG1, "execute_extension_script: '%s'", filename);
+
/*
* Force client_min_messages and log_min_messages to be at least WARNING,
* so that we won't spam the user with useless NOTICE messages from common
***************
*** 1192,1197 **** CreateExtension(CreateExtensionStmt *stmt)
--- 1199,1205 ----
List *requiredSchemas;
Oid extensionOid;
ListCell *lc;
+ bool unpackaged = false;
/* Check extension name validity before any filesystem access */
check_valid_extension_name(stmt->extname);
***************
*** 1289,1328 **** 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)
{
! oldVersionName = strVal(d_old_version->arg);
! check_valid_version_name(oldVersionName);
! if (strcmp(oldVersionName, versionName) == 0)
! ereport(ERROR,
! (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
! errmsg("FROM version must be different from installation target version \"%s\"",
! versionName)));
! updateVersions = identify_update_path(pcontrol,
! 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
{
! /*
! * 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
--- 1297,1371 ----
/*
* Determine the (unpackaged) version to update from, if any, and then
* figure out what sequence of update scripts we need to apply.
+ *
+ * When we have a default_full_version and the target is different from it,
+ * apply the same algorithm to find a sequence of updates. If the user did
+ * ask for a target version that happens to be the same as the
+ * default_full_version, just install that one directly.
*/
! if ((d_old_version && d_old_version->arg) || pcontrol->default_full_version)
{
! 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)
{
! if (unpackaged)
! {
! ereport(ERROR,
! (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
! errmsg("FROM version must be different from installation target version \"%s\"",
! versionName)));
! }
! else
! {
! /*
! * CREATE EXTENSION ... VERSION = default_full_version, just
! * pretend we don't have a default_full_version for the
! * remaining of the code here, as that's the behavior we want
! * to see happening.
! */
! pcontrol->default_full_version = NULL;
! oldVersionName = NULL;
! updateVersions = NIL;
! }
}
else
{
! /* oldVersionName != versionName */
! updateVersions = identify_update_path(pcontrol,
! oldVersionName,
! versionName);
! }
!
! /* in the create from unpackaged case, reduce the update list */
! if (unpackaged)
! {
! 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
***************
*** 1458,1475 **** 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);
}
/*
--- 1501,1530 ----
/*
* Execute the installation script file
! *
* If additional update scripts have to be executed, apply the updates as
* though a series of ALTER EXTENSION UPDATE commands were given
*/
! if (pcontrol->default_full_version && !unpackaged)
! {
! 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);
! }
}
/*
On Tue, Dec 4, 2012 at 7:54 PM, Dimitri Fontaine <dimitri@2ndquadrant.fr>wrote:
Ibrar Ahmed <ibrar.ahmad@gmail.com> writes:
I am still getting the same error message.
With the attached patch (v2), it works well:
create extension hstore version '1.2' from 'unpackaged';
DEBUG: execute_extension_script:
'/Users/dim/pgsql/ddl/share/extension/hstore--unpackaged--1.0.sql'
DEBUG: execute_extension_script:
'/Users/dim/pgsql/ddl/share/extension/hstore--1.0--1.1.sql'
DEBUG: execute_extension_script:
'/Users/dim/pgsql/ddl/share/extension/hstore--1.1--1.2.sql'
CREATE EXTENSIONYou have to remember that the spelling FROM 'unpackaged version' really
means that we have previously installed a "loose" version of the
extension (just \i hstore.sql) and want to apply the upgrade path from
there.We can't have FROM meaning the same thing as default_full_version.
I know.
With default_full_version = '1.1'
--------------------------------------------
postgres=# CREATE EXTENSION hstore version '1.3' from '1.1';
DEBUG: execute_extension_script:
'/usr/local/pgsql/share/extension/hstore--1.1.sql'
DEBUG: execute_extension_script:
'/usr/local/pgsql/share/extension/hstore--1.1--1.3.sql'
*ERROR: could not stat file
"/usr/local/pgsql/share/extension/hstore--1.1--1.3.sql": No such file or
directory*That's nonetheless a bug and is fixed now:
- if (pcontrol->default_full_version) + if (pcontrol->default_full_version && !unpackaged)Thanks, I will look at this again in detail.
See attached.
Regards,
--
Dimitri Fontaine
http://2ndQuadrant.fr PostgreSQL : Expertise, Formation et Support
--
Ibrar Ahmed
EnterpriseDB http://www.enterprisedb.com
Now it works in most of the cases, here is one more point about the patch.
* In case we have hstore--1.3.sql file and want to install that file, but
failed because of default_full_version.
No default_full_version specified
-----------------------------------------------
postgres=# CREATE EXTENSION hstore version '1.3';
CREATE EXTENSION
default_full_version = 1.2
------------------------------------
postgres=# CREATE EXTENSION hstore version '1.3';
ERROR: could not stat file
"/usr/local/pgsql/share/extension/hstore--1.2.sql": No such file or
directory
If we don't want to address this issue at least we should give some
meaningful error message.
On Tue, Dec 4, 2012 at 4:46 PM, Ibrar Ahmed <ibrar.ahmad@gmail.com> wrote:
On Tue, Dec 4, 2012 at 7:54 PM, Dimitri Fontaine <dimitri@2ndquadrant.fr>wrote:
Ibrar Ahmed <ibrar.ahmad@gmail.com> writes:
I am still getting the same error message.
With the attached patch (v2), it works well:
create extension hstore version '1.2' from 'unpackaged';
DEBUG: execute_extension_script:
'/Users/dim/pgsql/ddl/share/extension/hstore--unpackaged--1.0.sql'
DEBUG: execute_extension_script:
'/Users/dim/pgsql/ddl/share/extension/hstore--1.0--1.1.sql'
DEBUG: execute_extension_script:
'/Users/dim/pgsql/ddl/share/extension/hstore--1.1--1.2.sql'
CREATE EXTENSIONYou have to remember that the spelling FROM 'unpackaged version' really
means that we have previously installed a "loose" version of the
extension (just \i hstore.sql) and want to apply the upgrade path from
there.We can't have FROM meaning the same thing as default_full_version.
I know.
With default_full_version = '1.1'
--------------------------------------------
postgres=# CREATE EXTENSION hstore version '1.3' from '1.1';
DEBUG: execute_extension_script:
'/usr/local/pgsql/share/extension/hstore--1.1.sql'
DEBUG: execute_extension_script:
'/usr/local/pgsql/share/extension/hstore--1.1--1.3.sql'
*ERROR: could not stat file
"/usr/local/pgsql/share/extension/hstore--1.1--1.3.sql": No such file or
directory*That's nonetheless a bug and is fixed now:
- if (pcontrol->default_full_version) + if (pcontrol->default_full_version && !unpackaged)Thanks, I will look at this again in detail.
See attached.
Regards,
--
Dimitri Fontaine
http://2ndQuadrant.fr PostgreSQL : Expertise, Formation et Support--
Ibrar Ahmed
EnterpriseDB http://www.enterprisedb.com
--
Ibrar Ahmed
EnterpriseDB http://www.enterprisedb.com
Ibrar Ahmed <ibrar.ahmad@gmail.com> writes:
* In case we have hstore--1.3.sql file and want to install that file, but
failed because of default_full_version.
That's now fixed, please see the Extension Templates patch at
/messages/by-id/m21uc8l4j8.fsf@2ndQuadrant.fr
Where you will even find regression tests for that problem.
Regards,
--
Dimitri Fontaine
http://2ndQuadrant.fr PostgreSQL : Expertise, Formation et Support
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers