Create multiple schema in one DB on heroku postgresql - postgresql

I want to have two schemas(except public) in a pgsql database on heroku. On local I have done it like imported the data to public schema and renamed it to the name of my choice. In the similar manner i created two schema under one DB and connected it to a rails application using
search_schema_path: 'schema1, schema2'
Now I want to do the same on heroku and tried the same procedure. But it seems that, rails can not find tables from the DB. I am getting the error relationship "delayed_jobs" does not exists. Please suggest me how to do it.
Thanks in advance for any help.

When your Rails app is deployed on Heroku, an automatically generated database.yml over-writes your applications database.yml, which is dropping your schema_search_path setting, reseting it to public.
You can add an initializer that reset the value after load. For example, config/initializers/postgres_schema.rb:
ActiveRecord::Base.connection.schema_search_path = 'schema1, schema2'
You'll need to be careful to set this anywhere you're re-connecting or re-setting.

Related

Heroku Connect, detect salesforce update in postgres

So I have an app taking advantages of Heroku Connect to sync datas between platforms.
I need to find a way to detect when an update has been made by Salesforce (or at least, when the sync has been executed). I'm using sequelize in nodejs, but of course the hooks don't work since heroku connect works directly on the DB and doesn't use the ORM.
So I'm wondering what are my options here.
The solutions that come to my mind (likely there are more):
check out the Heroku Connect system tables like _trigger_log. This table will give you an exact log of the actions HC took (updates/insert/deletes) with information about the record. Yes, you would need to poll it :)
Postgres brings it's own queue-system with LISTEN and NOTIFY. You an write your own database-trigger that will react on change in the salesforce tables, and have a listening/worker-process on the LISTEN queue in PostgreSQL.

Should I create a database for every user in PostgreSQL?

My question is: when I create a PostgreSQL user different from the default postgres user, should I also create a new database for that user to connect to?
What's the point of a setup like that?
A few explanations:
Don't use the postgres database for user data. It is intended for administrative purposes, for example as a database to connect to if you want to run CREATE DATABASE.
This has nothing to do with users.
Users are cluster-wide, that is, all databases in a cluster share the same users. Note that that does not imply that every user can connect to each database.
PostgreSQL command line programs have two defaults:
If you don't specify a database user, the default is the database user that is called like the operating system user.
If you don't specify a database, the default is the database with the same name as the database user.
I assume that it is this last default that inspires your question.
This is just a default value and should not influence your database design.
Create one database for each separate body of data, like all the data that belong to one application.
Create users as your application and data maintenance procedures require. It is a good idea to use different users for different tasks. For example, the user that performs the backup should not be used by your application to connect to the database.
No. Even if it's a local admin user so you don't need to go through sudo, you should just add export PGDATABASE=postgres to your .bashrc or .profile. I always make a new superuser with the name of my local user, and configure pg_hba.conf to allow local connection if necessary.

Point in time reqovery for just one schema or database

I'm going to develop a multi-tenant application, where each tenant lives in its own database or schema (I've not decided this yet).
In this scenario, if I wanted to use point in time recovery (PITR), I also want to have it per-tenant. If a tenant has a problem, I want to be able to roll back only his database or schema and not the whole server.
While I found information how to do backup/restore in such situations with pg_dump and pg_restore, I haven't found any information for PITR.
Is this even possible? If yes, only per database or even per schema?
I can imagine that postgres maybe stores the log of the whole server in a single file, which may be the reason why it could not be possible. But I may be wrong..

Staging environment for Azure Mobile Services using Code First Migrations

