How to create a new schema from a flask application - postgresql

I have flask application,I'm trying to achieve multi-tenancy by multiple schema for users. When a user sign up, i'm trying to create a new schema with the username from the application and creating new two table in that particular schema.
i can create a new schema into the database using psql console using
postgres=# CREATE SCHEMA schema_name;
How can i create the schema from the flask application?

I have achieved the same. My aim was to create a SaSS app with a shared DB & separate schema in Flask.
So when users signup for my premium plan, my code will create a schema for my user.
First import the required modules.
from sqlalchemy import create_engine, MetaData, Table
In the user sign-up route, I have added the below code. The org_id is a random string & it is my schema. Also, I have to create a post table inside that schema. I also need to save the schema name in my user table & it helps to filter result later in that schema only.
# Create schema
engine = create_engine(app.config['SQLALCHEMY_DATABASE_URI'])
if not engine.dialect.has_schema(engine, org_id):
engine.execute('CREATE SCHEMA IF NOT EXISTS %s' % org_id)
# Create table inside this new schema
if engine.dialect.has_schema(engine, org_id):
meta = MetaData()
post = Table('post', meta,
db.Column('id', db.Integer, primary_key=True),
db.Column('body', db.String(140)),
db.Column('timestamp', db.DateTime, index=True, default=datetime.utcnow),
db.Column('user_id', db.Integer),
schema=org_id
)
post.create(engine)
Basically I'm a beginner in flask & python. So I'm not sure what is the correct method.

Related

Is there any way to create foreign key from different schemas?

I have an application where I am separating data with schemas where I have one table common in all schemas. lets say I have one public schema which is an admin schema and other schemas such as a,b,c,...,etc which are user schema. And all schemas have one common table T and all users can create entries in this T table and there are some entries which can only be created by admin user and all other users will use that rows.
so how I will achieve this.
I have two onptions in my mind
I will create T table in every schema and when ever admin adds new entry I will add that in all other schemas.
I will create T table in public schema and will add foreign key from that schema in other schema.
note: Schemas are dynamic and they are created run time and I am using postgres, Nestjs and sequelize-typescript

Why doesn't SQLAlchemy reflect tables in non-public schema?

I have a PostgreSQL database, which has had all objects in public schema.
Used SQLAlchemy to succesfully connect to it and reflect objects from it.
Now I needed to create a separate schema schema2 in the same database. I assigned to new user all rights in that schema, checked that I can connect from command line with psql and do things in it.
But SQLAlchemy doesn't see any tables in the schema, when I try to use the same method to reflect its tables -- despite trying various ways to specify schema!
This is what worked for initial connection to public schema:
from sqlalchemy.ext.automap import automap_base
from sqlalchemy import create_engine
from sqlalchemy import Table, Integer, String, Text, Column, ForeignKey
Base=automap_base()
sql_conn='postgres://my_user#/foo'
engine=create_engine(sql_conn)
Base.prepare(engine, reflect=True)
Then I could use Base.classes.* for tables and I didn't need to create Table classes on my own.
Now, this same works for this new user for public schema as well.
But whenever I somehow try to pass the schema2 to reflect tables from schema2, I always get empty Base.classes.*
I tried all the solutions in SQLAlchemy support of Postgres Schemas but I don't get anything at all reflected!
I tried:
making user's default schema schema2 via SQL means:
ALTER new_user SET search_path=schema2;
tried to pass schema in engine.connect via engine options
tried to set schema in MetaData and use that, as per SQLAlchemy docs:
Doing:
meta=MetaData(bind=engine,schema='schema2')
meta.reflect()
does work, as I can see all the tables correctly in meta.tables afterwards.
However, when I try to get Base.classes working as per SQLAlchemy automapper docs, the Base.classes don't get populated:
from sqlalchemy.ext.automap import automap_base
from sqlalchemy import create_engine
from sqlalchemy import Table, Integer, String, Text, Column, ForeignKey, MetaData
sql_conn='postgres://new_user#/foo'
engine=create_engine(sql_conn)
meta=MetaData(bind=engine,schema='schema2')
Base=automap_base(metadata=meta)
Base.prepare(engine, reflect=True)
Base.classes is empty...
I am now stumped. Any ideas?
PS. I am working on newest SQLAlchemy available (1.3) under pip for Python2.7, Ubuntu 18.04LTS.

