This is an automated email from the ASF dual-hosted git repository. ilgrosso pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/syncope.git
commit eb74ddb3555d77723d2bbba587c4743309c815db Author: Francesco Chicchiriccò <[email protected]> AuthorDate: Fri Nov 14 16:00:19 2025 +0100 [SYNCOPE-1930] Finally exploiting MariaDB with JSON (#1238) --- .../jpa/dao/MariaDBJPAAnySearchDAO.java | 102 +---------------- .../persistence/jpa/dao/MySQLJPAAnySearchDAO.java | 4 +- .../src/main/resources/META-INF/mariadb/views.xml | 125 +++++---------------- .../syncope/core/persistence/jpa/AbstractTest.java | 6 - .../src/main/resources/core-mariadb.properties | 7 +- .../docker-compose/docker-compose-mariadb.yml | 2 +- .../src/main/resources/core-mariadb.properties | 10 +- pom.xml | 4 +- .../reference-guide/configuration/dbms.adoc | 8 +- 9 files changed, 46 insertions(+), 222 deletions(-) diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/MariaDBJPAAnySearchDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/MariaDBJPAAnySearchDAO.java index 858496ee4a..7e627b7e3f 100644 --- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/MariaDBJPAAnySearchDAO.java +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/MariaDBJPAAnySearchDAO.java @@ -20,9 +20,6 @@ package org.apache.syncope.core.persistence.jpa.dao; import jakarta.persistence.EntityManager; import jakarta.persistence.EntityManagerFactory; -import java.time.format.DateTimeFormatter; -import java.util.List; -import java.util.Optional; import org.apache.syncope.core.persistence.api.attrvalue.PlainAttrValidationManager; import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO; import org.apache.syncope.core.persistence.api.dao.DynRealmDAO; @@ -30,15 +27,10 @@ import org.apache.syncope.core.persistence.api.dao.GroupDAO; import org.apache.syncope.core.persistence.api.dao.PlainSchemaDAO; import org.apache.syncope.core.persistence.api.dao.RealmSearchDAO; import org.apache.syncope.core.persistence.api.dao.UserDAO; -import org.apache.syncope.core.persistence.api.dao.search.AttrCond; import org.apache.syncope.core.persistence.api.entity.AnyUtilsFactory; import org.apache.syncope.core.persistence.api.entity.EntityFactory; -import org.apache.syncope.core.persistence.api.entity.PlainAttr; -import org.apache.syncope.core.persistence.api.entity.PlainSchema; -import org.apache.syncope.core.provisioning.api.serialization.POJOHelper; -import org.springframework.data.domain.Sort; -public class MariaDBJPAAnySearchDAO extends AbstractJPAAnySearchDAO { +public class MariaDBJPAAnySearchDAO extends MySQLJPAAnySearchDAO { public MariaDBJPAAnySearchDAO( final RealmSearchDAO realmSearchDAO, @@ -66,96 +58,4 @@ public class MariaDBJPAAnySearchDAO extends AbstractJPAAnySearchDAO { entityManagerFactory, entityManager); } - - @Override - protected void parseOrderByForPlainSchema( - final SearchSupport svs, - final OrderBySupport obs, - final OrderBySupport.Item item, - final Sort.Order clause, - final PlainSchema schema, - final String fieldName) { - - // keep track of involvement of non-mandatory schemas in the order by clauses - obs.nonMandatorySchemas = !"true".equals(schema.getMandatoryCondition()); - - obs.views.add(svs.field()); - - item.select = new StringBuilder(). - append("( SELECT usa").append('.').append(key(schema.getType())). - append(" FROM ").append(schema.isUniqueConstraint() - ? svs.asSearchViewSupport().uniqueAttr().name() - : svs.asSearchViewSupport().attr().name()). - append(" usa WHERE usa.any_id = "). - append(defaultSV(svs).alias()). - append(".any_id"). - append(" AND usa.schema_id ='").append(fieldName).append("'"). - append(" LIMIT 1"). - append(") AS ").append(fieldName).toString(); - item.where = "plainSchema = '" + fieldName + '\''; - item.orderBy = fieldName + ' ' + clause.getDirection().name(); - } - - @Override - protected AttrCondQuery getQuery( - final AttrCond cond, - final boolean not, - final CheckResult<AttrCond> checked, - final List<Object> parameters, - final SearchSupport svs) { - - // normalize NULL / NOT NULL checks - if (not) { - if (cond.getType() == AttrCond.Type.ISNULL) { - cond.setType(AttrCond.Type.ISNOTNULL); - } else if (cond.getType() == AttrCond.Type.ISNOTNULL) { - cond.setType(AttrCond.Type.ISNULL); - } - } - - switch (cond.getType()) { - case ISNOTNULL -> { - return new AttrCondQuery(true, new AnySearchNode.Leaf( - svs.field(), - "JSON_SEARCH(" - + "plainAttrs, 'one', '" + checked.schema().getKey() + "', NULL, '$[*].schema'" - + ") IS NOT NULL")); - } - - case ISNULL -> { - return new AttrCondQuery(true, new AnySearchNode.Leaf( - svs.field(), - "JSON_SEARCH(" - + "plainAttrs, 'one', '" + checked.schema().getKey() + "', NULL, '$[*].schema'" - + ") IS NULL")); - } - - default -> { - if (!not && cond.getType() == AttrCond.Type.EQ) { - PlainAttr container = new PlainAttr(); - container.setPlainSchema(checked.schema()); - if (checked.schema().isUniqueConstraint()) { - container.setUniqueValue(checked.value()); - } else { - container.add(checked.value()); - } - - return new AttrCondQuery(true, new AnySearchNode.Leaf( - svs.field(), - "JSON_CONTAINS(" - + "plainAttrs, '" + POJOHelper.serialize(List.of(container)).replace("'", "''") - + "')")); - } else { - Optional.ofNullable(checked.value().getDateValue()). - map(DateTimeFormatter.ISO_OFFSET_DATE_TIME::format). - ifPresent(formatted -> { - checked.value().setDateValue(null); - checked.value().setStringValue(formatted); - }); - - return super.getQuery(cond, not, checked, parameters, svs); - } - } - } - } } diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/MySQLJPAAnySearchDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/MySQLJPAAnySearchDAO.java index 9f9e62302a..31f8cebd69 100644 --- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/MySQLJPAAnySearchDAO.java +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/MySQLJPAAnySearchDAO.java @@ -84,7 +84,7 @@ public class MySQLJPAAnySearchDAO extends AbstractJPAAnySearchDAO { obs.views.add(svs.field()); item.select = new StringBuilder().append(schema.isUniqueConstraint() - ? "( SELECT JSON_UNQUOTE(JSON_EXTRACT(usa.attrUniqueValue, '$. " + key(schema.getType()) + "')) " + ? "( SELECT JSON_UNQUOTE(JSON_EXTRACT(usa.attrUniqueValue, '$." + key(schema.getType()) + "')) " : "( SELECT usa." + key(schema.getType())). append(" FROM "). append(svs.field().name()). @@ -119,7 +119,7 @@ public class MySQLJPAAnySearchDAO extends AbstractJPAAnySearchDAO { append(" AND "). append(lower ? "LOWER(" : ""). append(schema.isUniqueConstraint() - ? "attrUniqueValue ->> '$." + key + '\'' + ? "JSON_UNQUOTE(JSON_EXTRACT(attrUniqueValue, '$." + key + "'))" : key). append(lower ? ')' : ""); diff --git a/core/persistence-jpa/src/main/resources/META-INF/mariadb/views.xml b/core/persistence-jpa/src/main/resources/META-INF/mariadb/views.xml index b61d54e922..00af8ffba2 100644 --- a/core/persistence-jpa/src/main/resources/META-INF/mariadb/views.xml +++ b/core/persistence-jpa/src/main/resources/META-INF/mariadb/views.xml @@ -49,40 +49,19 @@ under the License. <!-- user --> <entry key="user_search"> CREATE VIEW user_search AS - - SELECT u.id as any_id, u.* FROM SyncopeUser u - </entry> - <entry key="user_search_unique_attr"> - CREATE VIEW user_search_unique_attr AS - - SELECT u.id as any_id, attrs.* - FROM SyncopeUser u LEFT OUTER JOIN JSON_TABLE(COALESCE(plainAttrs, '[]'), '$[*]' COLUMNS ( - schema_id VARCHAR(255) PATH '$.schema', - NESTED PATH '$.uniqueValue' COLUMNS ( - booleanvalue INT PATH '$.booleanValue', - datevalue VARCHAR(32) PATH '$.dateValue', - doublevalue DOUBLE PATH '$.doubleValue', - longvalue BIGINT(20) PATH '$.longValue', - stringvalue VARCHAR(255) PATH '$.stringValue')) - ) AS attrs ON 1=1 - WHERE schema_id IS NOT NULL - AND (booleanvalue IS NOT NULL OR datevalue IS NOT NULL OR doublevalue IS NOT NULL OR longvalue IS NOT NULL OR stringvalue IS NOT NULL) - </entry> - <entry key="user_search_attr"> - CREATE VIEW user_search_attr AS - - SELECT u.id as any_id, attrs.* - FROM SyncopeUser u LEFT OUTER JOIN JSON_TABLE(COALESCE(plainAttrs, '[]'), '$[*]' COLUMNS ( - schema_id VARCHAR(255) PATH '$.schema', + + SELECT u.id as any_id, u.*, attrs.* + FROM SyncopeUser u LEFT OUTER JOIN JSON_TABLE(COALESCE(plainAttrs, '[{}]'), '$[*]' COLUMNS ( + plainSchema VARCHAR(255) PATH '$.schema', NESTED PATH '$.values[*]' COLUMNS ( - booleanvalue INT PATH '$.booleanValue', - datevalue VARCHAR(32) PATH '$.dateValue', - doublevalue DOUBLE PATH '$.doubleValue', - longvalue BIGINT(20) PATH '$.longValue', - stringvalue VARCHAR(255) PATH '$.stringValue')) + binaryValue LONGBLOB PATH '$.binaryValue', + booleanValue INT PATH '$.booleanValue', + dateValue VARCHAR(32) PATH '$.dateValue', + doubleValue DOUBLE PATH '$.doubleValue', + longValue BIGINT(20) PATH '$.longValue', + stringValue VARCHAR(255) PATH '$.stringValue'), + attrUniqueValue JSON PATH '$.uniqueValue') ) AS attrs ON 1=1 - WHERE schema_id IS NOT NULL - AND (booleanvalue IS NOT NULL OR datevalue IS NOT NULL OR doublevalue IS NOT NULL OR longvalue IS NOT NULL OR stringvalue IS NOT NULL) </entry> <entry key="user_search_urelationship"> CREATE VIEW user_search_urelationship AS @@ -127,39 +106,18 @@ under the License. <entry key="anyObject_search"> CREATE VIEW anyObject_search AS - SELECT a.id as any_id, a.* FROM AnyObject a - </entry> - <entry key="anyObject_search_unique_attr"> - CREATE VIEW anyObject_search_unique_attr AS - - SELECT u.id as any_id, attrs.* - FROM AnyObject u LEFT OUTER JOIN JSON_TABLE(COALESCE(plainAttrs, '[]'), '$[*]' COLUMNS ( - schema_id VARCHAR(255) PATH '$.schema', - NESTED PATH '$.uniqueValue' COLUMNS ( - booleanvalue INT PATH '$.booleanValue', - datevalue VARCHAR(32) PATH '$.dateValue', - doublevalue DOUBLE PATH '$.doubleValue', - longvalue BIGINT(20) PATH '$.longValue', - stringvalue VARCHAR(255) PATH '$.stringValue')) - ) AS attrs ON 1=1 - WHERE schema_id IS NOT NULL - AND (booleanvalue IS NOT NULL OR datevalue IS NOT NULL OR doublevalue IS NOT NULL OR longvalue IS NOT NULL OR stringvalue IS NOT NULL) - </entry> - <entry key="anyObject_search_attr"> - CREATE VIEW anyObject_search_attr AS - - SELECT u.id as any_id, attrs.* - FROM AnyObject u LEFT OUTER JOIN JSON_TABLE(COALESCE(plainAttrs, '[]'), '$[*]' COLUMNS ( - schema_id VARCHAR(255) PATH '$.schema', + SELECT a.id as any_id, a.*, attrs.* + FROM AnyObject a LEFT OUTER JOIN JSON_TABLE(COALESCE(plainAttrs, '[{}]'), '$[*]' COLUMNS ( + plainSchema VARCHAR(255) PATH '$.schema', NESTED PATH '$.values[*]' COLUMNS ( - booleanvalue INT PATH '$.booleanValue', - datevalue VARCHAR(32) PATH '$.dateValue', - doublevalue DOUBLE PATH '$.doubleValue', - longvalue BIGINT(20) PATH '$.longValue', - stringvalue VARCHAR(255) PATH '$.stringValue')) + binaryValue LONGBLOB PATH '$.binaryValue', + booleanValue INT PATH '$.booleanValue', + dateValue VARCHAR(32) PATH '$.dateValue', + doubleValue DOUBLE PATH '$.doubleValue', + longValue BIGINT(20) PATH '$.longValue', + stringValue VARCHAR(255) PATH '$.stringValue'), + attrUniqueValue JSON PATH '$.uniqueValue') ) AS attrs ON 1=1 - WHERE schema_id IS NOT NULL - AND (booleanvalue IS NOT NULL OR datevalue IS NOT NULL OR doublevalue IS NOT NULL OR longvalue IS NOT NULL OR stringvalue IS NOT NULL) </entry> <entry key="anyObject_search_arelationship"> CREATE VIEW anyObject_search_arelationship AS @@ -198,39 +156,18 @@ under the License. <entry key="group_search"> CREATE VIEW group_search AS - SELECT r.id as any_id, r.* FROM SyncopeGroup r - </entry> - <entry key="group_search_unique_attr"> - CREATE VIEW group_search_unique_attr AS - - SELECT u.id as any_id, attrs.* - FROM SyncopeGroup u LEFT OUTER JOIN JSON_TABLE(COALESCE(plainAttrs, '[]'), '$[*]' COLUMNS ( - schema_id VARCHAR(255) PATH '$.schema', - NESTED PATH '$.uniqueValue' COLUMNS ( - booleanvalue INT PATH '$.booleanValue', - datevalue VARCHAR(32) PATH '$.dateValue', - doublevalue DOUBLE PATH '$.doubleValue', - longvalue BIGINT(20) PATH '$.longValue', - stringvalue VARCHAR(255) PATH '$.stringValue')) - ) AS attrs ON 1=1 - WHERE schema_id IS NOT NULL - AND (booleanvalue IS NOT NULL OR datevalue IS NOT NULL OR doublevalue IS NOT NULL OR longvalue IS NOT NULL OR stringvalue IS NOT NULL) - </entry> - <entry key="group_search_attr"> - CREATE VIEW group_search_attr AS - - SELECT u.id as any_id, attrs.* - FROM SyncopeGroup u LEFT OUTER JOIN JSON_TABLE(COALESCE(plainAttrs, '[]'), '$[*]' COLUMNS ( - schema_id VARCHAR(255) PATH '$.schema', + SELECT g.id as any_id, g.*, attrs.* + FROM SyncopeGroup g LEFT OUTER JOIN JSON_TABLE(COALESCE(plainAttrs, '[{}]'), '$[*]' COLUMNS ( + plainSchema VARCHAR(255) PATH '$.schema', NESTED PATH '$.values[*]' COLUMNS ( - booleanvalue INT PATH '$.booleanValue', - datevalue VARCHAR(32) PATH '$.dateValue', - doublevalue DOUBLE PATH '$.doubleValue', - longvalue BIGINT(20) PATH '$.longValue', - stringvalue VARCHAR(255) PATH '$.stringValue')) + binaryValue LONGBLOB PATH '$.binaryValue', + booleanValue INT PATH '$.booleanValue', + dateValue VARCHAR(32) PATH '$.dateValue', + doubleValue DOUBLE PATH '$.doubleValue', + longValue BIGINT(20) PATH '$.longValue', + stringValue VARCHAR(255) PATH '$.stringValue'), + attrUniqueValue JSON PATH '$.uniqueValue') ) AS attrs ON 1=1 - WHERE schema_id IS NOT NULL - AND (booleanvalue IS NOT NULL OR datevalue IS NOT NULL OR doublevalue IS NOT NULL OR longvalue IS NOT NULL OR stringvalue IS NOT NULL) </entry> <entry key="group_search_grelationship"> CREATE VIEW group_search_grelationship AS diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/AbstractTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/AbstractTest.java index 5f26de86bc..3f7cff474b 100644 --- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/AbstractTest.java +++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/AbstractTest.java @@ -164,12 +164,6 @@ public abstract class AbstractTest { withReuse(true); twoDomain.start(); JDBC2_URL_SUPPLIER = twoDomain::getJdbcUrl; - - // https://jira.mariadb.org/browse/MDEV-27898 - DB_USER_SUPPLIER = () -> "root"; - DB_PWD_SUPPLIER = () -> "syncope"; - DB2_USER_SUPPLIER = () -> "root"; - DB2_PWD_SUPPLIER = () -> "syncope"; } else if (classExists("oracle.jdbc.OracleDriver")) { JDBC_DRIVER = "oracle.jdbc.OracleDriver"; DATABASE_PLATFORM = "org.apache.openjpa.jdbc.sql.OracleDictionary"; diff --git a/docker/core/src/main/resources/core-mariadb.properties b/docker/core/src/main/resources/core-mariadb.properties index 0705e23302..928f6589db 100644 --- a/docker/core/src/main/resources/core-mariadb.properties +++ b/docker/core/src/main/resources/core-mariadb.properties @@ -21,11 +21,8 @@ persistence.viewsXML=classpath:META-INF/mariadb/views.xml persistence.domain[0].key=Master persistence.domain[0].jdbcDriver=org.mariadb.jdbc.Driver persistence.domain[0].jdbcURL=${DB_URL} -# keep the next two lines until https://jira.mariadb.org/browse/MDEV-27898 is fixed -persistence.domain[0].dbUsername=root -persistence.domain[0].dbPassword=password -#persistence.domain[0].dbUsername=${DB_USER} -#persistence.domain[0].dbPassword=${DB_PASSWORD} +persistence.domain[0].dbUsername=${DB_USER} +persistence.domain[0].dbPassword=${DB_PASSWORD} persistence.domain[0].databasePlatform=org.apache.openjpa.jdbc.sql.MariaDBDictionary(blobTypeName=LONGBLOB,dateFractionDigits=3) persistence.domain[0].orm=META-INF/mariadb/spring-orm.xml persistence.domain[0].poolMaxActive=${DB_POOL_MAX} diff --git a/docker/src/main/resources/docker-compose/docker-compose-mariadb.yml b/docker/src/main/resources/docker-compose/docker-compose-mariadb.yml index f11b50a13b..792f41b22d 100644 --- a/docker/src/main/resources/docker-compose/docker-compose-mariadb.yml +++ b/docker/src/main/resources/docker-compose/docker-compose-mariadb.yml @@ -19,7 +19,7 @@ services: db: - image: mariadb:12 + image: mariadb:11 restart: always command: ['--character-set-server=utf8mb4', '--collation-server=utf8mb4_bin'] environment: diff --git a/fit/core-reference/src/main/resources/core-mariadb.properties b/fit/core-reference/src/main/resources/core-mariadb.properties index 50bb11fb73..b435aca104 100644 --- a/fit/core-reference/src/main/resources/core-mariadb.properties +++ b/fit/core-reference/src/main/resources/core-mariadb.properties @@ -23,9 +23,8 @@ persistence.viewsXML=classpath:META-INF/mariadb/views.xml persistence.domain[0].key=Master persistence.domain[0].jdbcDriver=org.mariadb.jdbc.Driver persistence.domain[0].jdbcURL=jdbc:mariadb://${DB_CONTAINER_IP}:3306/syncope?characterEncoding=UTF-8 -# keep the next two lines until https://jira.mariadb.org/browse/MDEV-27898 is fixed -persistence.domain[0].dbUsername=root -persistence.domain[0].dbPassword=password +persistence.domain[0].dbUsername=syncope +persistence.domain[0].dbPassword=syncope persistence.domain[0].databasePlatform=org.apache.openjpa.jdbc.sql.MariaDBDictionary(blobTypeName=LONGBLOB,dateFractionDigits=3) persistence.domain[0].orm=META-INF/mariadb/spring-orm.xml persistence.domain[0].poolMaxActive=10 @@ -34,9 +33,8 @@ persistence.domain[0].poolMinIdle=2 persistence.domain[1].key=Two persistence.domain[1].jdbcDriver=org.mariadb.jdbc.Driver persistence.domain[1].jdbcURL=jdbc:mariadb://${DB_CONTAINER_IP}:3306/syncopetwo?characterEncoding=UTF-8 -# keep the next two lines until https://jira.mariadb.org/browse/MDEV-27898 is fixed -persistence.domain[1].dbUsername=root -persistence.domain[1].dbPassword=password +persistence.domain[1].dbUsername=syncopetwo +persistence.domain[1].dbPassword=syncopetwo persistence.domain[1].databasePlatform=org.apache.openjpa.jdbc.sql.MariaDBDictionary(blobTypeName=LONGBLOB,dateFractionDigits=3) persistence.domain[1].orm=META-INF/mariadb/spring-orm.xml persistence.domain[1].poolMaxActive=20 diff --git a/pom.xml b/pom.xml index a2bace74cb..7bb6c9c32a 100644 --- a/pom.xml +++ b/pom.xml @@ -530,7 +530,7 @@ under the License. <docker.postgresql.version>18-alpine</docker.postgresql.version> <docker.mysql.version>9.0</docker.mysql.version> - <docker.mariadb.version>12</docker.mariadb.version> + <docker.mariadb.version>11</docker.mariadb.version> <docker.oracle.version>23-slim-faststart</docker.oracle.version> <docker.neo4j.version>5.26</docker.neo4j.version> @@ -1847,7 +1847,7 @@ under the License. <plugin> <groupId>io.fabric8</groupId> <artifactId>docker-maven-plugin</artifactId> - <version>0.47.0</version> + <version>0.48-SNAPSHOT</version> </plugin> <plugin> diff --git a/src/main/asciidoc/reference-guide/configuration/dbms.adoc b/src/main/asciidoc/reference-guide/configuration/dbms.adoc index bf3dd003e4..d1eaf1f812 100644 --- a/src/main/asciidoc/reference-guide/configuration/dbms.adoc +++ b/src/main/asciidoc/reference-guide/configuration/dbms.adoc @@ -98,9 +98,8 @@ persistence.viewsXML=classpath:META-INF/mariadb/views.xml persistence.domain[0].key=Master persistence.domain[0].jdbcDriver=org.mariadb.jdbc.Driver persistence.domain[0].jdbcURL=jdbc:mariadb://localhost:3306/syncope?characterEncoding=UTF-8 -# keep the next two lines until https://jira.mariadb.org/browse/MDEV-27898 is fixed -persistence.domain[0].dbUsername=root -persistence.domain[0].dbPassword=password +persistence.domain[0].dbUsername=syncope +persistence.domain[0].dbPassword=syncope persistence.domain[0].databasePlatform=org.apache.openjpa.jdbc.sql.MariaDBDictionary(blobTypeName=LONGBLOB,dateFractionDigits=3,useSetStringForClobs=true) persistence.domain[0].orm=META-INF/mariadb/spring-orm.xml persistence.domain[0].poolMaxActive=20 @@ -129,8 +128,7 @@ https://mariadb.com/kb/en/configuring-mariadb-with-option-files/[option file^]. [WARNING] This assumes that you have a MariaDB instance running on localhost, listening on its default port 3306 with a database -`syncope` and super-admin user `root` with password `password`. + -Super-admin user is required until https://jira.mariadb.org/browse/MDEV-27898[this bug^] is fixed. +`syncope` fully accessible by user `syncope` with password `syncope`. ==== Oracle Database
