Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 16 additions & 4 deletions hana/lib/HANAService.js
Original file line number Diff line number Diff line change
Expand Up @@ -1426,9 +1426,21 @@ SELECT ${mixing} FROM JSON_TABLE(SRC.JSON, '$' COLUMNS(${extraction}) ERROR ON E
const con = await this.factory.create(this.options.credentials)
this.dbc = con

const stmt = await this.dbc.prepare(createContainerDatabase)
const res = this.ensureDBC() && await stmt.run([creds.user, creds.password, creds.containerGroup, !clean])
res && DEBUG?.(res.changes.map(r => r.MESSAGE).join('\n'))
let i = 0
let err
for (; i < 100; i++) {
try {
const stmt = await this.dbc.prepare(createContainerDatabase)
const res = this.ensureDBC() && await stmt.run([creds.user, creds.password, creds.containerGroup, !clean])
Array.isArray(res?.changes) && DEBUG?.(res.changes.map(r => r.MESSAGE).join('\n'))
break
} catch (e) {
err = e
}
}
if (i === 100) {
throw new Error(`Failed to create tenant: ${err.message || err.stack || err}`)
}
} finally {
if (this.dbc) {
// Release table lock
Expand Down Expand Up @@ -1474,7 +1486,7 @@ SELECT ${mixing} FROM JSON_TABLE(SRC.JSON, '$' COLUMNS(${extraction}) ERROR ON E
try {
const stmt = await this.dbc.prepare(createContainerTenant.replaceAll('{{{GROUP}}}', creds.containerGroup))
const res = this.ensureDBC() && await stmt.run([creds.user, creds.password, creds.schema, !clean])
res && DEBUG?.(res.changes.map?.(r => r.MESSAGE).join('\n'))
Array.isArray(res?.changes) && DEBUG?.(res.changes.map(r => r.MESSAGE).join('\n'))
break
} catch (e) {
err = e
Expand Down
48 changes: 24 additions & 24 deletions hana/lib/scripts/container-database.sql
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ DO (
IN CREATEGROUP BOOLEAN => ?
)
BEGIN SEQUENTIAL EXECUTION
DECLARE USER_EXISTS INT;
DECLARE USER_GROUP_EXISTS INT;
DECLARE CONTAINER_GROUP_EXISTS INT;
DECLARE OPERATOR_ROLE NVARCHAR(256);
DECLARE RETURN_CODE INT;
DECLARE REQUEST_ID BIGINT;
Expand All @@ -20,40 +19,41 @@ BEGIN SEQUENTIAL EXECUTION

NO_PARAMS = SELECT * FROM _SYS_DI.T_NO_PARAMETERS;

SELECT 1 FROM _SYS_DI.T_DEFAULT_CONTAINER_USER_PRIVILEGES FOR UPDATE; -- lock to prevent race conditions
SELECT COUNT(*) INTO USER_EXISTS FROM SYS.USERS WHERE USER_NAME = :USERNAME;
SELECT COUNT(*) INTO USER_GROUP_EXISTS FROM SYS.USERGROUPS WHERE USERGROUP_NAME = :SCHEMANAME || '_USERS';
SELECT NAME INTO OPERATOR_ROLE FROM SYS.PRIVILEGES WHERE NAME = 'OPERATOR' OR NAME = 'USERGROUP OPERATOR';
IF :CREATEGROUP = FALSE THEN
DECLARE EXIT HANDLER FOR SQLEXCEPTION BEGIN END;
CALL _SYS_DI.DROP_CONTAINER_GROUP(:SCHEMANAME, :NO_PARAMS, :RETURN_CODE, :REQUEST_ID, :MESSAGES);
COMMIT;
ALL_MESSAGES = SELECT * FROM :MESSAGES;

IF :USER_EXISTS > 0 THEN
EXEC 'DROP USER ' || :USERNAME || ' CASCADE';
END IF;
EXEC 'DROP USER ' || :USERNAME || ' CASCADE';
END IF;

IF :CREATEGROUP = TRUE THEN
IF :USER_GROUP_EXISTS = 0 THEN
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION BEGIN END; -- try catch
EXEC 'CREATE USERGROUP "' || :SCHEMANAME || '_USERS"';
END IF;
IF :USER_EXISTS = 0 THEN
END;
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION BEGIN END; -- try catch
EXEC 'CREATE USER ' || :USERNAME || ' PASSWORD ' || :USERPASS || ' NO FORCE_FIRST_PASSWORD_CHANGE SET USERGROUP "' || :SCHEMANAME || '_USERS"';
ELSE
EXEC 'ALTER USER ' || :USERNAME || ' DISABLE PASSWORD LIFETIME';
EXEC 'GRANT ' || :OPERATOR_ROLE || ' ON USERGROUP "' || :SCHEMANAME || '_USERS" TO ' || :USERNAME;
EXEC 'GRANT EXECUTE ON SYS.GET_INSUFFICIENT_PRIVILEGE_ERROR_DETAILS TO ' || :USERNAME || ' WITH GRANT OPTION';
EXEC 'GRANT OPTIMIZER ADMIN TO ' || :USERNAME || ' WITH ADMIN OPTION';
END;

SELECT COUNT(*) INTO CONTAINER_GROUP_EXISTS FROM _SYS_DI.M_ALL_CONTAINER_GROUPS WHERE CONTAINER_GROUP_NAME = :SCHEMANAME;
IF :CONTAINER_GROUP_EXISTS = 0 THEN
CALL _SYS_DI.CREATE_CONTAINER_GROUP(:SCHEMANAME, :NO_PARAMS, :RETURN_CODE, :REQUEST_ID, :MESSAGES);
COMMIT;
ALL_MESSAGES = SELECT * FROM :MESSAGES;

PRIVILEGES = SELECT PRIVILEGE_NAME, OBJECT_NAME, PRINCIPAL_SCHEMA_NAME, :USERNAME AS PRINCIPAL_NAME FROM _SYS_DI.T_DEFAULT_CONTAINER_GROUP_ADMIN_PRIVILEGES;
CALL _SYS_DI.GRANT_CONTAINER_GROUP_API_PRIVILEGES(:SCHEMANAME, :PRIVILEGES, :NO_PARAMS, :RETURN_CODE, :REQUEST_ID, :MESSAGES);
COMMIT;
ALL_MESSAGES = SELECT * FROM :ALL_MESSAGES UNION ALL SELECT * FROM :MESSAGES;
END IF;
EXEC 'GRANT ' || :OPERATOR_ROLE || ' ON USERGROUP "' || :SCHEMANAME || '_USERS" TO ' || :USERNAME;
EXEC 'GRANT EXECUTE ON SYS.GET_INSUFFICIENT_PRIVILEGE_ERROR_DETAILS TO ' || :USERNAME || ' WITH GRANT OPTION';
EXEC 'GRANT OPTIMIZER ADMIN TO ' || :USERNAME || ' WITH ADMIN OPTION';
CALL _SYS_DI.CREATE_CONTAINER_GROUP(:SCHEMANAME, :NO_PARAMS, :RETURN_CODE, :REQUEST_ID, :MESSAGES);
ALL_MESSAGES = SELECT * FROM :MESSAGES;
COMMIT;

PRIVILEGES = SELECT PRIVILEGE_NAME, OBJECT_NAME, PRINCIPAL_SCHEMA_NAME, :USERNAME AS PRINCIPAL_NAME FROM _SYS_DI.T_DEFAULT_CONTAINER_GROUP_ADMIN_PRIVILEGES;

CALL _SYS_DI.GRANT_CONTAINER_GROUP_API_PRIVILEGES(:SCHEMANAME, :PRIVILEGES, :NO_PARAMS, :RETURN_CODE, :REQUEST_ID, :MESSAGES);
ALL_MESSAGES = SELECT * FROM :ALL_MESSAGES UNION ALL SELECT * FROM :MESSAGES;
COMMIT;
SELECT * FROM :ALL_MESSAGES;
END IF;
COMMIT;
Expand Down