From bf99f9d08da32b119ab0301eac42ebc9c6417167 Mon Sep 17 00:00:00 2001 From: Roland Praml Date: Fri, 25 Feb 2022 11:19:25 +0100 Subject: [PATCH] Fix: HANA always requires stored procedures (similar to SqlServer), Fix: default value on intermediate alters --- .../config/dbplatform/hana/HanaPlatform.java | 4 +++ .../platform/AbstractHanaDdl.java | 12 ++++--- .../migrationtest/dbmigration/hana/1.3.sql | 2 +- .../dbmigration/hana/I__create_procs.sql | 33 +++++++++++++++++++ .../dbmigration/hana/idx_hana.migrations | 3 +- ebean-test/testconfig/ebean-hana.properties | 6 ++++ howto-test.md | 22 +++++++++++++ 7 files changed, 75 insertions(+), 7 deletions(-) create mode 100644 ebean-test/src/test/resources/migrationtest/dbmigration/hana/I__create_procs.sql create mode 100644 ebean-test/testconfig/ebean-hana.properties diff --git a/ebean-api/src/main/java/io/ebean/config/dbplatform/hana/HanaPlatform.java b/ebean-api/src/main/java/io/ebean/config/dbplatform/hana/HanaPlatform.java index 5fb91fcc8..f7f4c62e2 100644 --- a/ebean-api/src/main/java/io/ebean/config/dbplatform/hana/HanaPlatform.java +++ b/ebean-api/src/main/java/io/ebean/config/dbplatform/hana/HanaPlatform.java @@ -92,4 +92,8 @@ public class HanaPlatform extends DatabasePlatform { } } + @Override + public boolean isUseMigrationStoredProcedures() { + return true; + } } diff --git a/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/AbstractHanaDdl.java b/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/AbstractHanaDdl.java index dd9e57ff5..e2b796a9d 100644 --- a/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/AbstractHanaDdl.java +++ b/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/AbstractHanaDdl.java @@ -57,19 +57,21 @@ public abstract class AbstractHanaDdl extends PlatformDdl { if (isNumberType(currentType)) { // numbers can always be converted to decimal buffer.append("alter table ").append(tableName).append(" ").append(alterColumn).append(" ").append(columnName) - .append(" decimal ").append(defaultValueClause).append(notnullClause).append(alterColumnSuffix) - .endOfStatement(); + .append(" decimal ").append(notnullClause).append(alterColumnSuffix) + .endOfStatement(); } else if (isStringType(currentType)) { // strings can always be converted to nclob + // Note: we do not add default clause here to avoid error[SAP DBTech JDBC: [336]: invalid default value: + // default value cannot be created on column of data type NCLOB buffer.append("alter table ").append(tableName).append(" ").append(alterColumn).append(" ").append(columnName) - .append(" nclob ").append(defaultValueClause).append(notnullClause).append(alterColumnSuffix) - .endOfStatement(); + .append(" nclob").append(notnullClause).append(alterColumnSuffix) + .endOfStatement(); } } buffer.append("alter table ").append(tableName).append(" ").append(alterColumn).append(" ").append(columnName) - .append(" ").append(type).append(defaultValueClause).append(notnullClause).append(alterColumnSuffix); + .append(" ").append(type).append(defaultValueClause).append(notnullClause).append(alterColumnSuffix); return buffer.getBuffer(); } diff --git a/ebean-test/src/test/resources/migrationtest/dbmigration/hana/1.3.sql b/ebean-test/src/test/resources/migrationtest/dbmigration/hana/1.3.sql index 8090b369c..c5ec29186 100644 --- a/ebean-test/src/test/resources/migrationtest/dbmigration/hana/1.3.sql +++ b/ebean-test/src/test/resources/migrationtest/dbmigration/hana/1.3.sql @@ -32,7 +32,7 @@ declare exit handler for sql_error_code 397 begin end; exec 'alter table migtest_e_basic drop constraint ck_migtest_e_basic_status2'; end; $$; -alter table migtest_e_basic alter ( status2 nclob default 'N' not null); +alter table migtest_e_basic alter ( status2 nclob not null); alter table migtest_e_basic alter ( status2 nvarchar(1) default 'N' not null); alter table migtest_e_basic add constraint ck_migtest_e_basic_status2 check ( status2 in ('N','A','I')); delimiter $$ diff --git a/ebean-test/src/test/resources/migrationtest/dbmigration/hana/I__create_procs.sql b/ebean-test/src/test/resources/migrationtest/dbmigration/hana/I__create_procs.sql new file mode 100644 index 000000000..cec7863ac --- /dev/null +++ b/ebean-test/src/test/resources/migrationtest/dbmigration/hana/I__create_procs.sql @@ -0,0 +1,33 @@ +-- Inital script to create stored procedures etc for the hana platform +delimiter $$ +-- +-- PROCEDURE: usp_ebean_drop_foreign_keys TABLE, COLUMN +-- deletes all constraints and foreign keys referring to TABLE.COLUMN +-- +CREATE OR REPLACE PROCEDURE usp_ebean_drop_foreign_keys(IN table_name NVARCHAR(256), IN column_name NVARCHAR(256)) +AS +BEGIN +DECLARE foreign_key_names TABLE(CONSTRAINT_NAME NVARCHAR(256), TABLE_NAME NVARCHAR(256)); +DECLARE i INT; + +foreign_key_names = SELECT CONSTRAINT_NAME, TABLE_NAME FROM SYS.REFERENTIAL_CONSTRAINTS WHERE SCHEMA_NAME=CURRENT_SCHEMA AND TABLE_NAME=UPPER(:table_name) AND COLUMN_NAME=UPPER(:column_name); + +FOR I IN 1 .. RECORD_COUNT(:foreign_key_names) DO +EXEC 'ALTER TABLE "' || ESCAPE_DOUBLE_QUOTES(:foreign_key_names.TABLE_NAME[i]) || '" DROP CONSTRAINT "' || ESCAPE_DOUBLE_QUOTES(:foreign_key_names.CONSTRAINT_NAME[i]) || '"'; +END FOR; + +END; +$$ + +delimiter $$ +-- +-- PROCEDURE: usp_ebean_drop_column TABLE, COLUMN +-- deletes the column and ensures that all indices and constraints are dropped first +-- +CREATE OR REPLACE PROCEDURE usp_ebean_drop_column(IN table_name NVARCHAR(256), IN column_name NVARCHAR(256)) +AS +BEGIN +CALL usp_ebean_drop_foreign_keys(table_name, column_name); +EXEC 'ALTER TABLE "' || UPPER(ESCAPE_DOUBLE_QUOTES(table_name)) || '" DROP ("' || UPPER(ESCAPE_DOUBLE_QUOTES(column_name)) || '")'; +END; +$$ diff --git a/ebean-test/src/test/resources/migrationtest/dbmigration/hana/idx_hana.migrations b/ebean-test/src/test/resources/migrationtest/dbmigration/hana/idx_hana.migrations index 8f3461ab1..8f4cc673e 100644 --- a/ebean-test/src/test/resources/migrationtest/dbmigration/hana/idx_hana.migrations +++ b/ebean-test/src/test/resources/migrationtest/dbmigration/hana/idx_hana.migrations @@ -1,7 +1,8 @@ +-745347271, I__create_procs.sql 513351138, 1.0__initial.sql -1152055114, 1.1.sql 1830946249, 1.2__dropsFor_1.1.sql -1073423108, 1.3.sql +744723875, 1.3.sql 201970227, 1.4__dropsFor_1.3.sql 1906063401, R__order_views_hana.sql diff --git a/ebean-test/testconfig/ebean-hana.properties b/ebean-test/testconfig/ebean-hana.properties new file mode 100644 index 000000000..f7235d90c --- /dev/null +++ b/ebean-test/testconfig/ebean-hana.properties @@ -0,0 +1,6 @@ +# Note: You need a running docker container. See howto-test.md for details +datasource.default=hana +datasource.hana.username=SYSTEM +datasource.hana.password=VeryVerySecret#1234 +datasource.hana.url=jdbc:sap://localhost:39041/ + diff --git a/howto-test.md b/howto-test.md index 2913b24a9..63d7f900e 100644 --- a/howto-test.md +++ b/howto-test.md @@ -43,3 +43,25 @@ Maven Use the `-Dprops.file` parameter to start the test cases for a certain platform. +SAP HANA +-------- +To set up a SAP HANA container, you may need a docker account to download the image + +1. Remove any existing HANA container with `docker rm hana` + +2. Create an empty directory (e.g. `/tmp/hana`) + +3. Create a `settings.json` file with content `{ "master_password": "VeryVerySecret#1234" }` in that directory + +4. Run the container, e.g with this command: + +``` +docker run -p 39013:39013 -p 39017:39017 -p 39041-39045:39041-39045 -p 1128-1129:1128-1129 -p 59013-59014:59013-59014 \ + -v /tmp/hana:/hana/mounts \ + --ulimit nofile=1048576:1048576 --sysctl kernel.shmmax=1073741824 + --sysctl net.ipv4.ip_local_port_range="40000 60999" --sysctl kernel.shmall=8388608 \ + --name "hana" store/saplabs/hanaexpress:2.00.045.00.20200121.1 \ + --passwords-url file:///hana/mounts/settings.json --agree-to-sap-license +``` + +You can optionally add the `-d` parameter. Note, if you re-run that command, the best advice is to clear the data directory and recreate the settings.json file