Installing PostgreSQL Extension to all schemas - postgresql

I'm on PostgresQL 9.1.1 trying to have the extension unaccent available on all schemas.
So I ran the command CREATE EXTENSION unaccent;. Which works, but only for the current schema set on search_path. So this means if I change the search_path, I no longer can call unaccent. How do I make this extension available to all schemas in a particular database?
Thanks in advance!

CREATE EXTENSION unaccent; installs the extension into the public schema. To make it usable, simply include this to change the search_path:
set search_path = my_schema, public;
Or better create a schema to contain all extensions, then always append that schema to the search_path.
create schema extensions;
-- make sure everybody can use everything in the extensions schema
grant usage on schema extensions to public;
grant execute on all functions in schema extensions to public;
-- include future extensions
alter default privileges in schema extensions
grant execute on functions to public;
alter default privileges in schema extensions
grant usage on types to public;
Now install the extension:
create extension unaccent schema extensions;
Then use include that schema in the search_path
set search_path = my_schema, extensions;
If you don't want to repeat the above for every new database you create, run the above steps while being connected to the template1 database. You can even include the extensions schema in the default search_path by either editing postgresql.conf or using alter system

Had same question, but #Richard Huxton answer led to correct solution:
create extension unaccent schema pg_catalog;
This works!!
As Richard said, pg_catalog is automatically added (silently) to each search_path. Extensions added there will be found.
imho this is much better than schema.func() if the extension is global.
For example, I use a lot of schemae. I use the schema PUBLIC for debugging - everything should be in its own schema. If something is in PUBLIC, it's wrong.
Creating the extension in pg_catalog keeps all the schema clean, and lets the schema itself work as if it were part of the core postgres.

You don't. You can always call it fully qualified if you want to.
SELECT <schema>.<function>(...)
In fact, I believe the only reason the built-in functions are always available is that PG adds pg_catalog to the end of your search_path no matter what you do.

Related

Install postgres extension with schema

I am trying to install pgcrypto in pg_catalog schema. But this does not work with postgres 13 or higher since the function gen_random_uuid is globally available. How can I still create my extension?
I am trying:
CREATE EXTENSION IF NOT EXISTS "pgcrypto" WITH SCHEMA pg_catalog CASCADE
I get the error:
ERROR: function "gen_random_uuid" already exists with same argument types.
All functions in pg_catalog are automatically available within other schemas.
Any function with schema pg_catalog can be called by using schema for example pg_catalog.gen_random_uuid(), but also without defining the schema, for example gen_random_uuid().
Function gen_random_uuid() is part of extension pgcrypto, so when you are trying to enable it, it notifies you, that this function is already installed.
CREATE EXTENSION IF NOT EXISTS pgcrypto WITH SCHEMA pg_catalog CASCADE;
On most cases is recommended to install common Postgres extensions into pg_catalog, so these are available within any schema. All objects in pg_catalog are automatically appended to any other schema. For example if you put pgcrypto into public schema, then you have to always use public.gen_random_uuid() within any other schema, which is annoying etc. But if you put it into pg_catalog, then you can call anywhere gen_random_uuid(), which is more useful.

Create extension from postgres superuser to another database with it own owner?

Maybe I'm saying a silliness, but is it possible to create a extension from a superuser - like postgres - in other database with it own schema and owner?
I have a database called sdmed, with two schemas, public and sdmed. I also have a role called sdmed . This role can only create tables.
I would like to create a extension in those database. The extension has functions, tables and types.
If not, what would be the better way to do that?
Edit:
My original question was incomplete. I mean that I want to create extension from user postgres (or a superuser) in other database, with it owner, role and schema. Also, those extension would be used in those database.
I try this one:
First, I create a function only for those schema (sdmed is a database, with a schema called sdmed and it owner is sdmed):
CREATE OR REPLACE FUNCTION sdmed.di_hola()
RETURNS void AS
$BODY$
BEGIN
RAISE NOTICE 'Hola';
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION sdmed.di_hola()
OWNER TO sdmed;
Also (after prepare my own extension)
postgres=# create extension hola;
ERROR: schema "sdmed" does not exist
(The database role and schema sdmed exists)
And if I try from sdmed database:
sdmed=> create extension hola;
ERROR: permission denied to create extension "hola"
HINT: Must be superuser to create this extension.
I would make sdmed a SuperUser, but I would like to avoid that for keep best practices.
I'm not sure I got your question right, but in case you're wondering if it would somehow make the extension not to work properly the answer is: it shouldn't be an issue :)
Since the user sdmed is the owner of the database sdmed, it has access to all objects in this database - no matter who created them! So, objects installed by the function created with the user postgres should work with the user sdmed without any problem.

Amazon RDS Postgres -> Give permission to pg_catalog

I need to grant permission to the master user(MasterUsername) the access of of pg_catalog.
GRANT USAGE ON SCHEMA pg_catalog TO <master-user>;
On running this, I get the below warning:
WARNING: no privileges were granted for "pg_catalog".
Essentially, I have an automation script, where I create the database, I set search path and :
SET search_path = <my-schema>, pg_catalog;
CREATE TYPE <type> AS (
id bigint,
name character varying);
I get below error
Caused by: org.postgresql.util.PSQLException: ERROR: permission denied for schema pg_catalog
Essentially, it's not allowing me to create type, since the pg_type table exists in pg_catalog. How to create type?
I don't know if granting the USAGE rights will help? If there's another way to work-around this, please do let me know.
granting usage rights will only let you be able to access objects of a schema, creating new objects will require create privileges on that schema.
The way I worked around this is very simple, I created a role postgres using CREATE ROLE postgres, I assigned it to my user.
Added to search path public and the database by SET search_path=public,<database>
Assigning this to my user actually gave me all the rights I needed to create custom pg_type, use the schema pg_catalog in public schema. How this worked? I don't know, may be postgres guys can answer this? Or the AWS RDS guys can answer this may be.
Secondly, I faced another issue in using the pg_functions and the functions of extension Postgis, even they were resolved by adding the role postgres role to the user who needed to access the function.
I still think this is a workaround and not a direct fix, or may be a fix but there should be some documentation around this(which I did not find).

