diff --git a/README.md b/README.md
index 9a62fac0854a..d73ff18a8bab 100644
--- a/README.md
+++ b/README.md
@@ -284,13 +284,14 @@ If no profile is specified then an H2 DataSource will be used by default and no
Assuming Docker is running on the system where the build is running, then the following commands can be run:
-| Target Database | Build Command |
-|-----------------|--------------------------------------------------------------------|
-| All supported | `mvn verify -Ptest-all-dbs` |
-| H2 (default) | `mvn verify` |
-| MariaDB 10.3 | `mvn verify -Pcontrib-check -Dspring.profiles.active=mariadb-10-3` |
-| MySQL 8 | `mvn verify -Pcontrib-check -Dspring.profiles.active=mysql-8` |
-| PostgreSQL 10 | `mvn verify -Dspring.profiles.active=postgres-10` |
+| Target Database | Build Command |
+|-------------------|--------------------------------------------------------------------|
+| All supported | `mvn verify -Ptest-all-dbs` |
+| H2 (default) | `mvn verify` |
+| MariaDB 10.3 | `mvn verify -Pcontrib-check -Dspring.profiles.active=mariadb-10-3` |
+| MySQL 8 | `mvn verify -Pcontrib-check -Dspring.profiles.active=mysql-8` |
+| PostGreSQL 10 | `mvn verify -Dspring.profiles.active=postgres-10` |
+| MSSQL Server 2019 | `mvn verify -Dspring.profiles.active=mssql-15` |
For a full list of the available DataSource factories, consult the `nifi-registry-test` module.
diff --git a/nifi-registry/nifi-registry-core/nifi-registry-framework/pom.xml b/nifi-registry/nifi-registry-core/nifi-registry-framework/pom.xml
index 74a59e4b413c..09afeca5f4b8 100644
--- a/nifi-registry/nifi-registry-core/nifi-registry-framework/pom.xml
+++ b/nifi-registry/nifi-registry-core/nifi-registry-framework/pom.xml
@@ -314,6 +314,11 @@
flyway-mysql
${flyway.version}
+
+ org.flywaydb
+ flyway-sqlserver
+ ${flyway.version}
+
com.h2database
h2
diff --git a/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/CustomFlywayConfiguration.java b/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/CustomFlywayConfiguration.java
index 42e2946b7071..a491936fff95 100644
--- a/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/CustomFlywayConfiguration.java
+++ b/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/CustomFlywayConfiguration.java
@@ -24,6 +24,7 @@
import org.flywaydb.core.internal.jdbc.JdbcUtils;
import org.flywaydb.database.mysql.MySQLDatabaseType;
import org.flywaydb.database.mysql.mariadb.MariaDBDatabaseType;
+import org.flywaydb.database.sqlserver.SQLServerDatabaseType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.flyway.FlywayConfigurationCustomizer;
@@ -52,6 +53,9 @@ public class CustomFlywayConfiguration implements FlywayConfigurationCustomizer
private static final String LOCATION_POSTGRES = "classpath:db/migration/postgres";
private static final String[] LOCATIONS_POSTGRES = {LOCATION_COMMON, LOCATION_POSTGRES};
+ private static final String LOCATION_MSSQL = "classpath:db/migration/mssql";
+ private static final String[] LOCATIONS_MSSQL = {LOCATION_COMMON, LOCATION_MSSQL};
+
private static final String LEGACY_FLYWAY_SCHEMA_TABLE = "schema_version";
@Override
@@ -65,6 +69,9 @@ public void customize(final FluentConfiguration configuration) {
} else if (databaseType instanceof PostgreSQLDatabaseType) {
LOGGER.info("Setting migration locations to {}", Arrays.asList(LOCATIONS_POSTGRES));
configuration.locations(LOCATIONS_POSTGRES);
+ } else if (databaseType instanceof SQLServerDatabaseType) {
+ LOGGER.info("Setting migration locations to {}", Arrays.asList(LOCATIONS_MSSQL));
+ configuration.locations(LOCATIONS_MSSQL);
} else {
LOGGER.info("Setting migration locations to {}", Arrays.asList(LOCATIONS_DEFAULT));
configuration.locations(LOCATIONS_DEFAULT);
diff --git a/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/CustomFlywayMigrationStrategy.java b/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/CustomFlywayMigrationStrategy.java
index 13954c6a4f10..30ccb55203fb 100644
--- a/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/CustomFlywayMigrationStrategy.java
+++ b/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/CustomFlywayMigrationStrategy.java
@@ -97,16 +97,23 @@ public void migrate(Flyway flyway) {
/**
* Determines if the database represented by this data source is being initialized for the first time based on
- * whether or not the table named 'BUCKET' or 'bucket' already exists.
+ * whether the table named 'BUCKET' or 'bucket' already exists.
*
* @param dataSource the data source
* @return true if the database has never been initialized before, false otherwise
*/
private boolean isNewDatabase(final DataSource dataSource) {
try (final Connection connection = dataSource.getConnection();
- final ResultSet rsUpper = connection.getMetaData().getTables(null, null, "BUCKET", null);
- final ResultSet rsLower = connection.getMetaData().getTables(null, null, "bucket", null)) {
- return !rsUpper.next() && !rsLower.next();
+ final ResultSet rs = connection.getMetaData().getTables(null, null, "%", null)) {
+ boolean isNew = true;
+ while (rs.next()) {
+ String tableName = rs.getString("TABLE_NAME");
+ if ("BUCKET".equalsIgnoreCase(tableName)) {
+ isNew = false;
+ break;
+ }
+ }
+ return isNew;
} catch (SQLException e) {
LOGGER.error(e.getMessage(), e);
throw new FlywayException("Unable to obtain connection from Flyway DataSource", e);
diff --git a/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/DatabaseMetadataService.java b/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/DatabaseMetadataService.java
index d53328cc7be5..e135b0ee5f5b 100644
--- a/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/DatabaseMetadataService.java
+++ b/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/DatabaseMetadataService.java
@@ -46,11 +46,18 @@
import org.apache.nifi.extension.manifest.ExtensionType;
import org.apache.nifi.extension.manifest.ProvidedServiceAPI;
import org.apache.nifi.registry.service.MetadataService;
+import org.flywaydb.core.api.FlywayException;
+import org.flywaydb.core.internal.database.DatabaseType;
+import org.flywaydb.core.internal.database.DatabaseTypeRegister;
+import org.flywaydb.database.sqlserver.SQLServerDatabaseType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
+import javax.sql.DataSource;
+import java.sql.Connection;
+import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -66,10 +73,20 @@
public class DatabaseMetadataService implements MetadataService {
private final JdbcTemplate jdbcTemplate;
+ private final DatabaseType databaseType;
@Autowired
public DatabaseMetadataService(final JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
+ this.databaseType = getDatabaseType(jdbcTemplate.getDataSource());
+ }
+
+ private DatabaseType getDatabaseType(final DataSource dataSource) {
+ try (final Connection connection = dataSource.getConnection()) {
+ return DatabaseTypeRegister.getDatabaseTypeForConnection(connection);
+ } catch (SQLException e) {
+ throw new FlywayException("Unable to obtain connection from Flyway DataSource", e);
+ }
}
//----------------- Buckets ---------------------------------
@@ -391,7 +408,9 @@ public FlowSnapshotEntity getFlowSnapshot(final String flowIdentifier, final Int
@Override
public FlowSnapshotEntity getLatestSnapshot(final String flowIdentifier) {
- final String sql = "SELECT * FROM FLOW_SNAPSHOT WHERE flow_id = ? ORDER BY version DESC LIMIT 1";
+ final String sql = (databaseType instanceof SQLServerDatabaseType)
+ ? "SELECT TOP 1 * FROM FLOW_SNAPSHOT WHERE flow_id = ? ORDER BY version DESC"
+ : "SELECT * FROM FLOW_SNAPSHOT WHERE flow_id = ? ORDER BY version DESC LIMIT 1";
try {
return jdbcTemplate.queryForObject(sql, new FlowSnapshotEntityRowMapper(), flowIdentifier);
diff --git a/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/database/DatabaseUserGroupProvider.java b/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/database/DatabaseUserGroupProvider.java
index c44a553266a7..b9cacff9a819 100644
--- a/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/database/DatabaseUserGroupProvider.java
+++ b/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/database/DatabaseUserGroupProvider.java
@@ -34,6 +34,10 @@
import org.apache.nifi.registry.security.exception.SecurityProviderCreationException;
import org.apache.nifi.registry.security.exception.SecurityProviderDestructionException;
import org.apache.nifi.registry.security.identity.IdentityMapper;
+import org.flywaydb.core.api.FlywayException;
+import org.flywaydb.core.internal.database.DatabaseType;
+import org.flywaydb.core.internal.database.DatabaseTypeRegister;
+import org.flywaydb.database.sqlserver.SQLServerDatabaseType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.EmptyResultDataAccessException;
@@ -41,6 +45,8 @@
import org.springframework.jdbc.core.RowMapper;
import javax.sql.DataSource;
+import java.sql.Connection;
+import java.sql.SQLException;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@@ -59,6 +65,7 @@ public class DatabaseUserGroupProvider implements ConfigurableUserGroupProvider
private IdentityMapper identityMapper;
private JdbcTemplate jdbcTemplate;
+ private DatabaseType databaseType;
@AuthorizerContext
public void setDataSource(final DataSource dataSource) {
@@ -73,6 +80,7 @@ public void setIdentityMapper(final IdentityMapper identityMapper) {
@Override
public void initialize(final UserGroupProviderInitializationContext initializationContext) throws SecurityProviderCreationException {
this.jdbcTemplate = new JdbcTemplate(dataSource);
+ this.databaseType = getDatabaseType(dataSource);
}
@Override
@@ -121,7 +129,9 @@ public void checkInheritability(final String proposedFingerprint) throws Authori
@Override
public User addUser(final User user) throws AuthorizationAccessException {
Validate.notNull(user);
- final String sql = "INSERT INTO UGP_USER(IDENTIFIER, IDENTITY) VALUES (?, ?)";
+ final String sql = (databaseType instanceof SQLServerDatabaseType)
+ ? "INSERT INTO UGP_USER(IDENTIFIER, [IDENTITY]) VALUES (?, ?)"
+ : "INSERT INTO UGP_USER(IDENTIFIER, IDENTITY) VALUES (?, ?)";
jdbcTemplate.update(sql, new Object[] {user.getIdentifier(), user.getIdentity()});
return user;
}
@@ -131,7 +141,9 @@ public User updateUser(final User user) throws AuthorizationAccessException {
Validate.notNull(user);
// update the user identity
- final String sql = "UPDATE UGP_USER SET IDENTITY = ? WHERE IDENTIFIER = ?";
+ final String sql = (databaseType instanceof SQLServerDatabaseType)
+ ? "UPDATE UGP_USER SET [IDENTITY] = ? WHERE IDENTIFIER = ?"
+ : "UPDATE UGP_USER SET IDENTITY = ? WHERE IDENTIFIER = ?";
final int updated = jdbcTemplate.update(sql, user.getIdentity(), user.getIdentifier());
// if no rows were updated then there is no user with the given identifier, so return null
@@ -170,7 +182,9 @@ public User getUser(final String identifier) throws AuthorizationAccessException
public User getUserByIdentity(final String identity) throws AuthorizationAccessException {
Validate.notBlank(identity);
- final String sql = "SELECT * FROM UGP_USER WHERE IDENTITY = ?";
+ final String sql = (databaseType instanceof SQLServerDatabaseType)
+ ? "SELECT * FROM UGP_USER WHERE [IDENTITY] = ?"
+ : "SELECT * FROM UGP_USER WHERE IDENTITY = ?";
final DatabaseUser databaseUser = queryForObject(sql, new Object[] {identity}, new DatabaseUserRowMapper());
if (databaseUser == null) {
return null;
@@ -191,8 +205,17 @@ public UserAndGroups getUserAndGroups(final String userIdentity) throws Authoriz
if (user == null) {
groups = null;
} else {
- final String userGroupSql =
- "SELECT " +
+ final String userGroupSql = (databaseType instanceof SQLServerDatabaseType)
+ ? "SELECT " +
+ "G.IDENTIFIER AS IDENTIFIER, " +
+ "G.[IDENTITY] AS [IDENTITY] " +
+ "FROM " +
+ "UGP_GROUP AS G, " +
+ "UGP_USER_GROUP AS UG " +
+ "WHERE " +
+ "G.IDENTIFIER = UG.GROUP_IDENTIFIER AND " +
+ "UG.USER_IDENTIFIER = ?"
+ : "SELECT " +
"G.IDENTIFIER AS IDENTIFIER, " +
"G.IDENTITY AS IDENTITY " +
"FROM " +
@@ -202,6 +225,7 @@ public UserAndGroups getUserAndGroups(final String userIdentity) throws Authoriz
"G.IDENTIFIER = UG.GROUP_IDENTIFIER AND " +
"UG.USER_IDENTIFIER = ?";
+
final Object[] args = {user.getIdentifier()};
final List databaseGroups = jdbcTemplate.query(userGroupSql, args, new DatabaseGroupRowMapper());
@@ -260,7 +284,9 @@ public Group addGroup(final Group group) throws AuthorizationAccessException {
Validate.notNull(group);
// insert to the group table...
- final String groupSql = "INSERT INTO UGP_GROUP(IDENTIFIER, IDENTITY) VALUES (?, ?)";
+ final String groupSql = (databaseType instanceof SQLServerDatabaseType)
+ ? "INSERT INTO UGP_GROUP(IDENTIFIER, [IDENTITY]) VALUES (?, ?)"
+ : "INSERT INTO UGP_GROUP(IDENTIFIER, IDENTITY) VALUES (?, ?)";
jdbcTemplate.update(groupSql, group.getIdentifier(), group.getName());
// insert to the user-group table...
@@ -274,7 +300,9 @@ public Group updateGroup(final Group group) throws AuthorizationAccessException
Validate.notNull(group);
// update the group identity
- final String updateGroupSql = "UPDATE UGP_GROUP SET IDENTITY = ? WHERE IDENTIFIER = ?";
+ final String updateGroupSql = (databaseType instanceof SQLServerDatabaseType)
+ ? "UPDATE UGP_GROUP SET [IDENTITY] = ? WHERE IDENTIFIER = ?"
+ : "UPDATE UGP_GROUP SET IDENTITY = ? WHERE IDENTIFIER = ?";
final int updated = jdbcTemplate.update(updateGroupSql, group.getName(), group.getIdentifier());
// if no rows were updated then a group does not exist for the given identifier, so return null
@@ -384,4 +412,13 @@ private T queryForObject(final String sql, final Object[] args, final RowMap
return null;
}
}
+
+ private DatabaseType getDatabaseType(final DataSource dataSource) {
+ try (final Connection connection = dataSource.getConnection()) {
+ return DatabaseTypeRegister.getDatabaseTypeForConnection(connection);
+ } catch (SQLException e) {
+ LOGGER.error(e.getMessage(), e);
+ throw new FlywayException("Unable to obtain connection from Flyway DataSource", e);
+ }
+ }
}
diff --git a/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/resources/db/migration/mssql/V2__Initial.sql b/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/resources/db/migration/mssql/V2__Initial.sql
new file mode 100644
index 000000000000..0e821be56d35
--- /dev/null
+++ b/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/resources/db/migration/mssql/V2__Initial.sql
@@ -0,0 +1,60 @@
+-- Licensed to the Apache Software Foundation (ASF) under one or more
+-- contributor license agreements. See the NOTICE file distributed with
+-- this work for additional information regarding copyright ownership.
+-- The ASF licenses this file to You under the Apache License, Version 2.0
+-- (the "License"); you may not use this file except in compliance with
+-- the License. You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+
+-- The NAME column has a max size of 768 because this is the largest size that MySQL allows when using a unique constraint.
+CREATE TABLE BUCKET (
+ ID VARCHAR(50) NOT NULL,
+ NAME VARCHAR(767) NOT NULL,
+ DESCRIPTION TEXT,
+ CREATED DATETIME2 NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ CONSTRAINT PK__BUCKET_ID PRIMARY KEY (ID),
+ CONSTRAINT UNIQUE__BUCKET_NAME UNIQUE (NAME)
+);
+
+CREATE TABLE BUCKET_ITEM (
+ ID VARCHAR(50) NOT NULL,
+ NAME VARCHAR(1000) NOT NULL,
+ DESCRIPTION TEXT,
+ CREATED DATETIME2 NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ MODIFIED DATETIME2 NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ ITEM_TYPE VARCHAR(50) NOT NULL,
+ BUCKET_ID VARCHAR(50) NOT NULL,
+ CONSTRAINT PK__BUCKET_ITEM_ID PRIMARY KEY (ID),
+ CONSTRAINT FK__BUCKET_ITEM_BUCKET_ID FOREIGN KEY (BUCKET_ID) REFERENCES BUCKET(ID) ON DELETE CASCADE
+);
+
+CREATE TABLE FLOW (
+ ID VARCHAR(50) NOT NULL,
+ CONSTRAINT PK__FLOW_ID PRIMARY KEY (ID),
+ CONSTRAINT FK__FLOW_BUCKET_ITEM_ID FOREIGN KEY (ID) REFERENCES BUCKET_ITEM(ID) ON DELETE CASCADE
+);
+
+CREATE TABLE FLOW_SNAPSHOT (
+ FLOW_ID VARCHAR(50) NOT NULL,
+ VERSION INT NOT NULL,
+ CREATED DATETIME2 NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ CREATED_BY VARCHAR(1000) NOT NULL,
+ COMMENTS TEXT,
+ CONSTRAINT PK__FLOW_SNAPSHOT_FLOW_ID_AND_VERSION PRIMARY KEY (FLOW_ID, VERSION),
+ CONSTRAINT FK__FLOW_SNAPSHOT_FLOW_ID FOREIGN KEY (FLOW_ID) REFERENCES FLOW(ID) ON DELETE CASCADE
+);
+
+CREATE TABLE SIGNING_KEY (
+ ID VARCHAR(50) NOT NULL,
+ TENANT_IDENTITY VARCHAR(767) NOT NULL,
+ KEY_VALUE VARCHAR(50) NOT NULL,
+ CONSTRAINT PK__SIGNING_KEY_ID PRIMARY KEY (ID),
+ CONSTRAINT UNIQUE__SIGNING_KEY_TENANT_IDENTITY UNIQUE (TENANT_IDENTITY)
+);
\ No newline at end of file
diff --git a/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/resources/db/migration/mssql/V3__AddExtensions.sql b/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/resources/db/migration/mssql/V3__AddExtensions.sql
new file mode 100644
index 000000000000..33db4635f1fb
--- /dev/null
+++ b/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/resources/db/migration/mssql/V3__AddExtensions.sql
@@ -0,0 +1,105 @@
+-- Licensed to the Apache Software Foundation (ASF) under one or more
+-- contributor license agreements. See the NOTICE file distributed with
+-- this work for additional information regarding copyright ownership.
+-- The ASF licenses this file to You under the Apache License, Version 2.0
+-- (the "License"); you may not use this file except in compliance with
+-- the License. You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+
+CREATE TABLE BUNDLE (
+ ID VARCHAR(50) NOT NULL,
+ BUCKET_ID VARCHAR(50) NOT NULL,
+ BUNDLE_TYPE VARCHAR(200) NOT NULL,
+ GROUP_ID VARCHAR(200) NOT NULL,
+ ARTIFACT_ID VARCHAR(200) NOT NULL,
+ CONSTRAINT PK__EXTENSION_BUNDLE_ID PRIMARY KEY (ID),
+ CONSTRAINT FK__EXTENSION_BUNDLE_BUCKET_ITEM_ID FOREIGN KEY (ID) REFERENCES BUCKET_ITEM(ID) ON DELETE CASCADE,
+ CONSTRAINT FK__EXTENSION_BUNDLE_BUCKET_ID FOREIGN KEY(BUCKET_ID) REFERENCES BUCKET(ID),
+ CONSTRAINT UNIQUE__EXTENSION_BUNDLE_BUCKET_GROUP_ARTIFACT UNIQUE (BUCKET_ID, GROUP_ID, ARTIFACT_ID)
+);
+
+CREATE TABLE BUNDLE_VERSION (
+ ID VARCHAR(50) NOT NULL,
+ BUNDLE_ID VARCHAR(50) NOT NULL,
+ VERSION VARCHAR(100) NOT NULL,
+ CREATED DATETIME2 NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ CREATED_BY VARCHAR(767) NOT NULL,
+ DESCRIPTION TEXT,
+ SHA_256_HEX VARCHAR(512) NOT NULL,
+ SHA_256_SUPPLIED INT NOT NULL,
+ CONTENT_SIZE BIGINT NOT NULL,
+ SYSTEM_API_VERSION VARCHAR(50),
+ BUILD_TOOL VARCHAR(100),
+ BUILD_FLAGS VARCHAR(100),
+ BUILD_BRANCH VARCHAR(200),
+ BUILD_TAG VARCHAR(200),
+ BUILD_REVISION VARCHAR(100),
+ BUILT DATETIME2 DEFAULT CURRENT_TIMESTAMP,
+ BUILT_BY VARCHAR(767),
+ CONSTRAINT PK__BUNDLE_VERSION_ID PRIMARY KEY (ID),
+ CONSTRAINT FK__BUNDLE_VERSION_BUNDLE_ID FOREIGN KEY (BUNDLE_ID) REFERENCES BUNDLE(ID) ON DELETE CASCADE,
+ CONSTRAINT UNIQUE__BUNDLE_VERSION_BUNDLE_ID_VERSION UNIQUE (BUNDLE_ID, VERSION)
+);
+
+CREATE TABLE BUNDLE_VERSION_DEPENDENCY (
+ ID VARCHAR(50) NOT NULL,
+ BUNDLE_VERSION_ID VARCHAR(50) NOT NULL,
+ GROUP_ID VARCHAR(200) NOT NULL,
+ ARTIFACT_ID VARCHAR(200) NOT NULL,
+ VERSION VARCHAR(100) NOT NULL,
+ CONSTRAINT PK__BUNDLE_VERSION_DEPENDENCY_ID PRIMARY KEY (ID),
+ CONSTRAINT FK__BUNDLE_VERSION_DEPENDENCY_BUNDLE_VERSION_ID FOREIGN KEY (BUNDLE_VERSION_ID) REFERENCES BUNDLE_VERSION(ID) ON DELETE CASCADE,
+ CONSTRAINT UNIQUE__BUNDLE_VERSION_DEPENDENCY_BUNDLE_ID_GAV UNIQUE (BUNDLE_VERSION_ID, GROUP_ID, ARTIFACT_ID, VERSION)
+);
+
+CREATE TABLE EXTENSION (
+ ID VARCHAR(50) NOT NULL,
+ BUNDLE_VERSION_ID VARCHAR(50) NOT NULL,
+ NAME VARCHAR(500) NOT NULL,
+ DISPLAY_NAME VARCHAR(500) NOT NULL,
+ TYPE VARCHAR(100) NOT NULL,
+ CONTENT TEXT NOT NULL,
+ ADDITIONAL_DETAILS TEXT,
+ HAS_ADDITIONAL_DETAILS INT NOT NULL,
+ CONSTRAINT PK__EXTENSION_ID PRIMARY KEY (ID),
+ CONSTRAINT FK__EXTENSION_BUNDLE_VERSION_ID FOREIGN KEY (BUNDLE_VERSION_ID) REFERENCES BUNDLE_VERSION(ID) ON DELETE CASCADE,
+ CONSTRAINT UNIQUE__EXTENSION_BUNDLE_VERSION_ID_AND_NAME UNIQUE (BUNDLE_VERSION_ID, NAME)
+);
+
+CREATE TABLE EXTENSION_PROVIDED_SERVICE_API (
+ ID VARCHAR(50) NOT NULL,
+ EXTENSION_ID VARCHAR(50) NOT NULL,
+ CLASS_NAME VARCHAR (200) NOT NULL,
+ GROUP_ID VARCHAR(200) NOT NULL,
+ ARTIFACT_ID VARCHAR(200) NOT NULL,
+ VERSION VARCHAR(100) NOT NULL,
+ CONSTRAINT PK__EXTENSION_PROVIDED_SERVICE_API_ID PRIMARY KEY (ID),
+ CONSTRAINT FK__EXTENSION_PROVIDED_SERVICE_API_EXTENSION_ID FOREIGN KEY (EXTENSION_ID) REFERENCES EXTENSION(ID) ON DELETE CASCADE,
+ CONSTRAINT UNIQUE__EXTENSION_PROVIDED_SERVICE_API UNIQUE (EXTENSION_ID, CLASS_NAME, GROUP_ID, ARTIFACT_ID, VERSION)
+);
+
+CREATE TABLE EXTENSION_RESTRICTION (
+ ID VARCHAR(50) NOT NULL,
+ EXTENSION_ID VARCHAR(50) NOT NULL,
+ REQUIRED_PERMISSION VARCHAR(200) NOT NULL,
+ EXPLANATION VARCHAR (4096) NOT NULL,
+ CONSTRAINT PK__EXTENSION_RESTRICTION_ID PRIMARY KEY (ID),
+ CONSTRAINT FK__EXTENSION_RESTRICTION_EXTENSION_ID FOREIGN KEY (EXTENSION_ID) REFERENCES EXTENSION(ID) ON DELETE CASCADE,
+ CONSTRAINT UNIQUE__EXTENSION_RESTRICTION_EXTENSION_ID_REQUIRED_PERMISSION UNIQUE (EXTENSION_ID, REQUIRED_PERMISSION)
+);
+
+CREATE TABLE EXTENSION_TAG (
+ EXTENSION_ID VARCHAR(50) NOT NULL,
+ TAG VARCHAR(200) NOT NULL,
+ CONSTRAINT PK__EXTENSION_TAG_EXTENSION_ID_AND_TAG PRIMARY KEY (EXTENSION_ID, TAG),
+ CONSTRAINT FK__EXTENSION_TAG_EXTENSION_ID FOREIGN KEY (EXTENSION_ID) REFERENCES EXTENSION(ID) ON DELETE CASCADE
+);
+
+ALTER TABLE BUCKET ADD ALLOW_EXTENSION_BUNDLE_REDEPLOY INT NOT NULL DEFAULT (0);
\ No newline at end of file
diff --git a/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/resources/db/migration/mssql/V4__AddCascadeOnDelete.sql b/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/resources/db/migration/mssql/V4__AddCascadeOnDelete.sql
new file mode 100644
index 000000000000..77f61b009335
--- /dev/null
+++ b/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/resources/db/migration/mssql/V4__AddCascadeOnDelete.sql
@@ -0,0 +1,26 @@
+-- Licensed to the Apache Software Foundation (ASF) under one or more
+-- contributor license agreements. See the NOTICE file distributed with
+-- this work for additional information regarding copyright ownership.
+-- The ASF licenses this file to You under the Apache License, Version 2.0
+-- (the "License"); you may not use this file except in compliance with
+-- the License. You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+
+-- NOTE: This file is here to keep same version history as the default migrations, but since MySQL came
+-- later, the cascades are part of the original constraints in mysql/V2_Initial.sql
+
+--ALTER TABLE BUCKET_ITEM DROP CONSTRAINT FK__BUCKET_ITEM_BUCKET_ID;
+--ALTER TABLE BUCKET_ITEM ADD CONSTRAINT FK__BUCKET_ITEM_BUCKET_ID FOREIGN KEY (BUCKET_ID) REFERENCES BUCKET(ID) ON DELETE CASCADE;
+--
+--ALTER TABLE FLOW DROP CONSTRAINT FK__FLOW_BUCKET_ITEM_ID;
+--ALTER TABLE FLOW ADD CONSTRAINT FK__FLOW_BUCKET_ITEM_ID FOREIGN KEY (ID) REFERENCES BUCKET_ITEM(ID) ON DELETE CASCADE;
+--
+--ALTER TABLE FLOW_SNAPSHOT DROP CONSTRAINT FK__FLOW_SNAPSHOT_FLOW_ID;
+--ALTER TABLE FLOW_SNAPSHOT ADD CONSTRAINT FK__FLOW_SNAPSHOT_FLOW_ID FOREIGN KEY (FLOW_ID) REFERENCES FLOW(ID) ON DELETE CASCADE;
\ No newline at end of file
diff --git a/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/resources/db/migration/mssql/V5__AddBucketPublicFlags.sql b/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/resources/db/migration/mssql/V5__AddBucketPublicFlags.sql
new file mode 100644
index 000000000000..ef7478b3eb28
--- /dev/null
+++ b/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/resources/db/migration/mssql/V5__AddBucketPublicFlags.sql
@@ -0,0 +1,16 @@
+-- Licensed to the Apache Software Foundation (ASF) under one or more
+-- contributor license agreements. See the NOTICE file distributed with
+-- this work for additional information regarding copyright ownership.
+-- The ASF licenses this file to You under the Apache License, Version 2.0
+-- (the "License"); you may not use this file except in compliance with
+-- the License. You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+
+ALTER TABLE BUCKET ADD ALLOW_PUBLIC_READ INT NOT NULL DEFAULT (0);
diff --git a/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/resources/db/migration/mssql/V6__AddFlowPersistence.sql b/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/resources/db/migration/mssql/V6__AddFlowPersistence.sql
new file mode 100644
index 000000000000..02a36d458fb9
--- /dev/null
+++ b/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/resources/db/migration/mssql/V6__AddFlowPersistence.sql
@@ -0,0 +1,22 @@
+-- Licensed to the Apache Software Foundation (ASF) under one or more
+-- contributor license agreements. See the NOTICE file distributed with
+-- this work for additional information regarding copyright ownership.
+-- The ASF licenses this file to You under the Apache License, Version 2.0
+-- (the "License"); you may not use this file except in compliance with
+-- the License. You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+
+CREATE TABLE FLOW_PERSISTENCE_PROVIDER (
+ BUCKET_ID VARCHAR(50) NOT NULL,
+ FLOW_ID VARCHAR(50) NOT NULL,
+ VERSION INT NOT NULL,
+ FLOW_CONTENT VARBINARY(MAX) NOT NULL,
+ CONSTRAINT PK__FLOW_PERSISTENCE_PROVIDER PRIMARY KEY (BUCKET_ID, FLOW_ID, VERSION)
+);
\ No newline at end of file
diff --git a/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/resources/db/migration/mssql/V7__AddRevision.sql b/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/resources/db/migration/mssql/V7__AddRevision.sql
new file mode 100644
index 000000000000..eb37fcdcf647
--- /dev/null
+++ b/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/resources/db/migration/mssql/V7__AddRevision.sql
@@ -0,0 +1,21 @@
+-- Licensed to the Apache Software Foundation (ASF) under one or more
+-- contributor license agreements. See the NOTICE file distributed with
+-- this work for additional information regarding copyright ownership.
+-- The ASF licenses this file to You under the Apache License, Version 2.0
+-- (the "License"); you may not use this file except in compliance with
+-- the License. You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+
+CREATE TABLE REVISION (
+ ENTITY_ID VARCHAR(200) NOT NULL,
+ VERSION BIGINT NOT NULL DEFAULT (0),
+ CLIENT_ID VARCHAR(100),
+ CONSTRAINT PK__REVISION_ENTITY_ID PRIMARY KEY (ENTITY_ID)
+);
\ No newline at end of file
diff --git a/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/resources/db/migration/mssql/V8__AddUserGroupPolicy.sql b/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/resources/db/migration/mssql/V8__AddUserGroupPolicy.sql
new file mode 100644
index 000000000000..9bd7e3586cf5
--- /dev/null
+++ b/nifi-registry/nifi-registry-core/nifi-registry-framework/src/main/resources/db/migration/mssql/V8__AddUserGroupPolicy.sql
@@ -0,0 +1,63 @@
+-- Licensed to the Apache Software Foundation (ASF) under one or more
+-- contributor license agreements. See the NOTICE file distributed with
+-- this work for additional information regarding copyright ownership.
+-- The ASF licenses this file to You under the Apache License, Version 2.0
+-- (the "License"); you may not use this file except in compliance with
+-- the License. You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+
+-- UserGroupProvider tables
+
+CREATE TABLE UGP_USER (
+ IDENTIFIER VARCHAR(50) NOT NULL,
+ [IDENTITY] VARCHAR(767) NOT NULL,
+ CONSTRAINT PK__UGP_USER_IDENTIFIER PRIMARY KEY (IDENTIFIER),
+ CONSTRAINT UNIQUE__UGP_USER_IDENTITY UNIQUE ([IDENTITY])
+);
+
+CREATE TABLE UGP_GROUP (
+ IDENTIFIER VARCHAR(50) NOT NULL,
+ [IDENTITY] VARCHAR(767) NOT NULL,
+ CONSTRAINT PK__UGP_GROUP_IDENTIFIER PRIMARY KEY (IDENTIFIER),
+ CONSTRAINT UNIQUE__UGP_GROUP_IDENTITY UNIQUE ([IDENTITY])
+);
+
+-- There is no FK constraint from USER_IDENTIFIER to the UGP_USER table because users from multiple providers may be
+-- put into a group here, so it may not always be a user from the UGP_USER table
+CREATE TABLE UGP_USER_GROUP (
+ USER_IDENTIFIER VARCHAR(50) NOT NULL,
+ GROUP_IDENTIFIER VARCHAR(50) NOT NULL,
+ CONSTRAINT PK__UGP_USER_GROUP PRIMARY KEY (USER_IDENTIFIER, GROUP_IDENTIFIER),
+ CONSTRAINT FK__UGP_USER_GROUP_GROUP_IDENTIFIER FOREIGN KEY (GROUP_IDENTIFIER) REFERENCES UGP_GROUP(IDENTIFIER) ON DELETE CASCADE
+);
+
+-- AccessPolicyProvider tables
+
+CREATE TABLE APP_POLICY (
+ IDENTIFIER VARCHAR(50) NOT NULL,
+ RESOURCE VARCHAR(700) NOT NULL,
+ ACTION VARCHAR(50) NOT NULL,
+ CONSTRAINT PK__APP_POLICY_IDENTIFIER PRIMARY KEY (IDENTIFIER),
+ CONSTRAINT UNIQUE__APP_POLICY_RESOURCE_ACTION UNIQUE (RESOURCE, ACTION)
+);
+
+CREATE TABLE APP_POLICY_USER (
+ POLICY_IDENTIFIER VARCHAR(50) NOT NULL,
+ USER_IDENTIFIER VARCHAR(50) NOT NULL,
+ CONSTRAINT PK__APP_POLICY_USER PRIMARY KEY (POLICY_IDENTIFIER, USER_IDENTIFIER),
+ CONSTRAINT FK__APP_POLICY_USER_POLICY_IDENTIFIER FOREIGN KEY (POLICY_IDENTIFIER) REFERENCES APP_POLICY(IDENTIFIER) ON DELETE CASCADE
+);
+
+CREATE TABLE APP_POLICY_GROUP (
+ POLICY_IDENTIFIER VARCHAR(50) NOT NULL,
+ GROUP_IDENTIFIER VARCHAR(50) NOT NULL,
+ CONSTRAINT PK__APP_POLICY_GROUP PRIMARY KEY (POLICY_IDENTIFIER, GROUP_IDENTIFIER),
+ CONSTRAINT FK__APP_POLICY_GROUP_POLICY_IDENTIFIER FOREIGN KEY (POLICY_IDENTIFIER) REFERENCES APP_POLICY(IDENTIFIER) ON DELETE CASCADE
+);
\ No newline at end of file
diff --git a/nifi-registry/nifi-registry-core/nifi-registry-framework/src/test/java/org/apache/nifi/registry/security/authorization/database/TestDatabaseUserGroupProvider.java b/nifi-registry/nifi-registry-core/nifi-registry-framework/src/test/java/org/apache/nifi/registry/security/authorization/database/TestDatabaseUserGroupProvider.java
index f38ad068bd45..867a589dd2de 100644
--- a/nifi-registry/nifi-registry-core/nifi-registry-framework/src/test/java/org/apache/nifi/registry/security/authorization/database/TestDatabaseUserGroupProvider.java
+++ b/nifi-registry/nifi-registry-core/nifi-registry-framework/src/test/java/org/apache/nifi/registry/security/authorization/database/TestDatabaseUserGroupProvider.java
@@ -27,12 +27,18 @@
import org.apache.nifi.registry.security.authorization.util.UserGroupProviderUtils;
import org.apache.nifi.registry.security.identity.DefaultIdentityMapper;
import org.apache.nifi.registry.security.identity.IdentityMapper;
+import org.flywaydb.core.api.FlywayException;
+import org.flywaydb.core.internal.database.DatabaseType;
+import org.flywaydb.core.internal.database.DatabaseTypeRegister;
+import org.flywaydb.database.sqlserver.SQLServerDatabaseType;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import javax.sql.DataSource;
+import java.sql.Connection;
+import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
@@ -54,6 +60,7 @@ public class TestDatabaseUserGroupProvider extends DatabaseBaseTest {
private IdentityMapper identityMapper;
private ConfigurableUserGroupProvider userGroupProvider;
+ private DatabaseType databaseType;
@BeforeEach
public void setup() {
@@ -68,6 +75,20 @@ public void setup() {
databaseUserGroupProvider.initialize(initializationContext);
userGroupProvider = databaseUserGroupProvider;
+ databaseType = getDatabaseType(dataSource);
+ }
+
+ /**
+ * Helper method to determine databaseType.
+ *
+ * @param dataSource the dataSource
+ */
+ private DatabaseType getDatabaseType(final DataSource dataSource) {
+ try (final Connection connection = dataSource.getConnection()) {
+ return DatabaseTypeRegister.getDatabaseTypeForConnection(connection);
+ } catch (SQLException e) {
+ throw new FlywayException("Unable to obtain connection from Flyway DataSource", e);
+ }
}
/**
@@ -97,7 +118,9 @@ private void configureWithInitialUsers(final String ... initialUserIdentities) {
*/
private void createUser(final String userIdentifier, final String userIdentity) {
final JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
- final String sql = "INSERT INTO UGP_USER(IDENTIFIER, IDENTITY) VALUES (?, ?)";
+ final String sql = (databaseType instanceof SQLServerDatabaseType)
+ ? "INSERT INTO UGP_USER(IDENTIFIER, [IDENTITY]) VALUES (?, ?)"
+ : "INSERT INTO UGP_USER(IDENTIFIER, IDENTITY) VALUES (?, ?)";
final int updatedRows1 = jdbcTemplate.update(sql, new Object[] {userIdentifier, userIdentity});
assertEquals(1, updatedRows1);
}
@@ -110,7 +133,9 @@ private void createUser(final String userIdentifier, final String userIdentity)
*/
private void createGroup(final String groupIdentifier, final String groupIdentity) {
final JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
- final String sql = "INSERT INTO UGP_GROUP(IDENTIFIER, IDENTITY) VALUES (?, ?)";
+ final String sql = (databaseType instanceof SQLServerDatabaseType)
+ ? "INSERT INTO UGP_GROUP(IDENTIFIER, [IDENTITY]) VALUES (?, ?)"
+ : "INSERT INTO UGP_GROUP(IDENTIFIER, IDENTITY) VALUES (?, ?)";
final int updatedRows1 = jdbcTemplate.update(sql, new Object[] {groupIdentifier, groupIdentity});
assertEquals(1, updatedRows1);
}
diff --git a/nifi-registry/nifi-registry-core/nifi-registry-framework/src/test/resources/db/migration/common/V999999.1__test-setup.sql b/nifi-registry/nifi-registry-core/nifi-registry-framework/src/test/resources/db/migration/common/V999999.1__test-setup.sql
index c2218b7bd797..03aad11ef35f 100644
--- a/nifi-registry/nifi-registry-core/nifi-registry-framework/src/test/resources/db/migration/common/V999999.1__test-setup.sql
+++ b/nifi-registry/nifi-registry-core/nifi-registry-framework/src/test/resources/db/migration/common/V999999.1__test-setup.sql
@@ -16,38 +16,38 @@
-- test data for buckets
insert into BUCKET (id, name, description, created)
- values ('1', 'Bucket 1', 'This is test bucket 1', DATE'2017-09-11');
+ values ('1', 'Bucket 1', 'This is test bucket 1', '2017-09-11');
insert into BUCKET (id, name, description, created)
- values ('2', 'Bucket 2', 'This is test bucket 2', DATE'2017-09-12');
+ values ('2', 'Bucket 2', 'This is test bucket 2', '2017-09-12');
insert into BUCKET (id, name, description, created)
- values ('3', 'Bucket 3', 'This is test bucket 3', DATE'2017-09-13');
+ values ('3', 'Bucket 3', 'This is test bucket 3', '2017-09-13');
insert into BUCKET (id, name, description, created)
- values ('4', 'Bucket 4', 'This is test bucket 4', DATE'2017-09-14');
+ values ('4', 'Bucket 4', 'This is test bucket 4', '2017-09-14');
insert into BUCKET (id, name, description, created)
- values ('5', 'Bucket 5', 'This is test bucket 5', DATE'2017-09-15');
+ values ('5', 'Bucket 5', 'This is test bucket 5', '2017-09-15');
insert into BUCKET (id, name, description, created)
- values ('6', 'Bucket 6', 'This is test bucket 6', DATE'2017-09-16');
+ values ('6', 'Bucket 6', 'This is test bucket 6', '2017-09-16');
-- test data for flows
insert into BUCKET_ITEM (id, name, description, created, modified, item_type, bucket_id)
- values ('1', 'Flow 1', 'This is flow 1 bucket 1', DATE'2017-09-11', DATE'2017-09-11', 'FLOW', '1');
+ values ('1', 'Flow 1', 'This is flow 1 bucket 1', '2017-09-11', '2017-09-11', 'FLOW', '1');
insert into FLOW (id) values ('1');
insert into BUCKET_ITEM (id, name, description, created, modified, item_type, bucket_id)
- values ('2', 'Flow 2', 'This is flow 2 bucket 1', DATE'2017-09-11', DATE'2017-09-11', 'FLOW', '1');
+ values ('2', 'Flow 2', 'This is flow 2 bucket 1', '2017-09-11', '2017-09-11', 'FLOW', '1');
insert into FLOW (id) values ('2');
insert into BUCKET_ITEM (id, name, description, created, modified, item_type, bucket_id)
- values ('3', 'Flow 1', 'This is flow 1 bucket 2', DATE'2017-09-11', DATE'2017-09-11', 'FLOW', '2');
+ values ('3', 'Flow 1', 'This is flow 1 bucket 2', '2017-09-11', '2017-09-11', 'FLOW', '2');
insert into FLOW (id) values ('3');
@@ -55,13 +55,13 @@ insert into FLOW (id) values ('3');
-- test data for flow snapshots
insert into FLOW_SNAPSHOT (flow_id, version, created, created_by, comments)
- values ('1', 1, DATE'2017-09-11', 'user1', 'This is flow 1 snapshot 1');
+ values ('1', 1, '2017-09-11', 'user1', 'This is flow 1 snapshot 1');
insert into FLOW_SNAPSHOT (flow_id, version, created, created_by, comments)
- values ('1', 2, DATE'2017-09-12', 'user1', 'This is flow 1 snapshot 2');
+ values ('1', 2, '2017-09-12', 'user1', 'This is flow 1 snapshot 2');
insert into FLOW_SNAPSHOT (flow_id, version, created, created_by, comments)
- values ('1', 3, DATE'2017-09-11', 'user1', 'This is flow 1 snapshot 3');
+ values ('1', 3, '2017-09-11', 'user1', 'This is flow 1 snapshot 3');
-- test data for signing keys
@@ -84,8 +84,8 @@ insert into BUCKET_ITEM (
'eb1',
'nifi-example-processors-nar',
'Example processors bundle',
- DATE'2018-11-02',
- DATE'2018-11-02',
+ '2018-11-02',
+ '2018-11-02',
'BUNDLE',
'3'
);
@@ -118,7 +118,7 @@ insert into BUNDLE_VERSION (
'eb1-v1',
'eb1',
'1.0.0',
- DATE'2018-11-02',
+ '2018-11-02',
'user1',
'First version of eb1',
'123456789',
@@ -153,8 +153,8 @@ insert into BUCKET_ITEM (
'eb2',
'nifi-example-services-nar',
'Example services bundle',
- DATE'2018-11-03',
- DATE'2018-11-03',
+ '2018-11-03',
+ '2018-11-03',
'BUNDLE',
'3'
);
@@ -187,7 +187,7 @@ insert into BUNDLE_VERSION (
'eb2-v1',
'eb2',
'1.0.0',
- DATE'2018-11-03',
+ '2018-11-03',
'user1',
'First version of eb2',
'123456789',
@@ -222,8 +222,8 @@ insert into BUCKET_ITEM (
'eb3',
'nifi-example-service-api-nar',
'Example service API bundle',
- DATE'2018-11-04',
- DATE'2017-11-04',
+ '2018-11-04',
+ '2017-11-04',
'BUNDLE',
'3'
);
@@ -256,7 +256,7 @@ insert into BUNDLE_VERSION (
'eb3-v1',
'eb3',
'2.0.0',
- DATE'2018-11-04',
+ '2018-11-04',
'user1',
'First version of eb3',
'123456789',
diff --git a/nifi-registry/nifi-registry-core/nifi-registry-revision/nifi-registry-revision-spring-jdbc/pom.xml b/nifi-registry/nifi-registry-core/nifi-registry-revision/nifi-registry-revision-spring-jdbc/pom.xml
index 3e56049bb5af..b379f1660279 100644
--- a/nifi-registry/nifi-registry-core/nifi-registry-revision/nifi-registry-revision-spring-jdbc/pom.xml
+++ b/nifi-registry/nifi-registry-core/nifi-registry-revision/nifi-registry-revision-spring-jdbc/pom.xml
@@ -57,5 +57,11 @@
${flyway.version}
test
+
+ org.flywaydb
+ flyway-sqlserver
+ ${flyway.version}
+ test
+
diff --git a/nifi-registry/nifi-registry-core/nifi-registry-test/pom.xml b/nifi-registry/nifi-registry-core/nifi-registry-test/pom.xml
index e4f72cdf2fe4..0f9b9380329e 100644
--- a/nifi-registry/nifi-registry-core/nifi-registry-test/pom.xml
+++ b/nifi-registry/nifi-registry-core/nifi-registry-test/pom.xml
@@ -62,6 +62,10 @@
org.testcontainers
postgresql
+
+ org.testcontainers
+ mssqlserver
+
mysql
mysql-connector-java
@@ -77,6 +81,11 @@
postgresql
42.6.0
+
+ com.microsoft.sqlserver
+ mssql-jdbc
+ 12.2.0.jre11
+
junit
junit
diff --git a/nifi-registry/nifi-registry-core/nifi-registry-test/src/main/java/org/apache/nifi/registry/db/DatabaseProfileValueSource.java b/nifi-registry/nifi-registry-core/nifi-registry-test/src/main/java/org/apache/nifi/registry/db/DatabaseProfileValueSource.java
index 1a9e5d9ba9b1..b2622f483b1b 100644
--- a/nifi-registry/nifi-registry-core/nifi-registry-test/src/main/java/org/apache/nifi/registry/db/DatabaseProfileValueSource.java
+++ b/nifi-registry/nifi-registry-core/nifi-registry-test/src/main/java/org/apache/nifi/registry/db/DatabaseProfileValueSource.java
@@ -32,6 +32,7 @@ public class DatabaseProfileValueSource implements ProfileValueSource {
private static final String MARIADB = "mariadb";
private static final String POSTGRES = "postgres";
private static final String H2 = "h2";
+ private static final String MSSQL = "mssql";
private String currentDatabase;
@@ -46,6 +47,8 @@ public class DatabaseProfileValueSource implements ProfileValueSource {
currentDatabase = MARIADB;
} else if (activeProfiles.contains(POSTGRES)) {
currentDatabase = POSTGRES;
+ } else if (activeProfiles.contains(MSSQL)) {
+ currentDatabase = MSSQL;
}
}
diff --git a/nifi-registry/nifi-registry-core/nifi-registry-test/src/main/java/org/apache/nifi/registry/db/MSSQL15DataSourceFactory.java b/nifi-registry/nifi-registry-core/nifi-registry-test/src/main/java/org/apache/nifi/registry/db/MSSQL15DataSourceFactory.java
new file mode 100644
index 000000000000..3ade79f6e5e8
--- /dev/null
+++ b/nifi-registry/nifi-registry-core/nifi-registry-test/src/main/java/org/apache/nifi/registry/db/MSSQL15DataSourceFactory.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.registry.db;
+
+import com.microsoft.sqlserver.jdbc.SQLServerDataSource;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+import org.testcontainers.containers.MSSQLServerContainer;
+import org.testcontainers.delegate.DatabaseDelegate;
+import org.testcontainers.jdbc.JdbcDatabaseDelegate;
+
+import javax.annotation.PostConstruct;
+import javax.script.ScriptException;
+import javax.sql.DataSource;
+import java.sql.SQLException;
+
+@Configuration
+@Profile("mssql-15")
+public class MSSQL15DataSourceFactory extends TestDataSourceFactory{
+
+ private static final MSSQLServerContainer MSSQL_CONTAINER = new MSSQLServerContainer("mcr.microsoft.com/mssql/server:2019-latest").acceptLicense();
+
+ static {
+ MSSQL_CONTAINER.start();
+ }
+
+ @Override
+ protected DataSource createDataSource() {
+ final SQLServerDataSource dataSource = new SQLServerDataSource();
+ dataSource.setURL(MSSQL_CONTAINER.getJdbcUrl());
+ dataSource.setUser(MSSQL_CONTAINER.getUsername());
+ dataSource.setPassword(MSSQL_CONTAINER.getPassword());
+ return dataSource;
+ }
+
+ @PostConstruct
+ public void initDatabase() throws SQLException, ScriptException {
+ DatabaseDelegate databaseDelegate = new JdbcDatabaseDelegate(MSSQL_CONTAINER, "");
+ databaseDelegate.execute("DROP DATABASE test; CREATE DATABASE test;", "", 0, false, true);
+ }
+}
diff --git a/nifi-registry/nifi-registry-core/pom.xml b/nifi-registry/nifi-registry-core/pom.xml
index ff79171b089b..0371698ab7a8 100644
--- a/nifi-registry/nifi-registry-core/pom.xml
+++ b/nifi-registry/nifi-registry-core/pom.xml
@@ -233,6 +233,19 @@
+
+ mssql15-test
+ verify
+
+ integration-test
+ verify
+
+
+
+ mssql-15
+
+
+