I seem to have trouble understanding a concept with Azure Mobile Services that are using .NET backend with Code First and migrations enabled.
Currently I have deployed a "productive" instance of AMS, let's say it's called "AMD". It is running at amd.azure-mobile.net. Database structure has been created using Enable-Migrations and Add-Migration. This is all fine now for this productive instance, it is running and is fully functional.
Now I want to create an INT instance to have a separate environment for tests etc. I want to name it differently, say "AMDINT". It should run at amdint.azure-mobile.net and should also have a separate database, to make it impossible to break stuff in production.
Originally I thought I could pull it off like this:
1) Create the new instance under amdint.azure-mobile.net with a new database to go with it
2) Create a web.config transform for a newly created configuration called "INT" (primarily to change the MS_MobileServiceName value to the new name)
3) Download the publishing profile of the new instance, import it, make it use the "INT" configuration and deploy it
The new bits apparently get deployed, but whenever I hit an endpoint that requires DB access, an error will be generated in the logs and it says
Database initialization failed. Could not initialize one or more objects in schema 'amdint'. Please ensure that the database connection string is correct. For more details on the error, please see the inner exception. ---> System.InvalidOperationException: Database initialization failed. Could not initialize one or more objects in schema 'amdint'. Please ensure that the database connection string is correct. For more details on the error, please see the inner exception. ---> System.Data.SqlClient.SqlException: User does not have permission to perform this action.
So I used Azure User Management Console (AUMC) to see if permissions were missing for the user that is being specified in the connection string in the configuration tab of the new service, but the user was present for that database. I also edited the user's permissions to include every possible right, but this did not change anything.
Then I noticed that the migrations files specify a database schema for the Up() and Down() methods. For a test, I changed these strings from "amd.tablename" to "amdint.tablename" and was pretty confident I had nailed it.
However, this still brought the same error. So I used the database user's credentials from the connection string and opened database editor from the management console in the browser, and saw that with all the added rights it can edit the database schema just fine (created and deleted a table for testing purposes). However, no single table has been created by the Initializer; the database was blank.
But since I was able to edit, I somehow believe that either the error message about insufficient permissions is misleading or that I am looking at the wrong place.
Does anyone know of a way to accomplish what I am trying to do? I don't want to have separate Visual Studio projects for production and INT, obviously.
I think what you're running into is the issue that Mobile Services creates a special schema user that has rights to only tables in that schema. This schema has the same name as your mobile service. So, even if the two databases are on the same DB server, the connection string for a DEV mobile service wouldn't work for PROD, and vice versa.
Here are some suggestions to make your setup easier:
In the Azure Portal, Mobile Services doesn't allow modifying the connection string that it creates for you, which is called MS_TableConnectionString. I recommend that in your case, you create a new connection string with a different key and use that for each of your services, e.g., AMD_TableConnectionString. Make sure that for each service, the database user has access to each schema (more on that in a minute).
To use the new connection string, change your super constructor call in your DbContext class, e.g., base("name=AMD_TableConnectionString").
Use the application setting MS_MobileServiceName in your web.config and/or the Azure Portal to set the schema for your service. This is use by the Mobile Service Entity Framework initializer.
NOTE: If you're already using separate databases for DEV and PROD, you have the option of using the same schema name for both your DEV and PROD instances, which might make testing and setup easier.
Either way, the database user in the connection string must have full permissions to whatever schema name you specify in MS_MobileServiceName.
(You probably have this part working.) Make sure that the Mobile Services SQL Generator is run. It will automatically run if you set an Entity Framework database initializer, but some folks like to have all database changes done through DB migrations. In that case, follow this tutorial here: https://azure.microsoft.com/en-us/documentation/articles/mobile-services-dotnet-backend-how-to-use-code-first-migrations/#using-code-first-migrations-without-an-initializer

RealStudio and PostgreSQL

To connect to the database I use this example. But I can't find lessons on how to create a database.
For example:
connect to server
create new database
do something
drop database
close connection
Can anybody show me how to do it?
Thanks!
Follow the manual on how to create a database cluster:
http://www.postgresql.org/docs/9.1/interactive/creating-cluster.html
The database and users are created only once and you can use the client applications for that. Or are you trying to do it automatically as part of a software install package? After that you connect to it as many times as needed.
Since you are creating a new database and then dropping it, why not use the built-in SQLite database? You can do a completely in-memory database that will be lightning fast (unless you fill up available RAM).
I believe you can create databases by issuing standard SQL commands just as you can create tables in a database, as long as you are using a user (e.g. admin or similarly entitled user) that has permissions to create new databases.
So, all you need is to connect to the DB with the right user and then issue SQL commands with db.SQLExecute, such as "create database newDBname".