Additional module citext is installed, but type "citext" not found?

I'm trying to run an inline query on my database - which has the citext extension installed (using CREATE EXTENSION) - and yet the executed query keeps throwing this error when calling a function:
type "citext" does not exist
DO
LANGUAGE plpgsql
$$
DECLARE
_id INT;
BEGIN
SELECT * FROM "dbo"."MyFunction"(_id, 'some value'::citext);
END;
$$;
If I omit the ::citext cast, it says:
function dbo.MyFunction(integer, unknown) does not exist.
You might need to add explicit type casts.
The citext extension is added, is part of the schema and works with other queries. This keeps coming up randomly - what causes it?
EDIT:
The installed extensions:
extname | nspname
----------+-----------
plpgsql | pg_catalog
citext | public
uuid-ossp | public
Search path:
show search_path;
search_path
-----------
dbo
As suspected, the extension schema is missing from the search_path. Read up on how to set the schema search path in this related answer:
How does the search_path influence identifier resolution and the "current schema"
It seems like your client sets search_path = dbo on connection, which seems to be misconfigured. dbo is something we see a lot for SQL Server (used to be the default schema here or still is?), very untypical for Postgres. Not sure how you got there.
Why do table names in SQL Server start with "dbo"?
One alternative would be to install extensions into the dbo schema as well:
Best way to install hstore on multiple schemas in a Postgres database?
You can even move (most) extensions to a different schema:
ALTER EXTENSION citext SET SCHEMA dbo;
But I would advice to install extensions to a dedicated schema and include it in the search_path.
Leave plpgsql alone in any case. It's installed by default and should should stay in pg_catalog.
One way or another, clean up the mess with varying search_path settings.
As for the second question: that's guided by the rules of Function Type Resolution. The call cannot be resolved, because citext does not have an implicit cast to text.
Related
Is there a way to disable function overloading in Postgres

PostgreSQL: making a schema restricted/unchangable?

We like our production environment with a restricted/unchangable schema -- the development side can be owned by the developers and changed as they like -- and we like to vet changes as they are promoted.
I'm wondering if this may be a solution to making that happen:
postgres% create proddb with owner=postgres;
unixside% pg_restore --dbname=devdb [--schema-only] --no-owner proddb
/* grants to users on schema objects appear to remain intact */
/* here's the magic, I hope... */
postgres% revoke create on schema public from public;
postgres% grant usage on schema public to produser(s);
Some testing seems to show that a user in this new proddb can interact with tables normally (with appropriate grants) and cannot alter the schema (alter table, create table, drop table, etc). But I'm paranoid and very new to Postgres, so...
Q: Is this correct?
Q: Am I missing anything?
Thanks muchly.
Yes, that is correct. The only addition is that the owner of a table can always delete or modify it. So it may not work if you have existing tables in the schema.
Discovered a missing element: sequences.
The user was finding errors in his scripts; similar errors appeared in the logs:
ERROR: permission denied for sequence <sequence>
The production schema showed that although sequences were created, they were owned by postgres and no explicit grants were given to the users. As per the GRANT documentation:
Granting permission on a table does not automatically extend permissions to any sequences used by the table, including sequences tied to SERIAL columns. Permissions on sequence must be set separately.
Our fix (verbose for this demonstration) was to find all sequences:
unixside% pg_dump --schema-only proddb > proddb.schema
unixside% grep -i 'create sequence' proddb.schema
...and apply appropriate grants (select to prevent table scans, update to prevent the above errors):
postgres% grant select,update on <sequence> to produser(s);
So far, the user says it's working and errors to the log have stopped...
I forget what version PostgreSQL added the syntax, but one of the easiest ways to administer permissions in PostgreSQL is through the "GRANT foo, priv ON ALL something IN SCHEMA" syntax.
BEGIN;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA my_schema TO my_role;
GRANT USAGE ON ALL SEQUENCES IN SCHEMA my_schema TO my_role;
GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA my_schema TO my_role;
COMMIT;
Very handy for making sure that permissions are always set correctly.
The EXECUTE for FUNCTIONS may seem spooky, but shouldn't be unless your functions were created with the SECURITY DEFINER attribute (and if you are using SECURITY DEFINER, you'd better be cautious since you're playing around with the PostgreSQL version of a "setuid" function). If you space out your TABLES across different SCHEMAS based on the expected permissions, then this becomes a pretty handy convention when used with the search_path variable.
ALTER ROLE my_role SET search_path = my_schema, auth_schema, public;
-- Avoid using the public schema (pretty please)
Where auth_schema has a collection of tables that my_role shouldn't have direct read or write privileges on. Assigning privs to GROUPS is also useful.
Here are some relevant docs:
http://developer.postgresql.org/pgdocs/postgres/sql-grant.html
Don't forget you can use "\h GRANT" in psql to easily figure out the syntax or remember what can be done on all objects in a schema (search for "IN SCHEMA").