Namespacing versions of an PostgreSQL schema for backward-compatibility? - postgresql

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.

Related

Two names, or permanent alias, for the same Postgres table, and column -- during migration

How can I create a permanent alias for a table (and also a column) such that queries against either name work?
I'd like to do this to enable renaming tables in our software. Our migrations need to run against live clusters, thus there's a period where the software version will be older than the DB version. It has to work with the old names of the tables and columns.
I see that it's possible to create a view with rules for insert, update, and delete, which I think is fairly close, but I'm wondering if there is a simpler approach. This approach also doesn't work if I wish to simply rename a column in a table (that is, without having to rename the table at the same time).

How to implement schema migration for PostgreSQL database

I need to implement schema migration mechanism for PostgreSQL.
Just to remove ambiguity: with schema-migration I mean that I need upgrade my database structures to the latest version regardless of their current state on particular server instance.
For example in version one I created some tables, then in version two I renamed some columns and in version three I removed one table and created another one. I have multiple servers and on some of them I have version one on some version three etc.
My idea:
Generate hash for output produced by
pg_dump --schema-only
every time before I change my database schema. This will be a reliable way to identify database version in the future to which the patch should apply.
Contain a list of patches with the associated hashed to which they should apply.
When I need to upgrade my database I will run an application that will search for hash that corresponds to current database structure (by calculating hash of local database and comparing it with hash set that I have) and apply associated patch.
Repeat until next hash is not found.
Could you please point any weak sides of this approach?
Have you ever heard of https://pgmodeler.io ? At the company where I work we decided to go for this since it can perform schema diff even between local and remote. We are very satisfied with it.
Otherwise if you are more for a free solution, you could develop a migration tool which can be used to apply migrations you store in a single repo. Furthermore this tool could rely on a migration table you keep in a separate schema so that your DB(s) will always know which migrations were applied or not.
The beauty of this approach is that migrations can both be about a schema change and data changes.
I hope this can give you some ideas.

db2look from SQL

Is it possible to get the table structure like db2look from SQL?
Or the only way is from command line? Thus, by wrapping a external stored procedure in C I could call the db2look, but that is not what I am looking for.
Clarification added later:
I want to know which tables have the non logged option from SQL.
It is possible to create the table structure from regular SQL and the public DB2 catalog - however, it is complex and requires some deeper skills.
The metadata is available in the DB2 catalog views in the SYSCAT schema. For a regular table you would first start off by looking into the values in SYSCAT.TABLES and SYSCAT.COLUMNS. From there you would need to branch off to other views depending on what table and column options you are after, whether time-travel tables, special partitioning rules, or many other options are involved.
Serge Rielau published an article on developerWorks called Backup and restore SQL schemas for DB2 Universal Database that provides a set of stored procedures that will do exactly what you're looking for.
The article is quite old (2006) so you may need to put some time in to update the procedures to be able to handle features that were added to DB2 since the date of publication, but the procedures may work for you now and are a nice jumping off point.

PostgreSQL: update a schema when views from another schema depend on it

Here is my setup. I have two schemas: my_app and static_data. The latter is imported from a static dump. For the needs of my application logic, I made views that use the tables of static_data, and I stored them in the my_app schema.
It all works great. But I need to update the static_data schema with a new dump, and have my views use the new data. The problem is, whatever I do, my views will always reference the old schema!
I tried importing the new dump in a new schema, static_data_new, then trying to delete static_data and rename static_data_new to static_data. It doesn't work because my views depend on tables in static_data, therefore PostgreSQL won't let me delete it.
Then I tried setting search_path to static_data_new. But when I do that, the views still reference the old tables!
Is it possible to have views that reference tables using the search_path? Thanks.
Views are bound to the underlying objects. Renaming the object does not affect this link.
I see basically 3 different ways to deal with your problem:
DELETE your views and re-CREATE them after you have your new table(s) in place. Simple and fast, as soon as you have your complete create script together. Don't forget to reset privileges, too. The recreate script may be tedious to compile, though.
Use table-functions (functions RETURNING SETOF rows or RETURNING TABLE) instead of a views. Thereby you get "late binding": the object names will be looked up in the system catalogs at execution time, not at creation time. It will be your responsibility that those objects can, in fact, be found.
The search_path can be pre-set per function or the search_path of the executing role will be effective for objects that are not explicitly schema-qualified. Detailed instructions and links in this related answer on SO.
Functions are basically like prepared statements and behave subtly different from views. Details in this related answer on dba.SE.
Take the TRUNCATE and INSERT route for the new data instead of DELETE and CREATE. Then all references stay intact. Find a more detailed answer about that here.
If foreign keys reference your table you have to use DELETE FROM TABLE instead - or drop and recreate the foreign key constraints. it will be your responsibility that the referential integrity can be restored, or the recreation of the foreign key will fail.

Seamlessly updating a postgres database - schemas, rename, how?

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.