One of my models in Phoenix application has append-only semantics. There will be events that can be created, but should never be updated by the application (read only after creation).
Is there a postgres mechanism to enforce such thing on a table?
How should I define my migration to use it?
You can set the permissions on the table to allow INSERT and SELECT but not, for example, UPDATE or DELETE for the role that is used to access the data. This way there is no possibility to alter the data.
More information on permissions.
Related
I use postgresql. I have many databases in a server. There is one database which I use the most say 'main'. This 'main' has many tables inside it. And also other databases have many tables inside them.
What I want to do is, whenever a new row is inserted into 'main.users' table I wish to insert the same data into 'users' table of other databases. How shall I do it in postgresql? Similarly I wish to do the same for all actions like UPDATE, DELETE etc.,
I had gone through the "logical replication" concept as suggested by you. In my case I know the source db name up front and I will come to know the target db name as part of the query. So it is going to be dynamic.
How to achieve this? is there any db concept available in postgresql? Or I welcome all other possible ways as well. Please share me some idea on this.
If this is all on the same Postgres instance (aka "cluster"), then I would recommend to use a foreign table to access the tables from the "main" database in the other databases.
Those foreign tables look like "local" tables inside each database, but access the original data in the source database directly, so there is no need to synchronize anything.
Upgrade to a recent PostgreSQL release and use logical replication.
Add a trigger on the table in the master database that uses dblink to access and write the other databases.
Be sure to consider what should be done if the row alreasdy exists remotely, or if the rome server is unreachable.
Also not that updates propogated usign dblink are not rolled back if the inboking transaction is rolled back
I am new to Postgres and want to know if there is a way to CREATE a DB USER in such a way that it will have access to ALL the SCHEMA's including those which are not created yet, I mean access to all the current and future schema's.I have multiple Schema's in my Postgres DB which have the same Tables.If the above is possible I want this user to have SELECT,INSERT,UPDATE on only 2 Tables in the existing and future created Schemas.
You can use ALTER DEFAULT PRIVILEGES to give a user permissions on future schemas and tables, but you cannot restrict that to certain table names.
You may be able to do that with an event trigger.
Personally, I would put GRANT statements into the code that creates the tables.
Say we have an SQL database with a table Person and several applications accessing it. For some reason we would like to modify the Person table in a backward-incompatible way.
One potential solution for keeping compatibility is to rename the table to User and to create a Person view that provides the same interface as the legacy table. (Add on insert, on update and on delete triggers as needed).
The approach has the problem that we might run out of available semantically correct names after a few changes.
Is there a well-known best practice for "namespacing" the schema "interface" according to the DB version?
Alternatively, is there a better way to maintain backward-compatibility?
Is there a well-known best practice for "namespacing" the schema "interface" according to the DB version?
It's not a common requirement, but when I've seen the need for similar things I've tended to create a new schema that contains the backwards-compatible wrapper for the table in a separate schema (namespace). I then set the search_path on a per-user basis so that the user who needs the backward compat table sees it, and the others see the new version.
The BC view has a RULE or (in newer PostgreSQL versions) a DO INSTEAD trigger referring to the current version of the table explicitly from its normal schema, eg public.People, to support writes if required.
This only works if you need BC on a per-login-user basis where you can ALTER USER ... SET search_path, or (less likely) where you can set the application that needs BC to run a SET search_path command on each session.
I moved some tables in my postgresql (8.2) database to a new schema.
at first, my "user" could not see the tables in the new schema, but I used set search_path to tell it to look in this new schema
I access these tables with a simple web application that uses hibernate. At first, my web application, which uses the "user" user, could not see the tables either, even after I set the search_path. I eventually set the default-schema in the hibernate config file and it worked, but I understand from what I've read that I should not have to set this property? I have a few JDBC queries in this app that still can't see the tables in the new schema.
I've browsed through the postgresql docs and can't find the cause of my problems. Is there something simple I'm missing?
SET search_path is not persisted. It is only valid for the current session.
You need to use ALTER USER to make that change permanently, but you don't need special privileges to change the user you are logged in with (i.e. "yourself")
Actually a simple question, but I wasn't able to find any good conclusive answer.
Assuming a production database foo_prd, and a newer version of the same foo_new (on the same server) that is supposed to replace the old one. What is the cleanest way to seamlessly switch from _prd to _new?
RENAME-ing the databases would require to disconnect the current users via their pid. That would take down some requests, and new users might connect during the process. I was thinking of creating the tables of the new database as different SCHEMA and then change the search_path, e.g. from "$user",prd to "$user",new,prd.
What could possibly go wrong? Do you have any better suggestions? Am I taking the wrong approach altogether?
Do as you suggest: create the tables of the new database as different schema and then change the search_path.
But also create a user with the same name as the new schema and test everything before changing the search_path by logging in as this user with each of your apps - the new schema will be first in that user's search_path by default because the name matches.
Finally, take care when you come to drop the old schema - I suggest renaming first in case anything refers to it's objects using a qualified reference (eg prd.table or prd.function). After a few days/weeks it can then be dropped with confidence.
I would version my schema, and change my app to point to the new schema when ready.