Extensions support for pg_dump, patch v27

Started by Dimitri Fontainealmost 15 years ago41 messages
#1Dimitri Fontaine
dimitri@2ndQuadrant.fr
1 attachment(s)

Hi,

Following recent commit of the hstore Makefile cleaning, that I included
into my extension patch too, I have a nice occasion to push version 27
of the patch. Please find it enclosed. This time I'm not including the
contrib-only and doc-src split versions, just ask for them if that's
what you need.

Of course you can also use my git repository:

http://git.postgresql.org/gitweb?p=postgresql-extension.git;a=shortlog;h=refs/heads/extension

Regards,
--
Dimitri Fontaine
http://2ndQuadrant.fr PostgreSQL : Expertise, Formation et Support

Attachments:

extension.v27.patch.gzapplication/octet-streamDownload
#2Itagaki Takahiro
itagaki.takahiro@gmail.com
In reply to: Dimitri Fontaine (#1)
Re: Extensions support for pg_dump, patch v27

On Mon, Jan 24, 2011 at 18:22, Dimitri Fontaine <dimitri@2ndquadrant.fr> wrote:

Following recent commit of the hstore Makefile cleaning, that I included
into my extension patch too, I have a nice occasion to push version 27
of the patch.  Please find it enclosed.

Hi, I read the patch and test it in some degree. It works as expected
generally, but still needs a bit more development in edge case.

* commands/extension.h needs cleanup.
- Missing "extern" declarations for create_extension and
create_extension_with_user_data variables.
- ExtensionControlFile and ExtensionList can be hidden from the header.
- extension_objects_fctx is not used at all.

* There are many recordDependencyOn(&myself, &CreateExtensionAddress, ...)
in some places, but I'm not sure we forget something -- TRIGGERs?

* Will we still need uninstaller scripts?
DROP EXTENSION depends on object dependency to drop objects,
but we have a few configurations that cannot be described in the
dependency. For example, rows inserted into pg_am for user AMs
or reverting default settings modified by the extension.

* Extensions installed in pg_catalog:
If we install an extension into pg_catalog,
CREATE EXTENSION xxx WITH SCHEMA pg_catalog
pg_dump dumps nothing about the extension. We might need special care
for modules that install functions only in pg_catalog.

* I can install all extensions successfully, but there is a warning
in hstore. The warning was not reported to the client, but the whole
contents of hstore.sql.in was recorded in the server log.

WARNING: => is deprecated as an operator name

We sets client_min_messages for the issue in hstore.sql.in, but I think
we also need an additional "SET log_min_messages TO ERROR" around it.

* Is it support nested CREATE EXTENSION calls?
It's rare case, but we'd have some error checks for it.

* It passes all regression test for both backend and contrib modules,
but there are a couple of warnings during build and installation.

Three compiler warnings found. Please check.
pg_proc.c: In function 'ProcedureCreate':
pg_proc.c:110:8: warning: 'extensionOid' may be used uninitialized in
this function
pg_shdepend.c: In function 'shdepReassignOwned':
pg_shdepend.c:1335:6: warning: implicit declaration of function
'AlterOperatorOwner_oid'
operatorcmds.c:369:1: warning: no previous prototype for
'AlterOperatorOwner_oid'

* Five warnings also found during make install in contrib directory.
../../config/install-sh: ./uninstall_btree_gist.sql does not exist.
../../config/install-sh: ./uninstall_pageinspect.sql does not exist.
../../config/install-sh: ./uninstall_pgcrypto.sql does not exist.
../../config/install-sh: ./uninstall_pgrowlocks.sql does not exist.
../../config/install-sh: ./uninstall_pgstattuple.sql does not exist.

* You use "const = expr" in some places, ex. if( InvalidOid != ...),
but we seem to prefer "expr = const".

* [off topic] I found some installer scripts are inconsistent.
They uses CREATE FUNCTION for some of functions, but CREATE OR REPLACE
FUNCTION for others. We'd better write documentation about how to write
installer scripts because CREATE EXTENSION has some implicit assumptions
in them. For example, "Don't use transaction", etc.

--
Itagaki Takahiro

#3Dimitri Fontaine
dimitri@2ndQuadrant.fr
In reply to: Itagaki Takahiro (#2)
Re: Extensions support for pg_dump, patch v27

Hi,

Itagaki Takahiro <itagaki.takahiro@gmail.com> writes:

Hi, I read the patch and test it in some degree. It works as expected
generally, but still needs a bit more development in edge case.

Thanks for the review!

* commands/extension.h needs cleanup.
- Missing "extern" declarations for create_extension and
create_extension_with_user_data variables.
- ExtensionControlFile and ExtensionList can be hidden from the header.
- extension_objects_fctx is not used at all.

Fixed in git. I'm not yet used to the project style where we declare
some structures into the c code rather than the headers… and then it's
cleanup.

* There are many recordDependencyOn(&myself, &CreateExtensionAddress, ...)
in some places, but I'm not sure we forget something -- TRIGGERs?

I think we're good here. The extensions I know that use triggers are
installing the functions, it's still the user who CREATE TRIGGER and
uses the function. And even if we have an extension that contains some
CREATE TRIGGER commands in its script, the trigger will depend on a
function and the function on the extension.

If there's a use case for CREATE TRIGGER in an extension's script and
having the trigger not depend on another extension's object, like a
function, then I didn't see it. I'm ok to add the triggers as first
class dependency objects in the extension patch if there's a need…

* Will we still need uninstaller scripts?
DROP EXTENSION depends on object dependency to drop objects,
but we have a few configurations that cannot be described in the
dependency. For example, rows inserted into pg_am for user AMs
or reverting default settings modified by the extension.

Well I'm unconvinced by index AM extensions. Unfortunately, if you want
a crash safe AM, you need to patch core code, it's not an extension any
more. About reverting default settings, I'm not following.

What I saw is existing extensions that didn't need uninstall script once
you can DROP EXTENSION foo; but of course it would be quite easy to add
a parameter for that in the control file. Do we need it, though?

* Extensions installed in pg_catalog:
If we install an extension into pg_catalog,
CREATE EXTENSION xxx WITH SCHEMA pg_catalog
pg_dump dumps nothing about the extension. We might need special care
for modules that install functions only in pg_catalog.

I didn't spot that, I just didn't think about that use case. On a quick
test here it seems like the dependency is not recorded in this
case. Will fix.

* I can install all extensions successfully, but there is a warning
in hstore. The warning was not reported to the client, but the whole
contents of hstore.sql.in was recorded in the server log.

WARNING: => is deprecated as an operator name

We sets client_min_messages for the issue in hstore.sql.in, but I think
we also need an additional "SET log_min_messages TO ERROR" around it.

We can do that, but what's happening now is my understanding of the
consensus we reached on the list.

* Is it support nested CREATE EXTENSION calls?
It's rare case, but we'd have some error checks for it.

In fact earthdistance could CREATE EXTENSION cube; itself in its install
script. As you say, though, it's a rare case and it was agreed that
this feature could wait until a later version, so I didn't spend time on
it.

* It passes all regression test for both backend and contrib modules,
but there are a couple of warnings during build and installation.

Three compiler warnings found. Please check.
pg_proc.c: In function 'ProcedureCreate':
pg_proc.c:110:8: warning: 'extensionOid' may be used uninitialized in
this function
pg_shdepend.c: In function 'shdepReassignOwned':
pg_shdepend.c:1335:6: warning: implicit declaration of function
'AlterOperatorOwner_oid'
operatorcmds.c:369:1: warning: no previous prototype for
'AlterOperatorOwner_oid'

Oops sorry about that, I miss them too easily. What's the trick to turn
warnings into errors already please?

Fixed in the git repository.

* Five warnings also found during make install in contrib directory.
../../config/install-sh: ./uninstall_btree_gist.sql does not exist.
../../config/install-sh: ./uninstall_pageinspect.sql does not exist.
../../config/install-sh: ./uninstall_pgcrypto.sql does not exist.
../../config/install-sh: ./uninstall_pgrowlocks.sql does not exist.
../../config/install-sh: ./uninstall_pgstattuple.sql does not exist.

That's the DATA = uninstall_ lines in the Makefile. Removed in the git
repository. Cleared.

* You use "const = expr" in some places, ex. if( InvalidOid != ...),
but we seem to prefer "expr = const".

It allows to get a compiler error when you mistakenly use = rather than
== because the Left Hand Side is a constant, so I got used to writing
things this way. Should I review my patch and adapt? Will do after
some votes :)

* [off topic] I found some installer scripts are inconsistent.
They uses CREATE FUNCTION for some of functions, but CREATE OR REPLACE
FUNCTION for others. We'd better write documentation about how to write
installer scripts because CREATE EXTENSION has some implicit assumptions
in them. For example, "Don't use transaction", etc.

Will add some more documentation, ok. As far as contrib goes, I didn't
rework the install scripts.

Regards,
--
Dimitri Fontaine
http://2ndQuadrant.fr PostgreSQL : Expertise, Formation et Support

#4Dimitri Fontaine
dimitri@2ndQuadrant.fr
In reply to: Itagaki Takahiro (#2)
Re: Extensions support for pg_dump, patch v27

Itagaki Takahiro <itagaki.takahiro@gmail.com> writes:

* Extensions installed in pg_catalog:
If we install an extension into pg_catalog,
CREATE EXTENSION xxx WITH SCHEMA pg_catalog
pg_dump dumps nothing about the extension. We might need special care
for modules that install functions only in pg_catalog.

In src/backend/catalog/pg_depend.c we find the code for
recordDependencyOn() which is in fact in recordMultipleDependencies(),
and sayth so:

/*
* If the referenced object is pinned by the system, there's no real
* need to record dependencies on it. This saves lots of space in
* pg_depend, so it's worth the time taken to check.
*/

So I'm not sure about what we can do here other than error on using
pg_catalog in CREATE EXTENSION? How do we want to manage adminpack?

Other than adminpack, I think it makes sense to say that extensions are
not going into pg_catalog…

Regards,
--
Dimitri Fontaine
http://2ndQuadrant.fr PostgreSQL : Expertise, Formation et Support

#5David Fetter
david@fetter.org
In reply to: Dimitri Fontaine (#4)
Re: Extensions support for pg_dump, patch v27

On Tue, Jan 25, 2011 at 04:23:41PM +0100, Dimitri Fontaine wrote:

Itagaki Takahiro <itagaki.takahiro@gmail.com> writes:

* Extensions installed in pg_catalog:
If we install an extension into pg_catalog,
CREATE EXTENSION xxx WITH SCHEMA pg_catalog
pg_dump dumps nothing about the extension. We might need special care
for modules that install functions only in pg_catalog.

In src/backend/catalog/pg_depend.c we find the code for
recordDependencyOn() which is in fact in recordMultipleDependencies(),
and sayth so:

/*
* If the referenced object is pinned by the system, there's no real
* need to record dependencies on it. This saves lots of space in
* pg_depend, so it's worth the time taken to check.
*/

So I'm not sure about what we can do here other than error on using
pg_catalog in CREATE EXTENSION? How do we want to manage adminpack?

Other than adminpack, I think it makes sense to say that extensions
are not going into pg_catalog…

Given this, we should maybe see about either making adminpack part of
PostgreSQL's core distribution (probably a good idea) or moving it out
of pg_catalog so we don't have an exception to the rule.

Cheers,
David.
--
David Fetter <david@fetter.org> http://fetter.org/
Phone: +1 415 235 3778 AIM: dfetter666 Yahoo!: dfetter
Skype: davidfetter XMPP: david.fetter@gmail.com
iCal: webcal://www.tripit.com/feed/ical/people/david74/tripit.ics

Remember to vote!
Consider donating to Postgres: http://www.postgresql.org/about/donate

#6David E. Wheeler
david@kineticode.com
In reply to: David Fetter (#5)
Re: Extensions support for pg_dump, patch v27

On Jan 25, 2011, at 7:27 AM, David Fetter wrote:

Other than adminpack, I think it makes sense to say that extensions
are not going into pg_catalog…

Given this, we should maybe see about either making adminpack part of
PostgreSQL's core distribution (probably a good idea) or moving it out
of pg_catalog so we don't have an exception to the rule.

+1

David

#7Itagaki Takahiro
itagaki.takahiro@gmail.com
In reply to: David E. Wheeler (#6)
Re: Extensions support for pg_dump, patch v27

On Wed, Jan 26, 2011 at 02:57, David E. Wheeler <david@kineticode.com> wrote:

Other than adminpack, I think it makes sense to say that extensions
are not going into pg_catalog…

Given this, we should maybe see about either making adminpack part of
PostgreSQL's core distribution (probably a good idea) or moving it out
of pg_catalog so we don't have an exception to the rule.

+1

I doubt it can solve the real problem.
It is my understanding that we install them in pg_catalog because
they are designed to be installed in template1 for pgAdmin, right?

We have a problem in pg_dump when we install extension modules in
template1. If we create a database, installed functions are copied
from template1. However, they are also dumped with pg_dump unless
they are in pg_catalog. So, we encounter "function already exists"
errors when pg_restore.

Since pg_dump won't dump user objects in pg_catalog, adminpack can
avoid the above errors by installing functions in pg_catalog.
CREATE EXTENSION might have the same issue -- Can EXTENSION work
without errors when we install extensions in template databases?
To avoid errors, pg_dump might need to dump extensions as
"CREATE OR REPLACE EXTENSION" or "CREATE EXTENSION IF NOT EXISTS"
rather than "CREATE EXTENSION".

--
Itagaki Takahiro

#8Dimitri Fontaine
dimitri@2ndQuadrant.fr
In reply to: Itagaki Takahiro (#7)
Re: Extensions support for pg_dump, patch v27

Itagaki Takahiro <itagaki.takahiro@gmail.com> writes:

Since pg_dump won't dump user objects in pg_catalog, adminpack can
avoid the above errors by installing functions in pg_catalog.
CREATE EXTENSION might have the same issue -- Can EXTENSION work
without errors when we install extensions in template databases?

Well in fact the reason why pg_dump will not dump the extension when
it's installed in pg_catalog is that the pg_depend entry is not
recorded, and the SQL query pg_dump uses gets its data from pg_extension
JOIN pg_depend JOIN pg_namespace.

The missing entry in pg_depend is the reason why the extension is not
part of the dump. We could fix that using a LEFT JOIN here and COALESCE
to force the namespace as pg_catalog. Is that not a kludge? If
acceptable, I will do that next.

Regards,
--
Dimitri Fontaine
http://2ndQuadrant.fr PostgreSQL : Expertise, Formation et Support

#9Tom Lane
tgl@sss.pgh.pa.us
In reply to: Dimitri Fontaine (#8)
Re: Extensions support for pg_dump, patch v27

Dimitri Fontaine <dimitri@2ndQuadrant.fr> writes:

The missing entry in pg_depend is the reason why the extension is not
part of the dump. We could fix that using a LEFT JOIN here and COALESCE
to force the namespace as pg_catalog. Is that not a kludge?

Yes, it is. Why is the pg_depend entry missing?

regards, tom lane

#10Dimitri Fontaine
dimitri@2ndQuadrant.fr
In reply to: Tom Lane (#9)
Re: Extensions support for pg_dump, patch v27

Tom Lane <tgl@sss.pgh.pa.us> writes:

Dimitri Fontaine <dimitri@2ndQuadrant.fr> writes:

The missing entry in pg_depend is the reason why the extension is not
part of the dump. We could fix that using a LEFT JOIN here and COALESCE
to force the namespace as pg_catalog. Is that not a kludge?

Yes, it is. Why is the pg_depend entry missing?

See src/backend/catalog/pg_depend.c

/*
* If the referenced object is pinned by the system, there's no real
* need to record dependencies on it. This saves lots of space in
* pg_depend, so it's worth the time taken to check.
*/

Certainly, pg_catalog is pinned.

select *
from pg_depend
where refobjid = (select oid
from pg_namespace
where nspname = 'pg_catalog')
and refclassid = 'pg_namespace'::regclass;

classid | objid | objsubid | refclassid | refobjid | refobjsubid | deptype
---------+-------+----------+------------+----------+-------------+---------
0 | 0 | 0 | 2615 | 11 | 0 | p
(1 row)

Regards,
--
Dimitri Fontaine
http://2ndQuadrant.fr PostgreSQL : Expertise, Formation et Support

#11Tom Lane
tgl@sss.pgh.pa.us
In reply to: Dimitri Fontaine (#10)
Re: Extensions support for pg_dump, patch v27

Dimitri Fontaine <dimitri@2ndQuadrant.fr> writes:

Tom Lane <tgl@sss.pgh.pa.us> writes:

Dimitri Fontaine <dimitri@2ndQuadrant.fr> writes:

The missing entry in pg_depend is the reason why the extension is not
part of the dump. We could fix that using a LEFT JOIN here and COALESCE
to force the namespace as pg_catalog. Is that not a kludge?

Yes, it is. Why is the pg_depend entry missing?

See src/backend/catalog/pg_depend.c
Certainly, pg_catalog is pinned.

OK, so I guess I'm missing why the extension code is looking for stuff
dependent on the pg_catalog schema. That schema certainly doesn't
belong to any extension.

In any case, your proposed hack above is effectively assuming that
there's only one pinned schema, which is untrue now and is likely to
become even less true in the future. So I don't think we can go that way.

regards, tom lane

#12Dimitri Fontaine
dimitri@2ndQuadrant.fr
In reply to: Tom Lane (#11)
Re: Extensions support for pg_dump, patch v27

Tom Lane <tgl@sss.pgh.pa.us> writes:

OK, so I guess I'm missing why the extension code is looking for stuff
dependent on the pg_catalog schema. That schema certainly doesn't
belong to any extension.

Exactly. We're on the same page here, full agreement. So the extension
patch is not considering pg_catalog in any special way here, and the
problem comes from contrib/adminpack which installs its functions into
pg_catalog, yet is not part of core.

So in his tests, Itagaki was tempted to issue the following statement:

CREATE EXTENSION adminpack WITH SCHEMA pg_catalog;

That's supposed to register a dependency from the extension to its
declared hosting schema (adminpack is not relocatable so that entirely
depends on its script — which forces pg_catalog).

Then you get the same problems as with any other object that lives into
this schema, pg_dump will avoid dumping its definition…

In any case, your proposed hack above is effectively assuming that
there's only one pinned schema, which is untrue now and is likely to
become even less true in the future. So I don't think we can go that way.

Well I proposed is nothing more than a crock. What I'd like us to do
instead is ERRORing out when you want to use pg_catalog for an
extension.

We could use get_extension_namespace() just after recoding the
dependency and error out if we don't find the arguments we gave to
recordDependencyOn() so that we're not duplicating code. That will
cover any pinned schema. I'm preparing a patch to do that.

What do we want to do with adminpack? Including its functions into
core, or have it use another schema? I don't think an extension
installing its objects into pg_catalog is that good an idea…

Regards,
--
Dimitri Fontaine
http://2ndQuadrant.fr PostgreSQL : Expertise, Formation et Support

#13Tom Lane
tgl@sss.pgh.pa.us
In reply to: Dimitri Fontaine (#12)
Re: Extensions support for pg_dump, patch v27

Dimitri Fontaine <dimitri@2ndQuadrant.fr> writes:

So in his tests, Itagaki was tempted to issue the following statement:

CREATE EXTENSION adminpack WITH SCHEMA pg_catalog;

That's supposed to register a dependency from the extension to its
declared hosting schema (adminpack is not relocatable so that entirely
depends on its script - which forces pg_catalog).

Then you get the same problems as with any other object that lives into
this schema, pg_dump will avoid dumping its definition ...

Mph. Although such an extension should certainly carry a dependency on
the schema it's using, I'm not sure that it makes sense to consider that
the extension (as opposed to its contained objects) belongs to the
schema. If we think that extensions live inside schemas then it's
logically difficult for an extension to own objects scattered across
multiple schemas, which is surely a restriction we do not want. So I'd
have expected that extensions use unqualified names, like languages or
tablespaces. That being the case, there is no reason why pg_dump ought
to be making any such test.

There are places where pg_dump refuses to dump objects contained in
pg_catalog on the grounds that they're system objects, but that
heuristic ought not apply to extensions IMO, even if you don't agree
with the conclusion of the preceding paragraph. Any extension is, by
definition, not built-in.

Well I proposed is nothing more than a crock. What I'd like us to do
instead is ERRORing out when you want to use pg_catalog for an
extension.

Right offhand I'm not seeing the need for such a restriction, though
certainly I'd not cry a lot if we had to impose it. ISTM what we've got
here is some bogus what-to-dump rules in pg_dump. Extensions should
always be dumped.

What do we want to do with adminpack? Including its functions into
core, or have it use another schema? I don't think an extension
installing its objects into pg_catalog is that good an idea

I'm trying to avoid having an opinion on that. The reasons for it might
or might not be very good, but I'd rather that the extension mechanism
didn't break the ability for people to make such decisions.

regards, tom lane

#14Dimitri Fontaine
dimitri@2ndQuadrant.fr
In reply to: Dimitri Fontaine (#12)
Re: Extensions support for pg_dump, patch v27

Dimitri Fontaine <dimitri@2ndQuadrant.fr> writes:

We could use get_extension_namespace() just after recoding the
dependency and error out if we don't find the arguments we gave to
recordDependencyOn() so that we're not duplicating code. That will
cover any pinned schema. I'm preparing a patch to do that.

Kids are falling asleep and the patch there:

http://git.postgresql.org/gitweb?p=postgresql-extension.git;a=commitdiff;h=5d0834a8de54a52c601e4fd04aee2d19d1eef4c6

What do we want to do with adminpack? Including its functions into
core, or have it use another schema? I don't think an extension
installing its objects into pg_catalog is that good an idea…

As we're still waiting on some decision here, and some others in
previous mails of this same thread, I'm waiting some more before to
produce the next patch in the series. See

http://archives.postgresql.org/pgsql-hackers/2011-01/msg02385.php
http://archives.postgresql.org/pgsql-hackers/2011-01/msg02392.php

Of course the git repository is uptodate should you want to try the
newest code without waiting on me for the next patch release.

Regards,
--
Dimitri Fontaine
http://2ndQuadrant.fr PostgreSQL : Expertise, Formation et Support

#15Dimitri Fontaine
dimitri@2ndQuadrant.fr
In reply to: Tom Lane (#13)
Re: Extensions support for pg_dump, patch v27

Tom Lane <tgl@sss.pgh.pa.us> writes:

Mph. Although such an extension should certainly carry a dependency on
the schema it's using, I'm not sure that it makes sense to consider that
the extension (as opposed to its contained objects) belongs to the
schema. If we think that extensions live inside schemas then it's
logically difficult for an extension to own objects scattered across
multiple schemas, which is surely a restriction we do not want. So I'd
have expected that extensions use unqualified names, like languages or
tablespaces. That being the case, there is no reason why pg_dump ought
to be making any such test.

Well yes, extension are not living in a schema, we just offer users a
way to influence the script as far as where the extension's objects are
to be found and register a dependency so that it's easy to remember what
the users asked. So that for example we are able to act the same way on
pg_restore.

Now, pg_dump makes no such test already, but a query is using a JOIN to
list extensions and their target schema, where it's possible that the
target has not been recorded by recordDependencyOn(): in this case the
whole extension's is filtered out of the resultset. Quick and dirty
fix, I proposed to LEFT JOIN in the pg_dump query…

There are places where pg_dump refuses to dump objects contained in
pg_catalog on the grounds that they're system objects, but that
heuristic ought not apply to extensions IMO, even if you don't agree
with the conclusion of the preceding paragraph. Any extension is, by
definition, not built-in.

Agreed. The problem we're having here is how to implement all that yet
fully support adminpack. The design we're talking about is the same.

Well I proposed is nothing more than a crock. What I'd like us to do
instead is ERRORing out when you want to use pg_catalog for an
extension.

Right offhand I'm not seeing the need for such a restriction, though
certainly I'd not cry a lot if we had to impose it. ISTM what we've got
here is some bogus what-to-dump rules in pg_dump. Extensions should
always be dumped.

Agreed. Trying to solve an implementation detail, and that's the easier
way to prevent users from shooting themselves in the foot here.

What do we want to do with adminpack? Including its functions into
core, or have it use another schema? I don't think an extension
installing its objects into pg_catalog is that good an idea

I'm trying to avoid having an opinion on that. The reasons for it might
or might not be very good, but I'd rather that the extension mechanism
didn't break the ability for people to make such decisions.

You still can do one of the following commands, where you're not having
a say on the real schema that adminpack will use because it's not
relocatable and not paying attention to @extschema@, but apart from this
lie everything will just work. I'd be happy to ship with such a lie,
but I can see why people want something different.

CREATE EXTENSION adminpack;
CREATE EXTENSION adminpack WITH SCHEMA utils;

Regards,
--
Dimitri Fontaine
http://2ndQuadrant.fr PostgreSQL : Expertise, Formation et Support

#16Tom Lane
tgl@sss.pgh.pa.us
In reply to: Dimitri Fontaine (#15)
Re: Extensions support for pg_dump, patch v27

Dimitri Fontaine <dimitri@2ndQuadrant.fr> writes:

Tom Lane <tgl@sss.pgh.pa.us> writes:

Mph. Although such an extension should certainly carry a dependency on
the schema it's using, I'm not sure that it makes sense to consider that
the extension (as opposed to its contained objects) belongs to the
schema.

Well yes, extension are not living in a schema, we just offer users a
way to influence the script as far as where the extension's objects are
to be found and register a dependency so that it's easy to remember what
the users asked. So that for example we are able to act the same way on
pg_restore.

Oh: then you're doing it wrong. If you want to remember that WITH
SCHEMA was specified, you need to explicitly store that as another
column in pg_extension. You should not be depending on the dependency
mechanism to remember that for you, any more than we'd use pg_depend to
remember a table's relnamespace. The dependency mechanism is there
to figure out the consequences of a DROP command, it's not there to
remember arbitrary facts. (And yes, I know that we've cheated on that
principle a few times before; but you can't do it here.)

regards, tom lane

#17Dimitri Fontaine
dimitri@2ndQuadrant.fr
In reply to: Tom Lane (#16)
Re: Extensions support for pg_dump, patch v27

Tom Lane <tgl@sss.pgh.pa.us> writes:

Oh: then you're doing it wrong. If you want to remember that WITH
SCHEMA was specified, you need to explicitly store that as another
column in pg_extension. You should not be depending on the dependency
mechanism to remember that for you, any more than we'd use pg_depend to
remember a table's relnamespace. The dependency mechanism is there
to figure out the consequences of a DROP command, it's not there to
remember arbitrary facts. (And yes, I know that we've cheated on that
principle a few times before; but you can't do it here.)

The thinking is that we need to have the dependency registered too, so
that DROP SCHEMA will cascade to the extension. So while at it, I also
used the dependency for tracking the schema.

Even if I get to use a column to track the schema, I will have to
maintain registering the dependency. Should I do that?

Regards,
--
Dimitri Fontaine
http://2ndQuadrant.fr PostgreSQL : Expertise, Formation et Support

#18Dimitri Fontaine
dimitri@2ndQuadrant.fr
In reply to: Tom Lane (#16)
1 attachment(s)
Re: Extensions support for pg_dump, patch v27

Tom Lane <tgl@sss.pgh.pa.us> writes:

Oh: then you're doing it wrong. If you want to remember that WITH
SCHEMA was specified, you need to explicitly store that as another
column in pg_extension.

Ok, done. Of course, it solves the whole problem Itagaki had with
adminpack because we stop relying on dependencies to get it right now.

I've also added another parameter in the control file, named "schema".
It's only valid to use that when relocatable is false, and it allows to
force the schema where to install the extension. When this schema does
not already exists, it will be created for the user.

Of course the adminpack extension's control file now has relocatable =
false and schema = 'pg_catalog'.

~=# create extension lo;
CREATE EXTENSION
~=# create extension adminpack;
CREATE EXTENSION
~=# \dx
List of extensions
Schema | Name | Version | Description
------------+-----------+----------+-----------------------------------------
pg_catalog | adminpack | 9.1devel | Administrative functions for PostgreSQL
utils | lo | 9.1devel | managing Large Objects
(2 rows)

~=# drop extension adminpack;
DROP EXTENSION
~=# create extension adminpack with schema utils;
ERROR: this extension has to be installed in schema "pg_catalog"
~=# create extension adminpack with schema pg_catalog;
CREATE EXTENSION
~=# alter extension adminpack set schema utils;
ERROR: this extension does not support SET SCHEMA

The documentation is updated both in the patch and here:

http://pgsql.tapoueh.org/extensions/doc/html/extend-extension.html

Regards,
--
Dimitri Fontaine
http://2ndQuadrant.fr PostgreSQL : Expertise, Formation et Support

Attachments:

extension.v28.patch.gzapplication/octet-streamDownload
#19Itagaki Takahiro
itagaki.takahiro@gmail.com
In reply to: Dimitri Fontaine (#18)
Re: Extensions support for pg_dump, patch v27

On Thu, Jan 27, 2011 at 20:01, Dimitri Fontaine <dimitri@2ndquadrant.fr> wrote:

Ok, done.  Of course, it solves the whole problem Itagaki had with
adminpack because we stop relying on dependencies to get it right now.

I found pg_restore with -c option fails when an extension is created
in pg_catalog. Since pg_catalog is an implicit search target, so we
might need the catalog to search_path explicitly.
Note that I can restore adminpack with not errors because it has
explicit "pg_catalog." prefix in the installer script.

----
postgres=# CREATE EXTENSION cube WITH SCHEMA pg_catalog;
$ pg_dump -Fc postgres > postgres.dump
$ pg_restore -d postgres -c postgres.dump
pg_restore: [archiver (db)] Error while PROCESSING TOC:
pg_restore: [archiver (db)] Error from TOC entry 1; 3996 16678 EXTENSION cube
pg_restore: [archiver (db)] could not execute query: ERROR: no schema
has been selected to create in
----

BTW, I have a minor comments for the code.
extern bool extension_relocatable_p(Oid ext_oid);
What is "_p" ? Also, we could make the function static
because it is used only in extension.c.

--
Itagaki Takahiro

#20Dimitri Fontaine
dimitri@2ndQuadrant.fr
In reply to: Itagaki Takahiro (#19)
Re: Extensions support for pg_dump, patch v27

Itagaki Takahiro <itagaki.takahiro@gmail.com> writes:

I found pg_restore with -c option fails when an extension is created
in pg_catalog. Since pg_catalog is an implicit search target, so we
might need the catalog to search_path explicitly.
Note that I can restore adminpack with not errors because it has
explicit "pg_catalog." prefix in the installer script.

Nice catch, thank you very much (again) for finding those :)

Please find inline the patch I've just applied that fixes the issue by
managing the current search path and creation namespace before executing
the script, the same way that schemacmds.c does.

http://git.postgresql.org/gitweb?p=postgresql-extension.git;a=commitdiff;h=5c14c989426c0811e5bf8b993ae9a966fbf903c4

BTW, I have a minor comments for the code.
extern bool extension_relocatable_p(Oid ext_oid);
What is "_p" ? Also, we could make the function static
because it is used only in extension.c.

predicate. Maybe I've done too much Emacs Lisp coding at the time I
added that function, but it looked natural (enough) to me :)

Regards,
--
Dimitri Fontaine
http://2ndQuadrant.fr PostgreSQL : Expertise, Formation et Support

commit 5c14c989426c0811e5bf8b993ae9a966fbf903c4 (HEAD, refs/remotes/origin/extension, refs/heads/extension)
Author: Dimitri Fontaine <dim@tapoueh.org>
Date: Thu Jan 27 14:40:10 2011 +0100

Fully set the creation namespace before to execute the extenions's script.

	Modified src/backend/commands/extension.c
diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c
index 87310fb..4a8c757 100644
--- a/src/backend/commands/extension.c
+++ b/src/backend/commands/extension.c
@@ -415,6 +415,8 @@ execute_extension_script(ExtensionControlFile *control,
 	char       *filename = get_extension_absolute_path(control->script);
 	char       *old_cmsgs = NULL, *old_lmsgs = NULL; /* silence compiler */
 	bool        reset_cmsgs = false, reset_lmsgs = false;
+	Oid         target_schema;
+	OverrideSearchPath *overridePath;

/*
* Set create_extension and create_extension_with_user_data so that the
@@ -453,6 +455,21 @@ execute_extension_script(ExtensionControlFile *control,
SetConfigOption("log_min_messages", "warning", PGC_SUSET, PGC_S_SESSION);
}

+	if (control->relocatable)
+		target_schema = LookupCreationNamespace(schema);
+	else
+		target_schema = get_namespace_oid(schema, false);
+
+	/*
+	 * Temporarily make the new namespace be the front of the search path, as
+	 * well as the default creation target namespace.  This will be undone at
+	 * the end of this routine, or upon error.
+	 */
+	overridePath = GetOverrideSearchPath(CurrentMemoryContext);
+	overridePath->schemas = lcons_oid(target_schema, overridePath->schemas);
+	/* XXX should we clear overridePath->useTemp? */
+	PushOverrideSearchPath(overridePath);
+
 	/*
 	 * On failure, ensure that create_extension does not remain set.
 	 */
@@ -474,7 +491,8 @@ execute_extension_script(ExtensionControlFile *control,
 		if (control->relocatable)
 		{
 			List *search_path = fetch_search_path(false);
-			Oid   first_schema, target_schema;
+			Oid first_schema = linitial_oid(search_path);
+			list_free(search_path);
 			if (!execute_sql_string(sql))
 				ereport(ERROR,
@@ -495,10 +513,6 @@ execute_extension_script(ExtensionControlFile *control,
 			 * We skip this step if the target schema happens to be the
 			 * first schema of the current search_path.
 			 */
-			first_schema = linitial_oid(search_path);
-			target_schema = LookupCreationNamespace(schema);
-			list_free(search_path);
-
 			if (first_schema != target_schema)
 				AlterExtensionNamespace_oid(CreateExtensionAddress.objectId,
 											target_schema);
@@ -531,6 +545,9 @@ execute_extension_script(ExtensionControlFile *control,
 	}
 	PG_END_TRY();
+	/* Reset search path to normal state */
+	PopOverrideSearchPath();
+
 	if (reset_cmsgs)
 		SetConfigOption("client_min_messages",
 						old_cmsgs, PGC_SUSET, PGC_S_SESSION);
#21Itagaki Takahiro
itagaki.takahiro@gmail.com
In reply to: Dimitri Fontaine (#20)
1 attachment(s)
Re: Extensions support for pg_dump, patch v27

On Thu, Jan 27, 2011 at 22:48, Dimitri Fontaine <dimitri@2ndquadrant.fr> wrote:

Itagaki Takahiro <itagaki.takahiro@gmail.com> writes:

I found pg_restore with -c option fails when an extension is created
in pg_catalog.

Nice catch, thank you very much (again) for finding those :)

Seems good.

  extern bool extension_relocatable_p(Oid ext_oid);

predicate.  Maybe I've done too much Emacs Lisp coding at the time I
added that function, but it looked natural (enough) to me :)

Hmmm, I like extension_is_relocatable() or so...
Including the above, I wrote a patch on your patch for minor
cleanup. Please merge reasonable parts in it.

* access() is not portable.
The pre-checking with access() doesn't seems needed because
the same error will be raised in parse_extension_control_file().

* There are some dead code in the patch.
For example, you exported ObjectAddresses to public, but it is not
used in extension.c actually. I reverted some of changes.

* Should we support absolute control file paths?
Absolute paths are supported by get_extension_absolute_path(),
but I'm not sure actual use-cases.

* Each ereport(ERROR) should have a reasonable errcode unless
they are an internal logic error, and whether the error message
follows our guidline (starting with a lower case character, etc.)

* Changed create_extension_with_user_data to a static variable.
CreateExtensionAddress and create_extension are still exported.
We could have better names for them -- CurrentExtensionAddress
and in_create_extension? Or, in_create_extension might be
replaced with "CreateExtensionAddress.objectId != InvalidOid".

* Added psql tab completion for CREATE/DROP/ALTER EXTENSION.
* Use palloc0() instead of palloc() and memset(0).
* Several code cleanup.

--
Itagaki Takahiro

Attachments:

extension-diff-on.v28a.patchapplication/octet-stream; name=extension-diff-on.v28a.patchDownload
diff --git a/contrib/adminpack/adminpack.control b/contrib/adminpack/adminpack.control
index 5f4331d..79562b0 100644
*** a/contrib/adminpack/adminpack.control
--- b/contrib/adminpack/adminpack.control
***************
*** 2,5 ****
  comment = 'Administrative functions for PostgreSQL'
  version = '9.1devel'
  relocatable = false
! schema = 'pg_catalog'
\ No newline at end of file
--- 2,5 ----
  comment = 'Administrative functions for PostgreSQL'
  version = '9.1devel'
  relocatable = false
! schema = 'pg_catalog'
diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c
index ec463d3..f4bb6db 100644
*** a/src/backend/catalog/dependency.c
--- b/src/backend/catalog/dependency.c
***************
*** 79,84 ****
--- 79,113 ----
  #include "utils/tqual.h"
  
  
+ /*
+  * Deletion processing requires additional state for each ObjectAddress that
+  * it's planning to delete.  For simplicity and code-sharing we make the
+  * ObjectAddresses code support arrays with or without this extra state.
+  */
+ typedef struct
+ {
+ 	int			flags;			/* bitmask, see bit definitions below */
+ 	ObjectAddress dependee;		/* object whose deletion forced this one */
+ } ObjectAddressExtra;
+ 
+ /* ObjectAddressExtra flag bits */
+ #define DEPFLAG_ORIGINAL	0x0001		/* an original deletion target */
+ #define DEPFLAG_NORMAL		0x0002		/* reached via normal dependency */
+ #define DEPFLAG_AUTO		0x0004		/* reached via auto dependency */
+ #define DEPFLAG_INTERNAL	0x0008		/* reached via internal dependency */
+ 
+ 
+ /* expansible list of ObjectAddresses */
+ struct ObjectAddresses
+ {
+ 	ObjectAddress *refs;		/* => palloc'd array */
+ 	ObjectAddressExtra *extras; /* => palloc'd array, or NULL if not used */
+ 	int			numrefs;		/* current number of references */
+ 	int			maxrefs;		/* current size of palloc'd array(s) */
+ };
+ 
+ /* typedef ObjectAddresses appears in dependency.h */
+ 
  /* threaded list of ObjectAddresses, for recursion detection */
  typedef struct ObjectAddressStack
  {
*************** findDependentObjects(const ObjectAddress
*** 525,530 ****
--- 554,560 ----
  				/* no problem */
  				break;
  			case DEPENDENCY_INTERNAL:
+ 
  				/*
  				 * This object is part of the internal implementation of
  				 * another object.	We have four cases:
diff --git a/src/backend/catalog/pg_depend.c b/src/backend/catalog/pg_depend.c
index 4be6490..1810a71 100644
*** a/src/backend/catalog/pg_depend.c
--- b/src/backend/catalog/pg_depend.c
*************** changeDependencyTypeFor(Oid objid,
*** 328,334 ****
  	return count;
  }
  
- 
  /*
   * isObjectPinned()
   *
--- 328,333 ----
diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c
index d7d99d2..40bc2cb 100644
*** a/src/backend/catalog/pg_proc.c
--- b/src/backend/catalog/pg_proc.c
*************** ProcedureCreate(const char *procedureNam
*** 626,632 ****
  	{
  		recordDependencyOn(&myself, &CreateExtensionAddress, DEPENDENCY_INTERNAL);
  	}
! 	else if(is_update && OidIsValid(extensionOid))
  	{
  		/* we have to recreate the dependency to the known extension */
  		ObjectAddress extension;
--- 626,632 ----
  	{
  		recordDependencyOn(&myself, &CreateExtensionAddress, DEPENDENCY_INTERNAL);
  	}
! 	else if (is_update && OidIsValid(extensionOid))
  	{
  		/* we have to recreate the dependency to the known extension */
  		ObjectAddress extension;
diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c
index aaa08b0..7b791bf 100644
*** a/src/backend/commands/extension.c
--- b/src/backend/commands/extension.c
***************
*** 17,23 ****
   * parameter, which is the name of the SQL script to run to install the
   * extension.
   *
!  * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
   * Portions Copyright (c) 1994, Regents of the University of California
   *
   *
--- 17,23 ----
   * parameter, which is the name of the SQL script to run to install the
   * extension.
   *
!  * Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
   * Portions Copyright (c) 1994, Regents of the University of California
   *
   *
***************
*** 29,43 ****
  #include "postgres.h"
  
  #include <unistd.h>
- #include <dirent.h>
- #include <sys/types.h>
- #include <sys/stat.h>
  
  #include "access/xact.h"
- #include "access/genam.h"
- #include "access/heapam.h"
  #include "access/sysattr.h"
- #include "catalog/dependency.h"
  #include "catalog/indexing.h"
  #include "catalog/namespace.h"
  #include "catalog/pg_depend.h"
--- 29,37 ----
***************
*** 51,66 ****
  #include "funcapi.h"
  #include "mb/pg_wchar.h"
  #include "miscadmin.h"
- #include "storage/fd.h"
- #include "utils/array.h"
  #include "utils/builtins.h"
  #include "utils/fmgroids.h"
- #include "utils/genfile.h"
  #include "utils/guc.h"
  #include "utils/lsyscache.h"
- #include "utils/memutils.h"
- #include "utils/rel.h"
- #include "utils/syscache.h"
  #include "utils/tqual.h"
  
  /*
--- 45,54 ----
***************
*** 68,74 ****
   */
  ObjectAddress CreateExtensionAddress;
  bool create_extension = false;
! bool create_extension_with_user_data = true;
  
  /*
   * Internal data structures, for control file parsing and listings.
--- 56,63 ----
   */
  ObjectAddress CreateExtensionAddress;
  bool create_extension = false;
! 
! static bool create_extension_with_user_data;
  
  /*
   * Internal data structures, for control file parsing and listings.
*************** typedef struct extension_fctx
*** 101,146 ****
  	ExtensionList *installed;
  } extension_fctx;
  
  /*
   * Utility functions to handle extension related paths
   */
  static bool
! filename_extension_control_p(const char *filename)
! {
! 	return ! ( strcmp(filename, ".") == 0
! 			   || strcmp(filename, "..") == 0
! 			   || strrchr(filename, '.') == NULL
! 			   || strcmp(strrchr(filename, '.'), ".control") != 0 );
! }
! 
! /*
!  * Given the 'name.control' filename, return the extension's name:
!  *
!  * `basename $filename .control`
!  */
! static char *
! get_extension_name_from_control_filename(const char *filename)
  {
! 	if (filename_extension_control_p(filename))
! 	{
! 		char  *extname;
! 		char *slash = strrchr(filename, '/');
! 		char *dot   = strrchr(filename, '.');
! 
! 		if (slash == NULL)
! 			/* relative filename... */
! 			slash = (char *)filename;
! 		else
! 			/* the file ends with .control and has a / before, that's safe */
! 			slash++;
  
! 		extname = palloc(MAXPGPATH);
! 		memset(extname, '\0', MAXPGPATH);
! 		strncpy(extname, slash, dot - slash);
! 		return extname;
! 	}
! 	else
! 		return NULL;
  }
  
  static char *
--- 90,106 ----
  	ExtensionList *installed;
  } extension_fctx;
  
+ static bool extension_is_relocatable(Oid ext_oid);
+ 
  /*
   * Utility functions to handle extension related paths
   */
  static bool
! is_extension_control_filename(const char *filename)
  {
! 	const char *extension = strrchr(filename, '.');
  
! 	return extension != NULL && strcmp(extension, ".control") == 0;
  }
  
  static char *
*************** get_extension_control_basepath(void)
*** 150,156 ****
  	char	   *result;
  
  	get_share_path(my_exec_path, sharepath);
! 	result = palloc(MAXPGPATH);
  	snprintf(result, MAXPGPATH, "%s/contrib", sharepath);
  
  	return result;
--- 110,116 ----
  	char	   *result;
  
  	get_share_path(my_exec_path, sharepath);
! 	result = (char *) palloc(MAXPGPATH);
  	snprintf(result, MAXPGPATH, "%s/contrib", sharepath);
  
  	return result;
*************** get_extension_control_filename(const cha
*** 163,169 ****
  	char	   *result;
  
  	get_share_path(my_exec_path, sharepath);
! 	result = palloc(MAXPGPATH);
  	snprintf(result, MAXPGPATH, "%s/contrib/%s.control", sharepath, extname);
  
  	return result;
--- 123,129 ----
  	char	   *result;
  
  	get_share_path(my_exec_path, sharepath);
! 	result = (char *) palloc(MAXPGPATH);
  	snprintf(result, MAXPGPATH, "%s/contrib/%s.control", sharepath, extname);
  
  	return result;
*************** get_extension_absolute_path(const char *
*** 183,189 ****
  		return (char *)filename;
  
  	get_share_path(my_exec_path, sharepath);
! 	result = palloc(MAXPGPATH);
      snprintf(result, MAXPGPATH, "%s/contrib/%s", sharepath, filename);
  
  	return result;
--- 143,149 ----
  		return (char *)filename;
  
  	get_share_path(my_exec_path, sharepath);
! 	result = (char *) palloc(MAXPGPATH);
      snprintf(result, MAXPGPATH, "%s/contrib/%s", sharepath, filename);
  
  	return result;
*************** parse_extension_control_file(const char 
*** 203,210 ****
  {
  	FILE	   *file;
  	bool		saw_relocatable = false;
! 	ExtensionControlFile *control =
! 		(ExtensionControlFile *)palloc(sizeof(ExtensionControlFile));
  	ConfigVariable *item,
  				   *head = NULL,
  				   *tail = NULL;
--- 163,169 ----
  {
  	FILE	   *file;
  	bool		saw_relocatable = false;
! 	ExtensionControlFile *control;
  	ConfigVariable *item,
  				   *head = NULL,
  				   *tail = NULL;
*************** parse_extension_control_file(const char 
*** 216,224 ****
  	 * default values, all string fields are NULL til parsed, except for the
  	 * name, which ain't parsed
  	 */
  	control->name = pstrdup(extname);
- 	control->script =
- 		control->version = control->comment = control->schema = NULL;
  	control->encoding = -1;
  
  	/*
--- 175,182 ----
  	 * default values, all string fields are NULL til parsed, except for the
  	 * name, which ain't parsed
  	 */
+ 	control = (ExtensionControlFile *) palloc0(sizeof(ExtensionControlFile));
  	control->name = pstrdup(extname);
  	control->encoding = -1;
  
  	/*
*************** parse_extension_control_file(const char 
*** 294,305 ****
  		/*
  		 * script defaults to ${extension-name}.sql
  		 */
! 		char  *script;
  
! 		script = palloc(MAXPGPATH);
! 		memset(script, '\0', MAXPGPATH);
! 		sprintf(script, "%s.sql", control->name);
! 		control->script = script;;
  	}
  
  	if (!saw_relocatable)
--- 252,261 ----
  		/*
  		 * script defaults to ${extension-name}.sql
  		 */
! 		char	script[MAXPGPATH];
  
! 		snprintf(script, MAXPGPATH, "%s.sql", control->name);
! 		control->script = pstrdup(script);
  	}
  
  	if (!saw_relocatable)
*************** read_extension_control_file(const char *
*** 319,335 ****
  {
      char *filename = get_extension_control_filename(extname);
  
! 	if (access(filename, R_OK) == 0)
! 	{
! 		return parse_extension_control_file(extname, filename);
! 	}
! 
! 	ereport(ERROR,
! 			(errmsg("could not read extension control file '%s' "
! 					"for extension %s", filename, extname)));
! 
! 	/* make compiler happy */
! 	return NULL;
  }
  
  /*
--- 275,281 ----
  {
      char *filename = get_extension_control_filename(extname);
  
! 	return parse_extension_control_file(extname, filename);
  }
  
  /*
*************** execute_extension_script(ExtensionContro
*** 413,430 ****
  						 const char *schema, bool user_data)
  {
  	char       *filename = get_extension_absolute_path(control->script);
! 	char       *old_cmsgs = NULL, *old_lmsgs = NULL; /* silence compiler */
! 	bool        reset_cmsgs = false, reset_lmsgs = false;
  	Oid         target_schema;
  	OverrideSearchPath *overridePath;
  
- 	/*
- 	 * Set create_extension and create_extension_with_user_data so that the
- 	 * function pg_extension_with_user_data() returns the right value.
- 	 */
- 	create_extension = true;
- 	create_extension_with_user_data = user_data;
- 
  	elog(DEBUG1,
  		 "Installing extension '%s' from '%s', in schema %s, %s user data",
  		 control->name,
--- 359,369 ----
  						 const char *schema, bool user_data)
  {
  	char       *filename = get_extension_absolute_path(control->script);
! 	char	   *save_client_min_messages = NULL,
! 			   *save_log_min_messages = NULL;
  	Oid         target_schema;
  	OverrideSearchPath *overridePath;
  
  	elog(DEBUG1,
  		 "Installing extension '%s' from '%s', in schema %s, %s user data",
  		 control->name,
*************** execute_extension_script(ExtensionContro
*** 441,458 ****
  	 *
  	 * We want to avoid dumping the full script for each of those.
  	 */
! 	reset_cmsgs = client_min_messages < WARNING;
! 	reset_lmsgs = log_min_messages < WARNING;
! 
! 	if (reset_cmsgs)
  	{
! 		old_cmsgs = pstrdup((char *)GetConfigOption("client_min_messages", false));
! 		SetConfigOption("client_min_messages", "warning", PGC_SUSET, PGC_S_SESSION);
  	}
! 	if (reset_lmsgs)
  	{
! 		old_lmsgs = pstrdup((char *)GetConfigOption("log_min_messages", false));
! 		SetConfigOption("log_min_messages", "warning", PGC_SUSET, PGC_S_SESSION);
  	}
  
  	target_schema = LookupCreationNamespace(schema);
--- 380,399 ----
  	 *
  	 * We want to avoid dumping the full script for each of those.
  	 */
! 	if (client_min_messages < WARNING)
  	{
! 		save_client_min_messages =
! 			pstrdup(GetConfigOption("client_min_messages", false));
! 		SetConfigOption("client_min_messages", "warning",
! 						PGC_SUSET, PGC_S_SESSION);
  	}
! 
! 	if (log_min_messages < WARNING)
  	{
! 		save_log_min_messages =
! 			pstrdup(GetConfigOption("log_min_messages", false));
! 		SetConfigOption("log_min_messages", "warning",
! 						PGC_SUSET, PGC_S_SESSION);
  	}
  
  	target_schema = LookupCreationNamespace(schema);
*************** execute_extension_script(ExtensionContro
*** 468,475 ****
--- 409,420 ----
  	PushOverrideSearchPath(overridePath);
  
  	/*
+ 	 * Set create_extension and create_extension_with_user_data so that
+ 	 * the function pg_extension_with_user_data() returns the right value.
  	 * On failure, ensure that create_extension does not remain set.
  	 */
+ 	create_extension = true;
+ 	create_extension_with_user_data = user_data;
  	PG_TRY();
  	{
  		char *sql = read_extension_script_file(control);
*************** execute_extension_script(ExtensionContro
*** 542,559 ****
  	}
  	PG_END_TRY();
  
- 	/* Reset search path to normal state */
- 	PopOverrideSearchPath();
- 
- 	if (reset_cmsgs)
- 		SetConfigOption("client_min_messages",
- 						old_cmsgs, PGC_SUSET, PGC_S_SESSION);
- 	if (reset_lmsgs)
- 		SetConfigOption("log_min_messages",
- 						old_lmsgs, PGC_SUSET, PGC_S_SESSION);
- 
  	/* reset the current_extension dependency tracker */
  	create_extension = false;
  }
  
  /*
--- 487,504 ----
  	}
  	PG_END_TRY();
  
  	/* reset the current_extension dependency tracker */
  	create_extension = false;
+ 
+ 	/* Reset search path and GUC variables to normal state */
+ 	PopOverrideSearchPath();
+ 
+ 	if (save_client_min_messages != NULL)
+ 		SetConfigOption("client_min_messages", save_client_min_messages,
+ 						PGC_SUSET, PGC_S_SESSION);
+ 	if (save_log_min_messages != NULL)
+ 		SetConfigOption("log_min_messages", save_log_min_messages,
+ 						PGC_SUSET, PGC_S_SESSION);
  }
  
  /*
*************** execute_extension_script(ExtensionContro
*** 564,570 ****
  void
  CreateExtension(CreateExtensionStmt *stmt)
  {
- 
  	ListCell   *option;
  	DefElem    *d_user_data = NULL;
  	DefElem    *d_schema = NULL;
--- 509,514 ----
*************** CreateExtension(CreateExtensionStmt *stm
*** 594,605 ****
  	 * pg_extension catalog to forbid having two backends concurrently
  	 * creating the same extension.
  	 */
! 	if( InvalidOid != get_extension_oid(stmt->extname, true) )
! 	{
  		ereport(ERROR,
  				(errcode(ERRCODE_DUPLICATE_OBJECT),
  				 errmsg("extension \"%s\" already exists", stmt->extname)));
- 	}
  
  	/*
  	 * The control file does not contain any text given to the backend
--- 538,547 ----
  	 * pg_extension catalog to forbid having two backends concurrently
  	 * creating the same extension.
  	 */
! 	if (get_extension_oid(stmt->extname, true) != InvalidOid)
  		ereport(ERROR,
  				(errcode(ERRCODE_DUPLICATE_OBJECT),
  				 errmsg("extension \"%s\" already exists", stmt->extname)));
  
  	/*
  	 * The control file does not contain any text given to the backend
*************** CreateExtension(CreateExtensionStmt *stm
*** 650,662 ****
  		 */
  		schema = strVal(d_schema->arg);
  
! 		if (!control->relocatable && control->schema != NULL)
  		{
! 			if (strcmp(control->schema, schema) != 0)
! 				ereport(ERROR,
! 						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
! 						 errmsg("this extension has to be installed in schema \"%s\"",
! 								control->schema)));
  		}
  
  		/* If the user is giving us the schema name, it must exists already */
--- 592,604 ----
  		 */
  		schema = strVal(d_schema->arg);
  
! 		if (!control->relocatable && control->schema != NULL &&
! 			strcmp(control->schema, schema) != 0)
  		{
! 			ereport(ERROR,
! 					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
! 					 errmsg("this extension has to be installed in schema \"%s\"",
! 							control->schema)));
  		}
  
  		/* If the user is giving us the schema name, it must exists already */
*************** CreateExtension(CreateExtensionStmt *stm
*** 725,739 ****
  	 * pg_extension catalog to forbid having two backends concurrently
  	 * creating the same extension.
  	 */
! 	if( InvalidOid != get_extension_oid(stmt->extname, true) )
! 	{
  		ereport(ERROR,
  				(errcode(ERRCODE_DUPLICATE_OBJECT),
  				 errmsg("extension \"%s\" already exists", stmt->extname)));
- 	}
  
  	memset(values, 0, sizeof(values));
! 	MemSet(nulls, false, sizeof(nulls));
  
  	values[Anum_pg_extension_extname - 1] =
  		DirectFunctionCall1(namein, CStringGetDatum(control->name));
--- 667,679 ----
  	 * pg_extension catalog to forbid having two backends concurrently
  	 * creating the same extension.
  	 */
! 	if (get_extension_oid(stmt->extname, true) != InvalidOid)
  		ereport(ERROR,
  				(errcode(ERRCODE_DUPLICATE_OBJECT),
  				 errmsg("extension \"%s\" already exists", stmt->extname)));
  
  	memset(values, 0, sizeof(values));
! 	memset(nulls, 0, sizeof(nulls));
  
  	values[Anum_pg_extension_extname - 1] =
  		DirectFunctionCall1(namein, CStringGetDatum(control->name));
*************** CreateExtension(CreateExtensionStmt *stm
*** 743,749 ****
  	values[Anum_pg_extension_relocatable - 1] =
  		BoolGetDatum(control->relocatable);
  
! 	if( control->version == NULL )
  		nulls[Anum_pg_extension_extversion - 1] = true;
  	else
  		values[Anum_pg_extension_extversion - 1] =
--- 683,689 ----
  	values[Anum_pg_extension_relocatable - 1] =
  		BoolGetDatum(control->relocatable);
  
! 	if (control->version == NULL)
  		nulls[Anum_pg_extension_extversion - 1] = true;
  	else
  		values[Anum_pg_extension_extversion - 1] =
*************** CreateExtension(CreateExtensionStmt *stm
*** 759,765 ****
  	 * Comment on extension
  	 */
  	if (control->comment != NULL)
! 		CreateComments(extensionoid, ExtensionRelationId, 0,  control->comment);
  
  	/*
  	 * Set the globals create_extension and extension so that any object
--- 699,705 ----
  	 * Comment on extension
  	 */
  	if (control->comment != NULL)
! 		CreateComments(extensionoid, ExtensionRelationId, 0, control->comment);
  
  	/*
  	 * Set the globals create_extension and extension so that any object
*************** CreateExtension(CreateExtensionStmt *stm
*** 784,790 ****
  	}
  
  	execute_extension_script(control, schema, user_data);
- 	return;
  }
  
  /*
--- 724,729 ----
*************** DropExtension(DropExtensionStmt *stmt)
*** 852,859 ****
  	object.objectSubId = 0;
  
  	performDeletion(&object, stmt->behavior);
- 
- 	return;
  }
  
  /*
--- 791,796 ----
*************** get_extension_name(Oid ext_oid)
*** 939,950 ****
  }
  
  /*
!  * extension_relocatable_p
   *
   * Returns true when the extension is marked 'relocatable'
   */
! bool
! extension_relocatable_p(Oid ext_oid)
  {
  	bool	    relocatable;
  	Relation	rel;
--- 876,887 ----
  }
  
  /*
!  * extension_is_relocatable
   *
   * Returns true when the extension is marked 'relocatable'
   */
! static bool
! extension_is_relocatable(Oid ext_oid)
  {
  	bool	    relocatable;
  	Relation	rel;
*************** pg_extensions(PG_FUNCTION_ARGS)
*** 1192,1198 ****
  		/* Get an array of installed extensions, but only their names */
  		installed = extension_list_installed(true);
  
! 		fctx = palloc(sizeof(extension_fctx));
  		fctx->dir.location = get_extension_control_basepath();
  		fctx->dir.dirdesc  = AllocateDir(fctx->dir.location);
  		fctx->installed    = installed;
--- 1129,1135 ----
  		/* Get an array of installed extensions, but only their names */
  		installed = extension_list_installed(true);
  
! 		fctx = (extension_fctx *) palloc(sizeof(extension_fctx));
  		fctx->dir.location = get_extension_control_basepath();
  		fctx->dir.dirdesc  = AllocateDir(fctx->dir.location);
  		fctx->installed    = installed;
*************** pg_extensions(PG_FUNCTION_ARGS)
*** 1213,1243 ****
  	while ((de = ReadDir(fctx->dir.dirdesc, fctx->dir.location)) != NULL)
  	{
  		ExtensionControlFile *control;
  		Datum		values[5];
  		bool		nulls[5];
  		bool        is_installed = false;
  		int         i = 0;
  		HeapTuple	tuple;
  
! 		if (!filename_extension_control_p(de->d_name))
  			continue;
  
  		control = parse_extension_control_file(
! 			get_extension_name_from_control_filename(de->d_name),
! 			get_extension_absolute_path(de->d_name));
  
  		memset(values, 0, sizeof(values));
! 		MemSet(nulls, false, sizeof(nulls));
  
  		values[0] = DirectFunctionCall1(namein, CStringGetDatum(control->name));
  		values[2] = BoolGetDatum(control->relocatable);
  
! 		if( control->version == NULL )
  			nulls[1] = true;
  		else
  			values[1] = CStringGetTextDatum(control->version);
  
! 		if( control->comment == NULL )
  			nulls[3] = true;
  		else
  			values[3] = CStringGetTextDatum(control->comment);
--- 1150,1184 ----
  	while ((de = ReadDir(fctx->dir.dirdesc, fctx->dir.location)) != NULL)
  	{
  		ExtensionControlFile *control;
+ 		char	   *extname;
  		Datum		values[5];
  		bool		nulls[5];
  		bool        is_installed = false;
  		int         i = 0;
  		HeapTuple	tuple;
  
! 		if (!is_extension_control_filename(de->d_name))
  			continue;
  
+ 		/* extract extension name from 'name.control' filename */
+ 		extname = pstrdup(de->d_name);
+ 		*strrchr(extname, '.') = '\0';
+ 
  		control = parse_extension_control_file(
! 					extname, get_extension_absolute_path(de->d_name));
  
  		memset(values, 0, sizeof(values));
! 		memset(nulls, 0, sizeof(nulls));
  
  		values[0] = DirectFunctionCall1(namein, CStringGetDatum(control->name));
  		values[2] = BoolGetDatum(control->relocatable);
  
! 		if (control->version == NULL)
  			nulls[1] = true;
  		else
  			values[1] = CStringGetTextDatum(control->version);
  
! 		if (control->comment == NULL)
  			nulls[3] = true;
  		else
  			values[3] = CStringGetTextDatum(control->comment);
*************** pg_extensions(PG_FUNCTION_ARGS)
*** 1247,1253 ****
  		 * expect installations to typically have very few extensions
  		 * installed, we simple rescan the same array each time.
  		 */
! 		while( !is_installed && i < fctx->installed->numrefs )
  			is_installed = 0 == strcmp(fctx->installed->exts[i++].name,
  									   control->name);
  
--- 1188,1194 ----
  		 * expect installations to typically have very few extensions
  		 * installed, we simple rescan the same array each time.
  		 */
! 		while (!is_installed && i < fctx->installed->numrefs)
  			is_installed = 0 == strcmp(fctx->installed->exts[i++].name,
  									   control->name);
  
*************** AlterExtensionNamespace_oid(Oid extensio
*** 1289,1300 ****
  				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
  				 (errmsg("must be superuser to ALTER EXTENSION"))));
  
! 	if (!extension_relocatable_p(extensionOid))
  		ereport(ERROR,
  				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
  				 (errmsg("this extension does not support SET SCHEMA"))));
  
! 	object = (ObjectAddress *)palloc(sizeof(ObjectAddress));
  	object->classId = ExtensionRelationId;
  	object->objectId = extensionOid;
  	object->objectSubId = 0;
--- 1230,1241 ----
  				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
  				 (errmsg("must be superuser to ALTER EXTENSION"))));
  
! 	if (!extension_is_relocatable(extensionOid))
  		ereport(ERROR,
  				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
  				 (errmsg("this extension does not support SET SCHEMA"))));
  
! 	object = (ObjectAddress *) palloc(sizeof(ObjectAddress));
  	object->classId = ExtensionRelationId;
  	object->objectId = extensionOid;
  	object->objectSubId = 0;
*************** AlterExtensionNamespace_oid(Oid extensio
*** 1302,1308 ****
  	/*
  	 * We scan pg_depend to find objects that depend directly on the extension.
  	 */
! 	dep = (ObjectAddress *)palloc(sizeof(ObjectAddress));
  
  	depRel = heap_open(DependRelationId, AccessShareLock);
  
--- 1243,1249 ----
  	/*
  	 * We scan pg_depend to find objects that depend directly on the extension.
  	 */
! 	dep = (ObjectAddress *) palloc(sizeof(ObjectAddress));
  
  	depRel = heap_open(DependRelationId, AccessShareLock);
  
*************** AlterExtensionNamespace_oid(Oid extensio
*** 1375,1383 ****
  
  		if (HeapTupleIsValid(tup))
  		{
! 			values = palloc0(rel->rd_att->natts * sizeof(Datum));
! 			nulls = palloc0(rel->rd_att->natts * sizeof(bool));
! 			replaces = palloc0(rel->rd_att->natts * sizeof(bool));
  			values[Anum_pg_extension_extnamespace  - 1] = nspOid;
  			replaces[Anum_pg_extension_extnamespace  - 1] = true;
  			newtup = heap_modify_tuple(tup, rel->rd_att, values, nulls, replaces);
--- 1316,1324 ----
  
  		if (HeapTupleIsValid(tup))
  		{
! 			values = (Datum *) palloc0(rel->rd_att->natts * sizeof(Datum));
! 			nulls = (bool *) palloc0(rel->rd_att->natts * sizeof(bool));
! 			replaces = (bool *) palloc0(rel->rd_att->natts * sizeof(bool));
  			values[Anum_pg_extension_extnamespace  - 1] = nspOid;
  			replaces[Anum_pg_extension_extnamespace  - 1] = true;
  			newtup = heap_modify_tuple(tup, rel->rd_att, values, nulls, replaces);
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index 84c68a7..747fa52 100644
*** a/src/bin/psql/tab-complete.c
--- b/src/bin/psql/tab-complete.c
*************** static const SchemaQuery Query_for_list_
*** 578,583 ****
--- 578,593 ----
  "   FROM pg_catalog.pg_proc "\
  "  WHERE proname='%s'"
  
+ #define Query_for_list_of_extensions \
+ " SELECT pg_catalog.quote_ident(extname) "\
+ "   FROM pg_catalog.pg_extension "\
+ "  WHERE substring(pg_catalog.quote_ident(extname),1,%d)='%s'"
+ 
+ #define Query_for_list_of_available_extensions \
+ " SELECT pg_catalog.quote_ident(name) "\
+ "   FROM pg_catalog.pg_available_extensions "\
+ "  WHERE substring(pg_catalog.quote_ident(name),1,%d)='%s' AND NOT installed"
+ 
  /*
   * This is a list of all "things" in Pgsql, which can show up after CREATE or
   * DROP; and there is also a query to get a list of them.
*************** static const pgsql_thing_t words_after_c
*** 606,611 ****
--- 616,622 ----
  	{"DATABASE", Query_for_list_of_databases},
  	{"DICTIONARY", Query_for_list_of_ts_dictionaries, NULL, true},
  	{"DOMAIN", NULL, &Query_for_list_of_domains},
+ 	{"EXTENSION", Query_for_list_of_extensions},
  	{"FOREIGN DATA WRAPPER", NULL, NULL},
  	{"FOREIGN TABLE", NULL, NULL},
  	{"FUNCTION", NULL, &Query_for_list_of_functions},
*************** psql_completion(char *text, int start, i
*** 775,781 ****
  			 pg_strcasecmp(prev3_wd, "TABLE") != 0)
  	{
  		static const char *const list_ALTER[] =
! 		{"AGGREGATE", "CONVERSION", "DATABASE", "DEFAULT PRIVILEGES", "DOMAIN", "FOREIGN DATA WRAPPER", "FOREIGN TABLE", "FUNCTION",
  			"GROUP", "INDEX", "LANGUAGE", "LARGE OBJECT", "OPERATOR", "ROLE", "SCHEMA", "SERVER", "SEQUENCE", "TABLE",
  		"TABLESPACE", "TEXT SEARCH", "TRIGGER", "TYPE", "USER", "USER MAPPING FOR", "VIEW", NULL};
  
--- 786,793 ----
  			 pg_strcasecmp(prev3_wd, "TABLE") != 0)
  	{
  		static const char *const list_ALTER[] =
! 		{"AGGREGATE", "CONVERSION", "DATABASE", "DEFAULT PRIVILEGES", "DOMAIN",
! 			"EXTENSION", "FOREIGN DATA WRAPPER", "FOREIGN TABLE", "FUNCTION",
  			"GROUP", "INDEX", "LANGUAGE", "LARGE OBJECT", "OPERATOR", "ROLE", "SCHEMA", "SERVER", "SEQUENCE", "TABLE",
  		"TABLESPACE", "TEXT SEARCH", "TRIGGER", "TYPE", "USER", "USER MAPPING FOR", "VIEW", NULL};
  
*************** psql_completion(char *text, int start, i
*** 838,843 ****
--- 850,860 ----
  		COMPLETE_WITH_LIST(list_ALTERDATABASE);
  	}
  
+ 	/* ALTER EXTENSION <name> */
+ 	else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 &&
+ 			 pg_strcasecmp(prev2_wd, "EXTENSION") == 0)
+ 		COMPLETE_WITH_CONST("SET SCHEMA");
+ 
  	/* ALTER FOREIGN */
  	else if (pg_strcasecmp(prev2_wd, "ALTER") == 0 &&
  			 pg_strcasecmp(prev_wd, "FOREIGN") == 0)
*************** psql_completion(char *text, int start, i
*** 1579,1584 ****
--- 1596,1611 ----
  			 pg_strcasecmp(prev_wd, "TEMPLATE") == 0)
  		COMPLETE_WITH_QUERY(Query_for_list_of_template_databases);
  
+ /* CREATE EXTENSION */
+ 	/* Complete with available extensions rather than installed ones. */
+ 	else if (pg_strcasecmp(prev2_wd, "CREATE") == 0 &&
+ 			 pg_strcasecmp(prev_wd, "EXTENSION") == 0)
+ 		COMPLETE_WITH_QUERY(Query_for_list_of_available_extensions);
+ 	/* CREATE EXTENSION <name> */
+ 	else if (pg_strcasecmp(prev3_wd, "CREATE") == 0 &&
+ 			 pg_strcasecmp(prev2_wd, "EXTENSION") == 0)
+ 		COMPLETE_WITH_CONST("WITH SCHEMA");
+ 
  	/* CREATE FOREIGN */
  	else if (pg_strcasecmp(prev2_wd, "CREATE") == 0 &&
  			 pg_strcasecmp(prev_wd, "FOREIGN") == 0)
*************** psql_completion(char *text, int start, i
*** 1922,1927 ****
--- 1949,1955 ----
  	else if ((pg_strcasecmp(prev3_wd, "DROP") == 0 &&
  			  (pg_strcasecmp(prev2_wd, "CONVERSION") == 0 ||
  			   pg_strcasecmp(prev2_wd, "DOMAIN") == 0 ||
+ 			   pg_strcasecmp(prev2_wd, "EXTENSION") == 0 ||
  			   pg_strcasecmp(prev2_wd, "FUNCTION") == 0 ||
  			   pg_strcasecmp(prev2_wd, "INDEX") == 0 ||
  			   pg_strcasecmp(prev2_wd, "LANGUAGE") == 0 ||
diff --git a/src/include/catalog/dependency.h b/src/include/catalog/dependency.h
index 74ed40b..7607c06 100644
*** a/src/include/catalog/dependency.h
--- b/src/include/catalog/dependency.h
*************** typedef enum SharedDependencyType
*** 101,131 ****
  	SHARED_DEPENDENCY_INVALID = 0
  } SharedDependencyType;
  
! /*
!  * Deletion processing requires additional state for each ObjectAddress that
!  * it's planning to delete.  For simplicity and code-sharing we make the
!  * ObjectAddresses code support arrays with or without this extra state.
!  */
! typedef struct
! {
! 	int			flags;			/* bitmask, see bit definitions below */
! 	ObjectAddress dependee;		/* object whose deletion forced this one */
! } ObjectAddressExtra;
! 
! /* ObjectAddressExtra flag bits */
! #define DEPFLAG_ORIGINAL	0x0001		/* an original deletion target */
! #define DEPFLAG_NORMAL		0x0002		/* reached via normal dependency */
! #define DEPFLAG_AUTO		0x0004		/* reached via auto dependency */
! #define DEPFLAG_INTERNAL	0x0008		/* reached via internal dependency */
! 
! /* expansible list of ObjectAddresses (used in dependency.c and extension.c) */
! typedef struct
! {
! 	ObjectAddress *refs;		/* => palloc'd array */
! 	ObjectAddressExtra *extras; /* => palloc'd array, or NULL if not used */
! 	int			numrefs;		/* current number of references */
! 	int			maxrefs;		/* current size of palloc'd array(s) */
! } ObjectAddresses;
  
  /*
   * This enum covers all system catalogs whose OIDs can appear in
--- 101,108 ----
  	SHARED_DEPENDENCY_INVALID = 0
  } SharedDependencyType;
  
! /* expansible list of ObjectAddresses (private in dependency.c) */
! typedef struct ObjectAddresses ObjectAddresses;
  
  /*
   * This enum covers all system catalogs whose OIDs can appear in
diff --git a/src/include/catalog/pg_extension.h b/src/include/catalog/pg_extension.h
index 2ea24a6..32b3677 100644
*** a/src/include/catalog/pg_extension.h
--- b/src/include/catalog/pg_extension.h
***************
*** 3,9 ****
   * pg_extension.h
   *	  definition of the system "extension" relation (pg_extension)
   *
!  * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
   * Portions Copyright (c) 1994, Regents of the University of California
   *
   * src/include/catalog/pg_extension.h
--- 3,9 ----
   * pg_extension.h
   *	  definition of the system "extension" relation (pg_extension)
   *
!  * Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
   * Portions Copyright (c) 1994, Regents of the University of California
   *
   * src/include/catalog/pg_extension.h
*************** typedef FormData_pg_extension *Form_pg_e
*** 53,63 ****
  #define Anum_pg_extension_extversion		4
  
  /* ----------------
!  *		initial contents of pg_extension
   * ----------------
   */
  
- /* btree
- DATA(insert ("PostgreSQL" PG_VERSION _null_));
- */
  #endif   /* PG_EXTENSION_H */
--- 53,60 ----
  #define Anum_pg_extension_extversion		4
  
  /* ----------------
!  *		pg_extension has no initial contents
   * ----------------
   */
  
  #endif   /* PG_EXTENSION_H */
diff --git a/src/include/commands/extension.h b/src/include/commands/extension.h
index 11809b8..cc5e7ed 100644
*** a/src/include/commands/extension.h
--- b/src/include/commands/extension.h
***************
*** 4,10 ****
   *		Extension management commands (create/drop extension).
   *
   *
!  * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
   * Portions Copyright (c) 1994, Regents of the University of California
   *
   * src/include/commands/extension.h
--- 4,10 ----
   *		Extension management commands (create/drop extension).
   *
   *
!  * Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
   * Portions Copyright (c) 1994, Regents of the University of California
   *
   * src/include/commands/extension.h
***************
*** 30,46 ****
   */
  extern ObjectAddress CreateExtensionAddress;
  extern bool create_extension;
- extern bool create_extension_with_user_data;
  
  extern void CreateExtension(CreateExtensionStmt *stmt);
  extern void DropExtension(DropExtensionStmt *stmt);
  
  extern Oid get_extension_oid(const char *extname, bool missing_ok);
  extern char *get_extension_name(Oid ext_oid);
- extern bool extension_relocatable_p(Oid ext_oid);
  extern void RemoveExtensionById(Oid extId);
  extern void AlterExtensionNamespace(char *name, const char *newschema);
  extern void AlterExtensionNamespace_oid(Oid extensionOid, Oid nspOid);
  
- 
  #endif   /* EXTENSION_H */
--- 30,43 ----
#22Dimitri Fontaine
dimitri@2ndQuadrant.fr
In reply to: Itagaki Takahiro (#21)
1 attachment(s)
Re: Extensions support for pg_dump, patch v27

Itagaki Takahiro <itagaki.takahiro@gmail.com> writes:

Hmmm, I like extension_is_relocatable() or so...
Including the above, I wrote a patch on your patch for minor
cleanup. Please merge reasonable parts in it.

After review, I included all your proposed changes, thanks a lot!
Please find attached a new version of the patch, v29, including your
changes and merged against HEAD from this morning (there was no
conflict, but still).

* access() is not portable.
The pre-checking with access() doesn't seems needed because
the same error will be raised in parse_extension_control_file().

* There are some dead code in the patch.
For example, you exported ObjectAddresses to public, but it is not
used in extension.c actually. I reverted some of changes.

Thanks, those are due to late refactoring, removal of features and
adjustments etc. Doing that in "free time" rather than full time these
busy days, so I've missed some cleaning.

* Should we support absolute control file paths?
Absolute paths are supported by get_extension_absolute_path(),
but I'm not sure actual use-cases.

Well I don't see no harm in allowing non-core compliant extension
packaging, as this feature is not targeting only BSD compatible Open
Source extensions such as contribs. It seems to me to be a case of
mechanism versus policy, I don't think our policy here should mean that
we alter the mechanism for others.

* Each ereport(ERROR) should have a reasonable errcode unless
they are an internal logic error, and whether the error message
follows our guidline (starting with a lower case character, etc.)

Done.

* Changed create_extension_with_user_data to a static variable.
CreateExtensionAddress and create_extension are still exported.
We could have better names for them -- CurrentExtensionAddress
and in_create_extension? Or, in_create_extension might be
replaced with "CreateExtensionAddress.objectId != InvalidOid".

Well there has been enough discussion about those names I think, current
one where voted by Alvaro and Robert IIRC. I'm open to changes, but
would now prefer to include that in the commiter's work :)

* Added psql tab completion for CREATE/DROP/ALTER EXTENSION.
* Use palloc0() instead of palloc() and memset(0).
* Several code cleanup.

Thanks a lot!

Regards,
--
Dimitri Fontaine
http://2ndQuadrant.fr PostgreSQL : Expertise, Formation et Support

Attachments:

extension.v29.patch.gzapplication/octet-streamDownload
�)�BMextension.v29.patch��{�6�8��}�w��	�X�=nr�j+����^[i����>�D�<�D���x�=���$HQ�s���V���m0�3�?��n4����S�7Gc����k�m��_����u�c��[^�.��������:���x.tyxq��stq�����
�����6���u����5�8n����i8��E7��Y���x:
G��:6�����+�\��a�����V���?�dG��^����M��o��?�����o��6���\������������l�E�y"Z�l���N��v4m}
�=�`qn���wOG����4�>��h���M&����0�����&������~��0��n4#D�#�I�O�w��OG�	%���"J&7qp���GP�]cy,u�Q��|���O��A��� 	�i��
�>�"^�� �yD]u-�"����(r
���������r���S(��y~!^�9;j��������$;wq8	j�����yE�5qX�p���]?-]��t4Gok�J�X2�AR��+�'�K#��������z���h��4P �M&q���'qt�'E����m��C4e�]:e ��b��I�0Y@������V���'�~l����"���}1�F�������Y�����B�����|�2�� ~�������^O�����
gH���������>�6=�?Tr4q��PL�����Z?��)]C)�+�L�����&k?zur&��x�����9��q����PFD�v�(N*oJ�x�
�Z6�?��+�������������C�h��?�d"&�a"�`2	G7b	�]qw�@i�����	��D� I;��
�����rHX��?����^�.�Xh����l���%,����Q+����&��������x�H<����A�EO�=aA��5Zn�7�gW�M����x$�����������T�f&x?�a��y~M'��4��{����!��F�q��<�o����;?�}s����/0=�u�����1�;�C�R�R�r��E��pX�X*����w�",�p#pg��0��M�����}��{��bgV���E�G/���
�C�h���f��������/t�q���+�"��yu�<n�������Ex_���-��0g(�,���E�M��@����JL���W��bs7L�,�B����p�"R���o�!�t�2��������K����t
�������:
:Xc��������;���3�A3}�)h~�U��m������T�Qg�f���p����'��������Qp��d_r8������C�6*�w`�x���s��
.-lT�����Xrp$F��s��YE����K�
��7��t1Uv����]rZ���o���Y�]���,��C�x����}�Qg�������������,��/2�L�0���&�(lT����Xrp�B��c��u�y��h|y��������l���]�kU���-���JV�������z�������t�a����((��?u���*�5��w8FA]|��8_�1�Oy�9'SL��s��|������U�\�{~��Fs���K�L5��wXV���yG�����
'5�o��b���c����8�tS�?��&S��d�atc��ISM��wx��f=����/s�Q���<d��V��"��r�0!\G�^��<�H_�K����F$L'� �.g��L�'8~��/"��!h�jx �]���J`��p�����H@�J90l8
'��]?�%w������i�,�v 1!F���6���f�@�}��������������	����I��t~7W5��#��mp�
,��M�����#(p���#
uTr�|N���;��n��=5PQ/��%%z�8���$����aT�C��`�$���+tpH&y8��)$��x�d��ss�I��r3����~&_���+U|T��%N*%�27���&����N�P�X^$w�o1y&�&�����g����h�Ts������d<'���z����`���
P����j���G�d�"�l����]�Y`�t���z��KL&�s.��bSI%��I,?�D2x~Q��]%�����U�����-6G����U��s����������?P�J"�e�U0�j�B�'.�����YS��cU����q��k6��9���+�.1�T~�Y�2�M*]fN�sL*59�T@�f����|Ut�0?=�|'K����!�`N��B��,��p
sL�*��$u9�<����$�sD���"*��q�%&�*�c~$�cz�Gj��q�-���w��P~n��,�S`��t
����U@���]Z��l�Vs�%3J�K�(��sF��b3�E��Q�`������!����q#�����P&!�2b��W�2�ATt�	��G�&�������#q����'�u�jD���SFY�Rt��MU��4�,GQ�����]BK�gt�J�k[����J�BB/A��9�C�Z�DT�%�DV1�����������\s���\m/4W������s�=�\m���b����������������������r�~������l�17�K���s����l/;7�s��v��,�ns�Mc��i,07�������4���F��4�������A�%f��91Xd�y��KL�;?��n00�nn�����.���O���G���lCm5f��wg����6@��C��o�~�9��^D��tD��e�P�y^}z�]������u~�����'<��Wk����
����2_��)�V�3A�����b��y:\����L5�����;���j�������@��(�-����������������'��VNF��D��w4���4~#>��mR��$��q��<50���q��#TZ�'���EMvCWtB=/��T�
~��w
,�=�UXq�Mr��[�d6thM�%�\��Q�o��E���f@>]�q3oLx����v����>�r�d��<&�!w�$X���0�O��.nL�L�d)�l����] spfG�����9����~t������y��Y&�]���.V��vk�p9whh��
�}���Q/x�3�w-�9�|�b�>m��#���g�/$=�W�JL�� ����.:��k.W��J�r?&.��T�^��$��d�'Y��
�����EO!�i��#]	�l�������#��C����$��i�A9��)�UQ"�
J*��$�L-sd2)�^WP�o:�0�W �������P����{�m^���'��:Q�*0UZ{Q	�	���
U���
@_�o%�*U�o�NU�U�nTV��
����*����*H���J��V_[����%�V^�-`���{�6;��V�.�JK�G� �G�t�~�3B��Zv���V1�U����������"�`R�z�7�k��^+`�
��CmP2��1��c��o�������AU��<�qp��B�(X��stz�.���`w���{$5a�O�]�*)���
����tD��D?���9�Y^�z�d�Z�]g��v�I<�*�cB��p��~<��
G�"��%YW2����W�7O��Bk�����o�u������:	��_����Y�]n�z�e�st�j�u�~�z�+��2�ql��:�Zgvyc�<�1������;d�A���q�����qx�q��O|>�BS*��8H�jw��`��!�7�Tz�SD�y��:�z�t��G�M�#�:�I��l���K�z�n��:z$��Pj��Q�C���a�
�&E���#5�O�������*�ac�B��[x������v�������/~������|��M�z-I�'�z_`����3��|�����H��2�o}���M8f�!�.�s����"�2����2�d�w;mr��,��<��3\=���Vvv�Bx����:�r��n�?/t���0�bg�9��Vc�
���A����/*�S��l�o��
��B=�V��2�B��,�S��,(��T'�%���3��V^y�R�[��r}���
��_+�;�^�i��]�����$�{F�%����C�n7cr���T��$�W0�FZ���cfZ	4�~��������;xRzX�7�:�w3�X_E�Q�v����c�!<�`.�]c��"�a�m���u�������a���u���`���upX���"�������c�m�+{�=p���;��#\
��$����O��vC�F#Q��@��M_J�^�	���8��������e�~�h��?'Hu�����5r���QtxA�^�
���d:b�
&�������)�=��]lO�:�PIH�L�t��VfM�h��������4G�Fv���}�j�\�@�*$Z��cc�h��c\���$�+m_��������-��"�2V�z��M���c|���n~w��(���(��������-��R�8�~|/���~cm
+9;o���ej{*..O^7/o��b0�s(�!h`]����Uh�3�JW��|����7	>9vs������������] �i��|����WN�_��'[�1%�[��VF�/s�>:���)�Vr�u��+��cs��4���IG���`Q��u�����2z�I���CQ��w�E���.We/3��X^��'��N��%�N�!H��`��U���W�!�V
�"�7o����+vuv/��`��u��(	�y�De�yj.������gdU3kw��\`�fU�7;S
C�Rs���R�^��jWU�r*0�,�����*@v����J���as�;@��Q���Z%j������F�Ul�z���.*&�K$F��xc`���? ���ZU8Ug�-0�R��Bk`��;��h��b9��i$����l��zSd4�[����r�}�dftE���r����_���g���>h����H���z4"P�}q�k�PM�C����������A�m�E`s���<R���C�c�I���SO�S��W��c�6E���X�WI��X�tF+B6����4���B�T4�'~T{$Q���v�����Gk*��Au����W�%v~LT@#���	 7k��X���g�8<Il~�o��`J��J1�.[Fy�����C�yy��8>!��VI�E���k���s�k�������V.�b�$���T|���Je@�`-6��@,����Q��D���@
 K�%��|�e `l��y�g�-��%,n�ba�A~n2%R:���J�g$Uf�U,W���,��|&�%��G,	���+�-Z��)�%�����&xeNcI\���
�a��w���`�'/�D���7PJ0�ht?D��<m�.��9���]b��������[�����W�qUx�u�
�H�������~z}e��g}��\��1�_D{�r��w�
��<��'���-"�?����A�]DjEb�r�CY�����S1Cu�e_�78v����`��[��\�5����#+"[/���<�)(g�����<m���\�.p��0���)�cy$���_&��si�w�S&��;r��x�����qC$x��d2��~7`&����_6H�8_�@u�~ve�]�
������^�O������a��A���w�A���9��Pu�5�[$������D�!7C@���2h4���*�Fe^-�\l����Y��~�+���i���@�1&��7���+���xa5z��((�,�y{O	Q�K,����I�v�~��2�}�����uM�&�2�����p��Un�������tE����:k�kpU�i����}���_Ad`}�N��?�Pe���'a�@T�	3��U��U�,y�E�$���Y��v��:>�<�c.�F�L��O����d��W$��0�Y�q���8n=��Dd|�)o-�aR�����5��z�������Q���3hwc����H
��!��'�0�q8	v����:���(�i�
%U62�@_�@u�~ve���~�%�� �|MC�_��y��Q�����Wo��Z�H��~��=����'G��2��FU����En;���M|:gy�:���cSC�B��>�����4��%��
gCd�U����9r$���Sn&lg2Z'�m�*�8W*��m�6z�`����3��E�;����W�P'�`O���q�����F�+���_`��t��V������j�[�R��?�����,T���o��<<G�� {��J�XP�2�{��^��ojpCT��UI%K�-����6�P����g���3�c������3!��@#P#O�
h��A��!�r�j7ON��F�P�{)P������`�����E�����1hP����Y�#H��8������|�e��P������r�����	��<J��RI������r�[(>"d������w�`������iw�)^:A����_��;i)-���j���L��yV�n���B�d�"���{��S�0F��xE��!"���R�(z�����xgoNO�x� �"+" �b?����y��6���L��dOX�4�t�w����qu�-��� ��K�F�&h7�9
����/@�Wv��-���h]^�_���Z/D
w����v��:t��������..��Z�o.[��
bPi�rU��&/������,98W [M���30��;�/�)
�o������lg�1�$B�������J?���Z1�C�J�j���hV9���/����*Ia(�Es	�r����Iz��(����`���_U���o*5�_����UF��R]��w�Q���J`X�Jm�P����p?tg�� } ��>(`�����zv~�*�k�����m5����������Z
�E�_����d�T���f#�u�[M�h;!GAU��Ie��u*�9�\'�C�J��
�`����"+�2X�L(����	���=��0��t`y���f�����0���P�dn g�l���G�h'!9gu�t���-{�1����*H�$R�N\4ki�����,�hyQ���3�{����zJ����tR^:��%+���.���j��VX���-�CV�a��a��+��.(<+���Xitqw
c�/Q��+���%�;S��iR��;��ti�j�j�dLG���z9���"��G�����Ic]��75�t`�r�����,:����77E�8��n�N�v�U"u]�wx7�"I�K5�������(�����P�@�CAv�n���=�2��v�B��brK�G"M���W������e,����MU�`n��sX����8Vc��{"��v$���P�I*��.{#nT"�C�t��N	���1����������yPOP�� �����d�)����������D����q�D,���mgm������~�pDv��>���wypN��@��MR������	tY#g�O�����5�'���f����k*��~R�*�QooTL9�o���Bo~��D�:�LS?�VK��^
A}J��s�Q��O\�N[GmD��7��)�| ����X�sg
���`��E���T�v-�K-oC��[Y/%�$I&���G�>pM<�:�����DK�q8����iU1��������0�_�~��3�%b9���'���L�ck�&����.-Ve���mr/7����������^d�h���B��)�����bfs�#K%���3R�I�j����������X��.��NV0G�:Yb~�y�^��F	�?��73����'�#Cz�$X2�E�z��^n���������e$V�K���P�Vp:_d*��i1a�����[�4�i����8�TZ-���`P��'1������<2���'���j.�rz�1���0d2�Z������`b�� 4&)���g�T{�%m��]�h�MG�mI�����1�l�d6��V��
�7�TY��8wbE`f�����I��=�V%g�����W �2m0o$Dv�\�l�����}��F������Z��}�jn@�7��*'FIaDM����t�
fml�����z5�����Y�����WwS���-t��d�E�s*Y�m
����m�8�M1Q�tx����?��qo�{jn���r��U��F�iq��g�K��c�J�U��f�z$����8���a$�G{����[[���������
����=.|Q�Y�G<���e�5�}��t��6���������r��e����OH�e>��d]l�����;�5^��e����L����g
:e��?�o�O��T��
K�%�u�X\���t�������^(b��h�a�
D�$�f:\�F���[s���wF��mg�:��y6�A�\gm9��C�8%M����-��@���f���d���]�3gXf��97�U�-�,���V��*�5���
J�K=���
A�(������T4��.�}�eu�
��G��P!���x:�F�a@t�{t(�
J��#�@On�V2~�9�MGeu��f5�H�����K4��	���{x���h�Ec\�����=��|��$��t�8��iSD�=�j��<^��/��Y��;u��=���Q�z�}��{�M�!��DP�-�C2���x�SL#.z����&�'�`X�}�hP���/��X�T2�7X����������+v80�����`0y?�zW?�
*�<�_���9j�/M�5����D��4����*����
���>�����={F���=}[��`��duO�z��E3�}]H#�t+���oCP�`7	����� |`�)���q��lft�-�����r�?�8R������}m�-���`��H�s@�!��KDy�J,-
%G"S���U��
���C��
hF�G�h<�0��C�c�s ��X�y�ax"y���Z�}�`=�9�t��5�.)���k�%���9\-�����z	����,=���,4���*����,^�(^C�;Z4*�����Pu^*O�
�������K�����Hyi�qp��
����5���X���	�btf��-j`��"M�����������A��,�/�R��uv�������Ta���y��
��W>�6\���g�<��8-�g���T���SRqF*NH���8�����xO����V��*p���872�
,`r��LF'��V�o3�a�	��S]���*0�|;�73c4$����Rr�"b��R�rB����7�������Sm�*u��l~3��*L�r��j4P��=%�np��&$���rT����
���Q�������f)~4�,f�N�c��Qa��VYi]�8���t���E�0��7f���T��3��?*2�1�@��j2�,����Ve�7���``�k�g���&��x$"�������$�.���V���6s3�n����M�*�P�RU,Xx�bs�ZT&Z!-5�Zf�U#�@7���� ���5�2��l��7��j�������
mEX��a�W�T��JU}[
�2��0i��MeFrS��������u*����"kW��������� .;��W��7Xy.��	�
<��;|�)�.	|�m_��'C��:���4����y\���������|�A}�<;��]X�x��J&�
=$S�y�����~P�D��M����Ps����Q9�=gW?-���Z�R JZ�����/�J�X[�#�J��P5�X����L�Rx��G�q��~���a�0���J
��'JgS+�>��q��C�r�����V-���{�
p6�Q������[EP.��V��m.���I�~N�O��Yl�"b��������A:�q6{�2Yh��g��)���PjOnA��	��A���$.�S>*�6Q���E��>�������:R^���5.��>6���K�ut~y\����(]x�"��6��m|�m�����d:w)7���p��d�w��?.a�n��8�Y����E��)f�9������c�`kv�]Y�[�U��J�8Q{y�zmI�[:�"�[��\��B��;x��\Xw�7���$����3������V����o�V>�P���j�3x1���ZR��!�m�.��l9S���e ��@�|4�>�P�1��'�XP�+d������,���]���Z�s�)]BP�\a�;@+���"�@��%��
#.�@��k�\�'����0c1yX���8�*��.
{36�,f��%d�y��T�|�+�
$S[����|���7����~] �7�b>�MY%���[�M����GE�4�/�f�k�zW���Q��ni+K������v��{}�Lu8C�t�[jX�M<�����`�g�mtG��=z�af����-���-�����i��RM��r��}�-�]&5���p������V��8%�S����q���X�v|�\{�����Z���'�� �9,���������������x�B-E��]�2��H�Q�j��Da��S��s�g��Yq����-����J��~M_=!��0J�������X �*�[4�*��c����{]�fPb5��c�uwy�*U)��(O�a��U(ZK���<�tY�����"U���V<��0N�|��n������oa�9j��-��>R��0�md��R���'Q���}����y[22������]1~O��C����|�%��$K�H�a��6��7�����j%��Vl�)@�Vt�����gv��c��x�I��pN������u��^�_��]��~���8��Q�0���yAb��fI�!�����.�2����0�~����������v�4��N�u��Z�H&�����*#���(�g��=*r����/Nm����]�m����R�����'�(���H&�!� �q��������������?��6d�1�'�s��#K��eBu^��F��9~���U~�(W*%I�<k!�R�.K��g7�?�
��s9�1����l��]���=�B����W�#�A����G����UR��Db3.E������\�Y��#�mp~E���(�n��O~��\@O�I%�u����V����K��F*��b/
D��jQ�j������pT�?A�LjU��%3��TQ��)���5w�w�Jm�.�s��z����II�K;����F_��0U���GQ�����,���j�s
�������%�%��_��v�n�b!���1�74��k
��oHs���--4�
�Q��YD
a'�:���Y���{�D�="��@~[�U����.����2����w�Cg��`�<������\;��XL����(4z�oUE�����T�k_����bVT��S�\�)P�J@�Q����<���[��3D���8������iz�^g�}r���@���T�����8
���m��p�U��w�B���?�W�F�l�>6��P�B s�P]������H��s�JA�o�f��>�>�M'���b�6���<�3Q	z�NY
���8�����x�ZV���_u��,��3F���W'g�y�o��L���7��B�]b��;�����31Q`��]�`I9'NQZ�Z���'/�P�'���T
�)�:�uApL��J:@|=j�O��"vo�*pp���y��L���D��q�����WH��<d���39x|�$���o?�����`�!/6�O�@�D���h���6'���li�|�{�[�t����lD�p�D#s�-4��Ej9|���Or�^a�%����Ot���3�_D$D�U��!�}
^a�/����LN��8�D�����,%2��8E����"�]���j1�qM� ^.�ybS,���Q)j��5E0e"
���S�1�1g�]���!�;�V�.-rP����[��B~���R%���c�Y�����;K��j��
���D! 9��O��?D,1_Pa*��w+[��W�mE��`�N���R�V+N��wq��r���Y�,�og��|���U|3������L���2���U���,�	({{)� ��2~2$	��C��+3��������
Pi����o*S��+tQg���T�����*#T�iP��8����bR���$����SV�O���B����m��O��-#T@����N@>�����'�n8�z �b
D�>���}� wg����^2������H�K>��GWY��S���O���Y���4-��,t������W�g01g�0'��;7�'�*��!+��*��}4�n����xP�3��oAx��"�/F�}���j������aV
�B�u@��bpwB��?����3�@�n�'B��4)��D/�5l����NY�l�$���8�~z���F���e`3W��8j�}��#�D�\��Q:h�����p�����m�oK��l�Lq��f���^>�
����^�F/����f@��K����V�~}0:��l!��e����1��T�N����%��B����GV���"��A�mg�C?�G��F��mXU� ���,KF�)#3u���v����d��t�:J����)�a*6T���$U�(��i���h��9�z��Gq�QxWM/t�#�	c�:N���Q@�i��[����������r�|f ���c�:+�L��$��<�����^���u�o��
?�����7�W-q$���'G��*+���*E�w�4�U��|s�>t�	
�����p�*z+Caa����</��uH�-r�'� �
����W$�W��q?/�a=����L���[�����0�o�:q��<m���;{��:�����-Q�'��}�C�������c�0,����Gp/JiC��������_:N������2�]v@��jk�]Z����i]��b�/�Zt����Y�C.h��f����-�z�Lr��P$|���p!-Q�-K}��a4MRo&��}�S=��#.���zw0�������5mzP�T�v���Bi	`u�����C85W:G^"��}��T2�g@���Hb}dTX�w��)���H�[
�d:��O&�B�#�����Pa�,[\��������r+�wE�m�fW�U�����]M,����U�1�@g-�2a>H0SV:Q�8���M[�#�p�0oX1_��K,��PN����-�'�`B*��#���U�,/�#�F������@����8��\6M�W���U�
+t�yy��`���l�L���������U�RN3�_$��������~>�(&B������\��m<������B��*M�Aas��Tg1H���Bz���s)���X`v��1���yW���J
I�K�)�q�*��s�+�}&G`�5�sI�wl+��z������bQda�y��?��b2n��S�\���d"JK@���`8��g���:�+@BSx���.�M�B)9��r*+��d��l(�J��{KpL+�x	�*������0��/SU�bm9�����+�N�w0�(��O[Gm�����3�xat����Y�����l;����s���'5�������=���P������Et��/b��.�J�j
u7����d	��~�-�����:PEPN7${}v�0KPm��[�L�����������������A	�����:n�'���{�����c��&=L�@lms=��'�-u3A�����	�j(=� ���9a�"�0U �U����66���!�{6L�9�6#����i����U~s�9a�y�V"����N_����-��Ge�^p=���bE�0{�RI�E)QJ�8<�T��;�������w���Xx]/sQqXS���qy/�Nw��.��3 
���`�v[{����8�no��a���U#�"U�S���6
�g��`��~U�R�1hW���}����CL�i<Mf��B����u��n'�d�E��������@&wlG�����2���n���`����G�S�0(��I�8	���)^���Hs:�o�����,�������:������V��~���	����Z�p�������r6:l66R8�@���j�<����C)p��r������[�G��_=��{����RG��-�Wo��[`3J�lq�v���Y�&�LQZ��2e�V6��M8
U����zo�sb����E����C�N?��%u4��^)�b'z�����FnYxMJ:wq8�],Df.�%-�|����
�IYH�R?�Z\s��v����JK�ANIn������=vzUJPNv������`�������dg�udgW�S�����\�,8<����my�e������Y���R���������4	�]@�'�/��_��A��O��>��]�����Q����(#��wxd1�&!�}N�����u4Q���/~/�/�:��dd~R+�<�IC�����`��I��@>R8w����1G�N;�z���r+���m���?hW��l�����{����):"�Y���Gw�f���<@�]�c����������%���������Dp�������<(�~PT�����:U����i��}��������VR��c��)6T���;�3*�dWJQ|Xn�7���O�y����p��k�n��T����;
Xf��[�
��i�[��d\(��
��Ny]�������x��H���}^}
B������n����E��������~�[N?�eF\u@�V��$Q4/�x���pf���{@/:��y���%�h�%��qi�(���~���Y[+��M0
b��:����0�n��������:E�����)o��Z�bPJ4�T����$!�[�B(�M������{���cQ�%�,���[*�C"*��3����3|��aq�U�T�y?z���JC�+��������_D]b�Y&�# X��zmg�4X{0���hgL_�6��C��{F��;\���-��~����C�$���xQ��'�F��t�L���O�:��M���u�'��#���I�=z�v(�m9���C���� .rj:������Y����-������%�/uN���.���~T�����E��>��j$�����z�pI�)�BO1����`d��7S�@�(my�i������V������[Y���{-.8(E���J�?\��?���Ea��2#������M
����#}�@m�e��0Yr&�u
�U��MkK`cf1t���lX%/JV�:���X1?�d��&����W��h@k�x�"�
��aX	�y����.-La����v��z��Z	zQ�i�7��S���l�/9������m>�A�����)�}�;��`��������6@WZ�#���N�� x�-��;�}����j��>e`��e)I,h�C�/��J��������S����1m�{_���������c�L��#�,�����HZW��S�o��������*���C���z����V�$rXj�H3
-���BE��p�d�Eo�h:�$�W���9�d�_��8��?����g���O�{�]�~\��R�t)�8x�P�m�o�]���n�~_G���~K<Q������|X��o�i����B���-5'b�@����'��<c����!BXC�����$l�O��j��r}�kky�A����?{�# \��h�� �]���`��}jn�l���5x�<���{A�h�����Flk�){���@ &�1�����E�:��n�,�e����n��-
�P,���K��k�a�Qn�����q���pYHQ�������']������6�gzd0�E�R�2)��&�����m����:�{���>&�[}��b.t�@Gpo����So��{���[���[���v�;:j�9t��Kf���������}���kI�#h�t_J\��h�uy�nR�zE�1�T�AOK{���
����|()n���}u�ac��m4�9��mw{k��]a	o��V>O%\�9�!�Uh���-�-��;����%t��*Ja�
y��$0�������bU�m���mQ*�W$����� ��"���>���]~W���)�|9GZ>��+;U��.04����%#��u]x�M��5������B��W��P5�H����43�w:*������ ,#�O��������Ra��I`��0���U08��F�{��c���)
H	�D�tI;����S�u��Je�v|l�z[[��
�������<��fk����M<���D7��3y�dr����p�ZJ��";�S��������G��-M���1��tth��=AFk������~�����>%����YD���+��y����V�) ��C�����Y&���	�R��tb�Y��"+������������uhm3�wM���d-����8�8.�'�Iw�D1��#_S�``�'�G���� ���@�A_��2�I�o���N`�F;�-�/j���:�I�F1i�VT�H���!�;�6!��#����p�PC(������-����Wno:c���;5�x���������<�dx��;�Q�@y��5�`�6�5!%S���=�l�0��|��O�V_���3s�M��xSo��D����-�"��:	�c�vxR�"=�������b�c$'��
!.`�M0"i���;�8YSzio/���_����g�5����j/�Y��n�Q��C u��
�����q�Qp����� ���{���0X�� ��Ze������L|3'@"�>��?�����$E��$������e<i�z���$S��������y��UNg����?��.�/�"�����L��(��g���%r�i��)k�$m�I����a����	L����9G��yf��(X�����q[k��mH�).��S�rF����E����`�%�c����:�#����t/�D+4`�=�n:h1
�k`gyA`�.���v�}��u|r����mhA�Fl��4�=T�S��C���A�����;�<�?�Z�$���h��(��%#��� ��K���(MP8
��nZE�.���
�w&��+�kd�h0���f`w�x�>���^<O�zKa<2�;����6Nn������&���'�������$ �	a��F���6���Q�&�}�XUX!���V��M��H�@e�g(xH�5"��F#0��w����dh�5����q��U�A�K�f����;����u�E���a�x����X�@��E��p�WP����R��LS]d�C^8�{U����_��	�g�x���*�y��h��99���p�.Gv�4���
���q4�
���� @a���Qp!�>���C]�$V��`�2DmV'Aq��D����[g������������e�C�d:2;sV��.?%�J�{��3-�Y�T�{1E�I���Bs�;�>(*:�H�j&A�3v�D������~�
�b�6k��fF����I�${=����~��pw�|g(?-r�}�!��/���iZ��m�V�_�,�FUR�&��u�$6i�VKC�RwK2��<r-�GJ����)+N��D#	�y��Q��CM�q�Y��v�:�4ai!�?�M����5V�����1�|�������a6(��sG�A�14�H��$b��90��m6RO,)��"6U������nhT�.��A�&�#O�0�7a�;�]��B��C��e��������j��y�H�U���'R��zR:�0��������F�Ux
�X���Z���-q`��?1j#r�([��,v�Q"��#!Ik HF7�
���R�0��5O-G���0:z�<-��������d������9E�1��D��#������7��^�Vmf&���4��R��i��6D�:$G��A��#w��>������o>�S"�:��rN�)������'��������Mc%ub4�[@~��LZ������bw�&O�bLqs%!�3� iyI��7��C���4�"��L��!K������0�\Q�_]���������W�7r�Q5��(	�m3 �3>{,��s<N+��;�aW�9�&�6����72����	$*��kx�b�(��+�Qf�
��Zm�Hy�A@'_�l�������[1!3'��:��h�;��KU���'&w�:n��(�`�#�p�3�&s�X�9�O���p�V�A�Vg�����oW	���V3��;p�Q����up�!��� 7�o�:�b��1�/p�fY�?�L��K����x+#j��<k�����X��j�*|�}{�*?m��z�|�x�
/���`��?��V���k��!���-r7�v?|��?f�F���:�6����Q;m�l7/_Q�Hl�������9������������:�6��3��r3W�������Er��5���`@� ]��������we1TW��_�DL���:�DC�S�s�s{dnmn�7W�G��p��)�:�/��������H�{[0\�B��L�|� ���_fh�'�B3<��L������KmQ�I�i��1�9R��dK���-�����	�D�r�G��Wg���h���<
H������(��\D��&�N
���~4M������������H*���8��&6���������w]z
��}].G�����(}��`������s�o��p�5�&Y����~���a���X����4������t���)���F�Sx5}���P�sb$�r	(T/�y��2�U��;jE'������I������tH�e��Y�f�Ht85��&�x$L��
���3���9�������,�v
QzH�p���IA��[/��}��p)���Tw�U�/�3�f�����:b�����.�'�������S�6f |yt���A��n��>�$������&c����0K�B������,8���j������C5�ks��EJr�)m����u�������h��R���d!���!H�\�2�\����V����X>�T��up�����Z�2m�N��c���.+9�fw9!;s�g����"e��S�vep���a�.��j�Q����������x)�%)��Z��74���H!_�bN��`��D�5���l��/x�A��BT �����=bC��H���gqpC��2���5��+��h�]#��vO�M_�����i^$�_
����
�5o��	����[q���a�m���O�Z�lG6�0���q� �a$^��J�H������[�("���%����^2�;RnE*v@t��7'�"��fCw�G� ���9������s�������L�!�G���VBv�HRU�H�:�������������h�:���y\��C�1�x�q����2b!$������A�.
��]��	{�$�-��+���k��X�7����U�����p��.L��S,�M`:��X���
z���!���kbt��q����
o�2��������ev���lm[��3��;G��,��5yZ�QI
1�����mY-�����e@1CT�t�S�����t��W�U��,@���PCa���"��P�9�R�KG�����wx����O��@xG��1�D�����O��
��N���������
��������L��+B��,:]��;h��Ly~�k���(?����Z��*�$S2U'�%S���f_��z���|�>S�������45�g-�@I1��(�Se]�����<�����<���p���2�&�B#�|�%�X�)^Bq��I(��E���-J�-�)!YGEZ��cb)���Xd
&�dk�@-���A���e�;��QF��h%�'�*���y�]��R���P2E������.XF%PB#T�"�UIf����>���K2���������uv���M?
����j�>���L��DE�Z_�����*�2=����,@��.�]FycS��_s��E��t�b����]�0L�x�UJ�.N�����]A��T,�z5��5���I'����f����H/4�x��D�M
/��B_��!-����n�z���G��f-�M����z��������q&��o�o���O�\�.����-�[�A#L�)rc�����������S��L��h���6{[��L����4�����,7����<�����:8�G�f�L�Q�"�������.l��C����e�'�.D���qP�<S�����F�2|�O��,�1;*{�9����:bc����L����*���|j���)Y'*�������I�2U@lJ���|���TX;{�C�Y�=T�>����n�M5)[�m��o6�KJ������[)k���,(�e�&�k�B���rR
��z�xy��,���	Os�JB�#	�8��W�����
�����bb�M��gEq�B�
�����24X�������^���?WS<��*_G�)���B��4S�J6�v��Rj��`��;����Z��.q~�A<���������e���y�����/��]���t=���'K���y4�lw^�_�N^�	���c�m3�Q����&~���p[���a����RAG��V(6�c}����������I�����+)INk�l-���;KMr������1SQ��5%g'����1c�	��
���b����OkG�^.������
wP���p��������������j�i,�����\�.������U~
�v�.�'Yz0o�V�f��F������"��I�{�j���[�����i����&�^��8�����N��\��I���$D���<���"GP��Z��+��
�ul&����UL	�p�w��%t�vU�l�,��h�0/,a��[��N��s�Mw�vuPg��`3���C�<5��bP�7�K���p]��#s��ct� R��!��"Z�2�����IME���zG��>~��(4/3��Q��������X�K���`��26���sD1K��N/N�k����t4Rn;:�W��U1s�{qa�C���K
0���9>��mv\� �"���fY�Ac����`�K+�$]*�F<e�-��`��e,8�='���V��HNN��<��:�s(}��A%O��;�*�C��f��l�5,����^.�yP{��.�TD�����K*��Kg2M�{��u�2
�8�MO^!�6�o}�r|��xa���^����p�{;"c����&������gf���;���|d]�p�&����
�Z�
R,a�3S;F�4��\R��%$������� .�"��e��[?�a%���_^~�����w��1o�
r��q��QV��JfM��Z.���8,C������{%Wv2J���}��������T��d��3-C��
v!��Ulr���U���c��l��E��E�=(���|7e��m��viI��]����[�<�j_O
{g�R55����-�oL���<9j|KM[�����-U�VcY�f{��:1�����n����h�)2~X
�%Q�g�1/+���X��Zs6���[�S~MY�G~�6��h�����G�:�+��@�a7�@��]����=����6���l$,���v��C���p�:80���g�9�D����m�>)���1�����c��$�G<�L���K-1��Y�H�R���2~#X�oG��VuYH�d��E�W������7�/W�_�A��:��o��;_Jl �����->8����w������$��F��������cE�������m�!Er ^��4z�F	��yX������f���S�4�7#�0�������'�aC�&G���p3>�=������!r�F]h-�Y��r2By��b��� ^���9N��#����o�l�v�]�����_�B�B#!J�53o�/h�\K�o��E_�gN���QO�b�k@v%���*����,u/z�#\��M������m���;���o��R����-(�-]6������oX�����t!�~!m#��a��{f���o�V�F���<;^��R�r�
Z<��5����a���^�n����w�z�����}���x�VzaD
��	b�({k�zn&K��Kc��/^��n�x�m�v��?�`-����:��WWk��]���_��9m]�����G��Fa����4L��	=�����<~��H��1�����i�'3�����9���m>�
r��h�;�0���N&�m���ET9��$���z��y�a	��s�g���lr�c`o�{{K}J�����g�����La���k�s���u��R��C��LT�9��*�A7��C�g���<������r�2:`SQ��f��������l���7U��k_���G��	��f�5f-�80���Oe���*���/� ������!������+��;����suI|�o5�Y&B�>��h��k��\��%�������JA���[a�I���zF��C���[�K���>W7������N^0 �'��l��$�I���d�M��ki�CB�(6��[`N�d��R!n{�:��_�S����P����j!���(�<q+��=�3��T���������S���y�[��<;��=��z��V_�A�~s8S��1� ��a"��pwX�����h�����#�M�
vq�<T��;$���������6��~���;[�����V��sE�Fgv0�������������j]�����b�70��y
���b���y
����+Y���
J���u�����QF��R����b}�;HK�������S��P2�<	�wv�t�6r,���-�5�y����bF�X��b�de��_�c�e$��� M %���Q��:L}����s\������@o1C
E�z�K[�o������%B�;�����]0���������!j?i%��~���/:rx��R`�&������s�����.����>e��L1�$��}ows{q��^�\�&�����F���"�0��9pi0H`��%dsA�*m/�}L+$2;�����5���4F��T���?J(�-���N�7���hw��XPy���es�z���������t�r���_�)���)en�bO�7�x�6�)���������d)5���|`�e��7�`g��)���c��2�^S�,�{`�%�q��w�'��Z�������.+�r;�3z%��VT���'L�f���<3������*=u�����|H�gGHh����<��i�d��k���gWK{\2<�,� n��&%�$3���5/�M�F�	=!��?d?a+�(���e�������{�5v��3�2�*�kg�k _68��#��Gr����`��PD��J"qe%�h�cg;�u!���J���+���������bxm�Q�v:}?$�X+����UO]���60�]Q���Q?�}s=��1)K��j����yi���^+�9��iwzu�<jI��]b\#nr=H���K�����jp���A\1�3��S�����J����-<>�o�%���Ju���(K��qP?�r� �:�J#9e�!�%�$��@Y�w�M(�@S���=FJ���������=>�uq2z���9�wx�Y��@�Kd�LEiPoMq(S����Z*��)�ik���@
t��[/�/�L�������o�#qE���1����x����"������3���dZ�W�!k����4)�B����O��;G��/��N���2��Ze��y���C�����$�N�v�n��k�sm
�+�bQnqM��d}�C3��ux���$�sth*������R�0b�P�N5j�����N�f2�vS#U��hU�,x����,m�ayT�j
�Gj��1:���	�e(�����Y46a���c~&
e��,����r�]���������Zz;���	��i�H�R�1P�e����i(�(�<t���4tv��/�q2o���~�f��d�9�6|G%�!��
�Gb���dB���Q#�Uq�:�K1u�V��D�+
��K�*@�d?�u3�$�X�-����g���[�-qv��.�5�=}�:zsyu�C��mpiZMH��;�$m�t�];�}=����O|sd��J���q��uv�:;��sr�n]�5OYV�C��l)��_�Z�r�!��q<|_W���d����1����N�G,ES�bOF0(�q�u�� rfA��KD-^>�T��B:%�}o�8������W����YXb97L�K����$�	��]	��~�tm�@N���v������5���Y��I�%�[�77|����^}+��:��k�@�����#yL������O��D��-��g(��>����t0z=��6t����1��J#������+���e�C��"3��H��.�OO9�3���x�Q���t�i��)��ap�R����:�
L����0�a��DgE���Z��z��G�~~��U�YK�,����v2�#
z������������9_�����������U��S�)0a[jZPc�1���^���],#��3U6Qz�����th�f���W�}R��'%�57����1��K
-�jJ���`w{����n�r�9�l��e�<��;���qF�k_��O�&�6��@�?�'��Xl�CzV�5(�'�XO��j)��X&��%��Q�/��a���Df��M�X����2�&�\�[^c�k���,�F�Xb:8�����V;�N=���w���������tPp�g7h����Y6�T ��D����
T��[^};5��E���Q��6L%�{P���� xL���d:^��g@��(��k����c�U'x�J(�����s�SwI>���6r�� c`TUP�����R��&��������VR5K��tY���4��D�k��k�[��J��V�R+���yRa?)_�s,���&��������w�Bm���l��S)jJ�/��F����gx��/��]T�����7dk���v=V�������R�2���"�t,���*FI ���*ib�nL��J;j��/=��Gq�������T>H��fI�z�	c(�72/`���Pk��1|��|����{tY��=?o����|�Xf��V��[�GO(E�NL?�������[������pe�g��H?�����L"����(����Al�����	��%�Q�N��]�����������|{�ed��?���`8�����N�������>X��x��YA�]��������n��&[�L����q����d�����S���Ke����G9�S�5���m4*�����J![�k� O�����[��<��#�v����tG�Ei`i�����fM�j����o�����ST�qe�u���g����o�~��T�N�I--�'O��Y |2����/�}�h����$[x��1�;������Y�wWq��o�u���������o����KFW�xsyC�4�A�K�]�z�qd���i��S�R�M-2BQ�����HB>>���
��0��v�F����S~�&��}�����K��nPI����N�x����kg��9�L�h���������������Z���J����v7�^��"#=^Yy%�!��yr,����Y5)!�y2�	(�,?6�B4(���<�IU9p�tfj"�s
���$a{�����`N��������w�lBR_e�f�B�i�k��V�2�^��h����0{�����a4�{�{�N������lm�k�U�4)}�����heI��gPh�E*&8���7T	�vr����K�4wD�����^�	n���h�I�F}���T�L��j�	��Xx
��)��Y\��G`4��V���6���@X��q0p�����z�2��>Gw�nF��L�n���v��=#�2ly�l0kt��"�8Qd�q��{��t[�i�o�
�V>������u��9n_$��s�NO�'N�������,J29�\�$Q:�����x��H��V���t�y[
�t���e�Y]�l�����9
�E��'A���P��6����x�;����s9�c��(�i���w�'���k�x�����aL�,���G
�Z�j�����"�4&Y1k�"b�A��h�:�6���x���Z}���}XW�y�7J^��,�Ae�N�hu���n�/�q8�d�9��;^�.O-�;���zw���m�AY��VHn^Y�k$?���I��h������h�tOWI�����Z���u�`�P�[�jp�)�h��Pq��F�D�/�'�;[;���b8��E~���Q��,�_��S�=���������tQ�1�;��%�9���:�"�@��2<��5}�ao����������6��n���n���U��`{�PO����i�$��}N�	c
'����7���(���S[���:4���jd
���	s�����=��8.���0hv�
�qT(��!����@QA@��*��S�'��J�9f�(��������*3����t\�}���U��U0B�*��'K�Cn�8���w�v���)��E��dV��d��hAGb������/���t��]J�FPNN-�<;�|-)�s�:�!g1�sd���0�K(.O1��@�Q���������I�Gt�����h^�����9|��1���U��u��[����S����#�Wg*���:F�5������km��Zej�^����9�=���[�~���_l���{���y1�^�7qD.m�")0��A�g�x�5�j��Ef��8gm�Su	C���������D����������[���8�"%�	�*�G���_~K�G]���,�N����J1�"�-D��GX���laxG��[�!��{�
����GB���u(�/R��`�H���R��O���x���'r~���$�`F��H�����)E��DzcN~g~H�b��V
^�5����d����Q������@��x3�T}�ag���N^�����NH�A���d�����'5�S�8�Oyw��1���H�I���R�=��@������w{
7����f�^�
�����vT��g�pT��������k����.�
�����P������\�����{��ODe�����m����g�#A`v���s0p6����5J�3)zt�1���k�@��4Z���,�_G�n
���#����e��o���?^���������Q�����h�Bw��U�0�&I8�e���C�:J!oe2r��X7|�o1����Q��h���su��L��K'��s�Gg6�e��%�����m�����!iO�b�`�K�@�T��B�q!�p��=�1�$��'��P�"�o�1����=��������������J��b��%J|�P�!��R��0�p5x�i�j��$j����hKZ���0WAm�::�����L��X|Q�����f{�����be�r<�K��LsI��8)��<r��&	0^������V23\}>3���"bR�=���\n��7v�����FJ��VtW���1:N�_�\��	��}u�JWW��h3����CBPPO[}!
@FIN�4����S�5#����"�+\-�BVa��vn!�Q�5�(�I�`T��_�*�*�\�����~���������. �%#����C	�"�%.� ���#����#9!�Jqvt�A�w�M��F�����C=p�9y��4�NP ���hTQ��`�1/��4�Q�A���vq�B�������PE
���fc� �mZ�Dd�������4��\�Mc�9<�h]6���EM�s�l�`����e?`s/��ON*n��?��(�.��W�B��{2�?`��'G�|s���=�S8~���[�/N��V�X��p���Q��9k�|�s�Ks<{�K�n���aD'��E���1�1V��Sq���l�S0\buB|�c�^K�-3)�\��(r�r�&���3(�O5�+g	�;v ��Z��=/���:'gWo^�<9:i��ag:�������:�`�arS[%��:H���*���P���@(�������n[S�9�BmMqz�T^���|��<�s4iZ��������Y
=r���`�5��}[�����4Q��W[��Cx3�; ����5�NA�?�{���BZ�<���)���i�2$� ��S�mx[���������2�4m�'yk����;���
��hWk$�����I���l�y����{^��N��l{[2p`��Q��
l��\f������!����!��E:H]�&��]i����=�\�=��Y$��Q�8�+�:{����[1����m�}��P��� {��A��
�������]J�a0.��������l`i��CI�[ 
W����i�p�u�Avr �o�B
���M�������g�r����&�bZ%�k��(;������:���Y��}�O�z���F��77eC��Y+������j�{�VZ���)}��Z�h�P�|6�����"�c�T
X�1oA��E�BN
!��i�jB?��
I�e�7���F������teZ���1mj���]���uC����=J��������\�8�9��I���V��d\k�*3��R�Z��-���PU
)���k����$=2�|��L�.}�gP�)B�Q��Kt��6��4}����O���"�GU>����d%����h����K�K .D^g���M(�;;��H_D�G��>on'��]������f��������1���$R����xVU�K��z��������C	E�(���q�'� �����l+�),��FW�����u����O`�W�NG�O�6n_d^����S�E���W ���I\�m�W��W	���N�:F��z�[#-����'.���=�����;T?)r�{RzO�Ii����i���
��=�K������d]�����l������p�G�j�u����)5H��	�!J)m:F�}Vfdr��z�id4Mb�-����0��Ll��[YE�;q/C��I�����|EI�O[�4��E���ETj�4����3)V5*1���E���X�jy��8�]�SbM*u��O|��J�F�&D0�Px�*R�0*r$\����8�:��t>Eb�]�&x��Q�����*jV��q�%��7p�@ ]>�K�IAuN��:tl���}�&o5\
KI���"��
�P@������_�� �}��w����1�1�HPF4�lw����/���"�s��������^C;����u0��r��������-�t�����
A|�����"-����_�*����\R���bJ� %C F�����	�T�;6#x������2���6��6��6��E�Q<���j
�|irQ�a���k��'m<r�X��z.�����M(��k�����y�JG+�F������A�CA�U�����&�PZI|���.^]4��sp�T��t�m[�2�qx�AVH?<�+Sz%�����5I�5���@3���5.�	��5��(�x��i'���s����/
QO�N4�mQ�
�,��%��E|y��rr����LA]����}��0���n����DU�B���-s�"��pg�N�n��X��]�������UU	c�|�.4�������{M^�^��To? Y����aS���,�0���M��p��E�{L�COn�AC�G�
F�
7}i�@�9��B��C�Ddg�����C��Nx@����B��a������&��+��a�6�����Q$`��{K�k������l����#J�������������_����J�R��%���DM��@��]">����9��cLN�������	����������(�q��7�����T����(}�<Z�y��rP��J�n��UO��N���P0�%�wE�*�
���L� ��?�.n��0�������a9�����f
����'S����M��1t�7�m_6�2�s�^��c�Qo�����r�hBf}\r�D���LND`�Q��U������O��59�����z�H���tv��Q��x��rA��&~��/��~Y�	�����zh$�J9�&:�gJ}9��!0��'d��o�Z1�P�.�-������w(�b�s��n��'�_�M�f�=���{���2Q����m/�d�������^Mu5$�������dSR�,mJ��K6�*����dC?t��g��j�>&��������Q~-�iX�,�����q��y�|���C�o�9����X���|�@��.���B)N�3r������h�*�T:���]��KeF��z��U�����[�Ju��9;n�<9kw�������@�3��z�ZN�G�X����2\������m��W?�������b:J�-)
`�����g�`���9_�N�aH��=�2�/�y��&l�c|�}��-�����JA]��������h�����]u�e;oVs�� WQj6����HK�Lrd"{d�han��{��l��E�lZ��Fd�H�6`���R�T� ������:���q���aJ���(R�Z�&��M��hQ�\A�[(?���WF���Av����~���|���TH��
�=���H1���m'*���w)t��a���~�B���R_(����ro��4�R���Id�u�JM��U�Bf��tV�E��G4O����:�AWk��T[��5
���z�K�i������8C��`��j8x��Y ����,����T�:����]���*e���f�| ���������^�L:���=��}K�\���$���c��f��������FS+���<���VsXw
x����5�=�h�u�1SlLc��*�2W��Z�Z���f�����|H$�clI��MC�@����L�"=��5����CU�g��QL�ED^)5�=3���N��4��~Im�&w�'�j��yyu���:���:�~|Y��JS*S	bB)�APT
���^h����	Y��$�e��<�|�&|��P(��IL�f*��~7�^��8u
�K:5	��GR�~�}����t� C�,����4�*�/�������jt�x��h��Jn�����V_�=�E$��)��+8�����):�'o�-e�Z��/���'�!�E!�A�&`�#�9`C�h&�1�dEl>�y+q�����_��[��C1_�)c�yY���Wz����\]�tdU��
A�O��00Z"����7��O�%���{��z�j}O}�&#�����feUx;�����7��xx#�t��@7�"�8�]�4�o�j�������I�'5���'�d��qN����e�:O���=P���OF	��|��z�@��=0V��v��`�I����(Ln��1�:���~�5%Mr�,��)A�)*�������|��������YT1q
Fr�M�&���rj����}[�S�"���v,�� ��/#�����B�	7G�!��	���!a�\`�YG�	&�F����u��!�/�X�q$��/������R\�O�>���W������N��* OY�-�J>��R�)�/���}��U|�*���h:Y�+�/��y�MH��$������{t}d���K�����yd��������'��\9�-����>B+B���wL	��y[������pB��:-����F8�u�O���U?��Y���}t�
0e19D��$Jt���C L���I��nD�����M�T�	*������z%96���o�������W��_�����
������VeV�$���jeV���w
y���Q���U��G��s���c����[������#��9<G���f�`4�Q�v:>��2i<k����(���&�U��4���<.���D����M|4������3����=M�I��)�Z�6��F4��	��=��b`��<����&=�����<?����k:��^P�R���"�����MdCG\�.�������6�baN�t!S����d�/�����f���q�}3�1�1K7}�:��y~�)������('B��HH�"��*�"��d/
����������p8�-���\X����:����e�wm�$)��H�Y_���M��I���$�U�n�(�0�Z5�c(�Uk���,�*�1������S�pI�1~�-�Z:�KWA���$>wY����7���]��(���5v]V&CU�J���H�^:��F���y�NI8
'j�V�L}��q
0����%-������E����!2?#Y� �	�0�����(���81�.`$@l�(���/%E���4*)����a�������^�p�`�g��;[����u���8������'���]�������k56�+����FS��ZWAb�"����2#oi�������������!�����������x�4M9JO)[YTq�v����x�>P�]	E-J��C��Ya���X6V�� ��3�n5	��GcH�7������y�"m+0�Ly����
<Mi�Z��Z;��  K��N�V�&5..�����0���^�+��i����[td��D��6DU����a?E�J����@���.�DG������L�a������L���h<���G�.]V+�+t@�����MK9cv�x����$F�Y
�:�O���U�H�`M��������Z5P�Z^N���>w&j��B����>��JJ.��B��lu��_��X3������q*�H��M01��)zQ�c�B]���r a���O���#��X���}SX
%�Fc�xk��
�L�����XTYUKw(������9���������k������=a�G����u/5�I�\��fy�zDZ�Ph:Be*�h�|�[�`��h�<��_6����{�K5��R�a��4k��8#���kuE(J������{�_c������\(Q�[Xq��h&l�K�7�x*U�Jc���cAL�8�5F!K���R6�;����>������A�N_�P�!�l����o���W��{�"����bhz1�$���V��x�"I��@���	�����x�[�9��+'�����{���H���Fk��6;��M��n�MI')��C�o.N��u+���";���I�:��Y��������k����� �^H�\�P��ct&�>H�1o{����)i�w�i���"e������Ay���C�q�w)�|�5j�Q�x��e��.��n��0~�s�������y�*�����������$hg�J0;��H��#��W�zv_`��($��_�n�h��m������Wb�Z�} �S@��z�xMH�����L�s)����}�`�7
��)[w���y�A���)����Z!z�������������FQ���f�#4����>�����i�7��9����/@�������P�""��oZ��������j����K���m7g�������;c(;��$i�����b����B������wTm���9�-3I��F��?+��zP��azR���&Z����>�:!����'Q@[�M�=�_�d����]���8�l��.�����F�k}/��������MKmS��N�Z�G��s�e� ��O����D�E�������>�� 
q�����&K����F�FRY�e�Q&)����r����F�{o�6��A�����EX��) �|��K�6�f������z�UVv��Nna���������tJSu��	��'�Wc�xS�P]		�AK8���i3��TDh�Md����T���(*���P'�.���J����-%"�����c4�H�lWo�D4����{����"g��k��RG��8�]����e��#.t2��@J�U5~��0QM�2{f������NRT<��B���������Z�t��y���R�V����W�7����{���3�IEm$Py�����y����w#�}Pl_��������9��d��'e8��+�R�����fI�������g����z�D�1Ie���������V����S�����������p;���C�T�mM
$�������j�_�&?��n����MO����D�N�Lb&=H+�v5�2��lW������u�aBO��>&��
Un�wn3�
3K����a�d���y �������"��W����n����Q�����8w��Nw�Y���`�N���k��:�Xx��w����p�:TKH����r�v;��
��9�PxA�������Mgp�#G���ks���%���&�Ij�x=�����7Y�����tQ8���d��\4�E����
zZ�aO�}���3������{
��d��sg'-�q
l&0����"V2c����NT�w)m��p��H0������M$x-��wc���L���)z�oscqf�-J>�
TT�W�v����-[�M�A�qTuG��_�q�������q�������������������0O����=J_p����Rg����k�	Mf�y�>�����C����>�yJe[:���(�z��;���
����j�;�������������?�`|�x�9k�n�����������$/5����0x�;���'���,��D�c����	���"5U�����u��I�1w^�%M�*	�x��$_�������"���	�R�6}�X��[+U�U����'G-�KU���Fc��z%��r�=Q��N������t����#M
�""j+�n8�j�T�Y�� ����!��g�Gz���YOs*���P��Z���z� ��3�
��,��-����c���7vTS����+l/�����r����c3�t_�kEX@3��R[���I$�������Jd`;
�j�K��l���b�
������{�[���>��X�k7�.�����iK���������&c�0��������K���T�(��iH��a\���yw�9�J�$��c���������M���'�e�U��r�*�O���wQ�2+8����9���0������F�������U���	�AE�����h�d
6���$���I���M��P�R��6��R��HW���\��P�#u[�u��eg���F�4�R���
YY?��N��(��j��]������L��`��-l~��B��\���	�IN2�Y��.e���[Q����������Z��mY&���W��U���Q[�a�G���X�,�S&��M(l���`��o����C��*��V|��$������d.2��T�b����Q�k��)����Y��]������QvQz�~=����"���5��<�/�a�.�V~w�S��$er��{���?�7��]dl���Z1�$����@<��/����aD%\�t����;��L�X`g��^���I�x������(�`�EL���b���`��^5�U@n'���{�g���|heq�e&��8���O9��D��
���cL��A��D���'���x�q��v�����F�r�L
);����~\�
Z�b�Q���h�H+c��\��x�y���o�u����4�d����<g������\��r���Py�j�����\!&��j��7��Y����������9�)�4dGN���t�M���X�G�tz�.��^�/��K�V*Gb�D:2�X�Q�h�����O�
�TC[�,�|b 'kw)�k�Y��zh�n��Q�2_��j�UH.�,per���t"/tr9�f��+<��A��5�Y
�?%�}2'����I���=��z�k�����2�r$=�B���+cv#|T���M���YU�8x��Zm��� �����1�_�eh�#C�q���!7�;
��P�h��'1�_�=D�L������i>m�?���<o�EV����JD���a�a[���Xw�]��~��s�i���'g���Y���p=u�>?�/g����:r�Y�t�,DS�K��)���+����iR�t���5��!�!��Q4�rFFHfD�V�-J�M�+��c+�������f���7�������'Q�!���e�(�t�����&�D�����jd}�
W�B�� 1p@>u��3��+��|�>
���#��!�5J�(2��[���8�3;;[��@�RO�N�pX�C�n�w���t3�����V��f.�)�V������t��lV|�R_!���K�X������ct�)IC$+[�T�X�L��n7�f���g�j���_����s��
9� �I��u�)3U/����C��E��zSe�<c�#�2/��=���#�����������A�6���X�4�g��)������4����f��Nb��E�!M?R��7�!dn�����J�����hf6�jeU����,������y���v�;G�N��Q�}�+}`�n@�r���f���l������������	g�|y5�H���l���g��J�
W��(��*���C��8�>C��@��10)��j�5Y���������bHf	������QZ�KX�r���>�R����������d�ja���<`���e���+,�5�B�J��gBfZ]��\1q+�
���6�q}l$f��n���k�r9�0�m*��Z&��sr�yyry�>j����]�
)D4�u�;�Z^(��Y�+-��&�%�V`)��:���n������+j����&����J{�\���)����
��`XI�f�GP�����CCsn�����54���v
M�������@��VX����r�
#I�Um������$���F�����\g�c��UM;3�k0xl�#g�;���N�l��>�7/)}*%��#5T��*���~��o]�{����b���?��5P�����m�WbO�
�hC'�|>+qq�(�GH2���Y��m�L�*��.p�|�V��8�'?,�~�siK�L�C���h�f�J*�D����'�N����]�.��]�Z}!�_<���d��ZK�Jb��D�'\����n��������������VX'��RI��c.#f��=&���K�M��<�x��^�H#L�l��40W;T�fjv65p(x��,+~����	2���$w��JZ�Q1g9�T�|���F�)����X�U���n��M��W��o�Z��h�����VV�`������~��"��s]�s_is��5����mgo�-�����`�>�N�bAY���]q�UgJ���������P���uP�*����Z��u}#�+��h�n^[�,$o����|��[��m�Z&��a,�8
2�J�$)���'l	�ud�H�g��v�<��-9�y��!�8/{���!M�g :������=����MLm����������.�'T;;��R�V&^b�ez����4J����<����G��p�6���� 3���<�/	���E5R���9���*���Q
>�U9���������_��&��N��� <���e���mp���'����=cq�����k���i�_�[�x_{�#�ZA�%�8/s�k���<������*`�����vQ���������S|5�h#�O�0�Y�������>�1Vv1���#?y����k"���I����r����\g�%��qw$3V��P�	�#�Oh�g�mO(S��.�@D�m.c���I2���$�o����7�P9$<�h~yh��HBL�&��<-����~�L��Ucf�.�&*���
�L��=/��ok�����ZX������L���� ��Y��;�\\(����
��v��T�~��oS�=�3�|Rp�4�T��BrC���f�?��l�A��N>2��9��(z�&T��>9����O�����k�c�A��-�������N�d�����G�~�:_��Z	�	���7ZHZ��W��@�(F`��3�G1�M�����p������,G-O)#�������-O�����|�����������7��MXS������Y�o
k�c�7�^�X��<c���^����+ngU���%�Q�[�?���y�:T�	��4�Z��4��r:�g������R&`���U ��AM�R�T���0���Z�_�pj[Y��fi�0���m���0K�����/�v����)�b����*i�����/]y��e�0S�������
0�1�g����PZ��g�A>�F���_�I�13,�F�oF�y�wy
��LR�:On2Nw�7��<����~����jFA�����&q���O����1��A/�u��d�����uq]����Z����7��z�g]������p��fu:	���g]��q��x
xw�0�=1��n�����?}���v}�x@]��/y��)�c"�Xf�x��3C���0���".c�������B�$��p��)
�6
�ye}�.�(E�4�!� eV4�/���+�t�(����U/B!����>����7�PId��'H��Y�����6��z���	5�e�v����54�V�1�cv6�����_�OL���^�k�Y!.&�WxaIg���p$���($�����
�M�����L����\�_�;���P��MF�k*������9�%��O�{j�'�i<8������t���"����,������N
��p����L���_�d6�<�9��3�<�E�8��fdC�hg���2Xt����P����������D�(%�h]��T�A�h��y��w��c x�������~�a������=s�����~�.wYf�an�Kl�j��<�i�G�y����/	��5��5/�M����W���c�Cz���o|&����/X%28U��77�G|�:%�w�S�quIkZWO��R��z��=��BX��Ce
�g�i����BY��x��q0� ��=M;��/'
I�� �w�*�I7�����AP��ly���V�b�����u(�Y�ytz�}���ds;���u�	x�����q������C�6���c��x�E���dn�t�(��uy�E��b7t��CH�����'.Zz��%�n	Zb~��>G"��O���E��z
'��s!9J�����kk4�dpg#,lX�
!���6kZ�;U
�E��`��y�@�{i��������$Dl�z�I��%�����D�QP���>'y�����&�sc� 8!O9�t�����*H�j9��N�H�����{�g���Y�.���x@N]I^9��)X���	�J��yGV��bM34��|�����q�����;�F��H!1���l����#;��8�>`7}l��s m6@$$9�Zem��MZx~Tw�+����v�_���nr/=����K������^(y|�< �����1�����c/O��=��%�)��(�����g��6��f��m�FN��������
�[��V}�T���/�a8��j�P����h,�	�H�*RB�?�`md��oz[��,o� �����)���3��G�������sC}���HW����*�m��@z��)�8�������h�~�����^c�a��Z��NK�?s�ih�Ox)�������{��kl�r��������0��F�B'V�����64����dO��"{�4�l_��&��h��YNM��v��5����_���
�X%;:m�5�tXki>��J��+)e�V���&��e�4Q�.o'�,��d�.+��k^:O&�:�V����
0��Y��|, e�8��!]]��R7iwN ��fM�NIDZh3d�)�I���9|� Gr��m�n4�uk�2����������E�$�h3�1V-�,��~���=�x�|}r�S����{��+iD.������=�"������o��h>��-� �UT��C��z������B���������u�l,��3=16�]dQ���+-�Y^�j�.�5`N<�6���-��z�K��JU�����
��@��~�XnJ_��Q��UN��S�����7�����2.�^�������sKn�R���vp�V�|0�o��4��t<����z��O#�D]h,�X�@(�-�����`Q9�S���&��\����������L��.Q�)F9i�p�Gr��t
�l�>�\t�!T7�)�l�x��kA�p���8��`
�!�`C��_��=�]W��?��w�B�;�6D����Ejz�6����0-RL��R����	�r�y��I};�X�w��3���Jx�n�"��K����n���x	��HTb�e�e�:��V�������}cO���=I�yx
1I:2'��P���^�^�8%U7)�Vq0����1��a��(�����6@S}���g?;�^}Wnr}���c���f�������g9������� ���=�,��%;D�C��L��^������o�85����k�p�HN>�h��W����B���+�
����\�j+���� �%E�m(��bT&��
w���f9�)�C:��a�S��z�O���s�sg/ei������>����p�^����Sq�C'���n������#)��d����e1�t��f"�����(q��	N���$i��M�O��9^�nO�qCA8�(�'L���,��� N������e�[��/�/(���j5/��i�%6��fc��������T4�
R�����3��	���?�Q8�XR���L��}��u���������;^��{�(;����	���c&��g%�����f�#a:�1��,f�v�(a(9�,�p��2���t��oh!G���Lc�S[��6�v>��k}{������� ��<
��Fq�����s_����Kq�@�����������w<�U�o�"��e��TY�)�>3��'�����Z|f�0Zd���3�[�B�r��,����^v���5Vy��k���|8�m?8�9:?{y�*'��[����[�T��%��*UR�2Y��������W�fS�Th}�W1�P����]���o���H�q_�U�U��mr�R}����� J�_���Us� ���
�	�����I�\}tpb�����O����e
�[-��2�P�DqM�'�F���C�����M�}��]J/�|%Mq�:*Q�M�.eks_ti�t�2/�p�wn�:P�Hc�G�| �9a&;hL�����Q_��cc�)I*� �
F<=}U���.�Qrv,Hs1��9O��r�d���[�~�j}2��/q/�b!��ir/��/G��*[xJ��'_����W�{�8��
�[v��;���
�.	Rk����E�[>
s�>U��B��Se�p��5�7��%;'����d�Y:3�w:]�Zr"@"�'��S#!Cz�����(���<w����D_�:�GKa��\7
�u�.o��93`�6@��|DG���d���m�Sc�8���>���u�����^�`g���x�>�FpVd�1�
��fB��(q�
Qu4X��E�9�qX�4
w'd�n(��m:p���ej>��F�{>�tI�y�9.��|H�����h��K5��x����*fWP����aC��2*4W��E�����@n�N�)���D������O�������������
��j�>����2�(�Iv����� G�Y���{Us[�u�w�65�X�����K��D��M'z[q����(��a�-�+\'���m�]�1�1
����J2��
5��aP�v�bO����3��AD��>cVc|��}B�c��T;[�W���oe>��A��T�(�b���5?q���zg�y�s�j�!�����(�G1�/E�-@��Y��*���x��������	�?�}O�_+[��:��a�w�}:5X��A����)�;}��l��b����T�C�cY=���$���3�������M����i�+m�^�"� ����,�]R$gl��k-���8���tk�-D�=c�j��cI��,�^�'P��Z����lt9����s"vPyz���{������&$�0ua�-[�B�IsD^����/�Q*_�8���+���J��A��&q�.7 <��I��r�������"�'�~O����'�_�w*w�*X�CO��`"A������L�*��g�G���0��h:6~�d�I��5Z�������)xEZ�t�f�J��taT��T�8��s-X�(B���:I6G��8�}�M����/w�w-i�;���T�(V���uH�:�q���,4��e�>���$�=�����o��w�8L/��@�����M$����M���g^��Gr�t�S�*4cT����l_�����U����MuMP�d�M�'-�ZN#��+�2zzM�����"q���c�(��,����Mt^j����}y�kl�|0&�5|�S�����;=�WG=b�Db6�+�G�������`�T��/G	v�Q��n��~�v"��l�!�a6k��v�UT;�3;�d���&?��M!;2�f����N�V�xl�#4����<Wr�~z����JZ��"������U�`��>���q��)�O������oG��c��>9;j��s������w��n����7�����<gi5������h���ZgG�������.��c�vL/���?����9j]�q�����cz�$~�:�����Pr����8��P�tF�/�������&���{��e�
��������	������?b3/�/���~�N^���T�e������������S����/Wl_�s�v��$sJ���Ngw@����{`�z�����!���;��O���a���
�����=�ELI/}������v��T��w����~oX�!P�/K2�j�<I�9���a���qYb\������U���K�����g� f{��iw���������?��.z��=��]�Cf�g���'����������j]��f�)~�����e??�U9��*���C�{��C�e,?`�����'�%{6{���<��XU��8d'e���7�2�K�/>�����7����bV��zN�_W�����lW��Db���1�t�^�ouO���fw����������x�T�������P��,6);�	�s��_�
�-�7j��0��O�UO#	��&�k��7��|O����6��t}0B2kr�����2��%�r�m+���J���<D�O�C3l��J��������/[xf�lM��a��0�].���Zd����d��uP;��v��ND0z��oU_��v�%�d���K��X�)l���|�p�F����w�bu�������)�c���	�y�pJ���#���������I�4}��Q�?,�;��������p������Y�<�C)]@�qCG6�]��K������	�Z���#|�>K������I�G�o�P&U8?��uI$�oq�<{���
!1�O�
�2��w�������B>�|ZE��8�����X����6��oqy�1�6]��b4�q^�+.�.�d�Z.�vi%�3j~�F������q|�m����wS���H��2���;u>v���P������[?��w;��hW��R�aDv��!y��g�s�O��R4���o�X�bN���~k4�S��1-���%wL<,HI����6�M'Rv�IO��������n�n�j����r���c�k�d���i�SvIe��evF'��;�-2t.t����zN�!;�'���R�����4���������c .mH�����P��N���"��5��#��lp���x6��"�d��M0L�Ak���
Zc��.�������^a`��}��'W���y�wO��Yy����o��������8�P�%3�;{��Y~���?�^� ���1����G �P�p�.�'����p+ ��+Pc�������*���p��M
@2���o���?=�M9fn��E����t��S��pr�\����m��?]�_L)}�G���>H["�6�E�"�19N����]P�(?����U��@�������i5M� ����T#���2�>�����Ejh}6�w+WXe#)x�NH�W���Y�s�����;{Pj��m�L���/�����*8����t�,��������}my��sJ8�$ox�e��sg���1.���W;�U������]L1�����^�=�y��Z�B5���Xf;=�<����I;����'Vs���r���\+p!�{�����=pgk�J������P����;;��N��u�>�.4�vMZ\]d2e]�	hu�Is��%�f���[�`�1��0����u���)�c�~�)�B���Y~���~�o��D������zrX�|U�������z���SV����[{���
&[��
�7�@i���f��A������j���.F��j�����T#�c��O��M���~8pk.(���u�fC�����&�/���r�KT��q�S���J����q�L�>��b<hh�&��:��~�*�z& m���!})3��8�@���(���w����B5�1yt���.�\�r�0	Z��C^=���N�;y/����#H��_��7����#��)Zi�r���n��b�(���Hd|U��QE��l<��'�~�$�$�V-���6�N����;j��tX�U���uJ  ���z{�0�;�\ \gu���� 6��G�(����_A
�5Uj��A]Fb������V����0~n~�
0O��C�/�^��T$�8O(fx�>�~�eVj�0�1�Yv��,M�#�� ���x��
���X�b^�������W����2{�����1��`�����C�����I'L:��������e5���(s���A����(���N����5�$#jG�e�<9�z�����	�']��pr�z�Z�DM����@�E2ZB�[5`�:t/�P[��"��,
�	�z����jf1H���Ot�x���O���?�������5S p�hz���,m�
:�_��1eA��W����c,:c�M���,^7v���#`1#dS��%�q�m��������}�Ev���I��_
�$
E��h�O����f��w���m��s�4�7:.\��Ub��]wbP�; x"�)��O7��������tr�~C�����-��H5Oo��� N�5�-u��=F�Q,0��1�w	@���Q�6�=�_��"�fa��������l�
G��$�"7�$����Cx����:=
�������U2telu��/���'1��I`����8�������^}{���Y�(kC�y[Mp�i"R�����d��0)a�wE��7W���SxP>�'��yG��_���kI4��2;+g��0,1����1����l�v#h?� /�`6�'Ix�a�\�4�V_���i�Y�}���OW��C#� �����d�bM�����H#�]q����T��.>��L��c�A_�HCT��O��v�_m��b�����J6��ncV�(S�����_3Ga����h��Bu��n��Zn��h�?�I;�~�l�V��Xt��
����YQ��$�-$?�
SD�:�s@�M�	��v��'1���tV~_E}y�������u���h��B��������u�����c���
�`.��8��;�����.�=b��8��4�`��1�d�z>���6P��AWV>�q��Q��{�
:�/_f�k���>�����A}���#�lz�ui��]aee�w���
�w�����,��y�{���S���h�":l�8��'��$���cYQ&�F������?�|�x)J����
��m��)�|sU1�����W��w@}i�(�[�aO�V�8�����q���v�6��v�n� �m���O�_���u�����__m:`F�x����{%���������*.^u�N^}���h��J�����
�x���FQ4��^��5�8����B�Q�a����A�� �Z��-`g;��j	�m#��
�}�%�F&��!RXX�W��\;�/%���_���o�,2G�gg��[,|wo�k�����.����;&��t������� ��l_��
�YH.Jw1I4�.).�3��{��jcOo�M���U����I��r������Q��
�L�Q��C=�Ye��Wo���\�.q�:�g�?�sf�+�d44�/_e���VW�����j������}������^�<����e��U��U*I;`�K�����k�H������+Km�"m�������HJ���o���Y�Z,��It	��h�aD����De���%����u8wv~���~��������U�T�U��P�H�����e���y��u	�����R�N�h�W���W�%�Z�������+���0V��(������v��B�r%���'��d�����^k&�2�U��-5m�{��[������+�J�FP�>tG����Cb7�����	4��f0L�0��W��%��D��3a�)fBQ���a�� �?���h:Q��,��x�0u*7�NRvl�CD�=���]���\XU�O�z�A�G�ij�$������Hx��:,^9�>,��62c�N�@vw�`���� ��v�*}4��f���6r���fw�8���a�,���gKO�,i�d�n�#:�����$��F��N����m=�����dD��-|��	l���~st��I�)�3V�]��[�d��hJ`�������Ry"�$����D��Si.	;l_����s��J�i���3�B�77����V?G������m�@����Q���W7<�^��t;���n�
���N�w�������������_���_�i����������8��'���� 'I�[d���U��J8������B7�K��*����$`'	���A���V�S�>�M~�����N����������iM�����dS�z�-������x��(���U��w;x���������U�=��Ar�5��m�8hX0������
J]�O���s�;��
B�v��?�H�y��v���H5<�:����H=2.v��-��>Mf���<S��k8���~���c/��:�b\�8e���������IP������5���= +?��L�7��#'��E���a���?Z���M�� 
��~2���R��n���S����~*��[�OFV��c�*'�)�����S2�<	��[��X*������m~(�DI�����F}�������Y�R���R�3���-}�
�I`l��c>�WLo2��C�nb�n\op�y�=%�`��H&�S��e�Y�++����@�c�tU����]�G1�`�N�; ���"�Y�<�~���_`��I�7&����M�M��0���8���?I������2�����6��L%@3�l�j���c�y�;���H����fXSW�r�������\�4QY)i'aJ)7!)wr�OD�{�8�Y�$J���F��-��}�R��8%�2��1�O�1\�V�Z�x;���" ���U���$|kP�L	��
IVi�K�a�������3|�� F3`���I����U#�:��?�)�	�=���@w0�K6�
=�pA�bD�M���N���)�9��n�V,55���	�������Y�kb���n�+&�o����RID/bj��,����^I!�����H��d��
i���xk�-'�]�|��Y����tZ�1��2!���"|���	�?��n�����������,,����a���D� ��7�}p�B�������lv=FMR8Q�9����TX��D�r�����J\������:HG=�����t�����J$a��Y����A��z��]0��sLN�Sn�H7����������\��eL	�b��H0T�%C��[��R��e(J1��n'��D�w���w"���O$SQ�v�*���>Q�:��cpM4�D
�P#l| ���n^
������L��(���ME,�����.L�n#�#�MV�p������BN��	�?��������J�z���N�w�u��fh�G��|�d�`q}�S	R�=�m8���`7��U	�,4�D����oi���Y-�
�*��U������.������X��)=�Q{&�Q�	!5�g�����C���wD/�y�J��*�����Kgd�n�
�'��*� ZBrYOE~M��f����!~�\<B��i���F�([�h�cP�Vp&jrd�@T9*���z��g�s7c�Y����n�5)�d0�������5�BlW���rP��
E�D/���b��dd@yP�v�z@��	���{�q�����_�Lr]�LV���#����3��a��������
��xCv���v�z���f��'H!P(�.��P=���G���G���h�9��v���T�"�{d�0��=��z���-��Q��\Kj�s��c���Z/��N������D�
E��W��o.�w?�g���#;����[��~_�����&+�P7c��?����gn���E�Ub{����!���\���R��%q��)�+�y�+����j��L9���Z��M�r{��x dIG:����\������(��;����}h���T�e�Q2=Z���d�����
�����]��B���3
��������4��(�]
t�3��}���4�rH\� ��D���K���C��g������s}[kB���J�2�u�#��G� ���L~t}�+?���s��k��c����dV��R���Em��	!*�$����F���P&�0f=�dB����8�A-@|�3n�������� #����/El�z����������o���#�:����v�X
�C���'@o1��E��@���8�I�Um���
��,�msu7��5�n#W�Dz6�*�o�WLt;�po�Ln�Q���Sg���'&��1bcc����3�+����R�h<�<{�<�$2�Od'q
��q0`��QE�Z� hae��i��U���e�.H"�R���[���~YbhZ��s�SY�5,Nd��H��+B���xa�Q�i�z�(�o�#{����y��^��>	�������Dr�pI�^���i�e[����X��$U�L�!�h\�S?�F1�h���c�1��P����%����+:y\�Gx�Kr;�����DD`�����I���|N��$Z�q�@�|jqjhg���l4�N�:�P����qjx=�SSfEs_���"IE"��9D2�O�
�1g7�0j����u����/�Ct����9�S�j���x�-X��r��q����������~�.�l�id6��������������p?*f	[�u���-����V�[[u[��H�_,S�0�~9S�WfJ<{r�jh/�����/���9A\h����������x�\�h�'��~��r���l�Vc�mxM����A$
�P������mm�9:v�s��`;�������7f�5�$�n�~�A��v���Ut���#�Z�r��������F/@@��lh�&����+a����I�<�L6��=Z{P��'^�N���Z��^*�Q�����L��qv������9�R�������%;BO����z%v4O��r"��}��I�
�G����1�����l�~�����}�@����co*a=��YO�?����������������s����fg��r�8$����kf������;"<%���z�j���<�q���-W�A����$����7�"q���{>��d���&��5�400��V{�u��'��kv��/�[���Du����p�I_^�N�~rv�Q�'�V���h�{���K��%�W�N����}f`����d^�?�z���q������;w�<�HYf�K9��2���9�c�S�������}o{�r�(*6d�xC�1i����E����:z��L�&L"�=Wq�-��4�"�[T��#D@/WyK��RW%x��?hl{�[����NA�H��~��i���h�@qg�����G_\t��t8��[�c��S�mx;�������+����5��A��
�������x
<��wA���>I�w>�xB-�%���E��n&�q0����#�v���%��������9�6���������92SE�>�p���e�b�]���}��0T��������4����{;[F���^�����`?�
.6lld���cLn�i����L��,��0���)���*v�`��A���quA9�k�z�����D�q��Ctx�B�)�'��`$f ��o�"gN�@��a�:��P�+����>i�9���vv7�n66��xC�Igt�`Ni�6���Q4����
��n��s��xn8��8����Ykw�����-\����~gog����5�P]����MO'~��p�t&�����yF���� ��l�O���qP�"�P������������AM��y�&�m�/��%���j�96�����&�1�?�%���S�.�Wu�e]��?[�����og_�D!���c5y�~����	�'���S9���J���6��_�R����.���.z
�W�s#��e�g#;A�ST0G�g��=�,���VR�R��������}����-g��x����w��M�����~O�<��`��L6�����z���/�����O��\V��
��9������#	�����?_��`d�#p�L4���������s�����9�tH	��O�g���q� �����k�dq���e��C�����8���0��#���m
��3'A�j��JO+t�[YIos����� k8~���	t6����[A�'���������v��M���v��]Pn�&�/�%C��Yy!n�O��hQ�,K�i=eD�1a��L,4��4O����",�
�~���P����������~#��s���..{w�s�s�3��sJU�?$|����g���pD�>.�����k����v���k������
�7O����Qy"D�*/�wM���se�����YL�0������]|	f9���.?�|������->�Qs�tg���>�{P��$��+�1�@
��_��(�qt�$�r�<�D<v�4n;����P�r�[��*=k�n]]4�Z����N�&+��N��
�R'�v�a��;���noss����-J\f!C�-���
��W�I�B�8�8�v�Q�L�H���P�s����r��z��7����Q`y����K���z���0�c�
zFz��d�2�0Ed�8�@��������KU�[q���VyF����E2/L89���~�9a��������B��:9�����
���e��nY�E��:�����?��1���8n���*O3Z���e���!h�c:9���$��k�1Eo�>�Q� ����H�J3��G������^#�C$]��o���V���S����[5g:I�@0���63}<����f�6\��bG��
3�/&��1������,!����)P�����5��3����4�U���6B��9Y�V�)��c�aFVUOgd/���������������
���H�*���#���Gp}%W@�U;���������1���� �'��s� ��E.��$;�I�x���J���C��MswS�?]��W��NO�g����W��s��:��T��uk��o�e�R:9\8�t��~RJ�,��,���������	9S{������&��"U�{��RR?���4�����!��=�$G�mo���C>���)I(2p��y0R�erFp����}�����{���^-+T<�k������6���� @j��j�8��}�bX��������dd���GqVe���53W�Q4�-[����h(�(���o�%W�<�;���e�%7���-9A3^Q���h\[�:��b�C5�������AE��8b�BrX`�U*����m[�����k�J�������M�f$[vh��_3�(H����3�0
�>$�
��5/���}����{i7�����]���U���i��5|�����7�P���S��S�JF�!�&��%�I�HKf���7z2��!oR�,o�W)��4������^��tL���bp�W�5���.�V���_��K�e�ogsSq�����5s�w�2%5��	��dMu����	%��G�=Ks��@�����j��d�@f[���kj&�i�����krKU<	*�mt���*y-F�Z �\�Y��cP������	�5(�i
k�A
9�"��A��&��V�yL��r��������������x��8(E��M*�[gL�}o����h���|(G1�x�_�x��&q8�t��'�������X'_�����\�wZp���#��kec�Eh���?3�}v�)���^�H
sTUJfd!	f=��`S>���c�'��m�������/��+�t�&7�����y�N�J�O�Ce�y��7����Y���D
J�jA�I��y[�?�%g��aAG������4��@C��x"��|>c�\7��]�~��*�
���V���s��N�����e���Ps�;�����{;0��0�
&&���5:�z���"p��6@�}V�o�;�QZ��S�{���ST[��Z8��D�N�c��,����VpF��_��2eB��[-�|]W���h���/&�7o��L@Ll�$�n2$� &]6�~\R�O��1�H��M�W�pB	�;�U��Q]M���.!c��'r��|.�:���)��C�<^Ud�I6�
����%�@��%�aE�!yU�U����n!��8�U��-h]x����!��g�(_���V��# ����/5���5���F�4>��'	i
\��Y���
d���1B\���c�.��|�F�z�CRkL����2w2��=\'�!�"�`���t����'���/&��E�����s�c��Z���E(�� ���'� 2r�a�a��a���#��f�$^�����?F�S��vwd��c�r���#�0��t�Q7t���k�c>���/3��"�"<�,v+���w���f�F�$&g0-�kI�3�n�k(�:����B�u���5Y�N�����zLn�S,?�z
TOl� X��b��k�[I�����G�A 'AH��6k0�"8��+@Yb�	m���+�v����9M�����DnX�&h���r<WI���C�`���s��T'}mJ�)th5��eTq��_���~�L�|��P3�ot����������D���(��)���r�\��J-��Nc|P����)��')��eI0�z9.5���T�G�$��: %��X&^�l�W��n{���(v{�'<���Uj�@R�5�-5�*6Oe.��v���(��~o���L?�r~y��u��i����p�nk�|�4�6^�!������7�����tIn��O��<�vZ,���i�Ve*�5%�/���??�U��%���	���/��J*x������]�U��UX��(�"�(�YX�{��G5��
��&N��p���I�]������Z��u����s��X���T����5�|sv���"<>�$����=)�3���p�<Q�/�����d��� ����� *��������x���A�'�1wm���!
���w��X��zC��������u�<�Q�Xe��W��r�iR���H�/�
;y�=��Sb<6���O�����c��Zz�����{_������)V��q8��sH���*z�*���y=�B��+�\P��[h$YE�����w�a�Vt����X�}�+�t`�b��ai�On��U��'I]A�4���F�M4o�^w�����>v&�.�{I�z�a'Ct�d�K�"��������w���������OB���j��''�����)����k8�<9S�����h4�a~� ��w�A�l�^�_�N^����������n?��0���c�[.������k���v�=�yXG�/�kH�����SdD�
���A����
��qm��:w,�{���~����,�N}n�_&�!����j�����+ ZT���~h]Jl���z�z�|s��'?���^������"���l ���������99;n���6�^�i�j���W-q���f�����f����<�*�+���.�vU��U�'n���
��V��<��~^��z����Egs�W��q���/�?��~�����t�a��K��/d������S%��}���=n�UM^�;����w�����i����u����U��N��F����z��[��������~E:fu!�Q�U>&�|���6<%�d-�s�?�:LU[��XUzU�_E?�aX�����E���e���N'��������/2����]��;r�B���8��:��r ���j�=Uj��fl(���2<��FJ��.��:��(���RL��D� ��MArj�H�:!�%��B��+��8�_
��%k-�.��r=}��p�hx����j8��u������#���@����m�����JO����Of��Nn�f�8G��(�w��L�G���`��JM����ro!K��Wh`j���+4x�G��o��3�����i�����lGn�������:C<�CL�\�l�vu
�����.�����'�����b;���9��L�	�;�������v��r���-�k	x�V7|
��}���e�s�r�?�i��4{=t� �x�)���]@���B�������8��Qe���^R��������h�:�-Z������N�Cw|���.R��@�d�k)�B�������mM� r�A�n�c�p^Fq:��tdP��t�ol6��%,�� T���R��e�?�e
P���*�wg��:������y��|��m���@�*l7�C!���y�F���av7~�\p���������<��.��� ����������
%�2*+������seV�r;D(��vB�{�[����9��z�����9S�6����an��
Q���Q!�4��$���oQ&���7�2���8�Fq�
�e�K������b�dG���.�O�?u�q �{���9;��C�!����It�`2A���}�>g�z�q�����*t	���mmj���
�\A��M�J�v�T�
DL���'x�X�8��h�xB{4�':�,L�6?��{�a%��#��+��U�=����f
�e��a:)�����qp�1�nl�(��Q���>$������f��b���+��r�R�}��s�3{z	0sU2	�h<�3
����y���i8 ,/��3`�b<����Ia��7'��8�����:����S<�.�wsl4���x������q�c���L�?2�Fz�#��"��bU��0��)]3*��bs�����v"j�5�)w������&��q*^
�k;��`����UM������epCd_��Brb����#�cG�o������g�m�d�lZ�~n��j~/����!@6|
b<��c��x�x�����C�Mm����N�H[�IG���a�B���T��|o,��*���lc�.���U}��lqe�Z�)em��zLH��d��%rK��W�1���)f�-\Jz^	\a��}�?=e�����krl[9>�/!F$	��P{+�Q���c�}	%��&���dA�t�?�z>�x�q�t��aR�����du�}P?�u~����Z%���A��F�����RV	��b���G�,|1�`�qw���Nv'5��^#�3�&�q6fL�����\g
���c��|�5��?5y�O0��Q�d�m�	�����p�*pDT++�RX��@v�U���h��iNG��me!�U@�a�5n�#��Nl��R�3�q�P�n�=�8Pb���em���d�&7 n�p�Db��(	b���EOk��;B���d++���.`To��u��7E��7�������X](:�?���`,=�aP�o��:����[�}��:{�O@�9���U��{c����������zQ�?z�-��	����eg���]B����G'��;Lza������*(�.�m���`���m9���W���e��$�����+�(�=��1���o�7v��]��z�;��D��f�^�JC�?���\h����!V�{�������A�����]�#O�p�������$����b���P��������d>�r���}(I
@�/�d��D�}	QK�HA0��������f}f���
�g8cI��HW��L�!��N�.��:c�c({u�`5c�@B=	���Q�DTZ8
�}j������'A-DP��F�;����k$��0����qt'��XT��b�e�^��M�&���p�=�����~6��G|�z�]G�Pa����Mn�q)�l4"��h
M0q/)kE%4`�gP4�x ������_l���3��d=yU��N*��bx�b��� g^ dG
'.�����>����NQ:m��\��*a�8�����7<�ce��*KF��)�t��df�6�.�5Qa��
-t7��^rn�Q7�������L�W����_�
��~x
0B.i��w��l�+�6���
����GU ��h�Qc��u�f9��������]M��q���m
�������t�-,}�=%k�7��h;�'���=�i�>���d��M�j�����D`���#�3�Zo�����]/'���v�s�
��������m$?�~�&
�f���c'i{�JrNW�2$�m���%����Tlz��ff��.%9���*"p�}����>�;*rLK��{?�
<��/
��'�/��a1J��,qjx
qI��i>���]�)TL���c�����x���/Ah��`����`����q�6��I9�fY%���M���>��7���*���PUg������������~<4��	���%��S.=�l2O����F�C�UD+Ti������O�'&�����Q�k:,aB�Z���i�-h������1��\��v�HYwl$G�{ �^�����_	[�/ k��:;����?-���9f��	���/�+fVX^��0�]���X��S���;�Osak)2C��v�3o�3
R6h�M�|
��=�B��2�6a]�Q�C*#�t%o���|Ey@)��8 ��(��RS�~���z�����p�����;��wT���N�EvI���Y�=����w]�yxq����P�rS����1^t���=J��8�����#�5�!�*��I�lP/���x���S�TY�n+�)E�^�62�U����,JQh_WK�f��q����y�3�H+bo���>@S�X��5��~���p�+�W$��5���d�����,mO"�c�<��Z��K�y1s���c�x��AEk��f�������2��e,�F��I8��-����9:���Q��1x�A���2�+�o)�g�I�����zt*\��-N�Y4�+](���g�Y��o�W����zR��������!��q�v���)R�aXO�U+T�*$WK��PP�aw�S�{�y "����&�\R�U4(6��X@em�1��?����y����.�3��9�x��w�eC|88�OY)9��r���^?������p	�~�l�"!��9�K�%�ZS\-9�$��,8��-�m������{}��Z��{��|����SX��^�q�N��Ee�x�LB��G�����V��]�U��>(u��{,�N�{�t;���/T_�|'i$�O'�I�%�����M�[��-�Vl:�
J:y{�����?��.k8���8��7����j�9+X����`�eRh���h���LEn��e�r�xX#�Be'7	��c��P�yV�wv{������U�We����`�6��2D������u�C5e_������t�# �|z��0�V�r>G�1�v� ���(��0<�����
3�I����k�V�p��"�nB4��2��?jM^�F�(�Z��b���g�p��:��K��8�f����Ew��O�!�$j��M���������f4�m%!�-3���t�-pP���JD����i�t�)qq�a��W�T$k�.m��X;}�+����m�:p��o�Z�]�a&���oO�V�CG�����q��������L���0x�k�X�6[�VAR�^�Yx��-3��6r*#U��W4z1���w����e���e7O�|�PA��IZ��C0�U�C�,�#�N����1����P��l
p��~z�kw�4�a��R=�j_�-j�BE���#}3���Q�Y�_�o���i)�a��D����	��]W��2N����?�R�/�P��z������j<��:*�y�[��K7���U�!����E�5S!�-����MU��@Y�k�e�(��7NDY3I�;�@�$q���0�/
!�H����/�~='��;�&�������J�F�c,�������kH�����3�5��|��R/r?,�Q>�
�=�NKqC���9����,'�%�K��y��59������;�x��h�o���7���;vs����*7�R
��J�hr���8����R�O�Kq�AE�r_����(����T���H#]D#�b���'�_�W�&���t�pR%
w/��
p[0No)�F�U�������W+�_>�����B����\�������mh���������s�����8�Pb��G��1��Ug�	�4#w4����%�n�B���(���_#v�u��3�����yl��>�"��?x���@&�g���0*�K&K� ���.7'b�iV`4��lf+����#��k�w}����a],��y��X�m����y�K���<oH}��"�_[����;{w����j����%�Q��LH�7Bp:�w�(�J�sJu����c��)�.��������8s8[�-T�^N<�y��=�&�zx~�a��2^��l
����@�����3:����-�h]�d��=�[EJf�#>��������O
��=���G�
�.}���7y"j�F8��8�[�I�Og�L��*��nq��.MV�g�qp�`�.x+���[[l�+4�����{����:�-���?��?��G�|����:b��J���-B�xD�wh����w�
����@e���?��o�o~|k�	���Z�S�7����i�8c�������pS����/�9-����z��*�~,�s~�t�[�����Y� ����V��j@�W��n����v�[�����qr�zl�i3�:$c����6���5�������cq�]	�G����S�:���?�� ��4��{��������3"�O ��������o� �WG4w������y�y�.���[,z:xwr�������^��igP���!��'�.�1N,%�|����O�X~��]�S?�$����(TC0I<�jm����8�����N]�'�,^�@j@�$=o����	��f����������������J������7V�8������?�8L�?�T����Nb�	�W��.c�o��ca0���'X���S�N��O�S��a$� X�s_.�!&<}�������VaW#���]W�W�����g�1A�48�e<�x��B
��Q���akv$�����[��0�������N2c���.o�'dghK/��������h�#<p�o�B��~LhS�h>*>u���^/5��!�9Z�P���?�������6|o���pOz
�K��i-^f�n`]I���u��qD*��/�4/�2���%J�)+����Tsh3�,��Em��5dCZ��l�l���}�����m�>�g�l���}����V���>�>�g�l���}����>�g�l���%=x��QV������&5��qR�&���&�1L�h������Ye�#�t}M������P��-X"n����o4�)����h�&���/�I���Sw�
��36���X��MM����
��`���-s}�t%�hPS�����I<�
�+'!^� ��S�+�����������@`�5`���A��U���'�R<�E�l]������#�%[�I�(�q��o���PF�pv����U��<)8�*���l�Z��Cs���z�n�|���"���YN�ym�.d���qd�� )�IO'�<=����(/\�"7d�����Q�Tm
����T(�<%�[��^��D�Bh�w%b���F�%��V�Pf�������*|�9�y0�9�5�T�)�����e�b&*y�l�)�U!����=M��z��1)��0���Q�[����x����2�N�pJ&g)�h��G��S��VO�I�L
�i��I Zf�0������L��A�����V
�PU5Y�gO	���*��J1�m�f�I����
Lxy�����,�Ht	N�>4��$�M��.S�".�$�H������\K��??����*�}��i�?�Y���?�/�)$p,!�+���!���m@�R#�����;}��{WMaG�h�+��[���
����u�i�p�F0����Y��OS�XWh6�SZ��]
VfW����-&d*[[pe�1's��5�~��_q�WR��$�b�;;
�q��&f����k0���L(�����3�.��~]�l���7K�����'Vu�I���H|�����~p�3��+B��d�m�%��k`��^���p$��EX����B�
}��>Xg�9��-
#23Itagaki Takahiro
itagaki.takahiro@gmail.com
In reply to: Dimitri Fontaine (#22)
Re: Extensions support for pg_dump, patch v27

On Fri, Jan 28, 2011 at 18:03, Dimitri Fontaine <dimitri@2ndquadrant.fr> wrote:

After review, I included all your proposed changes, thanks a lot!
Please find attached a new version of the patch, v29,

Additional questions and discussions:

* "relocatable" and "schema" seems to be duplicated options.
We could treat an extension is relocatable when schema is not
specified instead of relocatable option. Or, If we keep "schema"
option, it would be used as the default schema to be installed
when WITH SCHEMA is not specified.

* "version" field in pg_available_extension might mislead when
a newer version of an extension is available but an older version
is installed. How about returning installed version for "installed"
field instead of booleans? The field will be NULLs if not installed.

* I want to remove O(n^2) behavior in pg_extensions(). It scans
pg_extension catalog to return whether the extension is installed,
but it would be better to change the function to return just whole
extensions and JOIN with pg_extension in pg_available_extensions.
(it's the same technique used in pg_stat_replication)

--
Itagaki Takahiro

#24Dimitri Fontaine
dimitri@2ndQuadrant.fr
In reply to: Itagaki Takahiro (#23)
Re: Extensions support for pg_dump, patch v27

Itagaki Takahiro <itagaki.takahiro@gmail.com> writes:

* "relocatable" and "schema" seems to be duplicated options.

They are not, really. If you have a relocatable extension, then there's
no schema option in the control file (setting it is an ERROR). If you
have a non-relocatable extension, then you can either setup the schema
to force it as the extension's author (or distributor / packager), or
leave it alone and use the @extschema@ facility instead.

* "version" field in pg_available_extension might mislead when
a newer version of an extension is available but an older version
is installed. How about returning installed version for "installed"
field instead of booleans? The field will be NULLs if not installed.

Good idea, I've done that in the pg_available_extension system view.

* I want to remove O(n^2) behavior in pg_extensions(). It scans
pg_extension catalog to return whether the extension is installed,
but it would be better to change the function to return just whole
extensions and JOIN with pg_extension in pg_available_extensions.
(it's the same technique used in pg_stat_replication)

Well, that allows to get rid of the whole extension's listing internal
function. Less code is good :) Here's the new system's view:

http://pgsql.tapoueh.org/extensions/doc/html/view-pg-available-extensions.html

CREATE VIEW pg_available_extensions AS
SELECT n.nspname as "schema", E.name, X.extversion as "installed",
E.version, E.relocatable, E.comment
FROM pg_available_extensions() AS E
LEFT JOIN pg_extension as X ON E.name = X.extname
LEFT JOIN pg_namespace as N on N.oid = X.extnamespace;

The new code (and documentation) is published in the git repository, I'm
waiting a little bit more before (for your comments) to prepare the
patch v30, or just tell me and I'll do that.

Regards,
--
Dimitri Fontaine
http://2ndQuadrant.fr PostgreSQL : Expertise, Formation et Support

#25Itagaki Takahiro
itagaki.takahiro@gmail.com
In reply to: Dimitri Fontaine (#24)
1 attachment(s)
Re: Extensions support for pg_dump, patch v27

Hi, the attached is a further cleanup of the latest commit
(1db20cdd36cb1c2cc5ef2210a23b3c09f5058690).

* Accept paths under $PGSHARE during CREATE EXTENSION
"in addition to" normal paths in convert_and_check_filename().
I think we don't have to disallow normal file accesses in the case.
* Rewrite pg_available_extensions() to use materialize mode.
* Add a protection for nested CREATE EXTENSION calls.
* Removed some unneeded changes in the patch:
- utils/genfile.h (use DIR directly)
- missing merges from master in guc.c
- only #include changes in a few files

Comments and documentation would need to be checked native
English speakers. I cannot help you In this area, sorry.

There are last two issues before it goes to ready for committer.

On Mon, Jan 31, 2011 at 19:21, Dimitri Fontaine <dimitri@2ndquadrant.fr> wrote:

* "relocatable" and "schema" seems to be duplicated options.

They are not, really.

I'd suggest to remove "relocatable" option if you won't add
additional meanings to the "relocatable but having schema" case.

Or, I'm still not sure why only adminpack is not relocatable.
Is it possible to make all extensions to relocatable and add
"default_schema = pg_catalog" to adminpack for backward-compatibility?

From older mails:

* Should we support absolute control file paths?

Well I don't see no harm in allowing non-core compliant extension
packaging,

If you want to support absolute paths, you also need to adjust
convert_and_check_filename() because it only allows to read files
in $PGSHARE. So, absolute path support doesn't work actually.
I prefer to remove absolute path support from script option
because absolute paths are just unportable.

--
Itagaki Takahiro

Attachments:

patch-on-extension.patchapplication/octet-stream; name=patch-on-extension.patchDownload
diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml
index edd2be1..c333a01 100644
*** a/doc/src/sgml/catalogs.sgml
--- b/doc/src/sgml/catalogs.sgml
***************
*** 6383,6396 ****
      <tbody>
       <row>
        <entry><structfield>schema</structfield></entry>
!       <entry><type>text</type></entry>
        <entry>The name of the schema where the extension is registered,
        or <literal>NULL</literal> when the extension is not installed.</entry>
       </row>
  
       <row>
        <entry><structfield>name</structfield></entry>
!       <entry><type>text</type></entry>
        <entry>The name of the extensions</entry>
       </row>
  
--- 6383,6396 ----
      <tbody>
       <row>
        <entry><structfield>schema</structfield></entry>
!       <entry><type>name</type></entry>
        <entry>The name of the schema where the extension is registered,
        or <literal>NULL</literal> when the extension is not installed.</entry>
       </row>
  
       <row>
        <entry><structfield>name</structfield></entry>
!       <entry><type>name</type></entry>
        <entry>The name of the extensions</entry>
       </row>
  
diff --git a/src/backend/commands/conversioncmds.c b/src/backend/commands/conversioncmds.c
index 3df231d..7aca611 100644
*** a/src/backend/commands/conversioncmds.c
--- b/src/backend/commands/conversioncmds.c
***************
*** 32,38 ****
  #include "utils/rel.h"
  #include "utils/syscache.h"
  
! static void AlterConversionOwner_internal(Relation rel, Oid convOid,
  							  Oid newOwnerId);
  
  /*
--- 32,38 ----
  #include "utils/rel.h"
  #include "utils/syscache.h"
  
! static void AlterConversionOwner_internal(Relation rel, Oid conversionOid,
  							  Oid newOwnerId);
  
  /*
diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c
index 5e6b279..4350659 100644
*** a/src/backend/commands/extension.c
--- b/src/backend/commands/extension.c
***************
*** 28,33 ****
--- 28,34 ----
   */
  #include "postgres.h"
  
+ #include <dirent.h>
  #include <unistd.h>
  
  #include "access/xact.h"
*************** typedef struct ExtensionControlFile
*** 73,93 ****
  	char *schema;       /* when not relocatable, an extension can force its schema */
  } ExtensionControlFile;
  
- /* expansible list of extensions */
- typedef struct ExtensionList
- {
- 	ExtensionControlFile *exts;		/* => palloc'd array */
- 	int	numrefs;		/* current number of extensions */
- 	int	maxrefs;		/* current size of palloc'd array */
- } ExtensionList;
- 
- /*
-  * Context to reuse between extension listing SRF calls
-  */
- typedef struct extension_fctx
- {
- 	directory_fctx dir;
- } extension_fctx;
  
  static bool extension_is_relocatable(Oid ext_oid);
  
--- 74,79 ----
*************** read_extension_script_file(const Extensi
*** 309,315 ****
  				 errmsg("invalid source encoding name \"%s\"",
  						pg_encoding_to_char(control->encoding))));
  
! 	content = (bytea *)DatumGetPointer(raw);
  
  	/* make sure that source string is valid */
  	len = VARSIZE_ANY_EXHDR(content);
--- 295,301 ----
  				 errmsg("invalid source encoding name \"%s\"",
  						pg_encoding_to_char(control->encoding))));
  
! 	content = DatumGetByteaP(raw);
  
  	/* make sure that source string is valid */
  	len = VARSIZE_ANY_EXHDR(content);
*************** read_extension_script_file(const Extensi
*** 327,336 ****
  }
  
  /*
!  * Execute given SQL string, and returns true only when success.
   */
! static bool
! execute_sql_string(const char *sql)
  {
  	/*
  	 * We abuse some internal knowledge from spi.h here. As we don't know
--- 313,322 ----
  }
  
  /*
!  * Execute given SQL string. filename is used only to report errors.
   */
! static void
! execute_sql_string(const char *sql, const char *filename)
  {
  	/*
  	 * We abuse some internal knowledge from spi.h here. As we don't know
*************** execute_sql_string(const char *sql)
*** 344,355 ****
  		elog(ERROR, "SPI_connect failed");
  
  	if (SPI_execute(sql, false, 0) < SPI_OK_UTILITY)
! 		return false;
  
  	if (SPI_finish() != SPI_OK_FINISH)
  		elog(ERROR, "SPI_finish failed");
- 
- 	return true;
  }
  
   /*
--- 330,341 ----
  		elog(ERROR, "SPI_connect failed");
  
  	if (SPI_execute(sql, false, 0) < SPI_OK_UTILITY)
! 		ereport(ERROR,
! 				(errcode(ERRCODE_DATA_EXCEPTION),
! 				 errmsg("could not execute sql file: '%s'", filename)));
  
  	if (SPI_finish() != SPI_OK_FINISH)
  		elog(ERROR, "SPI_finish failed");
  }
  
   /*
*************** execute_extension_script(ExtensionContro
*** 439,448 ****
  			Oid first_schema = linitial_oid(search_path);
  			list_free(search_path);
  
! 			if (!execute_sql_string(sql))
! 				ereport(ERROR,
! 						(errcode(ERRCODE_DATA_EXCEPTION),
! 						 errmsg("could not execute sql file: '%s'", filename)));
  
  			/*
  			 * CREATE EXTENSION foo WITH SCHEMA bar;
--- 425,431 ----
  			Oid first_schema = linitial_oid(search_path);
  			list_free(search_path);
  
! 			execute_sql_string(sql, filename);
  
  			/*
  			 * CREATE EXTENSION foo WITH SCHEMA bar;
*************** execute_extension_script(ExtensionContro
*** 477,486 ****
  										CStringGetTextDatum("@extschema@"),
  										CStringGetTextDatum(schema))));
  
! 			if (!execute_sql_string(sql))
! 				ereport(ERROR,
! 						(errcode(ERRCODE_DATA_EXCEPTION),
! 						 errmsg("could not execute sql file: '%s'", filename)));
  		}
  	}
  	PG_CATCH();
--- 460,466 ----
  										CStringGetTextDatum("@extschema@"),
  										CStringGetTextDatum(schema))));
  
! 			execute_sql_string(sql, filename);
  		}
  	}
  	PG_CATCH();
*************** CreateExtension(CreateExtensionStmt *stm
*** 536,541 ****
--- 516,530 ----
  				 errhint("Must be superuser to create an extension.")));
  
  	/*
+ 	 * We use global variables to track the extension being created, so we
+ 	 * can create only one extension at the same time.
+ 	 */
+ 	if (create_extension)
+ 		ereport(ERROR,
+ 				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ 				 errmsg("nested CREATE EXTENSION is not supported")));
+ 
+ 	/*
  	 * This check is done once here, early, before we bother parsing the
  	 * control file, then redone once we have the ExclusiveLock on the
  	 * pg_extension catalog to forbid having two backends concurrently
*************** DropExtension(DropExtensionStmt *stmt)
*** 748,754 ****
  		ereport(ERROR,
  				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
  				 errmsg("permission denied to drop extension \"%s\"",
! 						stmt->extname),
  				 errhint("Must be superuser to drop an extension.")));
  
  	/*
--- 737,743 ----
  		ereport(ERROR,
  				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
  				 errmsg("permission denied to drop extension \"%s\"",
! 						extname),
  				 errhint("Must be superuser to drop an extension.")));
  
  	/*
*************** pg_extension_flag_dump(PG_FUNCTION_ARGS)
*** 1023,1030 ****
  }
  
  /*
!  * This function lists all extensions, the one currently already installed
!  * but also the one available for installation. For those, we parse the
   * control file and return the information that would be available in the
   * pg_extension catalog.
   *
--- 1012,1019 ----
  }
  
  /*
!  * This function lists all extensions not only already installed ones
!  * but also the ones available for installation. For those, we parse the
   * control file and return the information that would be available in the
   * pg_extension catalog.
   *
*************** pg_extension_flag_dump(PG_FUNCTION_ARGS)
*** 1033,1092 ****
  Datum
  pg_available_extensions(PG_FUNCTION_ARGS)
  {
! 	FuncCallContext *funcctx;
! 	struct dirent *de;
! 	extension_fctx *fctx;
  
  	if (!superuser())
  		ereport(ERROR,
  				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
  				 (errmsg("must be superuser to get extensions listings"))));
  
! 	if (SRF_IS_FIRSTCALL())
! 	{
! 		MemoryContext  oldcontext;
! 		TupleDesc	   tupdesc;
! 
! 		funcctx = SRF_FIRSTCALL_INIT();
! 		oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
! 
! 		tupdesc = CreateTemplateTupleDesc(4, false);
! 		TupleDescInitEntry(tupdesc, (AttrNumber) 1, "name",
! 						   NAMEOID, -1, 0);
! 		TupleDescInitEntry(tupdesc, (AttrNumber) 2, "version",
! 						   TEXTOID, -1, 0);
! 		TupleDescInitEntry(tupdesc, (AttrNumber) 3, "relocatable",
! 						   BOOLOID, -1, 0);
! 		TupleDescInitEntry(tupdesc, (AttrNumber) 4, "comment",
! 						   TEXTOID, -1, 0);
  
! 		funcctx->tuple_desc = BlessTupleDesc(tupdesc);
  
! 		fctx = (extension_fctx *) palloc(sizeof(extension_fctx));
! 		fctx->dir.location = get_extension_control_basepath();
! 		fctx->dir.dirdesc  = AllocateDir(fctx->dir.location);
  
! 		if (!fctx->dir.dirdesc)
! 			ereport(ERROR,
! 					(errcode_for_file_access(),
! 					 errmsg("could not open directory \"%s\": %m",
! 							fctx->dir.location)));
  
! 		funcctx->user_fctx = fctx;
! 		MemoryContextSwitchTo(oldcontext);
! 	}
  
! 	funcctx = SRF_PERCALL_SETUP();
! 	fctx = (extension_fctx *) funcctx->user_fctx;
  
! 	while ((de = ReadDir(fctx->dir.dirdesc, fctx->dir.location)) != NULL)
  	{
  		ExtensionControlFile *control;
  		char	   *extname;
! 		Datum		values[5];
! 		bool		nulls[5];
! 		int         i = 0;
! 		HeapTuple	tuple;
  
  		if (!is_extension_control_filename(de->d_name))
  			continue;
--- 1022,1081 ----
  Datum
  pg_available_extensions(PG_FUNCTION_ARGS)
  {
! #define PG_EXTENSIONS_COLS 	4
! 	ReturnSetInfo	   *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
! 	TupleDesc			tupdesc;
! 	Tuplestorestate	   *tupstore;
! 	MemoryContext		per_query_ctx;
! 	MemoryContext		oldcontext;
! 	char			   *location;	/* share/contrib path */
! 	DIR				   *dir;		/* share/contrib directory */
! 	struct dirent	   *de;
  
  	if (!superuser())
  		ereport(ERROR,
  				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
  				 (errmsg("must be superuser to get extensions listings"))));
  
! 	/* check to see if caller supports us returning a tuplestore */
! 	if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo))
! 		ereport(ERROR,
! 				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
! 				 errmsg("set-valued function called in context that cannot accept a set")));
! 	if (!(rsinfo->allowedModes & SFRM_Materialize))
! 		ereport(ERROR,
! 				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
! 				 errmsg("materialize mode required, but it is not " \
! 						"allowed in this context")));
  
! 	/* Build a tuple descriptor for our result type */
! 	if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
! 		elog(ERROR, "return type must be a row type");
  
! 	per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
! 	oldcontext = MemoryContextSwitchTo(per_query_ctx);
  
! 	tupstore = tuplestore_begin_heap(true, false, work_mem);
! 	rsinfo->returnMode = SFRM_Materialize;
! 	rsinfo->setResult = tupstore;
! 	rsinfo->setDesc = tupdesc;
  
! 	MemoryContextSwitchTo(oldcontext);
  
! 	location = get_extension_control_basepath();
! 	dir  = AllocateDir(location);
! 	if (dir == NULL)
! 		ereport(ERROR,
! 				(errcode_for_file_access(),
! 				 errmsg("could not open directory \"%s\": %m",
! 						location)));
  
! 	while ((de = ReadDir(dir, location)) != NULL)
  	{
  		ExtensionControlFile *control;
  		char	   *extname;
! 		Datum		values[PG_EXTENSIONS_COLS];
! 		bool		nulls[PG_EXTENSIONS_COLS];
  
  		if (!is_extension_control_filename(de->d_name))
  			continue;
*************** pg_available_extensions(PG_FUNCTION_ARGS
*** 1101,1124 ****
  		memset(values, 0, sizeof(values));
  		memset(nulls, 0, sizeof(nulls));
  
  		values[0] = DirectFunctionCall1(namein, CStringGetDatum(control->name));
! 		values[2] = BoolGetDatum(control->relocatable);
! 
  		if (control->version == NULL)
  			nulls[1] = true;
  		else
  			values[1] = CStringGetTextDatum(control->version);
! 
  		if (control->comment == NULL)
  			nulls[3] = true;
  		else
  			values[3] = CStringGetTextDatum(control->comment);
  
! 		tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls);
! 		SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(tuple));
  	}
! 	FreeDir(fctx->dir.dirdesc);
! 	SRF_RETURN_DONE(funcctx);
  }
  
  /*
--- 1090,1119 ----
  		memset(values, 0, sizeof(values));
  		memset(nulls, 0, sizeof(nulls));
  
+ 		/* name */
  		values[0] = DirectFunctionCall1(namein, CStringGetDatum(control->name));
! 		/* version */
  		if (control->version == NULL)
  			nulls[1] = true;
  		else
  			values[1] = CStringGetTextDatum(control->version);
! 		/* relocatable */
! 		values[2] = BoolGetDatum(control->relocatable);
! 		/* comment */
  		if (control->comment == NULL)
  			nulls[3] = true;
  		else
  			values[3] = CStringGetTextDatum(control->comment);
  
! 		tuplestore_putvalues(tupstore, tupdesc, values, nulls);
  	}
! 
! 	/* clean up and return the tuplestore */
! 	tuplestore_donestoring(tupstore);
! 
! 	FreeDir(dir);
! 
! 	return (Datum) 0;
  }
  
  /*
*************** AlterExtensionNamespace(char *name, cons
*** 1138,1149 ****
  void
  AlterExtensionNamespace_oid(Oid extensionOid, Oid nspOid)
  {
! 	Oid			     oldNspOid = InvalidOid;
! 	ObjectAddress   *object, *dep;
! 	Relation	depRel;
! 	ScanKeyData key[2];
! 	SysScanDesc depScan;
! 	HeapTuple	depTup;
  
  	if (!superuser())
  		ereport(ERROR,
--- 1133,1145 ----
  void
  AlterExtensionNamespace_oid(Oid extensionOid, Oid nspOid)
  {
! 	Oid				oldNspOid = InvalidOid;
! 	ObjectAddress  *object,
! 				   *dep;
! 	Relation		depRel;
! 	ScanKeyData		key[2];
! 	SysScanDesc		depScan;
! 	HeapTuple		depTup;
  
  	if (!superuser())
  		ereport(ERROR,
*************** AlterExtensionNamespace_oid(Oid extensio
*** 1205,1211 ****
  			ereport(ERROR,
  					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
  					 (errmsg("this extension does not support SET SCHEMA"),
! 					  errdetail("%s is not in the extension's schema [%i %i]",
  								getObjectDescription(dep),
  								oldNspOid,
  								dep_oldNspOid))));
--- 1201,1207 ----
  			ereport(ERROR,
  					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
  					 (errmsg("this extension does not support SET SCHEMA"),
! 					  errdetail("%s is not in the extension's schema [%d %d]",
  								getObjectDescription(dep),
  								oldNspOid,
  								dep_oldNspOid))));
diff --git a/src/backend/utils/adt/genfile.c b/src/backend/utils/adt/genfile.c
index aaffd38..3bdfc64 100644
*** a/src/backend/utils/adt/genfile.c
--- b/src/backend/utils/adt/genfile.c
***************
*** 28,37 ****
  #include "postmaster/syslogger.h"
  #include "storage/fd.h"
  #include "utils/builtins.h"
- #include "utils/genfile.h"
  #include "utils/memutils.h"
  #include "utils/timestamp.h"
  
  /*
   * Convert a "text" filename argument to C string, and check it's allowable.
   *
--- 28,43 ----
  #include "postmaster/syslogger.h"
  #include "storage/fd.h"
  #include "utils/builtins.h"
  #include "utils/memutils.h"
  #include "utils/timestamp.h"
  
+ typedef struct
+ {
+ 	char	   *location;
+ 	DIR		   *dirdesc;
+ } directory_fctx;
+ 
+ 
  /*
   * Convert a "text" filename argument to C string, and check it's allowable.
   *
diff --git a/src/backend/utils/adt/varlena.c b/src/backend/utils/adt/varlena.c
index 274f1d0..e111d26 100644
*** a/src/backend/utils/adt/varlena.c
--- b/src/backend/utils/adt/varlena.c
***************
*** 24,30 ****
  #include "miscadmin.h"
  #include "parser/scansup.h"
  #include "regex/regex.h"
- #include "utils/array.h"
  #include "utils/builtins.h"
  #include "utils/bytea.h"
  #include "utils/lsyscache.h"
--- 24,29 ----
diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c
index 493f289..f3ca5a5 100644
*** a/src/backend/utils/init/postinit.c
--- b/src/backend/utils/init/postinit.c
***************
*** 29,35 ****
  #include "catalog/pg_database.h"
  #include "catalog/pg_db_role_setting.h"
  #include "catalog/pg_tablespace.h"
- #include "commands/extension.h"
  #include "libpq/auth.h"
  #include "libpq/libpq-be.h"
  #include "mb/pg_wchar.h"
--- 29,34 ----
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 17232ab..2c95ef8 100644
*** a/src/backend/utils/misc/guc.c
--- b/src/backend/utils/misc/guc.c
*************** extern char *temp_tablespaces;
*** 128,133 ****
--- 128,134 ----
  extern bool synchronize_seqscans;
  extern bool fullPageWrites;
  extern int	ssl_renegotiation_limit;
+ extern char *SSLCipherSuites;
  
  #ifdef TRACE_SORT
  extern bool trace_sort;
*************** extern bool trace_syncscan;
*** 139,148 ****
  extern bool optimize_bounded_sort;
  #endif
  
- #ifdef USE_SSL
- extern char *SSLCipherSuites;
- #endif
- 
  static void set_config_sourcefile(const char *name, char *sourcefile,
  					  int sourceline);
  
--- 140,145 ----
*************** static const char *assign_log_destinatio
*** 151,162 ****
  
  #ifdef HAVE_SYSLOG
  static int	syslog_facility = LOG_LOCAL0;
  
  static bool assign_syslog_facility(int newval,
  					   bool doit, GucSource source);
  static const char *assign_syslog_ident(const char *ident,
  					bool doit, GucSource source);
- #endif
  
  static bool assign_session_replication_role(int newval, bool doit,
  								GucSource source);
--- 148,161 ----
  
  #ifdef HAVE_SYSLOG
  static int	syslog_facility = LOG_LOCAL0;
+ #else
+ static int	syslog_facility = 0;
+ #endif
  
  static bool assign_syslog_facility(int newval,
  					   bool doit, GucSource source);
  static const char *assign_syslog_ident(const char *ident,
  					bool doit, GucSource source);
  
  static bool assign_session_replication_role(int newval, bool doit,
  								GucSource source);
*************** static const struct config_enum_entry se
*** 279,286 ****
  	{NULL, 0, false}
  };
  
- #ifdef HAVE_SYSLOG
  static const struct config_enum_entry syslog_facility_options[] = {
  	{"local0", LOG_LOCAL0, false},
  	{"local1", LOG_LOCAL1, false},
  	{"local2", LOG_LOCAL2, false},
--- 278,285 ----
  	{NULL, 0, false}
  };
  
  static const struct config_enum_entry syslog_facility_options[] = {
+ #ifdef HAVE_SYSLOG
  	{"local0", LOG_LOCAL0, false},
  	{"local1", LOG_LOCAL1, false},
  	{"local2", LOG_LOCAL2, false},
*************** static const struct config_enum_entry sy
*** 289,297 ****
  	{"local5", LOG_LOCAL5, false},
  	{"local6", LOG_LOCAL6, false},
  	{"local7", LOG_LOCAL7, false},
  	{NULL, 0}
  };
- #endif
  
  static const struct config_enum_entry track_function_options[] = {
  	{"none", TRACK_FUNC_OFF, false},
--- 288,298 ----
  	{"local5", LOG_LOCAL5, false},
  	{"local6", LOG_LOCAL6, false},
  	{"local7", LOG_LOCAL7, false},
+ #else
+ 	{"none", 0, false},
+ #endif
  	{NULL, 0}
  };
  
  static const struct config_enum_entry track_function_options[] = {
  	{"none", TRACK_FUNC_OFF, false},
*************** int			tcp_keepalives_count;
*** 409,417 ****
   */
  static char *log_destination_string;
  
- #ifdef HAVE_SYSLOG
  static char *syslog_ident_str;
- #endif
  static bool phony_autocommit;
  static bool session_auth_is_superuser;
  static double phony_random_seed;
--- 410,416 ----
*************** static struct config_string ConfigureNam
*** 2530,2536 ****
  		"postgresql-%Y-%m-%d_%H%M%S.log", NULL, NULL
  	},
  
- #ifdef HAVE_SYSLOG
  	{
  		{"syslog_ident", PGC_SIGHUP, LOGGING_WHERE,
  			gettext_noop("Sets the program name used to identify PostgreSQL "
--- 2529,2534 ----
*************** static struct config_string ConfigureNam
*** 2540,2546 ****
  		&syslog_ident_str,
  		"postgres", assign_syslog_ident, NULL
  	},
- #endif
  
  	{
  		{"TimeZone", PGC_USERSET, CLIENT_CONN_LOCALE,
--- 2538,2543 ----
*************** static struct config_string ConfigureNam
*** 2679,2685 ****
  		"pg_catalog.simple", assignTSCurrentConfig, NULL
  	},
  
- #ifdef USE_SSL
  	{
  		{"ssl_ciphers", PGC_POSTMASTER, CONN_AUTH_SECURITY,
  			gettext_noop("Sets the list of allowed SSL ciphers."),
--- 2676,2681 ----
*************** static struct config_string ConfigureNam
*** 2687,2695 ****
  			GUC_SUPERUSER_ONLY
  		},
  		&SSLCipherSuites,
! 		"ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH", NULL, NULL
  	},
- #endif   /* USE_SSL */
  
  	{
  		{"application_name", PGC_USERSET, LOGGING_WHAT,
--- 2683,2695 ----
  			GUC_SUPERUSER_ONLY
  		},
  		&SSLCipherSuites,
! #ifdef USE_SSL
! 		"ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH",
! #else
! 		"none",
! #endif
! 		NULL, NULL
  	},
  
  	{
  		{"application_name", PGC_USERSET, LOGGING_WHAT,
*************** static struct config_enum ConfigureNames
*** 2806,2821 ****
  		LOGSTMT_NONE, log_statement_options, NULL, NULL
  	},
  
- #ifdef HAVE_SYSLOG
  	{
  		{"syslog_facility", PGC_SIGHUP, LOGGING_WHERE,
  			gettext_noop("Sets the syslog \"facility\" to be used when syslog enabled."),
  			NULL
  		},
  		&syslog_facility,
! 		LOG_LOCAL0, syslog_facility_options, assign_syslog_facility, NULL
! 	},
  #endif
  
  	{
  		{"session_replication_role", PGC_SUSET, CLIENT_CONN_STATEMENT,
--- 2806,2824 ----
  		LOGSTMT_NONE, log_statement_options, NULL, NULL
  	},
  
  	{
  		{"syslog_facility", PGC_SIGHUP, LOGGING_WHERE,
  			gettext_noop("Sets the syslog \"facility\" to be used when syslog enabled."),
  			NULL
  		},
  		&syslog_facility,
! #ifdef HAVE_SYSLOG
! 		LOG_LOCAL0,
! #else
! 		0,
  #endif
+ 		syslog_facility_options, assign_syslog_facility, NULL
+ 	},
  
  	{
  		{"session_replication_role", PGC_SUSET, CLIENT_CONN_STATEMENT,
*************** assign_log_destination(const char *value
*** 7636,7649 ****
  	return value;
  }
  
- #ifdef HAVE_SYSLOG
- 
  static bool
  assign_syslog_facility(int newval, bool doit, GucSource source)
  {
  	if (doit)
  		set_syslog_parameters(syslog_ident_str ? syslog_ident_str : "postgres",
  							  newval);
  
  	return true;
  }
--- 7639,7653 ----
  	return value;
  }
  
  static bool
  assign_syslog_facility(int newval, bool doit, GucSource source)
  {
+ #ifdef HAVE_SYSLOG
  	if (doit)
  		set_syslog_parameters(syslog_ident_str ? syslog_ident_str : "postgres",
  							  newval);
+ #endif
+ 	/* Without syslog support, just ignore it */
  
  	return true;
  }
*************** assign_syslog_facility(int newval, bool 
*** 7651,7662 ****
  static const char *
  assign_syslog_ident(const char *ident, bool doit, GucSource source)
  {
  	if (doit)
  		set_syslog_parameters(ident, syslog_facility);
  
  	return ident;
  }
- #endif   /* HAVE_SYSLOG */
  
  
  static bool
--- 7655,7668 ----
  static const char *
  assign_syslog_ident(const char *ident, bool doit, GucSource source)
  {
+ #ifdef HAVE_SYSLOG
  	if (doit)
  		set_syslog_parameters(ident, syslog_facility);
+ #endif
+ 	/* Without syslog support, it will always be set to "none", so ignore */
  
  	return ident;
  }
  
  
  static bool
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index 747fa52..dad99f8 100644
*** a/src/bin/psql/tab-complete.c
--- b/src/bin/psql/tab-complete.c
*************** static const SchemaQuery Query_for_list_
*** 586,592 ****
  #define Query_for_list_of_available_extensions \
  " SELECT pg_catalog.quote_ident(name) "\
  "   FROM pg_catalog.pg_available_extensions "\
! "  WHERE substring(pg_catalog.quote_ident(name),1,%d)='%s' AND NOT installed"
  
  /*
   * This is a list of all "things" in Pgsql, which can show up after CREATE or
--- 586,592 ----
  #define Query_for_list_of_available_extensions \
  " SELECT pg_catalog.quote_ident(name) "\
  "   FROM pg_catalog.pg_available_extensions "\
! "  WHERE substring(pg_catalog.quote_ident(name),1,%d)='%s' AND installed IS NULL"
  
  /*
   * This is a list of all "things" in Pgsql, which can show up after CREATE or
diff --git a/src/include/commands/extension.h b/src/include/commands/extension.h
index cc5e7ed..c51460c 100644
*** a/src/include/commands/extension.h
--- b/src/include/commands/extension.h
***************
*** 16,22 ****
  
  #include "catalog/dependency.h"
  #include "catalog/objectaddress.h"
- #include "utils/genfile.h"
  
  
  /*
--- 16,21 ----
diff --git a/src/include/utils/genfile.h b/src/include/utils/genfile.h
index e343a9d..e69de29 100644
*** a/src/include/utils/genfile.h
--- b/src/include/utils/genfile.h
***************
*** 1,25 ****
- /*--------------------------------------------------------------------
-  * genfile.h
-  *
-  * External declarations pertaining to backend/utils/misc/genfile.c
-  *
-  * Copyright (c) 2000-2010, PostgreSQL Global Development Group
-  *
-  * src/include/utils/genfile.h
-  *--------------------------------------------------------------------
-  */
- #ifndef GENFILE_H
- #define GENFILE_H
- 
- #include <dirent.h>
- 
- /*
-  * We need this in extension.c in the SRF that lists available extensions.
-  */
- typedef struct directory_fctx
- {
- 	char	   *location;
- 	DIR		   *dirdesc;
- } directory_fctx;
- 
- #endif   /* GENFILE_H */
--- 0 ----
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index 455f0db..3afdba3 100644
*** a/src/test/regress/expected/rules.out
--- b/src/test/regress/expected/rules.out
*************** SELECT viewname, definition FROM pg_view
*** 1279,1285 ****
            viewname           |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              definition                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               
  -----------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
   iexit                       | SELECT ih.name, ih.thepath, interpt_pp(ih.thepath, r.thepath) AS exit FROM ihighway ih, ramp r WHERE (ih.thepath ## r.thepath);
!  pg_available_extensions     | SELECT e.name, e.version, e.relocatable, e.comment, e.installed FROM pg_extensions() e(name, version, relocatable, comment, installed);
   pg_cursors                  | SELECT c.name, c.statement, c.is_holdable, c.is_binary, c.is_scrollable, c.creation_time FROM pg_cursor() c(name, statement, is_holdable, is_binary, is_scrollable, creation_time);
   pg_group                    | SELECT pg_authid.rolname AS groname, pg_authid.oid AS grosysid, ARRAY(SELECT pg_auth_members.member FROM pg_auth_members WHERE (pg_auth_members.roleid = pg_authid.oid)) AS grolist FROM pg_authid WHERE (NOT pg_authid.rolcanlogin);
   pg_indexes                  | SELECT n.nspname AS schemaname, c.relname AS tablename, i.relname AS indexname, t.spcname AS tablespace, pg_get_indexdef(i.oid) AS indexdef FROM ((((pg_index x JOIN pg_class c ON ((c.oid = x.indrelid))) JOIN pg_class i ON ((i.oid = x.indexrelid))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) LEFT JOIN pg_tablespace t ON ((t.oid = i.reltablespace))) WHERE ((c.relkind = 'r'::"char") AND (i.relkind = 'i'::"char"));
--- 1279,1285 ----
            viewname           |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              definition                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               
  -----------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
   iexit                       | SELECT ih.name, ih.thepath, interpt_pp(ih.thepath, r.thepath) AS exit FROM ihighway ih, ramp r WHERE (ih.thepath ## r.thepath);
!  pg_available_extensions     | SELECT n.nspname AS schema, e.name, x.extversion AS installed, e.version, e.relocatable, e.comment FROM ((pg_available_extensions() e(name, version, relocatable, comment) LEFT JOIN pg_extension x ON ((e.name = x.extname))) LEFT JOIN pg_namespace n ON ((n.oid = x.extnamespace)));
   pg_cursors                  | SELECT c.name, c.statement, c.is_holdable, c.is_binary, c.is_scrollable, c.creation_time FROM pg_cursor() c(name, statement, is_holdable, is_binary, is_scrollable, creation_time);
   pg_group                    | SELECT pg_authid.rolname AS groname, pg_authid.oid AS grosysid, ARRAY(SELECT pg_auth_members.member FROM pg_auth_members WHERE (pg_auth_members.roleid = pg_authid.oid)) AS grolist FROM pg_authid WHERE (NOT pg_authid.rolcanlogin);
   pg_indexes                  | SELECT n.nspname AS schemaname, c.relname AS tablename, i.relname AS indexname, t.spcname AS tablespace, pg_get_indexdef(i.oid) AS indexdef FROM ((((pg_index x JOIN pg_class c ON ((c.oid = x.indrelid))) JOIN pg_class i ON ((i.oid = x.indexrelid))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) LEFT JOIN pg_tablespace t ON ((t.oid = i.reltablespace))) WHERE ((c.relkind = 'r'::"char") AND (i.relkind = 'i'::"char"));
#26Dimitri Fontaine
dimitri@2ndQuadrant.fr
In reply to: Itagaki Takahiro (#25)
Re: Extensions support for pg_dump, patch v27

Itagaki Takahiro <itagaki.takahiro@gmail.com> writes:

Hi, the attached is a further cleanup of the latest commit
(1db20cdd36cb1c2cc5ef2210a23b3c09f5058690).

Thanks! Given that the patch contains some merging from master's
branch, I'm not sure if I should apply it to my repository then handle
conflicts, or let you manage the patch now?

* Accept paths under $PGSHARE during CREATE EXTENSION
"in addition to" normal paths in convert_and_check_filename().
I think we don't have to disallow normal file accesses in the case.
* Rewrite pg_available_extensions() to use materialize mode.
* Add a protection for nested CREATE EXTENSION calls.
* Removed some unneeded changes in the patch:
- utils/genfile.h (use DIR directly)
- missing merges from master in guc.c
- only #include changes in a few files

Comments and documentation would need to be checked native
English speakers. I cannot help you In this area, sorry.

Thanks. I don't see the PATH modifications when reading the patch, though.

There are last two issues before it goes to ready for committer.

On Mon, Jan 31, 2011 at 19:21, Dimitri Fontaine <dimitri@2ndquadrant.fr> wrote:

* "relocatable" and "schema" seems to be duplicated options.

They are not, really.

I'd suggest to remove "relocatable" option if you won't add
additional meanings to the "relocatable but having schema" case.

The schema option only makes sense when the extension is *NOT*
relocatable.

Or, I'm still not sure why only adminpack is not relocatable.
Is it possible to make all extensions to relocatable and add
"default_schema = pg_catalog" to adminpack for backward-compatibility?

The adminpack SQL script is hard-coding pg_catalog, so user won't be
able to choose where to install it. Technically, they could still move
the functions to another schema, but that would break pgAdmin AFAIUI, so
the extension's author here *wants* to forbid the user to relocate the
extension. And want to prevent to user from installing it where he
wants in the first place.

The option relocatable is allowing ALTER EXTENSION … SET SCHEMA, when
the control files also specify the schema, then you can't choose where
to install the extension in the first place.

I don't think we can go to only 1 options here.

From older mails:

* Should we support absolute control file paths?

Well I don't see no harm in allowing non-core compliant extension
packaging,

If you want to support absolute paths, you also need to adjust
convert_and_check_filename() because it only allows to read files
in $PGSHARE. So, absolute path support doesn't work actually.
I prefer to remove absolute path support from script option
because absolute paths are just unportable.

I have no strong opinion here, ok for me.

Regards,
--
Dimitri Fontaine
http://2ndQuadrant.fr PostgreSQL : Expertise, Formation et Support

#27Tom Lane
tgl@sss.pgh.pa.us
In reply to: Dimitri Fontaine (#26)
Re: Extensions support for pg_dump, patch v27

Dimitri Fontaine <dimitri@2ndQuadrant.fr> writes:

Itagaki Takahiro <itagaki.takahiro@gmail.com> writes:

Hi, the attached is a further cleanup of the latest commit
(1db20cdd36cb1c2cc5ef2210a23b3c09f5058690).

Thanks! Given that the patch contains some merging from master's
branch, I'm not sure if I should apply it to my repository then handle
conflicts, or let you manage the patch now?

Actually, I was about to pick up and start working on the whole
extensions patch series, but now I'm confused as to what and where is
the latest version.

regards, tom lane

#28Dimitri Fontaine
dimitri@2ndQuadrant.fr
In reply to: Tom Lane (#27)
1 attachment(s)
Re: Extensions support for pg_dump, patch v27

Tom Lane <tgl@sss.pgh.pa.us> writes:

Actually, I was about to pick up and start working on the whole
extensions patch series, but now I'm confused as to what and where is
the latest version.

Ok, here's what I have, attached, as patch v30. What Itagaki just sent
applies on top of that.

Regards,
--
Dimitri Fontaine
http://2ndQuadrant.fr PostgreSQL : Expertise, Formation et Support

Attachments:

extension.v30.patch.gzapplication/octet-streamDownload
#29Tom Lane
tgl@sss.pgh.pa.us
In reply to: Dimitri Fontaine (#28)
Re: Extensions support for pg_dump, patch v27

Dimitri Fontaine <dimitri@2ndQuadrant.fr> writes:

Tom Lane <tgl@sss.pgh.pa.us> writes:

Actually, I was about to pick up and start working on the whole
extensions patch series, but now I'm confused as to what and where is
the latest version.

Ok, here's what I have, attached, as patch v30. What Itagaki just sent
applies on top of that.

What are the guc.c changes in this patch? They appear completely
unrelated to the topic.

regards, tom lane

#30Dimitri Fontaine
dimitri@2ndQuadrant.fr
In reply to: Tom Lane (#29)
Re: Extensions support for pg_dump, patch v27

Tom Lane <tgl@sss.pgh.pa.us> writes:

What are the guc.c changes in this patch? They appear completely
unrelated to the topic.

Right. Didn't spot them. Sorry for the noise in the patch, it must be
a merge problem in my repository. Do you want me to clean that up or is
it already to late?

Regards,
--
Dimitri Fontaine
http://2ndQuadrant.fr PostgreSQL : Expertise, Formation et Support

#31Tom Lane
tgl@sss.pgh.pa.us
In reply to: Dimitri Fontaine (#30)
Re: Extensions support for pg_dump, patch v27

Dimitri Fontaine <dimitri@2ndQuadrant.fr> writes:

Tom Lane <tgl@sss.pgh.pa.us> writes:

What are the guc.c changes in this patch? They appear completely
unrelated to the topic.

Right. Didn't spot them. Sorry for the noise in the patch, it must be
a merge problem in my repository. Do you want me to clean that up or is
it already to late?

No need, I'll just drop that file from the patch.

regards, tom lane

#32Tom Lane
tgl@sss.pgh.pa.us
In reply to: Tom Lane (#31)
Re: Extensions support for pg_dump, patch v27

While I'm looking at this ... what is the rationale for treating rewrite
rules as members of extensions, ie, why does the patch touch
rewriteDefine.c? ISTM a rule is a property of a table and could not
sensibly be an independent member of an extension. If there is a use
for that, why are table constraints and triggers not given the same
treatment?

regards, tom lane

#33Dimitri Fontaine
dimitri@2ndQuadrant.fr
In reply to: Tom Lane (#32)
Re: Extensions support for pg_dump, patch v27

Tom Lane <tgl@sss.pgh.pa.us> writes:

While I'm looking at this ... what is the rationale for treating rewrite
rules as members of extensions, ie, why does the patch touch
rewriteDefine.c? ISTM a rule is a property of a table and could not
sensibly be an independent member of an extension. If there is a use
for that, why are table constraints and triggers not given the same
treatment?

I remember thinking I needed to do that for CREATE VIEW support while
discovering PostgreSQL internals.

Regards.
--
Dimitri Fontaine
http://2ndQuadrant.fr PostgreSQL : Expertise, Formation et Support

#34Tom Lane
tgl@sss.pgh.pa.us
In reply to: Dimitri Fontaine (#33)
Re: Extensions support for pg_dump, patch v27

Attached is an updated patch that incorporates all of the review I've
done so far on the core code. This omits the contrib changes, which
I've not looked at in any detail, and the docs changes since I've not
yet updated the docs to match today's code changes. User-visible
changes are that WITH NO DATA is gone, and instead there's
pg_extension_config_dump(regclass, text) as per today's discussion.
The latter is only lightly tested but seems to work as intended.

I believe the core code is now in pretty good shape; the only open issue
I have at the moment is that pg_dump will fail to suppress dumping of
USER MAPPING objects that are in an extension. Which is something I'm
not too excited about anyway. (The reason that's an issue is that I
reverted most of the changes in pg_dump.c in favor of using pg_dump's
already existing dependency mechanisms to suppress dumping unwanted
items. The USER MAPPING code tries to bypass the DumpableObject
representation, which means it doesn't get filtered.)

The documentation still needs a good bit of work, but I hope to have
this committed within a day or so.

regards, tom lane

#35Dimitri Fontaine
dimitri@2ndQuadrant.fr
In reply to: Tom Lane (#34)
Re: Extensions support for pg_dump, patch v27

Tom Lane <tgl@sss.pgh.pa.us> writes:

Attached is an updated patch that incorporates all of the review I've

And that looks great, thanks. I've only had time to read the patch,
will play with it later on today, hopefully.

I've spotted a comment that I think you missed updating. The schema
given in the control file is now created in all cases rather than only
when the extension is not relocatable, right?

+ 	else if (control->schema != NULL)
+ 	{
+ 		/*
+ 		 * The extension is not relocatable and the author gave us a schema
+ 		 * for it.  We create the schema here if it does not already exist.
+ 		 */

I also note that the attached version doesn't contain \dX, is that an
happenstance or a choice you did here?

done so far on the core code. This omits the contrib changes, which
I've not looked at in any detail, and the docs changes since I've not
yet updated the docs to match today's code changes. User-visible
changes are that WITH NO DATA is gone, and instead there's
pg_extension_config_dump(regclass, text) as per today's discussion.
The latter is only lightly tested but seems to work as intended.

I think I will have to test it and get my head around it, but as we
said, it's a good change (simpler, only target user tables).

I believe the core code is now in pretty good shape; the only open issue
I have at the moment is that pg_dump will fail to suppress dumping of
USER MAPPING objects that are in an extension. Which is something I'm
not too excited about anyway. (The reason that's an issue is that I
reverted most of the changes in pg_dump.c in favor of using pg_dump's
already existing dependency mechanisms to suppress dumping unwanted
items. The USER MAPPING code tries to bypass the DumpableObject
representation, which means it doesn't get filtered.)

Well the pg_dump support code is very different than the one I did, so I
will have to learn about the dependency management there before I can
comment.

The documentation still needs a good bit of work, but I hope to have
this committed within a day or so.

Great! Again, thanks a lot, I like the way you simplified and cleaned
the patch, and I still recognise the code :)

Regards,
--
Dimitri Fontaine
http://2ndQuadrant.fr PostgreSQL : Expertise, Formation et Support

#36Tom Lane
tgl@sss.pgh.pa.us
In reply to: Dimitri Fontaine (#35)
Re: Extensions support for pg_dump, patch v27

Dimitri Fontaine <dimitri@2ndQuadrant.fr> writes:

I've spotted a comment that I think you missed updating. The schema
given in the control file is now created in all cases rather than only
when the extension is not relocatable, right?

Hm, no, that logic is the same as before no?

I also note that the attached version doesn't contain \dX, is that an
happenstance or a choice you did here?

I removed it --- it wasn't documented and I didn't see much point anyway
in a \d command that just duplicates a system view, especially a view
only usable by superusers.

regards, tom lane

#37Dimitri Fontaine
dimitri@2ndQuadrant.fr
In reply to: Tom Lane (#36)
Re: Extensions support for pg_dump, patch v27

Tom Lane <tgl@sss.pgh.pa.us> writes:

Dimitri Fontaine <dimitri@2ndQuadrant.fr> writes:

I've spotted a comment that I think you missed updating. The schema
given in the control file is now created in all cases rather than only
when the extension is not relocatable, right?

Hm, no, that logic is the same as before no?

Well I had

if (!control->relocatable && control->schema != NULL)

And you have

+ else if (control->schema != NULL)

So you're considering the schema option independently of the relocatable
option, which is ok because you changed those options defaults and
conflicts in the control file parsing. Only the comment needs adjusting.

I removed it --- it wasn't documented and I didn't see much point anyway
in a \d command that just duplicates a system view, especially a view
only usable by superusers.

It used to not be a straight select from system view, and I wanted to
offer something as simple as clicking a check box in pgadmin for people
who want to see what's available and install it. But well, the system
view is good enough now I guess, we're talking about DBA here after all.

Regards,
--
Dimitri Fontaine
http://2ndQuadrant.fr PostgreSQL : Expertise, Formation et Support

#38Tom Lane
tgl@sss.pgh.pa.us
In reply to: Dimitri Fontaine (#37)
Re: Extensions support for pg_dump, patch v27

Dimitri Fontaine <dimitri@2ndQuadrant.fr> writes:

Tom Lane <tgl@sss.pgh.pa.us> writes:

Hm, no, that logic is the same as before no?

Well I had

if (!control->relocatable && control->schema != NULL)

And you have

+ else if (control->schema != NULL)

Yeah, I deleted that relocatable test because it's redundant:
control->schema cannot be set for a relocatable extension,
cf the test in read_extension_control_file.

regards, tom lane

#39Dimitri Fontaine
dimitri@2ndQuadrant.fr
In reply to: Tom Lane (#38)
Re: Extensions support for pg_dump, patch v27

Tom Lane <tgl@sss.pgh.pa.us> writes:

Yeah, I deleted that relocatable test because it's redundant:
control->schema cannot be set for a relocatable extension,
cf the test in read_extension_control_file.

I missed that you kept this test in your version of the patch. Sorry
for noise.

Regardsm
--
Dimitri Fontaine
http://2ndQuadrant.fr PostgreSQL : Expertise, Formation et Support

#40Tom Lane
tgl@sss.pgh.pa.us
In reply to: Dimitri Fontaine (#39)
Re: Extensions support for pg_dump, patch v27

I have gone ahead and committed the core and documentation parts of this
patch, but not as yet any of the contrib changes; that is, all the
contrib modules are still building old-style. I had intended to do it
in two steps all along, so as to get some buildfarm proof for the thesis
that we haven't broken old-style add-on modules. However, there is now
an additional motivation for delay: so long as we haven't pulled the
trigger on changing the contrib modules, this is an experimental feature
that nothing else depends on. Worst case, if we can't get to a
satisfactory resolution of the pg_upgrade and ALTER EXTENSION UPGRADE
issues, we can ship 9.1 as-is and just label the EXTENSION commands as
subject to change. I will however now go work on those issues.

regards, tom lane

#41Dimitri Fontaine
dimitri@2ndQuadrant.fr
In reply to: Tom Lane (#40)
Re: Extensions support for pg_dump, patch v27

Tom Lane <tgl@sss.pgh.pa.us> writes:

I have gone ahead and committed the core and documentation parts of this

Thank you!

And I'd like to take the time to thank all of you who helped me reach
this goal, but that ranges to about everyone here who I talked to at any
conference those last two or three years (I still remember talking about
that at PGDay 2008 in Prato, but the ball was already rolling if only in
my head).

You might also be interested to know that the research leading to these
results has received funding from the European Union's Seventh Framework
Programme (FP7/2007-2013) under grant agreement 258862.

patch, but not as yet any of the contrib changes; that is, all the
contrib modules are still building old-style. I had intended to do it
in two steps all along, so as to get some buildfarm proof for the thesis
that we haven't broken old-style add-on modules. However, there is now
an additional motivation for delay: so long as we haven't pulled the
trigger on changing the contrib modules, this is an experimental feature
that nothing else depends on. Worst case, if we can't get to a
satisfactory resolution of the pg_upgrade and ALTER EXTENSION UPGRADE
issues, we can ship 9.1 as-is and just label the EXTENSION commands as
subject to change. I will however now go work on those issues.

Wise move. Again :)

Regards,
--
Dimitri Fontaine
http://2ndQuadrant.fr PostgreSQL : Expertise, Formation et Support