INSERT ON CONFLICT and Row Level Security are awesome new additions.
If you don't know about RLS I recommend you read up on them[1], as they would allow you to handle select/update/delete rights on rows directly on the data itself.
Awesome! Though having read the explanation I can't think of a secure way to use this in a multi-tenanted app, as once the DB user has permission to execute "SET ROLE", it's got the same security issues with accessing other user data as the current "WHERE company_id=3" style of separation? Would it help this use-case, and does it add security?
> as once the DB user has permission to execute "SET ROLE", it's got the same security issues with accessing other user data as the current "WHERE company_id=3" style of separation?
DB users can only SET ROLE to roles they belong to. If each tenant has its own role it isn't possible to switch between them.
# CREATE ROLE bob;
CREATE ROLE
# CREATE ROLE alice;
CREATE ROLE
# SET SESSION AUTHORIZATION bob;
SET
> SET ROLE alice;
ERROR: permission denied to set role "alice"
"SET SESSION AUTHORIZATION <role>" changes the possible SET ROLE targets to those allowed for <role> (so only the roles it's a member of), whereas SET ROLE keeps the original possible roleset (which is every role if you SET ROLE from an admin account), so SET SESSION AUTHORIZATION is a better proxy for "logged as <role>".
The biggest annoyance is with connection pooling and the inability (to my knowledge) to prevent RESET SESSION AUTHORIZATION at the DB-level: when pooling connections you'll want to have a "base" role which is a NOINHERIT member of all "effective" (tenant) roles, so it can only SET ROLE/SET SESSION AUTHORIZATION but can't do anything (so it can't be exploited), the first thing you do when you get a connection from the pool is SSA to the effective user you want, and the last thing you do when you put the connection back in the pool is a RSA.
# CREATE TABLE foo ( id serial, c1 varchar, c2 varchar );
# GRANT SELECT (id, c1, c2) ON foo TO public;
# GRANT UPDATE (c1) ON foo TO bob;
# GRANT UPDATE (c2) ON foo TO alice;
# INSERT INTO foo (c1, c2) VALUES ('a', 'b');
# SELECT * FROM foo;
id | c1 | c2
----+----+----
1 | a | b
(3 rows)
# SET SESSION AUTHORIZATION base;
> UPDATE foo SET c1 = 'd' WHERE id = 1;
ERROR: permission denied for relation foo
> SET SESSION AUTHORIZATION bob;
> UPDATE foo SET c1 = 'd' WHERE id = 1;
UPDATE 1
> SELECT * FROM foo;
id | c1 | c2
----+----+----
1 | d | b
(3 rows)
That'll prevent honest mistakes, though an attacker could still RESET SESSION AUTHORIZATION then switch the connection to a different role and go to town. It might be possible to mitigate that at the application level, but that's less convenient.
An output parameter seems somewhat inconvenient to use from an application context, but yes that's a feature which — as the MSDN correctly notes — would be extremely useful for multiuser with connection pooling environment.
It does help this use case, as you can restrict which role's a user/connection can have. i.e. you can't set role to anything you want if you are not a superuser.
I'm confused by your question, but I think "table column". Think generic SaaS application: one app, one (sharded) database, one set of tables, used by many different companies.
The ALTER TABLE UNLOGGED feature is awesome, we've been looking for ways to speed up our Django test runner and this seems like it would help.
I've been thinking that a "test-only" mode of Postgres would be quite useful - i.e no persistence/WAL/crash-safety at all, in return for raw speed. My tests don't need any of this, and the Django test runner is awfully wasteful when it comes to setting up and tearing down tests.
Unlogged tables have existed since 9.1. The only thing that was added now was a quick way to toggle between modes. Before, you could achieve the he same by creating a second unlogged table (using 'like x including indexes'), followed by an 'insert into ... select ...' an the subsequent dropping and renaming (remember: DDL is transactional in Postgres, so you can do all of this in a transaction).
Yes, the new toggle is much more convenient, but you do not have to wait for 9.5 if you really want it.
In our case, we converted some tables we use as kind of materialized views the moment 9.1 came out.
Thanks for that tip, I will try and integrate it with our tests later and see if there is much of a speedup (before I was trying to alter Django's CREATE TABLE statements which is harder than I thought).
I was also suggesting something further than unlogged tables, maybe something completely in-memory? Good tests are run in isolation and are really just care about the constraints rather than any form of persistence, combined with the fact that all data inserted is erased at the end of the test anyway it just seems a bit wasteful.
if it's just for testing, you can use a ram disk to store the data directory. If you don't want the entire db on the ramdisk, you can create a tablespace for the ramdisk, and then create tables on it.
http://www.postgresql.org/docs/9.5/static/manage-ag-tablespa...
The idea is, since it's a development db, after you destroy it, you can recreate it easily.
But there is a way to do it without destroying the db. When you're finished, stop postgres, copy the files off of the ramdisk, and then you can destroy the ramdisk. When you want to start it back up, create the ramdisk, copy the files back, and then start postgres.
Obviously something like MySQL's memory tables would be a better solution.. but postgres doesn't have anything similar. So this is as close as you can get.
Thanks for writing back! I don't love either of those options. Maybe I should just make a separate cluster for my test database?!: `initdb -D /pgramdisk` I wonder if anyone has tried this, and what the drawbacks are.
and when you use alter table unlogged.. that's actually what it does anyway -- it rewrites the entire table (holding an exclusive lock the entire time).
What's the easiest way to try out an alpha version of postgres? I can't find a ubuntu or homebrew pacakged build of it... easiest to build it from source?
> "Relatively simple - at least on Ubuntu / Debian"
I realize we're all professionals here and technical know-how is expected, but nothing about this is "simple". Brings me PTSD of working w/ academics' alphabet soup of "open source" simulation code written in C, Perl and Makefiles.
Build tools have come along away, maybe not with vanilla Postgres installs, but I guess that's what DBAs are paid to know these days.
I honestly don't see what's so hard about the gp's set of instructions. Your grandma doesn't need to install alpha builds of PostgreSQL (though I shouldn't assume, there are some technical grandmas out there ;) ), for 99% of people out there they can use "apt-get" or "yum" or whatever and can wait until the release.
So let's turn this around, how would you like to see builds become easier?
This can slightly more easily done using 'apt-get build-dep postgresql-9.4'. That'll also pull in the tools to build the docs, but I'd consider that a good thing.
> make world && make install
You're building world, but not installing it -> make install-world.
If you don't know about RLS I recommend you read up on them[1], as they would allow you to handle select/update/delete rights on rows directly on the data itself.
[1]http://michael.otacoo.com/postgresql-2/postgres-9-5-feature-...