How do I append a schema to the postgresql database default search_path? - postgresql

I already know how to set the search_path per database or user (alter database set search_path to schema1, schema2, ...).
What I would like to do is append a schema to the default search path. I know I can get the current search path (show search_path) but this could have been altered during the session.
The purpose is something like:
create schema postgis;
set search_path to postgis;
create extension postgis;
alter database the_db set search_path to <the current default>, postgis;
I can do this manually but I want to add this to a function that could be called after the user altered the session search path.

Ah, found it.
For my purposes I can just do
set search_path to default;
before appending.

This updates search_path for current session & also future sessions. base on these two posts
DO $$
BEGIN
execute 'alter database '||current_database()||' set search_path to '||current_setting('search_path')||',extensions';
execute 'set search_path to '||current_setting('search_path')||',extensions';
END
$$;

Related

Grant privileges to set session_replication_role

A script has to import SQL data into an PostgreSQL database. The SQL includes these two lines of code:
SET session_replication_role = 'replica';
...
SET session_replication_role = 'origin';
The user xyz who starts the import doesn't have the power to do this yet. The error PG::InsufficientPrivilege gets displayed.
How (with which SQL query) can the user postgres grant the user xyz the right to set session_replication_role? I can't find any documentation about that.
As of PostgreSQL 15+ there is a way to do this:
GRANT SET ON PARAMETER session_replication_role TO xyz;
https://www.postgresql.org/docs/15/sql-grant.html
I haven't tried this yet but I bet it works good - in version 14, I used SECURITY DEFINER at the end of a plpgsql procedure with "SET session_replication_role" statements inside of it, and made sure a superuser account was the definer/owner of the procedure - then, any user with EXECUTE privilege can still run it and the parameter setting works as you would hope.
It is impossible :-(. See:
It seems this is currently only possible with superuser privilege:
Setting this variable requires superuser privilege, cf.
postgresql.org/docs/current/runtime-config-client.html

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.

SET/RESET command in ALTER DATABASE is not supported

Encountered this issue when trying to modify the search_path to my new Redshift db.
Presently, I've migrated the contents of my MySQL db into a redshift cluster via AWS' Data Migration Service. The data was imported into a schema lets call my_schema. When I try to execute queries against the cluster it requires me to prefix table names with the schema name
i.e.
select * from my_schema.my_table
I wanted to change the setup so that I can reference the table directly without needing the prefix. After a bit of looking around I found out that this was possible by modifying the search_path attribute.
First I tried doing this by running
set search_path = "$user", my_schema;
This appeared to work but then I realized that this was simply setting my_schema as the default schema in the context of the current session, I wanted it set on a database level. I found several sources saying that the way to do this was to use the alter command like so...
alter database my_db set search_path = "$user", public, my_schema
However, running this command results in the following error which somehow shows up in 0 google results:
SET/RESET commmand in ALTER DATABASE is not supported
I'm pretty baffled by how the above error hasn't ever had a post made about it but I'm also pretty interested in figuring out how to resolve my initial issue of setting a global default schema for my redshift cluster.
ALTER DATABASE SET is not supported in Redshift. However you can SET/RESET configuration parameters at USER level using the ALTER USER SET SEARCH_PATH TO <SCHEMA1>,<SCHMEA2>;
Please check: http://docs.aws.amazon.com/redshift/latest/dg/r_ALTER_USER.html
http://docs.aws.amazon.com/redshift/latest/dg/r_search_path.html
When you set the search_path to <SCHEMA1>,<SCHMEA2> in db1 for a user it is not for just current session, it will be set for all future sessions.

Set deafult schema while querying in pgAdmin 4 with query tool

Whenever i have to execute sql commands in pgAdmin 4 i have to append schema_name with tables.
Eg :-
SELECT * FROM my_schema.users //where myschema is schema name
ORDER BY id ASC
Is there any way to execute sql commands in pgAdmin 4 without schema name, by setting a default schema in advance.
Some thing like this
SELECT * FROM programme
ORDER BY id ASC
- without specifying schema name with table.
Is there a way to set default schema in pgAdmin 4 for querying in sql tool?
You can do it in 2 ways:
SET search_path = my_schema, "$user", public; -- For current session only
ALTER ROLE your_role SET search_path = my_schema, "$user", public; -- Persistent, for role
You can also set it for whole database, same way as for role.
EDIT: Just to explain what this does - it will change where and in what order Postgres will search for objects matching object identifiers that did not get prefixed with schema name.
You might need also to restart pgAdmin4 in order for the search_path to start working. At least it was my case.
A good double check if the search_path was set in pgAdmin4 is to go to:
Login/Group Roles -> Right click on the user (by default it is 'postgres') -> Properties -> Parameters tab. Here you should see your new parameter 'search_path' with the value 'your_schema_name'.

Postgresql ignores lack of EXECUTE permission if USAGE permission is granted on containing schema

From http://www.postgresql.org/docs/9.1/static/sql-grant.html:
USAGE
...
For schemas, allows access to objects contained in the specified schema (assuming that the objects' own privilege requirements are also met). Essentially this allows the grantee to "look up" objects within the schema. Without this permission, it is still possible to see the object names, e.g. by querying the system tables. ...
...
However, running the following script through psql seems to show that although the lack of a SELECT permission causes an error, lack on an EXECUTE permission does not, which contradicts the documentation as the 'own privilege requirement' is not met.
CREATE DATABASE testdb WITH OWNER postgres ENCODING 'UTF8';
\connect testdb
CREATE ROLE testrole;
CREATE SCHEMA testschema;
GRANT USAGE ON SCHEMA testschema TO testrole;
SET search_path TO testschema;
CREATE FUNCTION testfunc ()
RETURNS VOID
AS $$
BEGIN
RAISE NOTICE 'IN TESTFUNC';
RAISE NOTICE 'Current user: %', current_user;
END;
$$
LANGUAGE plpgsql;
CREATE TABLE testtable
(
testrow INT
);
INSERT INTO testtable (testrow) VALUES (1), (2), (3);
SET ROLE testrole;
SELECT testfunc();
SELECT * FROM testtable;
RESET ROLE;
Output:
$ psql -f usage.sql
CREATE DATABASE
You are now connected to database "testdb" as user "postgres".
CREATE ROLE
CREATE SCHEMA
GRANT
SET
CREATE FUNCTION
CREATE TABLE
INSERT 0 3
SET
psql:usage.sql:27: NOTICE: IN TESTFUNC
psql:usage.sql:27: NOTICE: Current user: testrole
testfunc
----------
(1 row)
psql:usage.sql:28: ERROR: permission denied for relation testtable
RESET
Have I missed something or am using the permissions incorrectly?
The schema is not what matters here, what you're seeing is the default execute permissions of functions.
Consider this excerpt from the CREATE FUNCTION documentation:
Another point to keep in mind is that by default, execute privilege is
granted to PUBLIC for newly created functions (see GRANT for more
information). Frequently you will wish to restrict use of a security
definer function to only some users. To do that, you must revoke the
default PUBLIC privileges and then grant execute privilege
selectively.