Replacing schema name when sharing sql script with other users

When collaborating with colleagues I need to change the schema name every time I receive a SQL script (Postgres).
I am only an ordinary user of a corporate database (no permissions to change anything). Also, we are not allowed to create tables in PUBLIC schema. However, we can use (read-only) all the tables from BASE schema.
It is cumbersome for the team of users, where everybody is creating SQL scripts (mostly only for creating tables), which need to be shared amongst others. Every user has its own schema.
Is it possible to change the script below, where I will share the script to another user without the need for the other user to find/replace the schema, in this case, user1?
DROP TABLE IF EXISTS user1.table1;
CREATE TABLE user1.table1 AS
SELECT * FROM base.table1;
You can set the default schema at the start of the script (similar to what pg_dump generates):
set search_path = user1;
DROP TABLE IF EXISTS table1;
CREATE TABLE table1 AS
SELECT * FROM base.table1;
Because the search path was change to contain user1 as the first schema, tables will be searched in that schema when dropping and creating. And because the search path does not include any other schema, no other schema will be consulted.
If you
However the default search_path is "$user", public which means that any unqualified table will be searched or created in a schema with the same name as the current user.
Caution
Note that a DROP TABLE will drop the table in the first schema found in that case. So if table1 doesn't exist in the user's schema, but in the public schema, it would be dropped from the public schema. So for your use-case setting the path to exactly one schema might be more secure.

Unable to create a table in new database

beginner at SQL here, specifically using PostgreSQL. I'm trying to do something for a class here, but I keep receiving an error message and I'm not sure why. I've created a new database called "games", and I'm trying to create a basic table. The code is below.
The error message I receive is, [0A000] ERROR: cross-database references are not implemented: "games.games_schema.player_data" Position: 14
I can make the table in the default DB with postgreSQL fine, but why am I having issues trying to specifically create this table within this new Database?
CREATE DATABASE games;
CREATE TABLE games.games_schema.Player_Data
(Player_ID int,
Player_Name VARCHAR(255),
Player_System VARCHAR(255));
I thought the way I have my create table statement set up, is telling the server to create a table at that location. (database --> DBschema --> table)
Thanks for any help.
You created the games database, but that does not create a games_schema within it. It'll only create the schema Public (unless the default template has been modified) The solution is to either create a "games_schema" in the "games" database, or create your DB objects in the public schema.
Option 1: Create a schema.
create schema games_schema;
create table games_schema.player_data( ... );
Option 2: Use the Public schema.
create table player_data( ... );
My choice would be option 1, as I never allow anything other than extensions and Postgres supplied objects in public.

sqlachemy explanation of schema generation

I am trying to use sqlalchemy to create a schema in postgres. I cannot find a working example of the method of creating the schema via the MetaData and reflect function where one declares the name of the schema.
conn = db.postgres_db(host, port, database, pass, user)
postg_meta = sql.MetaData(bind=conn.engine)
postg_meta.reflect(schema='transactions')
stat_query = sql.select([sql.distinct(acocunts.c.user_id)]
This is a snippet of the code given to me and I am attempting to clarify where and how the schema ('transactions') is defined. I am new to sqlalchemy and the rational of some of its working pieces so I would appreciate some assistance.
Could this refer to a file with an external class where the schema is defined?
Thanks.
Postgres has the concept of a schema which is hierarchically ordered between the database and table like database.schema.table.
SQLAlchemy supports this concept of schemas for Postgres and other databases.
Since you performing a reflection, it is implicit that this schema already exists in your database. This is what the schema keyword is referring to.
You can confirm that this is the case by listing all the schemas in your database:
select schema_name
from information_schema.schemata