Why does my db/structure.sql file contain a CREATE SCHEMA statement after running db:structure:dump? - postgresql

After migrating my development database, I'm unable to run rails db:test:prepare.
My application uses the db/structure.sql file to update the test database:
# config/application.rb
config.active_record.schema_format = :sql
When I run rails db:migrate (which also runs db:structure:dump), my db/structure.sql is updated. Unfortunately, it now contains this line near the top after updating:
CREATE SCHEMA public;
This will bomb when loaded into a database that already contains the public schema.
I can manually update that line and the SQL dump loads successfully:
CREATE SCHEMA IF NOT EXISTS public;
...but I don't want to do that every time.
I expect the test database to be built successfully from the SQL dump in db/structure.sql when I run rails db:test:prepare because the SQL dump should not try to create the public schema.

My development environment config explicitly specified the "public" schema. I removed that specification, which allowed db:test:prepare to complete successfully.
# config/environments/development.rb
Rails.application.configure do
...
config.active_record.dump_schemas = "public" # <<-- DELETED!
end
You can configure which database schemas will be dumped when calling db:structure:dump by setting config.active_record.dump_schemas to one of the following options:
:schema_search_path: This looks for the schema names in the schema_search_path setting in config/database.yml.
"<some string>": It will dump the schema names in the string. Names here are comma separated values.
:all: No schema names are specified.
Or just don't set it at all, which is what I did.
If config.active_record.dump_schemas.blank? == true, ActiveRecord's Postgres adaptor will set the --schema=<schema name> flag on pg_dump, which in turn adds the line CREATE SCHEMA <schema name> to its output in db/structure.sql.
An interesting side effect is that now db:test:prepare inserts this instead:
CREATE SCHEMA _template;

Related

Found non-empty schema(s) "public" but no schema history table. Use baseline() or set baselineOnMigrate to true to initialize the schema history table

I know this has been asked previously but I am spinning in circles here....
I have a postgres 14 database and a Springboot application running flyway-db:7.13.0 and flyway-core:8.5.10
I am using RDS. I created a new database manually using root account. When I run my springboot my flyway migration fails with the error
Found non-empty schema(s) "public" but no schema history table. Use baseline() or set baselineOnMigrate to true to initialize the schema history table.
I understand the reason why this is happening but when I add the baselineVersion and baselineOnMigrate to my flyway gradle config it still doesn't work. I even added
flyway {
url = dbUrl
user = dbUser
password = dbPassword
schemas = ['public']
baselineVersion = '0.0'
baselineOnMigrate = true
locations = ["filesystem:${dbMigrationPath}"]
}
also I added
spring.flyway.baseline-on-migrate = true
to my application.properties
What confuses me the most is if I start the application pointing to the default postgres database with the root user. The migration works and it creates the flyway history table. but when I run it pointing to the newly created database it doesn't work.
Any idea?
I figured it out. It turned out I needed to add the baselineOnMigration flag to my configuration
Flyway.configure().baselineOnMigrate(true).dataSource(new TransactionAwareDataSourceProxy(dataSource)).load();
Whether to automatically call baseline when migrate is executed against a non-empty schema with no schema history
table. This schema will then be initialized with the baselineVersion before executing the migrations.
Only migrations above baselineVersion will then be applied.
This is useful for initial Flyway production deployments on projects with an existing DB.
Be careful when enabling this as it removes the safety net that ensures
Flyway does not migrate the wrong database in case of a configuration mistake! (default: false)
flyway.baselineOnMigrate=
flyway.baselineOnMigrate=true
I added flyway.baselineOnMigrate=true under the statement above and it worked.

How to set default database in Postgresql database dump script?

I'd need to initialize postgres instance to Docker container from dump SQL-file. Otherwise it works fine but the problem is I cannot set database to be something else than "postgres". Creating new database works fine but schema clauses eg. CREATE TABLE end up going nowhere.
I tried to set default database with --env option in docker run command but it returns error --env requires a value.
Is there any way to set default database? Hopefully in SQL-clause.
Apparently you need to use /connect "dbname=[database name]" before schema clauses in order to point script towards correct dabase.
This wasn't (quite understandbly) included into the script when dump was generated only for a single database instead of the whole cluster.

Creating a new Postgres Scheme for Offer-Ready in Azure Cloud - "Non empty schema"

I tried to build an Offer-Ready Docker container on Azure Cloud. Although I created a new (blank) table in PostgreSQL, I got this strange error message.
javax.servlet.ServletException: org.eclipse.jetty.servlet.ServletHolder$1: org.flywaydb.core.api.FlywayException: Found non-empty schema(s) "public" without schema history table! Use baseline() or set baselineOnMigrate to true to initialize the schema history table.
I double-checked the database, there is no table in schema "public". I didn't have that problem on AWS. Has anybody an idea what is different on Azure?
I had the same experience once.
The PostgreSQL database on Azure seemed empty (\dt returned no results),
But Flyway claimed the database was not empty (and therefore would not apply the migration scripts, for fear of interfering with whatever was already there).
Here is what I did was:
Create a new schema within the database e.g. myschema
Delete the default schema called public
Add the parameter currentSchema=myschema to the JDBC URL
And then it worked. I never got to find out what the root cause of this problem was.
EDIT: This link might provide more information on what objects are in the "public" schema by default on Azure PostgreSQL: https://community.atlassian.com/t5/Jira-questions/Re-quot-database-that-is-not-empty-quot-when-trying-to-use-azure/qaq-p/1308795/comment-id/410329#M410329

Dropped postgres tables recreated when database dropped and recreated [duplicate]

Whenever I create a new database from pgAdmin or using the command line (using CREATE DATABASE database_name), it's not empty.
It contains some tables that are part of a previous project I worked on.
I'm not yet very familiar with Psql so I don't know what I'm doing wrong.
You probably have created objects in the database template1.
Quote from the manual:
By default, the new database will be created by cloning the standard system database template1. A different template can be specified by writing TEMPLATE name. In particular, by writing TEMPLATE template0, you can create a virgin database containing only the standard objects predefined by your version of PostgreSQL. This is useful if you wish to avoid copying any installation-local objects that might have been added to template1.
So, anything that is in the template1 database will be copied over to the new database when you run create database.
Connect to the template1 database and drop all objects you don't want.

Why is my new PostgreSQL database not empty?

Whenever I create a new database from pgAdmin or using the command line (using CREATE DATABASE database_name), it's not empty.
It contains some tables that are part of a previous project I worked on.
I'm not yet very familiar with Psql so I don't know what I'm doing wrong.
You probably have created objects in the database template1.
Quote from the manual:
By default, the new database will be created by cloning the standard system database template1. A different template can be specified by writing TEMPLATE name. In particular, by writing TEMPLATE template0, you can create a virgin database containing only the standard objects predefined by your version of PostgreSQL. This is useful if you wish to avoid copying any installation-local objects that might have been added to template1.
So, anything that is in the template1 database will be copied over to the new database when you run create database.
Connect to the template1 database and drop all objects you don't want.