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

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.

Related

Postgres inherit from schema

I am initiating a new project which will be available as a SaaS for multiple customers. So, I am thinking of creating a database and then create individual schema for every customer.
I have defined some rules and the first rule is all the customers must always have the same schema. No matter what. If one customer gets an update, all the other customers will get the update as well.
For this purpose, my question is, is it possible to inherit schema from another schema in the same database? If not, do I have to manually create all the tables and indexes in the new schema and inherit them from the tables in master schema?
I am using Postgresql 9.6 but I can upgrade it as well if needed.
I open to suggestions.
Thanks in advance
There is no automated way to establish inheritance between all tables in two schemas, you'd have to do it one by one (a function can help).
However, I invite you to stop and think about your data model for a bit. How many users do you expect? If there could be many, plan differently, because databases with thousands of schemas become unwieldy (e.g. catalog lookups will become slow).
You might be better off with one schema for all users. If you are concerned with separation of the data and security, row level security might be the solution for you.

Best strategy for db update when updating application

I have function that initialize my database create tables etc.
Now I prepare version two of the application and in this function at the end I added check for column existence and if not exist I alter table.
My question is:
To avoid checking this all the time is it good to put in UserDefaults some flag that indicate that current app is version two and if it is to avoid this code?
This seams logical to me but other opinion is always welcome ;)
You could have a version number table/column in your database which stores the schema version number. Every time you change the schema, increment the number in your application file and then run the relevant migration code to get from one schema version to another whilst updating the schema version in the database.
This answer has a handy way of tracking db schema version numbers without creating a separate table in SQLite
Yes, you can user NSUSER Default to check this. I don't think anything wrong with this.

Namespacing versions of an PostgreSQL schema for backward-compatibility?

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.

libpq code to create, list and delete databases (C++/VC++, PostgreSQL)

I am new to the PostgreSQL database. What my visual c++ application needs to do is to create multiple tables and add/retrieve data from them.
Each session of my application should create a new and distinct database. I can use the current date and time for a unique database name.
There should also be an option to delete all the databases.
I have worked out how to connect to a database, create tables, and add data to tables. I am not sure how to make a new database for each run or how to retrieve number and name of databases if user want to clear all databases.
Please help.
See the libpq examples in the documentation. The example program shows you how to list databases, and in general how to execute commands against the database. The example code there is trivial to adapt to creating and dropping databases.
Creating a database is a simple CREATE DATABASE SQL statement, same as any other libpq operation. You must connect to a temporary database (usually template1) to issue the CREATE DATABASE, then disconnect and make a new connection to the database you just created.
Rather than creating new databases, consider creating new schema instead. Much less hassle, since all you need to do is change the search_path or prefix your table references, you don't have to disconnect and reconnect to change schemas. See the documentation on schemas.
I question the wisdom of your design, though. It is rarely a good idea for applications to be creating and dropping databases (or tables, except temporary tables) as a normal part of their operation. Maybe if you elaborated on why you want to do this, we can come up with solutions that may be easier and/or perform better than your current approach.

web application cannot see tables in new postgresql schema

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")