H2 error or renaming table from PascalCase to snake_case - spring-boot

I use spring boot in a project. I have liquibase scripts to create tables and enter seed data. The repo tests are run using the #DataJpaTest annotation which by default uses an in-memory h2 database.
The db for this project was initially SQLServer, so the liquibase scripts had table names in PascalCase e.g. FooBar. Later the db had to be changed to PostgreSQL, so new liquibase scripts were added to rename to tables from PascalCase to snake_case e.g. from FooBar to foo_bar.
The liquibase scripts run successfully against the PostgreSQL database, but when they run as part of the repo tests (against the H2 db), the rename scripts fail. They fail when trying to rename a table name with a single word e.g. from Insitution to institution. I get the below error:
Caused by: org.h2.jdbc.JdbcSQLException: Table "INSTITUTION" already exists; SQL statement:
ALTER TABLE PUBLIC.Institution RENAME TO institution [42101-196]
Solution that I have already tried and failed:
A separate application.properties file in src/test/resources pointing to a custom in-memory h2 database which looks as follows:
spring.datasource.url = jdbc:h2:mem:test;DB_CLOSE_ON_EXIT=FALSE;MODE=PostgreSQL
spring.datasource.username = sa
spring.datasource.password = sa
spring.datasource.driverClassName = org.h2.Driver
I have also tried to mention the table name in double quotes in the liquibase script thinking it would preserve the case. Did not work
Please help! :(

H2 converts your unquoted table name references to uppercase. If you quote the target name with double quotes:
ALTER TABLE Institution RENAME TO "institution"
... will rename the INSTITUTION table to institution.
Your JPA implementation may have to be configured to quote the table names from here on. With hibernate you can use hibernate.globally_quoted_identifiers=true for that.

Related

The problem of openGauss database connection schema

we encountered a problem when migrating the database from oracle to guassdb. It is a compatible version with postgresdb, which uses schema,
For example, select * from table1
Now because gauss uses schema, our table is in a01
The query becomes select * from a01.table1, which causes all the codes to be changed during the migration. The schema is added to the front of each table name, which is too big. Is there a better solution, such as adding schema to the url connection, because we only use one schema for each project
You can configure the user's search_path in the openGauss database. This parameter can also be configured through the url parameter in the jdbc.
for example: jdbc:postgresql://localhost:5432/mydatabase?currentSchema=a1

2 databases on the one H2 instance

I have JPA Repository with #Query that joins tables from other DBs, that located on the same server.
SELECT id,co.name from Agenc a inner join[other_db_mame].[schema_name].[table_name] co .....
I want to write integration tests to cover the flow with this query.
In intégration tests I use H2 DB
And my question is, how to correctly configure H2 DB to have 2 DBs and make this query work?
Maybe there is a way, to create another db via scripts, or smth like this?
H2 supports direct access only to one database at once, but you can create linked tables to tables from other databases.
To create a linked table, you can use a CREATE LINKED TABLE command:
https://h2database.com/html/commands.html#create_linked_table
CREATE LINKED TABLE targetTableName('', 'jdbcURL', 'username', 'password', 'sourceTableName');
You can also link the whole schema with LINK_SCHEMA function:
https://h2database.com/html/functions.html#link_schema
CALL LINK_SCHEMA('targetSchemaName', '', 'jdbcURL', 'username', 'password', 'sourceSchemaName');
Note that format of fully-qualified table name in H2 (and in the SQL Standard) is catalogName.schemaName.tableName. H2 supports only one catalog (and its name is the same as a name of database) and you can't define additional catalogs. Non-standard -syntax with [identifier] is not accepted by H2 unless you use a MSSQLServer compatibility mode. In this mode you can use that syntax, but you can't have different names of catalogs anyway, so if they are fixed in your application, you have a problem.
Actually H2 can ignore the specified name of catalog if IGNORE_CATALOGS setting is set to TRUE:
https://h2database.com/html/commands.html#set_ignore_catalogs
SET IGNORE_CATALOGS TRUE;
But if combinations of schema and table name aren't unique in your original configuration, there is nothing to do with H2. You can't create different tables with the same schema and table name in H2 in any way.

Spring Boot Flyway migration placeholder

Can someone show the right format to use to use application.properties config in Flyway migrations.
I'd like to use the username for the datasource config in my application.properties file to grant permissions on a database table (db migration using Flyway, username will ultimately vary between environments), however I can't find an example of the syntax.
Example application.properties:
# Database
spring.datasource.driver-class-name=org.postgresql.Driver
spring.datasource.url=jdbc:postgresql://localhost:5432/example_db
spring.datasource.username=example_db_application
spring.datasource.password=examplePassword1
Migration:
CREATE TABLE token
(
id TEXT,
value TEXT,
);
GRANT SELECT, INSERT, UPDATE, DELETE ON token TO ${spring.datasource.username};
I've tried various iterations (flyway.placeholders.spring.datasource.username, tried specifying no prefix: spring.flyway.placeholder-prefix=) but no luck.
Spring-Boot provides a common application-property for flyway migration placeholder-values under the path spring.flyway.placeholders.*=
Usage
# application.properties
# -> placeholder value `user`
spring.flyway.placeholders.user=joe
-- db/migration/V3__Migration_With_Placeholder.sql`:
CREATE TABLE ${user} (
...
)

How to change the schema name using liquibase

I am using embedded database H2 which has default schema PUBLIC.
I want to have a schema XYZ as opposed to the default H2 schema. How can I change it using liquibase. I tried to create the very first changeset to create schema XYZ and added schemaName attribute to all the DDL statements henceforth to use the schemaName. But databasechangelog and databasechangeloglock are created in PUBLIC schema. How can specify the schema for those tables as well ?
Thank you in advance for your response.
Used INIT=CREATE SCHEMA IF NOT EXISTS TEST and specify 'defaultSchema' attribute to the 'schemaName' in the liquibase bean.

Schema name prefix issue in SQL query

I have WMADMIN schema. This schema is configured as connection credential in websphere datasource.
I have table in other schema/user OCS_JOBS. But the problem is my application looking for the table in WMADMIN schema.
It looks i need to prefix schemaname OCS_JOBS in SQL query to run them.
Is there any other way to run the SQL query the table which is in other user/schema without prefixing the other schema name
You can create a SYNONYM see it here: http://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_7001.htm

Resources