This is an automated email from the ASF dual-hosted git repository. dlych pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/asterixdb.git
commit b434fbe476a699d0333d30890da85e2ab976e9ba Author: Dmitry Lychagin <dmitry.lycha...@couchbase.com> AuthorDate: Fri Dec 11 16:28:25 2020 -0800 [NO ISSUE][COMP] Limit dataverse name length - user model changes: yes - storage format changes: no - interface changes: no Details: - Limit each part in a dataverse name length to 255 bytes (in UTF-8) - Limit total length of a dataverse name to 1023 bytes (in UTF-8) Change-Id: I044e71a0267299e50698fe9181ea2eb1819d97b0 Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/9324 Integration-Tests: Jenkins <jenk...@fulliautomatix.ics.uci.edu> Tested-by: Jenkins <jenk...@fulliautomatix.ics.uci.edu> Reviewed-by: Dmitry Lychagin <dmitry.lycha...@couchbase.com> Reviewed-by: Ali Alsuliman <ali.al.solai...@gmail.com> --- .../asterix/test/metadata/MetadataManagerTest.java | 99 ++++++++++++++++++++++ .../metadata/declared/MetadataProvider.java | 10 +++ .../asterix/metadata/utils/MetadataConstants.java | 3 + 3 files changed, 112 insertions(+) diff --git a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/metadata/MetadataManagerTest.java b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/metadata/MetadataManagerTest.java index 9045680..164ea7f 100644 --- a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/metadata/MetadataManagerTest.java +++ b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/metadata/MetadataManagerTest.java @@ -18,11 +18,20 @@ */ package org.apache.asterix.test.metadata; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + import org.apache.asterix.api.common.AsterixHyracksIntegrationUtil; import org.apache.asterix.common.config.GlobalConfig; +import org.apache.asterix.common.exceptions.ErrorCode; +import org.apache.asterix.common.metadata.DataverseName; +import org.apache.asterix.metadata.utils.MetadataConstants; import org.apache.asterix.test.common.TestExecutor; import org.apache.asterix.testframework.context.TestCaseContext; +import org.apache.commons.lang3.StringUtils; import org.junit.After; +import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -61,4 +70,94 @@ public class MetadataManagerTest { testExecutor.executeSqlppUpdateOrDdl("drop dataverse test;", cleanJson); testExecutor.executeSqlppUpdateOrDdl(sql.toString(), cleanJson); } + + @Test + public void testDataverseNameLimits() throws Exception { + TestCaseContext.OutputFormat cleanJson = TestCaseContext.OutputFormat.CLEAN_JSON; + + // at max dataverse name limits + + char auml = 228, euml = 235; + + List<DataverseName> dvNameOkList = + Arrays.asList( + // #1. max single-part name + DataverseName.createSinglePartName( + StringUtils.repeat('a', MetadataConstants.DATAVERSE_NAME_PART_LENGTH_LIMIT_UTF8)), + // #2. max single-part name (2-byte characters) + DataverseName.createSinglePartName( + StringUtils.repeat(auml, MetadataConstants.DATAVERSE_NAME_PART_LENGTH_LIMIT_UTF8 / 2)), + // #3. 4 max parts + DataverseName.create(Arrays.asList( + StringUtils.repeat('a', MetadataConstants.DATAVERSE_NAME_PART_LENGTH_LIMIT_UTF8), + StringUtils.repeat('b', MetadataConstants.DATAVERSE_NAME_PART_LENGTH_LIMIT_UTF8), + StringUtils.repeat('c', MetadataConstants.DATAVERSE_NAME_PART_LENGTH_LIMIT_UTF8), + StringUtils.repeat('d', MetadataConstants.DATAVERSE_NAME_PART_LENGTH_LIMIT_UTF8))), + // #3. 4 max parts (2-byte characters) + DataverseName.create(Arrays.asList( + StringUtils.repeat(auml, MetadataConstants.DATAVERSE_NAME_PART_LENGTH_LIMIT_UTF8 / 2), + StringUtils.repeat(euml, MetadataConstants.DATAVERSE_NAME_PART_LENGTH_LIMIT_UTF8 / 2), + StringUtils.repeat(auml, MetadataConstants.DATAVERSE_NAME_PART_LENGTH_LIMIT_UTF8 / 2), + StringUtils.repeat(euml, + MetadataConstants.DATAVERSE_NAME_PART_LENGTH_LIMIT_UTF8 / 2)))); + + for (DataverseName dvNameOk : dvNameOkList) { + String sql = String.format("create dataverse %s;", dvNameOk); + testExecutor.executeSqlppUpdateOrDdl(sql, cleanJson); + } + + // exceeding dataverse name limits + + char iuml = 239, ouml = 246; + + List<DataverseName> dvNameErrList = + Arrays.asList( + // #1. single-part name exceeds part length limit + DataverseName.createSinglePartName( + StringUtils.repeat('A', MetadataConstants.DATAVERSE_NAME_PART_LENGTH_LIMIT_UTF8 + 1)), + // #2 single-part name exceeds part length limit (2-byte characters) + DataverseName.createSinglePartName(StringUtils.repeat(iuml, + MetadataConstants.DATAVERSE_NAME_PART_LENGTH_LIMIT_UTF8 / 2 + 1)), + // #3. 2-part name, 2nd part exceed part length limit + DataverseName.create(Arrays.asList("A", + StringUtils.repeat('B', MetadataConstants.DATAVERSE_NAME_PART_LENGTH_LIMIT_UTF8 + 1))), + // #4. 2-part name, 2nd part exceed part length limit (2-byte characters) + DataverseName.create(Arrays.asList("A", + StringUtils.repeat(ouml, + MetadataConstants.DATAVERSE_NAME_PART_LENGTH_LIMIT_UTF8 / 2 + 1))), + // #5. 5-part name, each part at the part length limit, total length limit is exceeded + DataverseName.create(Arrays.asList( + StringUtils.repeat('A', MetadataConstants.DATAVERSE_NAME_PART_LENGTH_LIMIT_UTF8), + StringUtils.repeat('B', MetadataConstants.DATAVERSE_NAME_PART_LENGTH_LIMIT_UTF8), + StringUtils.repeat('C', MetadataConstants.DATAVERSE_NAME_PART_LENGTH_LIMIT_UTF8), + StringUtils.repeat('D', MetadataConstants.DATAVERSE_NAME_PART_LENGTH_LIMIT_UTF8), + StringUtils.repeat('E', MetadataConstants.DATAVERSE_NAME_PART_LENGTH_LIMIT_UTF8))), + // #6. 5-part name, each part at the part length limit, total length limit is exceeded (2-byte characters) + DataverseName.create(Arrays.asList( + StringUtils.repeat(iuml, MetadataConstants.DATAVERSE_NAME_PART_LENGTH_LIMIT_UTF8 / 2), + StringUtils.repeat(ouml, MetadataConstants.DATAVERSE_NAME_PART_LENGTH_LIMIT_UTF8 / 2), + StringUtils.repeat(iuml, MetadataConstants.DATAVERSE_NAME_PART_LENGTH_LIMIT_UTF8 / 2), + StringUtils.repeat(ouml, MetadataConstants.DATAVERSE_NAME_PART_LENGTH_LIMIT_UTF8 / 2), + StringUtils.repeat(iuml, MetadataConstants.DATAVERSE_NAME_PART_LENGTH_LIMIT_UTF8 / 2))), + // #7. Multi-part name, each part at the part length limit, total length limit is exceeded + DataverseName.create( + Collections.nCopies(MetadataConstants.DATAVERSE_NAME_TOTAL_LENGTH_LIMIT_UTF8 + 1, "A")), + // #8. Multi-part name, each part at the part length limit, total length limit is exceeded (2-bytes characters) + DataverseName.create( + Collections.nCopies(MetadataConstants.DATAVERSE_NAME_TOTAL_LENGTH_LIMIT_UTF8 / 2 + 1, + String.valueOf(iuml)))); + + String invalidNameErrCode = ErrorCode.ASTERIX + ErrorCode.INVALID_DATABASE_OBJECT_NAME; + for (DataverseName dvNameErr : dvNameErrList) { + String sql = String.format("create dataverse %s;", dvNameErr); + try { + testExecutor.executeSqlppUpdateOrDdl(sql, cleanJson); + Assert.fail("Expected failure: " + invalidNameErrCode); + } catch (Exception e) { + + Assert.assertTrue("Unexpected error message: " + e.getMessage(), + e.getMessage().contains(invalidNameErrCode)); + } + } + } } diff --git a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/declared/MetadataProvider.java b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/declared/MetadataProvider.java index 7d00c4b..075c2a8 100644 --- a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/declared/MetadataProvider.java +++ b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/declared/MetadataProvider.java @@ -20,6 +20,7 @@ package org.apache.asterix.metadata.declared; import java.io.File; import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -1759,8 +1760,17 @@ public class MetadataProvider implements IMetadataProvider<DataSourceId, String> public void validateDataverseName(DataverseName dataverseName, SourceLocation sourceLoc) throws AlgebricksException { + int totalLengthUTF8 = 0; for (String dvNamePart : dataverseName.getParts()) { validateDatabaseObjectNameImpl(dvNamePart, sourceLoc); + int lengthUTF8 = dvNamePart.getBytes(StandardCharsets.UTF_8).length; + if (lengthUTF8 > MetadataConstants.DATAVERSE_NAME_PART_LENGTH_LIMIT_UTF8) { + throw new AsterixException(ErrorCode.INVALID_DATABASE_OBJECT_NAME, sourceLoc, dvNamePart); + } + totalLengthUTF8 += lengthUTF8; + } + if (totalLengthUTF8 > MetadataConstants.DATAVERSE_NAME_TOTAL_LENGTH_LIMIT_UTF8) { + throw new AsterixException(ErrorCode.INVALID_DATABASE_OBJECT_NAME, sourceLoc, dataverseName.toString()); } } diff --git a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/utils/MetadataConstants.java b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/utils/MetadataConstants.java index 4489050..9b037d6 100644 --- a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/utils/MetadataConstants.java +++ b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/utils/MetadataConstants.java @@ -26,6 +26,9 @@ import org.apache.asterix.common.metadata.DataverseName; */ public class MetadataConstants { + public static final int DATAVERSE_NAME_PART_LENGTH_LIMIT_UTF8 = 255; + public static final int DATAVERSE_NAME_TOTAL_LENGTH_LIMIT_UTF8 = 1023; + // Name of the dataverse the metadata lives in. public static final DataverseName METADATA_DATAVERSE_NAME = DataverseName.createBuiltinDataverseName("Metadata"); // Name of the node group where metadata is stored on.