[Enhancement] Support for `IF NOT EXISTS` and `IF EXISTS` clauses to the GROUP PROVIDER (#63248)
What I'm doing: This pull request adds support for IF NOT EXISTS and IF EXISTS clauses to the CREATE GROUP PROVIDER and DROP GROUP PROVIDER SQL statements, ensuring these operations are idempotent and error-tolerant. It also introduces comprehensive unit tests to verify the correct behavior of these clauses, and updates the parser and semantic analyzer accordingly. Enhancements to Group Provider DDL Statements: Added support for IF NOT EXISTS to CREATE GROUP PROVIDER and IF EXISTS to DROP GROUP PROVIDER, allowing these statements to succeed silently if the provider already exists or does not exist, respectively. The implementation includes proper error handling and DDL exception messages for cases where these clauses are not specified. [1] [2] Updated the SQL parser (AstBuilder) to recognize and propagate the IF NOT EXISTS and IF EXISTS flags in CreateGroupProviderStmt and DropGroupProviderStmt objects. Enhanced the semantic analyzer to respect the new flags, throwing exceptions only when appropriate (i.e., when the flags are not set and the provider's existence does not match the operation). [1] [2] Testing Improvements: Added a new test class GroupProviderStatementTest with comprehensive unit tests covering all scenarios for the new IF NOT EXISTS and IF EXISTS functionality, including creation, dropping, legacy constructors, and sequential operations. Error Handling: Wrapped the execution of dropGroupProviderStatement in the DDL statement executor with error reporting to ensure runtime exceptions are properly managed.
This commit is contained in:
parent
cfe33249d4
commit
348cd8f151
|
|
@ -611,6 +611,16 @@ public class AuthenticationMgr {
|
|||
// ---------------------------------------- Group Provider Statement --------------------------------------
|
||||
|
||||
public void createGroupProviderStatement(CreateGroupProviderStmt stmt, ConnectContext context) throws DdlException {
|
||||
// Check if group provider already exists
|
||||
if (this.nameToGroupProviderMap.containsKey(stmt.getName())) {
|
||||
if (stmt.isIfNotExists()) {
|
||||
// If IF NOT EXISTS is specified, silently return without error
|
||||
return;
|
||||
} else {
|
||||
throw new DdlException("Group provider '" + stmt.getName() + "' already exists");
|
||||
}
|
||||
}
|
||||
|
||||
GroupProvider groupProvider = GroupProviderFactory.createGroupProvider(stmt.getName(), stmt.getPropertyMap());
|
||||
groupProvider.init();
|
||||
this.nameToGroupProviderMap.put(stmt.getName(), groupProvider);
|
||||
|
|
@ -629,8 +639,18 @@ public class AuthenticationMgr {
|
|||
}
|
||||
}
|
||||
|
||||
public void dropGroupProviderStatement(DropGroupProviderStmt stmt, ConnectContext context) {
|
||||
GroupProvider groupProvider = this.nameToGroupProviderMap.remove(stmt.getName());
|
||||
public void dropGroupProviderStatement(DropGroupProviderStmt stmt, ConnectContext context) throws DdlException {
|
||||
GroupProvider groupProvider = this.nameToGroupProviderMap.get(stmt.getName());
|
||||
if (groupProvider == null) {
|
||||
if (stmt.isIfExists()) {
|
||||
// If IF EXISTS is specified, silently return without error
|
||||
return;
|
||||
} else {
|
||||
throw new DdlException("Group provider '" + stmt.getName() + "' does not exist");
|
||||
}
|
||||
}
|
||||
|
||||
this.nameToGroupProviderMap.remove(stmt.getName());
|
||||
groupProvider.destroy();
|
||||
|
||||
GlobalStateMgr.getCurrentState().getEditLog().logJsonObject(OperationType.OP_DROP_GROUP_PROVIDER,
|
||||
|
|
|
|||
|
|
@ -657,8 +657,10 @@ public class DDLStmtExecutor {
|
|||
|
||||
@Override
|
||||
public ShowResultSet visitDropGroupProviderStatement(DropGroupProviderStmt statement, ConnectContext context) {
|
||||
AuthenticationMgr authenticationMgr = GlobalStateMgr.getCurrentState().getAuthenticationMgr();
|
||||
authenticationMgr.dropGroupProviderStatement(statement, context);
|
||||
ErrorReport.wrapWithRuntimeException(() -> {
|
||||
AuthenticationMgr authenticationMgr = GlobalStateMgr.getCurrentState().getAuthenticationMgr();
|
||||
authenticationMgr.dropGroupProviderStatement(statement, context);
|
||||
});
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ public class GroupProviderStatementAnalyzer {
|
|||
groupProvider.checkProperty();
|
||||
|
||||
AuthenticationMgr authenticationMgr = GlobalStateMgr.getCurrentState().getAuthenticationMgr();
|
||||
if (authenticationMgr.getGroupProvider(statement.getName()) != null) {
|
||||
if (authenticationMgr.getGroupProvider(statement.getName()) != null && !statement.isIfNotExists()) {
|
||||
throw new SemanticException("Group Provider '" + statement.getName() + "' already exists");
|
||||
}
|
||||
return null;
|
||||
|
|
@ -62,7 +62,7 @@ public class GroupProviderStatementAnalyzer {
|
|||
@Override
|
||||
public Void visitDropGroupProviderStatement(DropGroupProviderStmt statement, ConnectContext context) {
|
||||
AuthenticationMgr authenticationMgr = GlobalStateMgr.getCurrentState().getAuthenticationMgr();
|
||||
if (authenticationMgr.getGroupProvider(statement.getName()) == null) {
|
||||
if (authenticationMgr.getGroupProvider(statement.getName()) == null && !statement.isIfExists()) {
|
||||
throw new SemanticException("Group Provider '" + statement.getName() + "' not found");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7186,14 +7186,14 @@ public class AstBuilder extends com.starrocks.sql.parser.StarRocksBaseVisitor<Pa
|
|||
propertyMap.put(property.getKey(), property.getValue());
|
||||
}
|
||||
}
|
||||
return new CreateGroupProviderStmt(name, propertyMap, createPos(context));
|
||||
return new CreateGroupProviderStmt(name, propertyMap, context.IF() != null, createPos(context));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParseNode visitDropGroupProviderStatement(
|
||||
com.starrocks.sql.parser.StarRocksParser.DropGroupProviderStatementContext context) {
|
||||
String name = ((Identifier) visit(context.identifier())).getValue();
|
||||
return new DropGroupProviderStmt(name, createPos(context));
|
||||
return new DropGroupProviderStmt(name, context.IF() != null, createPos(context));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -0,0 +1,351 @@
|
|||
// Copyright 2021-present StarRocks, Inc. All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// https://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 com.starrocks.authentication;
|
||||
|
||||
import com.starrocks.catalog.UserIdentity;
|
||||
import com.starrocks.common.DdlException;
|
||||
import com.starrocks.persist.EditLog;
|
||||
import com.starrocks.qe.ConnectContext;
|
||||
import com.starrocks.server.GlobalStateMgr;
|
||||
import com.starrocks.sql.ast.group.CreateGroupProviderStmt;
|
||||
import com.starrocks.sql.ast.group.DropGroupProviderStmt;
|
||||
import com.starrocks.sql.parser.NodePosition;
|
||||
import com.starrocks.utframe.UtFrameUtils;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyShort;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.spy;
|
||||
|
||||
/**
|
||||
* Unit tests for Group Provider statements with IF NOT EXISTS and IF EXISTS functionality
|
||||
*/
|
||||
public class GroupProviderStatementTest {
|
||||
private ConnectContext ctx;
|
||||
private AuthenticationMgr authenticationMgr;
|
||||
private static final String TEST_PROVIDER_NAME = "test_provider";
|
||||
private static final String NON_EXISTENT_PROVIDER_NAME = "non_existent_provider";
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() throws Exception {
|
||||
// Mock EditLog
|
||||
EditLog editLog = spy(new EditLog(null));
|
||||
doNothing().when(editLog).logEdit(anyShort(), any());
|
||||
GlobalStateMgr.getCurrentState().setEditLog(editLog);
|
||||
|
||||
ctx = UtFrameUtils.initCtxForNewPrivilege(UserIdentity.ROOT);
|
||||
authenticationMgr = GlobalStateMgr.getCurrentState().getAuthenticationMgr();
|
||||
|
||||
// Clean up any existing test providers
|
||||
cleanupTestProviders();
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void tearDown() throws Exception {
|
||||
cleanupTestProviders();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case: Create Group Provider with IF NOT EXISTS when provider does not exist
|
||||
* Test point: Should successfully create the provider without error
|
||||
*/
|
||||
@Test
|
||||
public void testCreateGroupProviderIfNotExistsWhenNotExists() throws Exception {
|
||||
Map<String, String> properties = createUnixGroupProviderProperties();
|
||||
CreateGroupProviderStmt stmt = new CreateGroupProviderStmt(TEST_PROVIDER_NAME, properties, true, NodePosition.ZERO);
|
||||
|
||||
// Should not throw exception
|
||||
authenticationMgr.createGroupProviderStatement(stmt, ctx);
|
||||
|
||||
// Verify provider was created
|
||||
GroupProvider provider = authenticationMgr.getGroupProvider(TEST_PROVIDER_NAME);
|
||||
Assertions.assertNotNull(provider, "Group provider should be created successfully");
|
||||
Assertions.assertEquals(TEST_PROVIDER_NAME, provider.getName());
|
||||
Assertions.assertEquals("unix", provider.getType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case: Create Group Provider with IF NOT EXISTS when provider already exists
|
||||
* Test point: Should silently return without error and not modify existing provider
|
||||
*/
|
||||
@Test
|
||||
public void testCreateGroupProviderIfNotExistsWhenExists() throws Exception {
|
||||
Map<String, String> properties = createUnixGroupProviderProperties();
|
||||
|
||||
// First create the provider
|
||||
CreateGroupProviderStmt firstStmt = new CreateGroupProviderStmt(TEST_PROVIDER_NAME, properties, false, NodePosition.ZERO);
|
||||
authenticationMgr.createGroupProviderStatement(firstStmt, ctx);
|
||||
|
||||
// Get the original provider for comparison
|
||||
GroupProvider originalProvider = authenticationMgr.getGroupProvider(TEST_PROVIDER_NAME);
|
||||
Assertions.assertNotNull(originalProvider, "Original provider should exist");
|
||||
|
||||
// Try to create again with IF NOT EXISTS
|
||||
CreateGroupProviderStmt secondStmt = new CreateGroupProviderStmt(TEST_PROVIDER_NAME, properties, true, NodePosition.ZERO);
|
||||
|
||||
// Should not throw exception
|
||||
authenticationMgr.createGroupProviderStatement(secondStmt, ctx);
|
||||
|
||||
// Verify provider still exists and is unchanged
|
||||
GroupProvider provider = authenticationMgr.getGroupProvider(TEST_PROVIDER_NAME);
|
||||
Assertions.assertNotNull(provider, "Group provider should still exist");
|
||||
Assertions.assertEquals(originalProvider.getName(), provider.getName());
|
||||
Assertions.assertEquals(originalProvider.getType(), provider.getType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case: Create Group Provider without IF NOT EXISTS when provider already exists
|
||||
* Test point: Should throw DdlException with appropriate error message
|
||||
*/
|
||||
@Test
|
||||
public void testCreateGroupProviderWithoutIfNotExistsWhenExists() throws Exception {
|
||||
Map<String, String> properties = createUnixGroupProviderProperties();
|
||||
|
||||
// First create the provider
|
||||
CreateGroupProviderStmt firstStmt = new CreateGroupProviderStmt(TEST_PROVIDER_NAME, properties, false, NodePosition.ZERO);
|
||||
authenticationMgr.createGroupProviderStatement(firstStmt, ctx);
|
||||
|
||||
// Try to create again without IF NOT EXISTS
|
||||
CreateGroupProviderStmt secondStmt =
|
||||
new CreateGroupProviderStmt(TEST_PROVIDER_NAME, properties, false, NodePosition.ZERO);
|
||||
|
||||
// Should throw DdlException
|
||||
DdlException exception = Assertions.assertThrows(DdlException.class, () -> {
|
||||
authenticationMgr.createGroupProviderStatement(secondStmt, ctx);
|
||||
});
|
||||
|
||||
Assertions.assertTrue(exception.getMessage().contains("Group provider '" + TEST_PROVIDER_NAME + "' already exists"),
|
||||
"Error message should indicate provider already exists: " + exception.getMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case: Drop Group Provider with IF EXISTS when provider does not exist
|
||||
* Test point: Should silently return without error
|
||||
*/
|
||||
@Test
|
||||
public void testDropGroupProviderIfExistsWhenNotExists() throws Exception {
|
||||
DropGroupProviderStmt stmt = new DropGroupProviderStmt(NON_EXISTENT_PROVIDER_NAME, true, NodePosition.ZERO);
|
||||
|
||||
// Should not throw exception
|
||||
authenticationMgr.dropGroupProviderStatement(stmt, ctx);
|
||||
|
||||
// Verify provider still does not exist
|
||||
GroupProvider provider = authenticationMgr.getGroupProvider(NON_EXISTENT_PROVIDER_NAME);
|
||||
Assertions.assertNull(provider, "Group provider should not exist");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case: Drop Group Provider with IF EXISTS when provider exists
|
||||
* Test point: Should successfully drop the provider
|
||||
*/
|
||||
@Test
|
||||
public void testDropGroupProviderIfExistsWhenExists() throws Exception {
|
||||
Map<String, String> properties = createUnixGroupProviderProperties();
|
||||
|
||||
// First create the provider
|
||||
CreateGroupProviderStmt createStmt =
|
||||
new CreateGroupProviderStmt(TEST_PROVIDER_NAME, properties, false, NodePosition.ZERO);
|
||||
authenticationMgr.createGroupProviderStatement(createStmt, ctx);
|
||||
|
||||
// Verify provider exists
|
||||
GroupProvider provider = authenticationMgr.getGroupProvider(TEST_PROVIDER_NAME);
|
||||
Assertions.assertNotNull(provider, "Group provider should exist before drop");
|
||||
|
||||
// Drop with IF EXISTS
|
||||
DropGroupProviderStmt dropStmt = new DropGroupProviderStmt(TEST_PROVIDER_NAME, true, NodePosition.ZERO);
|
||||
|
||||
// Should not throw exception
|
||||
authenticationMgr.dropGroupProviderStatement(dropStmt, ctx);
|
||||
|
||||
// Verify provider was dropped
|
||||
provider = authenticationMgr.getGroupProvider(TEST_PROVIDER_NAME);
|
||||
Assertions.assertNull(provider, "Group provider should be dropped successfully");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case: Drop Group Provider without IF EXISTS when provider does not exist
|
||||
* Test point: Should throw DdlException with appropriate error message
|
||||
*/
|
||||
@Test
|
||||
public void testDropGroupProviderWithoutIfExistsWhenNotExists() throws Exception {
|
||||
DropGroupProviderStmt stmt = new DropGroupProviderStmt(NON_EXISTENT_PROVIDER_NAME, false, NodePosition.ZERO);
|
||||
|
||||
// Should throw DdlException
|
||||
DdlException exception = Assertions.assertThrows(DdlException.class, () -> {
|
||||
authenticationMgr.dropGroupProviderStatement(stmt, ctx);
|
||||
});
|
||||
|
||||
Assertions.assertTrue(
|
||||
exception.getMessage().contains("Group provider '" + NON_EXISTENT_PROVIDER_NAME + "' does not exist"),
|
||||
"Error message should indicate provider does not exist: " + exception.getMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case: Test CreateGroupProviderStmt constructor and getters
|
||||
* Test point: Verify proper initialization of statement properties
|
||||
*/
|
||||
@Test
|
||||
public void testCreateGroupProviderStmtProperties() {
|
||||
Map<String, String> properties = createUnixGroupProviderProperties();
|
||||
CreateGroupProviderStmt stmt = new CreateGroupProviderStmt(TEST_PROVIDER_NAME, properties, true, NodePosition.ZERO);
|
||||
|
||||
Assertions.assertEquals(TEST_PROVIDER_NAME, stmt.getName(), "Provider name should match");
|
||||
Assertions.assertEquals(properties, stmt.getPropertyMap(), "Properties should match");
|
||||
Assertions.assertTrue(stmt.isIfNotExists(), "IF NOT EXISTS should be true");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case: Test DropGroupProviderStmt constructor and getters
|
||||
* Test point: Verify proper initialization of statement properties
|
||||
*/
|
||||
@Test
|
||||
public void testDropGroupProviderStmtProperties() {
|
||||
DropGroupProviderStmt stmt = new DropGroupProviderStmt(TEST_PROVIDER_NAME, true, NodePosition.ZERO);
|
||||
|
||||
Assertions.assertEquals(TEST_PROVIDER_NAME, stmt.getName(), "Provider name should match");
|
||||
Assertions.assertTrue(stmt.isIfExists(), "IF EXISTS should be true");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case: Test CreateGroupProviderStmt without IF NOT EXISTS
|
||||
* Test point: Verify default behavior when IF NOT EXISTS is false
|
||||
*/
|
||||
@Test
|
||||
public void testCreateGroupProviderStmtWithoutIfNotExists() {
|
||||
Map<String, String> properties = createUnixGroupProviderProperties();
|
||||
CreateGroupProviderStmt stmt = new CreateGroupProviderStmt(TEST_PROVIDER_NAME, properties, false, NodePosition.ZERO);
|
||||
|
||||
Assertions.assertEquals(TEST_PROVIDER_NAME, stmt.getName(), "Provider name should match");
|
||||
Assertions.assertEquals(properties, stmt.getPropertyMap(), "Properties should match");
|
||||
Assertions.assertFalse(stmt.isIfNotExists(), "IF NOT EXISTS should be false");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case: Test DropGroupProviderStmt without IF EXISTS
|
||||
* Test point: Verify default behavior when IF EXISTS is false
|
||||
*/
|
||||
@Test
|
||||
public void testDropGroupProviderStmtWithoutIfExists() {
|
||||
DropGroupProviderStmt stmt = new DropGroupProviderStmt(TEST_PROVIDER_NAME, false, NodePosition.ZERO);
|
||||
|
||||
Assertions.assertEquals(TEST_PROVIDER_NAME, stmt.getName(), "Provider name should match");
|
||||
Assertions.assertFalse(stmt.isIfExists(), "IF EXISTS should be false");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case: Test CreateGroupProviderStmt with legacy constructor
|
||||
* Test point: Verify backward compatibility with existing constructor
|
||||
*/
|
||||
@Test
|
||||
public void testCreateGroupProviderStmtLegacyConstructor() {
|
||||
Map<String, String> properties = createUnixGroupProviderProperties();
|
||||
CreateGroupProviderStmt stmt = new CreateGroupProviderStmt(TEST_PROVIDER_NAME, properties, NodePosition.ZERO);
|
||||
|
||||
Assertions.assertEquals(TEST_PROVIDER_NAME, stmt.getName(), "Provider name should match");
|
||||
Assertions.assertEquals(properties, stmt.getPropertyMap(), "Properties should match");
|
||||
Assertions.assertFalse(stmt.isIfNotExists(), "IF NOT EXISTS should default to false");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case: Test DropGroupProviderStmt with legacy constructor
|
||||
* Test point: Verify backward compatibility with existing constructor
|
||||
*/
|
||||
@Test
|
||||
public void testDropGroupProviderStmtLegacyConstructor() {
|
||||
DropGroupProviderStmt stmt = new DropGroupProviderStmt(TEST_PROVIDER_NAME, NodePosition.ZERO);
|
||||
|
||||
Assertions.assertEquals(TEST_PROVIDER_NAME, stmt.getName(), "Provider name should match");
|
||||
Assertions.assertFalse(stmt.isIfExists(), "IF EXISTS should default to false");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case: Test multiple Group Provider operations in sequence
|
||||
* Test point: Verify proper handling of multiple create/drop operations
|
||||
*/
|
||||
@Test
|
||||
public void testMultipleGroupProviderOperations() throws Exception {
|
||||
Map<String, String> properties = createUnixGroupProviderProperties();
|
||||
|
||||
// Create provider
|
||||
CreateGroupProviderStmt createStmt =
|
||||
new CreateGroupProviderStmt(TEST_PROVIDER_NAME, properties, false, NodePosition.ZERO);
|
||||
authenticationMgr.createGroupProviderStatement(createStmt, ctx);
|
||||
|
||||
// Verify exists
|
||||
GroupProvider provider = authenticationMgr.getGroupProvider(TEST_PROVIDER_NAME);
|
||||
Assertions.assertNotNull(provider, "Provider should exist after creation");
|
||||
|
||||
// Try to create again with IF NOT EXISTS (should not error)
|
||||
CreateGroupProviderStmt createAgainStmt =
|
||||
new CreateGroupProviderStmt(TEST_PROVIDER_NAME, properties, true, NodePosition.ZERO);
|
||||
authenticationMgr.createGroupProviderStatement(createAgainStmt, ctx);
|
||||
|
||||
// Verify still exists
|
||||
provider = authenticationMgr.getGroupProvider(TEST_PROVIDER_NAME);
|
||||
Assertions.assertNotNull(provider, "Provider should still exist after IF NOT EXISTS create");
|
||||
|
||||
// Drop with IF EXISTS
|
||||
DropGroupProviderStmt dropStmt = new DropGroupProviderStmt(TEST_PROVIDER_NAME, true, NodePosition.ZERO);
|
||||
authenticationMgr.dropGroupProviderStatement(dropStmt, ctx);
|
||||
|
||||
// Verify dropped
|
||||
provider = authenticationMgr.getGroupProvider(TEST_PROVIDER_NAME);
|
||||
Assertions.assertNull(provider, "Provider should be dropped");
|
||||
|
||||
// Try to drop again with IF EXISTS (should not error)
|
||||
DropGroupProviderStmt dropAgainStmt = new DropGroupProviderStmt(TEST_PROVIDER_NAME, true, NodePosition.ZERO);
|
||||
authenticationMgr.dropGroupProviderStatement(dropAgainStmt, ctx);
|
||||
|
||||
// Verify still does not exist
|
||||
provider = authenticationMgr.getGroupProvider(TEST_PROVIDER_NAME);
|
||||
Assertions.assertNull(provider, "Provider should still not exist after IF EXISTS drop");
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to create Unix Group Provider properties
|
||||
*/
|
||||
private Map<String, String> createUnixGroupProviderProperties() {
|
||||
Map<String, String> properties = new HashMap<>();
|
||||
properties.put("type", "unix");
|
||||
return properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to clean up test providers
|
||||
*/
|
||||
private void cleanupTestProviders() {
|
||||
try {
|
||||
// Try to drop test providers if they exist
|
||||
DropGroupProviderStmt dropStmt = new DropGroupProviderStmt(TEST_PROVIDER_NAME, true, NodePosition.ZERO);
|
||||
authenticationMgr.dropGroupProviderStatement(dropStmt, ctx);
|
||||
} catch (Exception e) {
|
||||
// Ignore cleanup errors
|
||||
}
|
||||
|
||||
try {
|
||||
DropGroupProviderStmt dropStmt = new DropGroupProviderStmt(NON_EXISTENT_PROVIDER_NAME, true, NodePosition.ZERO);
|
||||
authenticationMgr.dropGroupProviderStatement(dropStmt, ctx);
|
||||
} catch (Exception e) {
|
||||
// Ignore cleanup errors
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,318 @@
|
|||
// Copyright 2021-present StarRocks, Inc. All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// https://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 com.starrocks.sql.analyzer;
|
||||
|
||||
import com.starrocks.authentication.AuthenticationMgr;
|
||||
import com.starrocks.authentication.GroupProvider;
|
||||
import com.starrocks.catalog.UserIdentity;
|
||||
import com.starrocks.qe.ConnectContext;
|
||||
import com.starrocks.server.GlobalStateMgr;
|
||||
import com.starrocks.sql.ast.group.CreateGroupProviderStmt;
|
||||
import com.starrocks.sql.ast.group.DropGroupProviderStmt;
|
||||
import com.starrocks.sql.parser.NodePosition;
|
||||
import com.starrocks.utframe.UtFrameUtils;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
* Unit tests for GroupProviderStatementAnalyzer with IF NOT EXISTS and IF EXISTS functionality
|
||||
*/
|
||||
public class GroupProviderStatementAnalyzerTest {
|
||||
private ConnectContext ctx;
|
||||
private AuthenticationMgr authenticationMgr;
|
||||
private static final String TEST_PROVIDER_NAME = "test_provider";
|
||||
private static final String NON_EXISTENT_PROVIDER_NAME = "non_existent_provider";
|
||||
|
||||
@Mock
|
||||
private GroupProvider mockGroupProvider;
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() throws Exception {
|
||||
MockitoAnnotations.openMocks(this);
|
||||
UtFrameUtils.setUpForPersistTest();
|
||||
ctx = UtFrameUtils.initCtxForNewPrivilege(UserIdentity.ROOT);
|
||||
authenticationMgr = GlobalStateMgr.getCurrentState().getAuthenticationMgr();
|
||||
|
||||
// Setup mock group provider
|
||||
when(mockGroupProvider.getName()).thenReturn(TEST_PROVIDER_NAME);
|
||||
when(mockGroupProvider.getType()).thenReturn("unix");
|
||||
// Mock checkProperty method (void method)
|
||||
// when(mockGroupProvider.checkProperty()).thenReturn(null);
|
||||
|
||||
// Clean up any existing test providers
|
||||
cleanupTestProviders();
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void tearDown() throws Exception {
|
||||
cleanupTestProviders();
|
||||
UtFrameUtils.tearDownForPersisTest();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case: Analyze Create Group Provider with IF NOT EXISTS when provider does not exist
|
||||
* Test point: Should pass analysis without error
|
||||
*/
|
||||
@Test
|
||||
public void testAnalyzeCreateGroupProviderIfNotExistsWhenNotExists() throws Exception {
|
||||
Map<String, String> properties = createUnixGroupProviderProperties();
|
||||
CreateGroupProviderStmt stmt = new CreateGroupProviderStmt(TEST_PROVIDER_NAME, properties, true, NodePosition.ZERO);
|
||||
|
||||
// Should not throw exception
|
||||
GroupProviderStatementAnalyzer.analyze(stmt, ctx);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case: Analyze Create Group Provider with IF NOT EXISTS when provider already exists
|
||||
* Test point: Should pass analysis without error due to IF NOT EXISTS
|
||||
*/
|
||||
@Test
|
||||
public void testAnalyzeCreateGroupProviderIfNotExistsWhenExists() throws Exception {
|
||||
Map<String, String> properties = createUnixGroupProviderProperties();
|
||||
|
||||
// First create the provider
|
||||
CreateGroupProviderStmt firstStmt = new CreateGroupProviderStmt(TEST_PROVIDER_NAME, properties, false, NodePosition.ZERO);
|
||||
authenticationMgr.createGroupProviderStatement(firstStmt, ctx);
|
||||
|
||||
// Analyze create again with IF NOT EXISTS
|
||||
CreateGroupProviderStmt secondStmt = new CreateGroupProviderStmt(TEST_PROVIDER_NAME, properties, true, NodePosition.ZERO);
|
||||
|
||||
// Should not throw exception
|
||||
GroupProviderStatementAnalyzer.analyze(secondStmt, ctx);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case: Analyze Create Group Provider without IF NOT EXISTS when provider already exists
|
||||
* Test point: Should throw SemanticException with appropriate error message
|
||||
*/
|
||||
@Test
|
||||
public void testAnalyzeCreateGroupProviderWithoutIfNotExistsWhenExists() throws Exception {
|
||||
Map<String, String> properties = createUnixGroupProviderProperties();
|
||||
|
||||
// First create the provider
|
||||
CreateGroupProviderStmt firstStmt = new CreateGroupProviderStmt(TEST_PROVIDER_NAME, properties, false, NodePosition.ZERO);
|
||||
authenticationMgr.createGroupProviderStatement(firstStmt, ctx);
|
||||
|
||||
// Analyze create again without IF NOT EXISTS
|
||||
CreateGroupProviderStmt secondStmt =
|
||||
new CreateGroupProviderStmt(TEST_PROVIDER_NAME, properties, false, NodePosition.ZERO);
|
||||
|
||||
// Should throw SemanticException
|
||||
SemanticException exception = Assertions.assertThrows(SemanticException.class, () -> {
|
||||
GroupProviderStatementAnalyzer.analyze(secondStmt, ctx);
|
||||
});
|
||||
|
||||
Assertions.assertTrue(exception.getMessage().contains("Group Provider '" + TEST_PROVIDER_NAME + "' already exists"),
|
||||
"Error message should indicate provider already exists: " + exception.getMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case: Analyze Drop Group Provider with IF EXISTS when provider does not exist
|
||||
* Test point: Should pass analysis without error
|
||||
*/
|
||||
@Test
|
||||
public void testAnalyzeDropGroupProviderIfExistsWhenNotExists() throws Exception {
|
||||
DropGroupProviderStmt stmt = new DropGroupProviderStmt(NON_EXISTENT_PROVIDER_NAME, true, NodePosition.ZERO);
|
||||
|
||||
// Should not throw exception
|
||||
GroupProviderStatementAnalyzer.analyze(stmt, ctx);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case: Analyze Drop Group Provider with IF EXISTS when provider exists
|
||||
* Test point: Should pass analysis without error
|
||||
*/
|
||||
@Test
|
||||
public void testAnalyzeDropGroupProviderIfExistsWhenExists() throws Exception {
|
||||
Map<String, String> properties = createUnixGroupProviderProperties();
|
||||
|
||||
// First create the provider
|
||||
CreateGroupProviderStmt createStmt =
|
||||
new CreateGroupProviderStmt(TEST_PROVIDER_NAME, properties, false, NodePosition.ZERO);
|
||||
authenticationMgr.createGroupProviderStatement(createStmt, ctx);
|
||||
|
||||
// Analyze drop with IF EXISTS
|
||||
DropGroupProviderStmt dropStmt = new DropGroupProviderStmt(TEST_PROVIDER_NAME, true, NodePosition.ZERO);
|
||||
|
||||
// Should not throw exception
|
||||
GroupProviderStatementAnalyzer.analyze(dropStmt, ctx);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case: Analyze Drop Group Provider without IF EXISTS when provider does not exist
|
||||
* Test point: Should throw SemanticException with appropriate error message
|
||||
*/
|
||||
@Test
|
||||
public void testAnalyzeDropGroupProviderWithoutIfExistsWhenNotExists() throws Exception {
|
||||
DropGroupProviderStmt stmt = new DropGroupProviderStmt(NON_EXISTENT_PROVIDER_NAME, false, NodePosition.ZERO);
|
||||
|
||||
// Should throw SemanticException
|
||||
SemanticException exception = Assertions.assertThrows(SemanticException.class, () -> {
|
||||
GroupProviderStatementAnalyzer.analyze(stmt, ctx);
|
||||
});
|
||||
|
||||
Assertions.assertTrue(exception.getMessage().contains("Group Provider '" + NON_EXISTENT_PROVIDER_NAME + "' not found"),
|
||||
"Error message should indicate provider not found: " + exception.getMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case: Analyze Create Group Provider with missing type property
|
||||
* Test point: Should throw SemanticException for missing required property
|
||||
*/
|
||||
@Test
|
||||
public void testAnalyzeCreateGroupProviderMissingType() throws Exception {
|
||||
Map<String, String> properties = new HashMap<>();
|
||||
// Missing "type" property
|
||||
CreateGroupProviderStmt stmt = new CreateGroupProviderStmt(TEST_PROVIDER_NAME, properties, false, NodePosition.ZERO);
|
||||
|
||||
// Should throw SemanticException
|
||||
SemanticException exception = Assertions.assertThrows(SemanticException.class, () -> {
|
||||
GroupProviderStatementAnalyzer.analyze(stmt, ctx);
|
||||
});
|
||||
|
||||
Assertions.assertTrue(exception.getMessage().contains("missing required property: type"),
|
||||
"Error message should indicate missing type property: " + exception.getMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case: Analyze Create Group Provider with unsupported type
|
||||
* Test point: Should throw SemanticException for unsupported group provider type
|
||||
*/
|
||||
@Test
|
||||
public void testAnalyzeCreateGroupProviderUnsupportedType() throws Exception {
|
||||
Map<String, String> properties = new HashMap<>();
|
||||
properties.put("type", "unsupported_type");
|
||||
CreateGroupProviderStmt stmt = new CreateGroupProviderStmt(TEST_PROVIDER_NAME, properties, false, NodePosition.ZERO);
|
||||
|
||||
// Should throw SemanticException
|
||||
SemanticException exception = Assertions.assertThrows(SemanticException.class, () -> {
|
||||
GroupProviderStatementAnalyzer.analyze(stmt, ctx);
|
||||
});
|
||||
|
||||
Assertions.assertTrue(exception.getMessage().contains("unsupported group provider type"),
|
||||
"Error message should indicate unsupported type: " + exception.getMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case: Analyze Create Group Provider with valid Unix type
|
||||
* Test point: Should pass analysis for valid Unix group provider
|
||||
*/
|
||||
@Test
|
||||
public void testAnalyzeCreateGroupProviderValidUnixType() throws Exception {
|
||||
Map<String, String> properties = createUnixGroupProviderProperties();
|
||||
CreateGroupProviderStmt stmt = new CreateGroupProviderStmt(TEST_PROVIDER_NAME, properties, false, NodePosition.ZERO);
|
||||
|
||||
// Should not throw exception
|
||||
GroupProviderStatementAnalyzer.analyze(stmt, ctx);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case: Analyze Create Group Provider with valid File type
|
||||
* Test point: Should pass analysis for valid File group provider
|
||||
*/
|
||||
@Test
|
||||
public void testAnalyzeCreateGroupProviderValidFileType() throws Exception {
|
||||
Map<String, String> properties = new HashMap<>();
|
||||
properties.put("type", "file");
|
||||
properties.put("group_file_url", "test_file");
|
||||
CreateGroupProviderStmt stmt = new CreateGroupProviderStmt(TEST_PROVIDER_NAME, properties, false, NodePosition.ZERO);
|
||||
|
||||
// Should not throw exception
|
||||
GroupProviderStatementAnalyzer.analyze(stmt, ctx);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case: Analyze Create Group Provider with valid LDAP type
|
||||
* Test point: Should pass analysis for valid LDAP group provider
|
||||
*/
|
||||
@Test
|
||||
public void testAnalyzeCreateGroupProviderValidLDAPType() throws Exception {
|
||||
Map<String, String> properties = new HashMap<>();
|
||||
properties.put("type", "ldap");
|
||||
properties.put("ldap_conn_url", "ldap://localhost:389");
|
||||
properties.put("ldap_bind_root_dn", "cn=admin,dc=example,dc=com");
|
||||
properties.put("ldap_bind_root_pwd", "password");
|
||||
properties.put("ldap_bind_base_dn", "dc=example,dc=com");
|
||||
properties.put("ldap_group_dn", "ou=groups,dc=example,dc=com");
|
||||
CreateGroupProviderStmt stmt = new CreateGroupProviderStmt(TEST_PROVIDER_NAME, properties, false, NodePosition.ZERO);
|
||||
|
||||
// Should not throw exception
|
||||
GroupProviderStatementAnalyzer.analyze(stmt, ctx);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case: Test analysis with null context
|
||||
* Test point: Should handle null context gracefully
|
||||
*/
|
||||
@Test
|
||||
public void testAnalyzeWithNullContext() throws Exception {
|
||||
Map<String, String> properties = createUnixGroupProviderProperties();
|
||||
CreateGroupProviderStmt stmt = new CreateGroupProviderStmt(TEST_PROVIDER_NAME, properties, false, NodePosition.ZERO);
|
||||
|
||||
// Should not throw exception even with null context
|
||||
GroupProviderStatementAnalyzer.analyze(stmt, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case: Test analysis with empty provider name
|
||||
* Test point: Should handle empty provider name appropriately
|
||||
*/
|
||||
@Test
|
||||
public void testAnalyzeWithEmptyProviderName() throws Exception {
|
||||
Map<String, String> properties = createUnixGroupProviderProperties();
|
||||
CreateGroupProviderStmt stmt = new CreateGroupProviderStmt("", properties, false, NodePosition.ZERO);
|
||||
|
||||
// Should not throw exception during analysis (name validation happens elsewhere)
|
||||
GroupProviderStatementAnalyzer.analyze(stmt, ctx);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to create Unix Group Provider properties
|
||||
*/
|
||||
private Map<String, String> createUnixGroupProviderProperties() {
|
||||
Map<String, String> properties = new HashMap<>();
|
||||
properties.put("type", "unix");
|
||||
return properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to clean up test providers
|
||||
*/
|
||||
private void cleanupTestProviders() {
|
||||
try {
|
||||
// Try to drop test providers if they exist
|
||||
DropGroupProviderStmt dropStmt = new DropGroupProviderStmt(TEST_PROVIDER_NAME, true, NodePosition.ZERO);
|
||||
authenticationMgr.dropGroupProviderStatement(dropStmt, ctx);
|
||||
} catch (Exception e) {
|
||||
// Ignore cleanup errors
|
||||
}
|
||||
|
||||
try {
|
||||
DropGroupProviderStmt dropStmt = new DropGroupProviderStmt(NON_EXISTENT_PROVIDER_NAME, true, NodePosition.ZERO);
|
||||
authenticationMgr.dropGroupProviderStatement(dropStmt, ctx);
|
||||
} catch (Exception e) {
|
||||
// Ignore cleanup errors
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,251 @@
|
|||
// Copyright 2021-present StarRocks, Inc. All rights reserved.
|
||||
//
|
||||
// Licensed 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
|
||||
//
|
||||
// https://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 com.starrocks.sql.parser;
|
||||
|
||||
import com.starrocks.catalog.UserIdentity;
|
||||
import com.starrocks.qe.ConnectContext;
|
||||
import com.starrocks.sql.ast.group.CreateGroupProviderStmt;
|
||||
import com.starrocks.sql.ast.group.DropGroupProviderStmt;
|
||||
import com.starrocks.sql.parser.SqlParser;
|
||||
import com.starrocks.utframe.UtFrameUtils;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Unit tests for AstBuilder Group Provider parsing with IF NOT EXISTS and IF EXISTS functionality
|
||||
*/
|
||||
public class GroupProviderAstBuilderTest {
|
||||
private ConnectContext ctx;
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() throws Exception {
|
||||
ctx = UtFrameUtils.initCtxForNewPrivilege(UserIdentity.ROOT);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void tearDown() throws Exception {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case: Parse CREATE GROUP PROVIDER without IF NOT EXISTS
|
||||
* Test point: Should create statement with ifNotExists = false
|
||||
*/
|
||||
@Test
|
||||
public void testParseCreateGroupProviderWithoutIfNotExists() throws Exception {
|
||||
String sql = "CREATE GROUP PROVIDER test_provider PROPERTIES(\"type\" = \"unix\")";
|
||||
|
||||
CreateGroupProviderStmt stmt =
|
||||
(CreateGroupProviderStmt) SqlParser.parseSingleStatement(sql, ctx.getSessionVariable().getSqlMode());
|
||||
|
||||
Assertions.assertNotNull(stmt, "Statement should not be null");
|
||||
Assertions.assertEquals("test_provider", stmt.getName(), "Provider name should match");
|
||||
Assertions.assertFalse(stmt.isIfNotExists(), "IF NOT EXISTS should be false");
|
||||
|
||||
Map<String, String> properties = stmt.getPropertyMap();
|
||||
Assertions.assertNotNull(properties, "Properties should not be null");
|
||||
Assertions.assertEquals("unix", properties.get("type"), "Type should be unix");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case: Parse CREATE GROUP PROVIDER with IF NOT EXISTS
|
||||
* Test point: Should create statement with ifNotExists = true
|
||||
*/
|
||||
@Test
|
||||
public void testParseCreateGroupProviderWithIfNotExists() throws Exception {
|
||||
String sql = "CREATE GROUP PROVIDER IF NOT EXISTS test_provider PROPERTIES(\"type\" = \"unix\")";
|
||||
|
||||
CreateGroupProviderStmt stmt =
|
||||
(CreateGroupProviderStmt) SqlParser.parseSingleStatement(sql, ctx.getSessionVariable().getSqlMode());
|
||||
|
||||
Assertions.assertNotNull(stmt, "Statement should not be null");
|
||||
Assertions.assertEquals("test_provider", stmt.getName(), "Provider name should match");
|
||||
Assertions.assertTrue(stmt.isIfNotExists(), "IF NOT EXISTS should be true");
|
||||
|
||||
Map<String, String> properties = stmt.getPropertyMap();
|
||||
Assertions.assertNotNull(properties, "Properties should not be null");
|
||||
Assertions.assertEquals("unix", properties.get("type"), "Type should be unix");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case: Parse DROP GROUP PROVIDER without IF EXISTS
|
||||
* Test point: Should create statement with ifExists = false
|
||||
*/
|
||||
@Test
|
||||
public void testParseDropGroupProviderWithoutIfExists() throws Exception {
|
||||
String sql = "DROP GROUP PROVIDER test_provider";
|
||||
|
||||
DropGroupProviderStmt stmt =
|
||||
(DropGroupProviderStmt) SqlParser.parseSingleStatement(sql, ctx.getSessionVariable().getSqlMode());
|
||||
|
||||
Assertions.assertNotNull(stmt, "Statement should not be null");
|
||||
Assertions.assertEquals("test_provider", stmt.getName(), "Provider name should match");
|
||||
Assertions.assertFalse(stmt.isIfExists(), "IF EXISTS should be false");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case: Parse DROP GROUP PROVIDER with IF EXISTS
|
||||
* Test point: Should create statement with ifExists = true
|
||||
*/
|
||||
@Test
|
||||
public void testParseDropGroupProviderWithIfExists() throws Exception {
|
||||
String sql = "DROP GROUP PROVIDER IF EXISTS test_provider";
|
||||
|
||||
DropGroupProviderStmt stmt =
|
||||
(DropGroupProviderStmt) SqlParser.parseSingleStatement(sql, ctx.getSessionVariable().getSqlMode());
|
||||
|
||||
Assertions.assertNotNull(stmt, "Statement should not be null");
|
||||
Assertions.assertEquals("test_provider", stmt.getName(), "Provider name should match");
|
||||
Assertions.assertTrue(stmt.isIfExists(), "IF EXISTS should be true");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case: Parse CREATE GROUP PROVIDER with File type
|
||||
* Test point: Should correctly parse File group provider properties
|
||||
*/
|
||||
@Test
|
||||
public void testParseCreateGroupProviderFileType() throws Exception {
|
||||
String sql = "CREATE GROUP PROVIDER IF NOT EXISTS file_provider PROPERTIES(\"type\" = \"file\"," +
|
||||
" \"file_url\" = \"/path/to/file\")";
|
||||
|
||||
CreateGroupProviderStmt stmt =
|
||||
(CreateGroupProviderStmt) SqlParser.parseSingleStatement(sql, ctx.getSessionVariable().getSqlMode());
|
||||
|
||||
Assertions.assertNotNull(stmt, "Statement should not be null");
|
||||
Assertions.assertEquals("file_provider", stmt.getName(), "Provider name should match");
|
||||
Assertions.assertTrue(stmt.isIfNotExists(), "IF NOT EXISTS should be true");
|
||||
|
||||
Map<String, String> properties = stmt.getPropertyMap();
|
||||
Assertions.assertNotNull(properties, "Properties should not be null");
|
||||
Assertions.assertEquals("file", properties.get("type"), "Type should be file");
|
||||
Assertions.assertEquals("/path/to/file", properties.get("file_url"), "File URL should match");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case: Parse CREATE GROUP PROVIDER with LDAP type
|
||||
* Test point: Should correctly parse LDAP group provider properties
|
||||
*/
|
||||
@Test
|
||||
public void testParseCreateGroupProviderLDAPType() throws Exception {
|
||||
String sql = "CREATE GROUP PROVIDER IF NOT EXISTS ldap_provider PROPERTIES(" +
|
||||
"\"type\" = \"ldap\", " +
|
||||
"\"ldap_conn_url\" = \"ldap://localhost:389\", " +
|
||||
"\"ldap_bind_root_dn\" = \"cn=admin,dc=example,dc=com\", " +
|
||||
"\"ldap_bind_root_pwd\" = \"password\", " +
|
||||
"\"ldap_bind_base_dn\" = \"dc=example,dc=com\")";
|
||||
|
||||
CreateGroupProviderStmt stmt =
|
||||
(CreateGroupProviderStmt) SqlParser.parseSingleStatement(sql, ctx.getSessionVariable().getSqlMode());
|
||||
|
||||
Assertions.assertNotNull(stmt, "Statement should not be null");
|
||||
Assertions.assertEquals("ldap_provider", stmt.getName(), "Provider name should match");
|
||||
Assertions.assertTrue(stmt.isIfNotExists(), "IF NOT EXISTS should be true");
|
||||
|
||||
Map<String, String> properties = stmt.getPropertyMap();
|
||||
Assertions.assertNotNull(properties, "Properties should not be null");
|
||||
Assertions.assertEquals("ldap", properties.get("type"), "Type should be ldap");
|
||||
Assertions.assertEquals("ldap://localhost:389", properties.get("ldap_conn_url"), "LDAP URL should match");
|
||||
Assertions.assertEquals("cn=admin,dc=example,dc=com", properties.get("ldap_bind_root_dn"), "Root DN should match");
|
||||
Assertions.assertEquals("password", properties.get("ldap_bind_root_pwd"), "Password should match");
|
||||
Assertions.assertEquals("dc=example,dc=com", properties.get("ldap_bind_base_dn"), "Base DN should match");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case: Parse CREATE GROUP PROVIDER with quoted identifier
|
||||
* Test point: Should correctly handle quoted provider names
|
||||
*/
|
||||
@Test
|
||||
public void testParseCreateGroupProviderWithQuotedIdentifier() throws Exception {
|
||||
String sql = "CREATE GROUP PROVIDER IF NOT EXISTS `test-provider` PROPERTIES(\"type\" = \"unix\")";
|
||||
|
||||
CreateGroupProviderStmt stmt =
|
||||
(CreateGroupProviderStmt) SqlParser.parseSingleStatement(sql, ctx.getSessionVariable().getSqlMode());
|
||||
|
||||
Assertions.assertNotNull(stmt, "Statement should not be null");
|
||||
Assertions.assertEquals("test-provider", stmt.getName(), "Provider name should match");
|
||||
Assertions.assertTrue(stmt.isIfNotExists(), "IF NOT EXISTS should be true");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case: Parse DROP GROUP PROVIDER with quoted identifier
|
||||
* Test point: Should correctly handle quoted provider names
|
||||
*/
|
||||
@Test
|
||||
public void testParseDropGroupProviderWithQuotedIdentifier() throws Exception {
|
||||
String sql = "DROP GROUP PROVIDER IF EXISTS `test-provider`";
|
||||
|
||||
DropGroupProviderStmt stmt =
|
||||
(DropGroupProviderStmt) SqlParser.parseSingleStatement(sql, ctx.getSessionVariable().getSqlMode());
|
||||
|
||||
Assertions.assertNotNull(stmt, "Statement should not be null");
|
||||
Assertions.assertEquals("test-provider", stmt.getName(), "Provider name should match");
|
||||
Assertions.assertTrue(stmt.isIfExists(), "IF EXISTS should be true");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case: Parse CREATE GROUP PROVIDER with complex properties
|
||||
* Test point: Should correctly parse multiple properties with various types
|
||||
*/
|
||||
@Test
|
||||
public void testParseCreateGroupProviderWithComplexProperties() throws Exception {
|
||||
String sql = "CREATE GROUP PROVIDER IF NOT EXISTS complex_provider PROPERTIES(" +
|
||||
"\"type\" = \"ldap\", " +
|
||||
"\"ldap_conn_url\" = \"ldap://localhost:389\", " +
|
||||
"\"ldap_conn_timeout\" = \"5000\", " +
|
||||
"\"ldap_conn_read_timeout\" = \"3000\", " +
|
||||
"\"ldap_ssl_conn_allow_insecure\" = \"true\")";
|
||||
|
||||
CreateGroupProviderStmt stmt =
|
||||
(CreateGroupProviderStmt) SqlParser.parseSingleStatement(sql, ctx.getSessionVariable().getSqlMode());
|
||||
|
||||
Assertions.assertNotNull(stmt, "Statement should not be null");
|
||||
Assertions.assertEquals("complex_provider", stmt.getName(), "Provider name should match");
|
||||
Assertions.assertTrue(stmt.isIfNotExists(), "IF NOT EXISTS should be true");
|
||||
|
||||
Map<String, String> properties = stmt.getPropertyMap();
|
||||
Assertions.assertNotNull(properties, "Properties should not be null");
|
||||
Assertions.assertEquals("ldap", properties.get("type"), "Type should be ldap");
|
||||
Assertions.assertEquals("ldap://localhost:389", properties.get("ldap_conn_url"), "LDAP URL should match");
|
||||
Assertions.assertEquals("5000", properties.get("ldap_conn_timeout"), "Timeout should match");
|
||||
Assertions.assertEquals("3000", properties.get("ldap_conn_read_timeout"), "Read timeout should match");
|
||||
Assertions.assertEquals("true", properties.get("ldap_ssl_conn_allow_insecure"), "SSL setting should match");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case: Parse statements with case variations
|
||||
* Test point: Should handle case-insensitive keywords correctly
|
||||
*/
|
||||
@Test
|
||||
public void testParseWithCaseVariations() throws Exception {
|
||||
// Test CREATE with different case
|
||||
String createSql = "create group provider if not exists case_test PROPERTIES(\"type\" = \"unix\")";
|
||||
CreateGroupProviderStmt createStmt = (CreateGroupProviderStmt) UtFrameUtils.parseStmtWithNewParser(createSql, ctx);
|
||||
|
||||
Assertions.assertNotNull(createStmt, "Create statement should not be null");
|
||||
Assertions.assertEquals("case_test", createStmt.getName(), "Provider name should match");
|
||||
Assertions.assertTrue(createStmt.isIfNotExists(), "IF NOT EXISTS should be true");
|
||||
|
||||
// Test DROP with different case
|
||||
String dropSql = "drop group provider if exists case_test";
|
||||
DropGroupProviderStmt dropStmt = (DropGroupProviderStmt) UtFrameUtils.parseStmtWithNewParser(dropSql, ctx);
|
||||
|
||||
Assertions.assertNotNull(dropStmt, "Drop statement should not be null");
|
||||
Assertions.assertEquals("case_test", dropStmt.getName(), "Provider name should match");
|
||||
Assertions.assertTrue(dropStmt.isIfExists(), "IF EXISTS should be true");
|
||||
}
|
||||
}
|
||||
|
|
@ -1892,11 +1892,11 @@ showCreateSecurityIntegrationStatement
|
|||
// ------------------------------------------- Group Provider Statement ------------------------------------------
|
||||
|
||||
createGroupProviderStatement
|
||||
: CREATE GROUP PROVIDER identifier properties
|
||||
: CREATE GROUP PROVIDER (IF NOT EXISTS)? identifier properties
|
||||
;
|
||||
|
||||
dropGroupProviderStatement
|
||||
: DROP GROUP PROVIDER identifier
|
||||
: DROP GROUP PROVIDER (IF EXISTS)? identifier
|
||||
;
|
||||
|
||||
showGroupProvidersStatement
|
||||
|
|
|
|||
|
|
@ -23,11 +23,17 @@ import java.util.Map;
|
|||
public class CreateGroupProviderStmt extends DdlStmt {
|
||||
private final String name;
|
||||
private final Map<String, String> propertyMap;
|
||||
private final boolean ifNotExists;
|
||||
|
||||
public CreateGroupProviderStmt(String name, Map<String, String> propertyMap, NodePosition pos) {
|
||||
this(name, propertyMap, false, pos);
|
||||
}
|
||||
|
||||
public CreateGroupProviderStmt(String name, Map<String, String> propertyMap, boolean ifNotExists, NodePosition pos) {
|
||||
super(pos);
|
||||
this.name = name;
|
||||
this.propertyMap = propertyMap;
|
||||
this.ifNotExists = ifNotExists;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
|
|
@ -38,6 +44,10 @@ public class CreateGroupProviderStmt extends DdlStmt {
|
|||
return propertyMap;
|
||||
}
|
||||
|
||||
public boolean isIfNotExists() {
|
||||
return ifNotExists;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
|
||||
return visitor.visitCreateGroupProviderStatement(this, context);
|
||||
|
|
|
|||
|
|
@ -20,16 +20,26 @@ import com.starrocks.sql.parser.NodePosition;
|
|||
|
||||
public class DropGroupProviderStmt extends DdlStmt {
|
||||
private final String name;
|
||||
private final boolean ifExists;
|
||||
|
||||
public DropGroupProviderStmt(String name, NodePosition pos) {
|
||||
this(name, false, pos);
|
||||
}
|
||||
|
||||
public DropGroupProviderStmt(String name, boolean ifExists, NodePosition pos) {
|
||||
super(pos);
|
||||
this.name = name;
|
||||
this.ifExists = ifExists;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public boolean isIfExists() {
|
||||
return ifExists;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
|
||||
return visitor.visitDropGroupProviderStatement(this, context);
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@ create user u1;
|
|||
grant impersonate on user root to u1;
|
||||
-- result:
|
||||
-- !result
|
||||
create group provider foo properties("type" = "foo");
|
||||
create group provider if not exists foo properties("type" = "foo");
|
||||
-- result:
|
||||
E: (1064, "Getting analyzing error. Detail message: unsupported group provider type 'foo'.")
|
||||
-- !result
|
||||
create group provider unix_group_provider properties("type" = "unix");
|
||||
create group provider if not exists unix_group_provider properties("type" = "unix");
|
||||
-- result:
|
||||
-- !result
|
||||
show create group provider unix_group_provider;
|
||||
|
|
@ -32,11 +32,11 @@ show create group provider unix_group_provider;
|
|||
-- result:
|
||||
E: (5203, 'Access denied; you need (at least one of) the SECURITY privilege(s) on SYSTEM for this operation. Please ask the admin to grant permission(s) or try activating existing roles using <set [default] role>. Current role(s): NONE. Inactivated role(s): NONE.')
|
||||
-- !result
|
||||
drop group provider unix_group_provider;
|
||||
drop group provider if exists unix_group_provider;
|
||||
-- result:
|
||||
E: (5203, 'Access denied; you need (at least one of) the SECURITY privilege(s) on SYSTEM for this operation. Please ask the admin to grant permission(s) or try activating existing roles using <set [default] role>. Current role(s): NONE. Inactivated role(s): NONE.')
|
||||
-- !result
|
||||
create group provider unix_group_provider2 properties("type" = "unix");
|
||||
create group provider if not exists unix_group_provider2 properties("type" = "unix");
|
||||
-- result:
|
||||
E: (5203, 'Access denied; you need (at least one of) the SECURITY privilege(s) on SYSTEM for this operation. Please ask the admin to grant permission(s) or try activating existing roles using <set [default] role>. Current role(s): NONE. Inactivated role(s): NONE.')
|
||||
-- !result
|
||||
|
|
@ -46,6 +46,6 @@ execute as root with no revert;
|
|||
drop user u1;
|
||||
-- result:
|
||||
-- !result
|
||||
drop group provider unix_group_provider;
|
||||
drop group provider if exists unix_group_provider;
|
||||
-- result:
|
||||
-- !result
|
||||
|
|
@ -4,19 +4,19 @@ drop user if exists u1;
|
|||
create user u1;
|
||||
grant impersonate on user root to u1;
|
||||
|
||||
create group provider foo properties("type" = "foo");
|
||||
create group provider if not exists foo properties("type" = "foo");
|
||||
|
||||
create group provider unix_group_provider properties("type" = "unix");
|
||||
create group provider if not exists unix_group_provider properties("type" = "unix");
|
||||
show create group provider unix_group_provider;
|
||||
|
||||
execute as u1 with no revert;
|
||||
show group providers;
|
||||
show create group provider unix_group_provider;
|
||||
|
||||
drop group provider unix_group_provider;
|
||||
create group provider unix_group_provider2 properties("type" = "unix");
|
||||
drop group provider if exists unix_group_provider;
|
||||
create group provider if not exists unix_group_provider2 properties("type" = "unix");
|
||||
|
||||
execute as root with no revert;
|
||||
drop user u1;
|
||||
|
||||
drop group provider unix_group_provider;
|
||||
drop group provider if exists unix_group_provider;
|
||||
Loading…
Reference in New Issue