This is an automated email from the ASF dual-hosted git repository. alsuliman pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/asterixdb.git
The following commit(s) were added to refs/heads/master by this push: new 3869f2f913 [ASTERIXDB-3259][MTD] Implement database name resolution 3869f2f913 is described below commit 3869f2f913b1d940f578229b071573f996a4c6b2 Author: Ali Alsuliman <ali.al.solai...@gmail.com> AuthorDate: Thu Oct 12 00:00:32 2023 -0700 [ASTERIXDB-3259][MTD] Implement database name resolution - user model changes: no - storage format changes: no - interface changes: yes Details: Currently, qualification to database objects are resolved as DataverseName only. That is a multipart identifier is resolved as pure DataverseName only and the database name is defaulted to 'System'/'Default'. This patch is to resolve qualification to database objects as database_name + dataverse_name + database_object. This resolution is only applicable when database is used. That is when cloud deployment is used. Change-Id: Ic3f1d7b2019fcf62e5dcbce8c05a78d18cc0a710 Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/17861 Reviewed-by: Murtadha Hubail <mhub...@apache.org> Integration-Tests: Jenkins <jenk...@fulliautomatix.ics.uci.edu> Tested-by: Ali Alsuliman <ali.al.solai...@gmail.com> --- .../asterix/app/cc/CcApplicationContext.java | 9 ++--- .../apache/asterix/app/nc/NCAppRuntimeContext.java | 11 +++--- .../asterix/app/translator/QueryTranslator.java | 28 ++++++++++++-- .../asterix/hyracks/bootstrap/CCApplication.java | 20 +++++++--- .../asterix/hyracks/bootstrap/NCApplication.java | 19 ++++++--- .../test/cloud_storage/CloudStorageTest.java | 18 ++++++++- .../apache/asterix/test/common/TestExecutor.java | 45 ++++++++++++++++++---- .../request-dataverse.1.ddl.sqlpp | 2 + .../cloud_storage/special-chars/test.000.ddl.sqlpp | 2 + .../cloud_storage/special-chars/test.999.ddl.sqlpp | 1 + .../index_1/index_1.1.ddl.sqlpp | 2 + .../resolution_1/resolution_1.1.ddl.sqlpp | 2 + .../multipart-dataverse/udf_1/udf_1.1.ddl.sqlpp | 2 + .../src/test/resources/runtimets/sqlpp_queries.xml | 2 + .../asterix/cloud/AbstractCloudIOManager.java | 13 +++++-- .../apache/asterix/cloud/CloudManagerProvider.java | 9 +++-- .../apache/asterix/cloud/EagerCloudIOManager.java | 6 ++- .../apache/asterix/cloud/LazyCloudIOManager.java | 6 ++- .../asterix/common/api/INamespaceResolver.java | 1 + .../asterix/common/config/CompilerProperties.java | 13 ++++++- .../asterix/common/exceptions/ErrorCode.java | 2 + .../common/metadata/DatasetFullyQualifiedName.java | 3 +- .../asterix/common/metadata/MetadataConstants.java | 1 + .../asterix/common/metadata/MetadataUtil.java | 5 +++ .../common/metadata/NamespacePathResolver.java | 24 ++++++++++-- .../asterix/common/metadata/NamespaceResolver.java | 42 ++++++++++++++++++-- .../common/storage/DatasetCopyIdentifier.java | 21 +++++----- .../asterix/common/storage/ResourceReference.java | 17 +++++++- .../src/main/resources/asx_errormsg/en.properties | 2 + .../ioopcallbacks/LSMIOOperationCallbackTest.java | 11 ++++-- .../asterix/lang/common/base/IQueryRewriter.java | 3 +- .../lang/sqlpp/rewrites/SqlppQueryRewriter.java | 29 ++++++++++---- .../visitor/VariableCheckAndRewriteVisitor.java | 7 ++-- .../org/apache/asterix/metadata/MetadataNode.java | 23 ++++++++++- .../apache/asterix/metadata/utils/DatasetUtil.java | 5 +++ 35 files changed, 327 insertions(+), 79 deletions(-) diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/cc/CcApplicationContext.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/cc/CcApplicationContext.java index 24b4856ffe..6ea7aebf83 100644 --- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/cc/CcApplicationContext.java +++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/cc/CcApplicationContext.java @@ -57,7 +57,6 @@ import org.apache.asterix.common.dataflow.IDataPartitioningProvider; import org.apache.asterix.common.external.IAdapterFactoryService; import org.apache.asterix.common.metadata.IMetadataBootstrap; import org.apache.asterix.common.metadata.IMetadataLockUtil; -import org.apache.asterix.common.metadata.NamespacePathResolver; import org.apache.asterix.common.replication.INcLifecycleCoordinator; import org.apache.asterix.common.storage.ICompressionManager; import org.apache.asterix.common.transactions.IResourceIdManager; @@ -126,7 +125,7 @@ public class CcApplicationContext implements ICcApplicationContext { private final IDataPartitioningProvider dataPartitioningProvider; private final IGlobalTxManager globalTxManager; private final IOManager ioManager; - private final NamespacePathResolver namespacePathResolver; + private final INamespacePathResolver namespacePathResolver; private final INamespaceResolver namespaceResolver; public CcApplicationContext(ICCServiceContext ccServiceCtx, HyracksConnection hcc, @@ -136,8 +135,8 @@ public class CcApplicationContext implements ICcApplicationContext { IMetadataLockUtil mdLockUtil, IReceptionistFactory receptionistFactory, IConfigValidatorFactory configValidatorFactory, Object extensionManager, IAdapterFactoryService adapterFactoryService, IGlobalTxManager globalTxManager, IOManager ioManager, - CloudProperties cloudProperties, INamespaceResolver namespaceResolver) - throws AlgebricksException, IOException { + CloudProperties cloudProperties, INamespaceResolver namespaceResolver, + INamespacePathResolver namespacePathResolver) throws AlgebricksException, IOException { this.ccServiceCtx = ccServiceCtx; this.hcc = hcc; this.activeLifeCycleListener = activeLifeCycleListener; @@ -173,7 +172,7 @@ public class CcApplicationContext implements ICcApplicationContext { requestTracker = new RequestTracker(this); configValidator = configValidatorFactory.create(); this.adapterFactoryService = adapterFactoryService; - this.namespacePathResolver = new NamespacePathResolver(isCloudDeployment()); + this.namespacePathResolver = namespacePathResolver; this.namespaceResolver = namespaceResolver; this.globalTxManager = globalTxManager; this.ioManager = ioManager; diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/nc/NCAppRuntimeContext.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/nc/NCAppRuntimeContext.java index ab6a62ac13..a439fe57bf 100644 --- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/nc/NCAppRuntimeContext.java +++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/nc/NCAppRuntimeContext.java @@ -61,7 +61,6 @@ import org.apache.asterix.common.context.DiskWriteRateLimiterProvider; import org.apache.asterix.common.context.GlobalVirtualBufferCache; import org.apache.asterix.common.context.IStorageComponentProvider; import org.apache.asterix.common.library.ILibraryManager; -import org.apache.asterix.common.metadata.NamespacePathResolver; import org.apache.asterix.common.replication.IReplicationChannel; import org.apache.asterix.common.replication.IReplicationManager; import org.apache.asterix.common.replication.IReplicationStrategyFactory; @@ -172,11 +171,12 @@ public class NCAppRuntimeContext implements INcApplicationContext { private IDiskWriteRateLimiterProvider diskWriteRateLimiterProvider; private final CloudProperties cloudProperties; private IPartitionBootstrapper partitionBootstrapper; - private final NamespacePathResolver namespacePathResolver; + private final INamespacePathResolver namespacePathResolver; private final INamespaceResolver namespaceResolver; public NCAppRuntimeContext(INCServiceContext ncServiceContext, NCExtensionManager extensionManager, - IPropertiesFactory propertiesFactory, INamespaceResolver namespaceResolver) { + IPropertiesFactory propertiesFactory, INamespaceResolver namespaceResolver, + INamespacePathResolver namespacePathResolver) { this.ncServiceContext = ncServiceContext; compilerProperties = propertiesFactory.newCompilerProperties(); externalProperties = propertiesFactory.newExternalProperties(); @@ -195,7 +195,7 @@ public class NCAppRuntimeContext implements INcApplicationContext { .createResourceIdFactory(); persistedResourceRegistry = ncServiceContext.getPersistedResourceRegistry(); cacheManager = new CacheManager(); - namespacePathResolver = new NamespacePathResolver(isCloudDeployment()); + this.namespacePathResolver = namespacePathResolver; this.namespaceResolver = namespaceResolver; } @@ -205,7 +205,8 @@ public class NCAppRuntimeContext implements INcApplicationContext { boolean initialRun) throws IOException { ioManager = getServiceContext().getIoManager(); if (isCloudDeployment()) { - persistenceIOManager = CloudManagerProvider.createIOManager(cloudProperties, ioManager); + persistenceIOManager = + CloudManagerProvider.createIOManager(cloudProperties, ioManager, namespacePathResolver); partitionBootstrapper = CloudManagerProvider.getCloudPartitionBootstrapper(persistenceIOManager); } else { persistenceIOManager = ioManager; diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/translator/QueryTranslator.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/translator/QueryTranslator.java index 4b19200102..f404ca5f6a 100644 --- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/translator/QueryTranslator.java +++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/translator/QueryTranslator.java @@ -663,8 +663,7 @@ public class QueryTranslator extends AbstractLangTranslator implements IStatemen MetadataManager.INSTANCE.commitTransaction(mdTxnCtx); return false; } else { - //TODO(DB): change - throw new CompilationException(ErrorCode.DATAVERSE_EXISTS, stmtCreateDatabase.getSourceLocation(), + throw new CompilationException(ErrorCode.DATABASE_EXISTS, stmtCreateDatabase.getSourceLocation(), databaseName); } } @@ -703,6 +702,12 @@ public class QueryTranslator extends AbstractLangTranslator implements IStatemen try { DataverseName dvName = stmtCreateDataverse.getDataverseName(); String dbName = stmtCreateDataverse.getDatabaseName(); + Database db = MetadataManager.INSTANCE.getDatabase(mdTxnCtx, dbName); + if (db == null) { + throw new CompilationException(ErrorCode.UNKNOWN_DATABASE, stmtCreateDataverse.getSourceLocation(), + dbName); + } + Dataverse dv = MetadataManager.INSTANCE.getDataverse(metadataProvider.getMetadataTxnContext(), dbName, dvName); if (dv != null) { @@ -872,6 +877,8 @@ public class QueryTranslator extends AbstractLangTranslator implements IStatemen DatasetFormatInfo datasetFormatInfo = dd.getDatasetFormatInfo(storageProperties.getStorageFormat(), storageProperties.getColumnMaxTupleCount(), storageProperties.getColumnFreeSpaceTolerance()); try { + //TODO(DB): also check for database existence? + // Check if the dataverse exists Dataverse dv = MetadataManager.INSTANCE.getDataverse(mdTxnCtx, databaseName, dataverseName); if (dv == null) { @@ -2137,6 +2144,18 @@ public class QueryTranslator extends AbstractLangTranslator implements IStatemen List<FeedEventsListener> feedsToStop = new ArrayList<>(); List<JobSpecification> jobsToExecute = new ArrayList<>(); try { + Database db = MetadataManager.INSTANCE.getDatabase(mdTxnCtx, databaseName); + if (db == null) { + if (stmtDropDataverse.getIfExists()) { + if (warningCollector.shouldWarn()) { + warningCollector.warn(Warning.of(sourceLoc, ErrorCode.UNKNOWN_DATABASE, databaseName)); + } + MetadataManager.INSTANCE.commitTransaction(mdTxnCtx); + return false; + } else { + throw new CompilationException(ErrorCode.UNKNOWN_DATABASE, sourceLoc, databaseName); + } + } Dataverse dv = MetadataManager.INSTANCE.getDataverse(mdTxnCtx, databaseName, dataverseName); if (dv == null) { if (stmtDropDataverse.getIfExists()) { @@ -2338,6 +2357,8 @@ public class QueryTranslator extends AbstractLangTranslator implements IStatemen List<JobSpecification> jobsToExecute = new ArrayList<>(); Dataset ds = null; try { + //TODO(DB): also check for database existence? + // Check if the dataverse exists Dataverse dv = MetadataManager.INSTANCE.getDataverse(mdTxnCtx.getValue(), databaseName, dataverseName); if (dv == null) { @@ -2896,7 +2917,8 @@ public class QueryTranslator extends AbstractLangTranslator implements IStatemen ViewDecl viewDecl = new ViewDecl(viewQualifiedName, cvs.getViewBodyExpression()); viewDecl.setSourceLocation(sourceLoc); IQueryRewriter queryRewriter = rewriterFactory.createQueryRewriter(); - Query wrappedQuery = queryRewriter.createViewAccessorQuery(viewDecl); + Query wrappedQuery = + queryRewriter.createViewAccessorQuery(viewDecl, metadataProvider.getNamespaceResolver()); metadataProvider.setDefaultNamespace(ns); LangRewritingContext langRewritingContext = createLangRewritingContext(metadataProvider, declaredFunctions, Collections.singletonList(viewDecl), warningCollector, wrappedQuery.getVarCounter()); diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/hyracks/bootstrap/CCApplication.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/hyracks/bootstrap/CCApplication.java index de3cb82379..c93a23b50d 100644 --- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/hyracks/bootstrap/CCApplication.java +++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/hyracks/bootstrap/CCApplication.java @@ -64,6 +64,7 @@ import org.apache.asterix.app.result.JobResultCallback; import org.apache.asterix.cloud.CloudManagerProvider; import org.apache.asterix.common.api.AsterixThreadFactory; import org.apache.asterix.common.api.IConfigValidatorFactory; +import org.apache.asterix.common.api.INamespacePathResolver; import org.apache.asterix.common.api.INamespaceResolver; import org.apache.asterix.common.api.INodeJobTracker; import org.apache.asterix.common.api.IReceptionistFactory; @@ -71,6 +72,7 @@ import org.apache.asterix.common.cluster.IGlobalRecoveryManager; import org.apache.asterix.common.cluster.IGlobalTxManager; import org.apache.asterix.common.config.AsterixExtension; import org.apache.asterix.common.config.CloudProperties; +import org.apache.asterix.common.config.CompilerProperties; import org.apache.asterix.common.config.ExtensionProperties; import org.apache.asterix.common.config.ExternalProperties; import org.apache.asterix.common.config.GlobalConfig; @@ -82,6 +84,7 @@ import org.apache.asterix.common.dataflow.ICcApplicationContext; import org.apache.asterix.common.external.IAdapterFactoryService; import org.apache.asterix.common.library.ILibraryManager; import org.apache.asterix.common.metadata.IMetadataLockUtil; +import org.apache.asterix.common.metadata.NamespacePathResolver; import org.apache.asterix.common.metadata.NamespaceResolver; import org.apache.asterix.common.replication.INcLifecycleCoordinator; import org.apache.asterix.common.utils.Servlets; @@ -167,8 +170,12 @@ public class CCApplication extends BaseCCApplication { new ReplicationProperties(PropertiesAccessor.getInstance(ccServiceCtx.getAppConfig())); INcLifecycleCoordinator lifecycleCoordinator = createNcLifeCycleCoordinator(repProp.isReplicationEnabled()); componentProvider = new StorageComponentProvider(); + boolean isDbResolutionEnabled = + ccServiceCtx.getAppConfig().getBoolean(CompilerProperties.Option.COMPILER_ENABLE_DB_RESOLUTION); boolean cloudDeployment = ccServiceCtx.getAppConfig().getBoolean(CLOUD_DEPLOYMENT); - INamespaceResolver namespaceResolver = new NamespaceResolver(cloudDeployment); + boolean useDatabaseResolution = cloudDeployment && isDbResolutionEnabled; + INamespaceResolver namespaceResolver = new NamespaceResolver(useDatabaseResolution); + INamespacePathResolver namespacePathResolver = new NamespacePathResolver(useDatabaseResolution); ccExtensionManager = new CCExtensionManager(new ArrayList<>(getExtensions()), namespaceResolver); IGlobalRecoveryManager globalRecoveryManager = createGlobalRecoveryManager(); final CCConfig ccConfig = controllerService.getCCConfig(); @@ -179,12 +186,13 @@ public class CCApplication extends BaseCCApplication { CloudProperties cloudProperties = null; if (cloudDeployment) { cloudProperties = new CloudProperties(PropertiesAccessor.getInstance(ccServiceCtx.getAppConfig())); - ioManager = (IOManager) CloudManagerProvider.createIOManager(cloudProperties, ioManager); + ioManager = + (IOManager) CloudManagerProvider.createIOManager(cloudProperties, ioManager, namespacePathResolver); } IGlobalTxManager globalTxManager = createGlobalTxManager(ioManager); appCtx = createApplicationContext(null, globalRecoveryManager, lifecycleCoordinator, Receptionist::new, ConfigValidator::new, ccExtensionManager, new AdapterFactoryService(), globalTxManager, ioManager, - cloudProperties, namespaceResolver); + cloudProperties, namespaceResolver, namespacePathResolver); if (System.getProperty("java.rmi.server.hostname") == null) { System.setProperty("java.rmi.server.hostname", ccConfig.getClusterPublicAddress()); } @@ -233,11 +241,13 @@ public class CCApplication extends BaseCCApplication { IReceptionistFactory receptionistFactory, IConfigValidatorFactory configValidatorFactory, CCExtensionManager ccExtensionManager, IAdapterFactoryService adapterFactoryService, IGlobalTxManager globalTxManager, IOManager ioManager, CloudProperties cloudProperties, - INamespaceResolver namespaceResolver) throws AlgebricksException, IOException { + INamespaceResolver namespaceResolver, INamespacePathResolver namespacePathResolver) + throws AlgebricksException, IOException { return new CcApplicationContext(ccServiceCtx, hcc, () -> MetadataManager.INSTANCE, globalRecoveryManager, lifecycleCoordinator, new ActiveNotificationHandler(), componentProvider, new MetadataLockManager(), createMetadataLockUtil(), receptionistFactory, configValidatorFactory, ccExtensionManager, - adapterFactoryService, globalTxManager, ioManager, cloudProperties, namespaceResolver); + adapterFactoryService, globalTxManager, ioManager, cloudProperties, namespaceResolver, + namespacePathResolver); } protected IGlobalRecoveryManager createGlobalRecoveryManager() throws Exception { diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/hyracks/bootstrap/NCApplication.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/hyracks/bootstrap/NCApplication.java index eea87d853f..4acc0396d3 100644 --- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/hyracks/bootstrap/NCApplication.java +++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/hyracks/bootstrap/NCApplication.java @@ -55,11 +55,13 @@ import org.apache.asterix.app.nc.RecoveryManager; import org.apache.asterix.app.replication.message.RegistrationTasksRequestMessage; import org.apache.asterix.common.api.AsterixThreadFactory; import org.apache.asterix.common.api.IConfigValidatorFactory; +import org.apache.asterix.common.api.INamespacePathResolver; import org.apache.asterix.common.api.INamespaceResolver; import org.apache.asterix.common.api.INcApplicationContext; import org.apache.asterix.common.api.IPropertiesFactory; import org.apache.asterix.common.api.IReceptionistFactory; import org.apache.asterix.common.config.AsterixExtension; +import org.apache.asterix.common.config.CompilerProperties; import org.apache.asterix.common.config.ExtensionProperties; import org.apache.asterix.common.config.ExternalProperties; import org.apache.asterix.common.config.GlobalConfig; @@ -70,6 +72,7 @@ import org.apache.asterix.common.config.PropertiesAccessor; import org.apache.asterix.common.config.PropertiesFactory; import org.apache.asterix.common.config.StorageProperties; import org.apache.asterix.common.exceptions.AsterixException; +import org.apache.asterix.common.metadata.NamespacePathResolver; import org.apache.asterix.common.metadata.NamespaceResolver; import org.apache.asterix.common.replication.IReplicationStrategyFactory; import org.apache.asterix.common.replication.ReplicationStrategyFactory; @@ -157,12 +160,16 @@ public class NCApplication extends BaseNCApplication { } MetadataBuiltinFunctions.init(); + boolean isDbResolutionEnabled = + ncServiceCtx.getAppConfig().getBoolean(CompilerProperties.Option.COMPILER_ENABLE_DB_RESOLUTION); boolean cloudDeployment = ncServiceCtx.getAppConfig().getBoolean(CLOUD_DEPLOYMENT); - NamespaceResolver namespaceResolver = new NamespaceResolver(cloudDeployment); + boolean useDatabaseResolution = cloudDeployment && isDbResolutionEnabled; + NamespaceResolver namespaceResolver = new NamespaceResolver(useDatabaseResolution); + NamespacePathResolver namespacePathResolver = new NamespacePathResolver(useDatabaseResolution); ncExtensionManager = new NCExtensionManager(new ArrayList<>(getExtensions()), cloudDeployment, namespaceResolver); - runtimeContext = - createNCApplicationContext(ncServiceCtx, ncExtensionManager, getPropertiesFactory(), namespaceResolver); + runtimeContext = createNCApplicationContext(ncServiceCtx, ncExtensionManager, getPropertiesFactory(), + namespaceResolver, namespacePathResolver); MetadataProperties metadataProperties = runtimeContext.getMetadataProperties(); if (!metadataProperties.getNodeNames().contains(this.ncServiceCtx.getNodeId())) { if (LOGGER.isInfoEnabled()) { @@ -196,8 +203,10 @@ public class NCApplication extends BaseNCApplication { protected INcApplicationContext createNCApplicationContext(INCServiceContext ncServiceCtx, NCExtensionManager ncExtensionManager, IPropertiesFactory propertiesFactory, - INamespaceResolver namespaceResolver) throws IOException, AsterixException { - return new NCAppRuntimeContext(ncServiceCtx, ncExtensionManager, propertiesFactory, namespaceResolver); + INamespaceResolver namespaceResolver, INamespacePathResolver namespacePathResolver) + throws IOException, AsterixException { + return new NCAppRuntimeContext(ncServiceCtx, ncExtensionManager, propertiesFactory, namespaceResolver, + namespacePathResolver); } protected IRecoveryManagerFactory getRecoveryManagerFactory() { diff --git a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/cloud_storage/CloudStorageTest.java b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/cloud_storage/CloudStorageTest.java index a45a1bfa01..a23da8c0e8 100644 --- a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/cloud_storage/CloudStorageTest.java +++ b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/cloud_storage/CloudStorageTest.java @@ -19,13 +19,19 @@ package org.apache.asterix.test.cloud_storage; import java.util.Collection; +import java.util.List; import org.apache.asterix.api.common.LocalCloudUtil; import org.apache.asterix.common.config.GlobalConfig; import org.apache.asterix.test.common.TestExecutor; import org.apache.asterix.test.runtime.LangExecutionUtil; import org.apache.asterix.testframework.context.TestCaseContext; +import org.apache.asterix.testframework.xml.Description; +import org.apache.asterix.testframework.xml.TestCase; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.junit.AfterClass; +import org.junit.Assume; import org.junit.BeforeClass; import org.junit.FixMethodOrder; import org.junit.Test; @@ -41,11 +47,14 @@ import org.junit.runners.Parameterized.Parameters; @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class CloudStorageTest { - protected TestCaseContext tcCtx; + private static final Logger LOGGER = LogManager.getLogger(); + + private final TestCaseContext tcCtx; private static final String SUITE_TESTS = "testsuite_cloud_storage.xml"; private static final String ONLY_TESTS = "testsuite_cloud_storage_only.xml"; private static final String CONFIG_FILE_NAME = "src/test/resources/cc-cloud-storage.conf"; private static final String DELTA_RESULT_PATH = "results_cloud"; + private static final String EXCLUDED_TESTS = "MP"; public CloudStorageTest(TestCaseContext tcCtx) { this.tcCtx = tcCtx; @@ -55,6 +64,7 @@ public class CloudStorageTest { public static void setUp() throws Exception { LocalCloudUtil.startS3CloudEnvironment(true); TestExecutor testExecutor = new TestExecutor(DELTA_RESULT_PATH); + testExecutor.stripSubstring = "//DB:"; LangExecutionUtil.setUp(CONFIG_FILE_NAME, testExecutor); System.setProperty(GlobalConfig.CONFIG_FILE_PROPERTY, CONFIG_FILE_NAME); } @@ -71,6 +81,12 @@ public class CloudStorageTest { @Test public void test() throws Exception { + List<TestCase.CompilationUnit> cu = tcCtx.getTestCase().getCompilationUnit(); + Assume.assumeTrue(cu.size() > 1 || !EXCLUDED_TESTS.equals(getText(cu.get(0).getDescription()))); LangExecutionUtil.test(tcCtx); } + + private static String getText(Description description) { + return description == null ? "" : description.getValue(); + } } diff --git a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/TestExecutor.java b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/TestExecutor.java index 28608131f0..9498979a47 100644 --- a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/TestExecutor.java +++ b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/TestExecutor.java @@ -276,6 +276,7 @@ public class TestExecutor { protected int loopIteration; protected String deltaPath = null; + public String stripSubstring = null; public TestExecutor() { this(Collections.singletonList( @@ -861,6 +862,9 @@ public class TestExecutor { } str = applyExternalDatasetSubstitution(str, placeholders); + if (stripSubstring != null && !stripSubstring.isBlank()) { + str = strip(str, stripSubstring); + } HttpUriRequest method = jsonEncoded ? constructPostMethodJson(str, uri, "statement", params) : constructPostMethodUrl(str, uri, "statement", params); @@ -2325,6 +2329,10 @@ public class TestExecutor { return substitute; } + protected static String strip(String str, String target) { + return str.replace(target, ""); + } + protected String applyExternalDatasetSubstitution(String str, List<Placeholder> placeholders) { // This replaces the full template of parameters depending on the adapter type for (Placeholder placeholder : placeholders) { @@ -2589,12 +2597,12 @@ public class TestExecutor { public void cleanup(String testCase, List<String> badtestcases) throws Exception { try { - List<DataverseName> toBeDropped = new ArrayList<>(); + List<Pair<String, DataverseName>> toBeDropped = new ArrayList<>(); listUserDefinedDataverses(toBeDropped); if (!toBeDropped.isEmpty()) { badtestcases.add(testCase); LOGGER.info("Last test left some garbage. Dropping dataverses: " + StringUtils.join(toBeDropped, ',')); - for (DataverseName dv : toBeDropped) { + for (Pair<String, DataverseName> dv : toBeDropped) { dropDataverse(dv); } } @@ -2604,8 +2612,9 @@ public class TestExecutor { } } - protected void listUserDefinedDataverses(List<DataverseName> outDataverses) throws Exception { - String query = "select dv.DataverseName from Metadata.`Dataverse` as dv order by dv.DataverseName"; + protected void listUserDefinedDataverses(List<Pair<String, DataverseName>> outDataverses) throws Exception { + String query = + "select dv.DatabaseName, dv.DataverseName from Metadata.`Dataverse` as dv order by dv.DataverseName"; InputStream resultStream = executeQueryService(query, getEndpoint(Servlets.QUERY_SERVICE), OutputFormat.CLEAN_JSON); JsonNode result = extractResult(IOUtils.toString(resultStream, UTF_8)); @@ -2615,16 +2624,26 @@ public class TestExecutor { DataverseName dvName = DataverseName.createFromCanonicalForm(json.get("DataverseName").asText()); if (!dvName.equals(MetadataConstants.METADATA_DATAVERSE_NAME) && !dvName.equals(MetadataConstants.DEFAULT_DATAVERSE_NAME)) { - outDataverses.add(dvName); + JsonNode databaseName = json.get("DatabaseName"); + String dbName = null; + if (databaseName != null && !databaseName.isNull() && !databaseName.isMissingNode()) { + dbName = databaseName.asText(); + } + outDataverses.add(new Pair<>(dbName, dvName)); } } } } - protected void dropDataverse(DataverseName dv) throws Exception { + protected void dropDataverse(Pair<String, DataverseName> dv) throws Exception { StringBuilder dropStatement = new StringBuilder(); dropStatement.append("drop dataverse "); - SqlppStatementUtil.encloseDataverseName(dropStatement, dv); + if (dv.first == null) { + SqlppStatementUtil.encloseDataverseName(dropStatement, dv.second); + } else { + SqlppStatementUtil.enclose(dropStatement, dv.first).append(SqlppStatementUtil.DOT); + SqlppStatementUtil.encloseDataverseName(dropStatement, dv.second); + } dropStatement.append(";\n"); InputStream resultStream = executeQueryService(dropStatement.toString(), getEndpoint(Servlets.QUERY_SERVICE), OutputFormat.CLEAN_JSON, UTF_8); @@ -2652,6 +2671,18 @@ public class TestExecutor { } } + protected boolean metadataHasDatabase() throws Exception { + String query = "select d.DatabaseName from Metadata.`Dataverse` d limit 1;"; + InputStream resultStream = executeQueryService(query, getEndpoint(Servlets.QUERY_SERVICE), + TestCaseContext.OutputFormat.CLEAN_JSON); + JsonNode result = extractResult(IOUtils.toString(resultStream, UTF_8)); + if (result.size() > 1) { + JsonNode json = result.get(0); + return json != null && !json.get("DatabaseName").isNull() && !json.get("DatabaseName").isMissingNode(); + } + return false; + } + private JsonNode extractResult(String jsonString) throws IOException { try { final JsonNode result = RESULT_NODE_READER.<ObjectNode> readValue(jsonString).get("results"); diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-dataverse/request-dataverse.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-dataverse/request-dataverse.1.ddl.sqlpp index cb28d2fb26..33130f2aca 100644 --- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-dataverse/request-dataverse.1.ddl.sqlpp +++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/api/request-dataverse/request-dataverse.1.ddl.sqlpp @@ -20,6 +20,8 @@ drop dataverse test1 if exists; create dataverse test1; +//DB: drop database test2 if exists; +//DB: create database test2; drop dataverse test2.test3 if exists; create dataverse test2.test3; diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cloud_storage/special-chars/test.000.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cloud_storage/special-chars/test.000.ddl.sqlpp index 18a98e38c2..e7c276902f 100644 --- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cloud_storage/special-chars/test.000.ddl.sqlpp +++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cloud_storage/special-chars/test.000.ddl.sqlpp @@ -17,6 +17,8 @@ * under the License. */ +DROP DATABASE `part1` IF EXISTS; +CREATE DATABASE `part1`; DROP DATAVERSE `part1`.`p%r t2` IF EXISTS; CREATE DATAVERSE `part1`.`p%r t2`; diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cloud_storage/special-chars/test.999.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cloud_storage/special-chars/test.999.ddl.sqlpp index 3580ae92cc..923c81b9f0 100644 --- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cloud_storage/special-chars/test.999.ddl.sqlpp +++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cloud_storage/special-chars/test.999.ddl.sqlpp @@ -18,3 +18,4 @@ */ DROP DATAVERSE `part1`.`p%r t2` IF EXISTS; +DROP DATABASE `part1`; \ No newline at end of file diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/multipart-dataverse/index_1/index_1.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/multipart-dataverse/index_1/index_1.1.ddl.sqlpp index 910b6df187..e657e61f99 100644 --- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/multipart-dataverse/index_1/index_1.1.ddl.sqlpp +++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/multipart-dataverse/index_1/index_1.1.ddl.sqlpp @@ -20,6 +20,8 @@ * Description: index in a dataverse with a multipart name */ +//DB: drop database x if exists; +//DB: create database x; drop dataverse x.y if exists; create dataverse x.y; diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/multipart-dataverse/resolution_1/resolution_1.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/multipart-dataverse/resolution_1/resolution_1.1.ddl.sqlpp index 1089bc3fc2..e6c06f9611 100644 --- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/multipart-dataverse/resolution_1/resolution_1.1.ddl.sqlpp +++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/multipart-dataverse/resolution_1/resolution_1.1.ddl.sqlpp @@ -20,6 +20,8 @@ * Description: name resolution for a dataverse with a multipart name */ +//DB: drop database sales if exists; +//DB: create database sales; drop dataverse sales.east if exists; create dataverse sales.east; diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/multipart-dataverse/udf_1/udf_1.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/multipart-dataverse/udf_1/udf_1.1.ddl.sqlpp index 6b01a1123b..fea7c0a4a7 100644 --- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/multipart-dataverse/udf_1/udf_1.1.ddl.sqlpp +++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/multipart-dataverse/udf_1/udf_1.1.ddl.sqlpp @@ -20,6 +20,8 @@ * Description: user-defined function in a dataverse with a multipart name */ +//DB: drop database x if exists; +//DB: create database x; drop dataverse x.y if exists; create dataverse x.y; diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/sqlpp_queries.xml b/asterixdb/asterix-app/src/test/resources/runtimets/sqlpp_queries.xml index ffe81d62e9..0f537d7814 100644 --- a/asterixdb/asterix-app/src/test/resources/runtimets/sqlpp_queries.xml +++ b/asterixdb/asterix-app/src/test/resources/runtimets/sqlpp_queries.xml @@ -7352,11 +7352,13 @@ </test-case> <test-case FilePath="multipart-dataverse"> <compilation-unit name="special_chars_1"> + <description>MP</description> <output-dir compare="Text">special_chars_1</output-dir> </compilation-unit> </test-case> <test-case FilePath="multipart-dataverse"> <compilation-unit name="special_chars_2"> + <description>MP</description> <output-dir compare="Text">special_chars_2</output-dir> </compilation-unit> </test-case> diff --git a/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/AbstractCloudIOManager.java b/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/AbstractCloudIOManager.java index 317928060f..8c7cd8a4f1 100644 --- a/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/AbstractCloudIOManager.java +++ b/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/AbstractCloudIOManager.java @@ -35,8 +35,10 @@ import org.apache.asterix.cloud.bulk.NoOpDeleteBulkCallBack; import org.apache.asterix.cloud.clients.CloudClientProvider; import org.apache.asterix.cloud.clients.ICloudClient; import org.apache.asterix.cloud.util.CloudFileUtil; +import org.apache.asterix.common.api.INamespacePathResolver; import org.apache.asterix.common.cloud.IPartitionBootstrapper; import org.apache.asterix.common.config.CloudProperties; +import org.apache.asterix.common.metadata.MetadataConstants; import org.apache.asterix.common.transactions.IRecoveryManager; import org.apache.asterix.common.utils.StoragePathUtil; import org.apache.hyracks.api.exceptions.HyracksDataException; @@ -54,8 +56,8 @@ import com.fasterxml.jackson.databind.ObjectMapper; public abstract class AbstractCloudIOManager extends IOManager implements IPartitionBootstrapper { private static final Logger LOGGER = LogManager.getLogger(); - private static final String DATAVERSE_PATH = - FileUtil.joinPath(STORAGE_ROOT_DIR_NAME, PARTITION_DIR_PREFIX + METADATA_PARTITION, "Metadata"); + //TODO(DB): change + private final String metadataNamespacePath; protected final ICloudClient cloudClient; protected final WriteBufferProvider writeBufferProvider; protected final String bucket; @@ -63,9 +65,12 @@ public abstract class AbstractCloudIOManager extends IOManager implements IParti protected final List<FileReference> partitionPaths; protected final IOManager localIoManager; - public AbstractCloudIOManager(IOManager ioManager, CloudProperties cloudProperties) throws HyracksDataException { + public AbstractCloudIOManager(IOManager ioManager, CloudProperties cloudProperties, + INamespacePathResolver nsPathResolver) throws HyracksDataException { super(ioManager.getIODevices(), ioManager.getDeviceComputer(), ioManager.getIOParallelism(), ioManager.getQueueSize()); + this.metadataNamespacePath = FileUtil.joinPath(STORAGE_ROOT_DIR_NAME, PARTITION_DIR_PREFIX + METADATA_PARTITION, + nsPathResolver.resolve(MetadataConstants.METADATA_NAMESPACE)); this.bucket = cloudProperties.getStorageBucket(); cloudClient = CloudClientProvider.getClient(cloudProperties); int numOfThreads = getIODevices().size() * getIOParallelism(); @@ -83,7 +88,7 @@ public abstract class AbstractCloudIOManager extends IOManager implements IParti @Override public IRecoveryManager.SystemState getSystemStateOnMissingCheckpoint() { - if (cloudClient.listObjects(bucket, DATAVERSE_PATH, IoUtil.NO_OP_FILTER).isEmpty()) { + if (cloudClient.listObjects(bucket, metadataNamespacePath, IoUtil.NO_OP_FILTER).isEmpty()) { LOGGER.info("First time to initialize this cluster: systemState = PERMANENT_DATA_LOSS"); return IRecoveryManager.SystemState.PERMANENT_DATA_LOSS; } else { diff --git a/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/CloudManagerProvider.java b/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/CloudManagerProvider.java index 6ba31db4f1..f325f41065 100644 --- a/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/CloudManagerProvider.java +++ b/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/CloudManagerProvider.java @@ -18,6 +18,7 @@ */ package org.apache.asterix.cloud; +import org.apache.asterix.common.api.INamespacePathResolver; import org.apache.asterix.common.cloud.CloudCachePolicy; import org.apache.asterix.common.cloud.IPartitionBootstrapper; import org.apache.asterix.common.config.CloudProperties; @@ -29,14 +30,14 @@ public class CloudManagerProvider { private CloudManagerProvider() { } - public static IIOManager createIOManager(CloudProperties cloudProperties, IIOManager ioManager) - throws HyracksDataException { + public static IIOManager createIOManager(CloudProperties cloudProperties, IIOManager ioManager, + INamespacePathResolver nsPathResolver) throws HyracksDataException { IOManager localIoManager = (IOManager) ioManager; if (cloudProperties.getCloudCachePolicy() == CloudCachePolicy.LAZY) { - return new LazyCloudIOManager(localIoManager, cloudProperties); + return new LazyCloudIOManager(localIoManager, cloudProperties, nsPathResolver); } - return new EagerCloudIOManager(localIoManager, cloudProperties); + return new EagerCloudIOManager(localIoManager, cloudProperties, nsPathResolver); } public static IPartitionBootstrapper getCloudPartitionBootstrapper(IIOManager ioManager) { diff --git a/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/EagerCloudIOManager.java b/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/EagerCloudIOManager.java index b1f88cb083..d0b982c834 100644 --- a/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/EagerCloudIOManager.java +++ b/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/EagerCloudIOManager.java @@ -26,6 +26,7 @@ import java.util.Set; import java.util.stream.Collectors; import org.apache.asterix.cloud.clients.IParallelDownloader; +import org.apache.asterix.common.api.INamespacePathResolver; import org.apache.asterix.common.config.CloudProperties; import org.apache.hyracks.api.exceptions.HyracksDataException; import org.apache.hyracks.api.io.FileReference; @@ -44,8 +45,9 @@ import org.apache.logging.log4j.Logger; final class EagerCloudIOManager extends AbstractCloudIOManager { private static final Logger LOGGER = LogManager.getLogger(); - public EagerCloudIOManager(IOManager ioManager, CloudProperties cloudProperties) throws HyracksDataException { - super(ioManager, cloudProperties); + public EagerCloudIOManager(IOManager ioManager, CloudProperties cloudProperties, + INamespacePathResolver nsPathResolver) throws HyracksDataException { + super(ioManager, cloudProperties, nsPathResolver); } /* diff --git a/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/LazyCloudIOManager.java b/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/LazyCloudIOManager.java index 97a61733f0..6ecd201425 100644 --- a/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/LazyCloudIOManager.java +++ b/asterixdb/asterix-cloud/src/main/java/org/apache/asterix/cloud/LazyCloudIOManager.java @@ -39,6 +39,7 @@ import org.apache.asterix.cloud.lazy.accessor.ILazyAccessorReplacer; import org.apache.asterix.cloud.lazy.accessor.InitialCloudAccessor; import org.apache.asterix.cloud.lazy.accessor.LocalAccessor; import org.apache.asterix.cloud.lazy.accessor.ReplaceableCloudAccessor; +import org.apache.asterix.common.api.INamespacePathResolver; import org.apache.asterix.common.config.CloudProperties; import org.apache.asterix.common.utils.StoragePathUtil; import org.apache.hyracks.api.exceptions.HyracksDataException; @@ -60,8 +61,9 @@ final class LazyCloudIOManager extends AbstractCloudIOManager { private final ILazyAccessorReplacer replacer; private ILazyAccessor accessor; - public LazyCloudIOManager(IOManager ioManager, CloudProperties cloudProperties) throws HyracksDataException { - super(ioManager, cloudProperties); + public LazyCloudIOManager(IOManager ioManager, CloudProperties cloudProperties, + INamespacePathResolver nsPathResolver) throws HyracksDataException { + super(ioManager, cloudProperties, nsPathResolver); accessor = new InitialCloudAccessor(cloudClient, bucket, localIoManager); replacer = () -> { synchronized (this) { diff --git a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/api/INamespaceResolver.java b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/api/INamespaceResolver.java index 7f9bde614f..fb305095ee 100644 --- a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/api/INamespaceResolver.java +++ b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/api/INamespaceResolver.java @@ -31,4 +31,5 @@ public interface INamespaceResolver { Namespace resolve(String namespace) throws AsterixException; + boolean isUsingDatabase(); } diff --git a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/config/CompilerProperties.java b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/config/CompilerProperties.java index 01f9509663..85b80a6136 100644 --- a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/config/CompilerProperties.java +++ b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/config/CompilerProperties.java @@ -122,7 +122,9 @@ public class CompilerProperties extends AbstractProperties { COMPILER_COLUMN_FILTER( BOOLEAN, AlgebricksConfig.COLUMN_FILTER_DEFAULT, - "Enable/disable the use of column min/max filters"); + "Enable/disable the use of column min/max filters"), + //TODO(DB): remove after + COMPILER_ENABLE_DB_RESOLUTION(BOOLEAN, true, "Enable/disable the resolution of namespaces to database"); private final IOptionType type; private final Object defaultValue; @@ -156,7 +158,8 @@ public class CompilerProperties extends AbstractProperties { @Override public boolean hidden() { - return this == COMPILER_EXTERNALSCANMEMORY || this == COMPILER_CBOTEST; + return this == COMPILER_EXTERNALSCANMEMORY || this == COMPILER_CBOTEST + || this == COMPILER_ENABLE_DB_RESOLUTION; } } @@ -204,6 +207,8 @@ public class CompilerProperties extends AbstractProperties { public static final String COMPILER_COLUMN_FILTER_KEY = Option.COMPILER_COLUMN_FILTER.ini(); + public static final String COMPILER_ENABLE_DB_RESOLUTION_KEY = Option.COMPILER_ENABLE_DB_RESOLUTION.ini(); + public static final int COMPILER_PARALLELISM_AS_STORAGE = 0; public CompilerProperties(PropertiesAccessor accessor) { @@ -306,4 +311,8 @@ public class CompilerProperties extends AbstractProperties { public boolean isColumnFilter() { return accessor.getBoolean(Option.COMPILER_COLUMN_FILTER); } + + public boolean isDbResolutionEnabled() { + return accessor.getBoolean(Option.COMPILER_ENABLE_DB_RESOLUTION); + } } diff --git a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java index ff00aefb03..83418a4ecc 100644 --- a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java +++ b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java @@ -279,6 +279,8 @@ public enum ErrorCode implements IError { FAILED_TO_CALCULATE_COMPUTED_FIELDS(1182), FAILED_TO_EVALUATE_COMPUTED_FIELD(1183), ILLEGAL_DML_OPERATION(1184), + UNKNOWN_DATABASE(1185), + DATABASE_EXISTS(1186), // Feed errors DATAFLOW_ILLEGAL_STATE(3001), diff --git a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/metadata/DatasetFullyQualifiedName.java b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/metadata/DatasetFullyQualifiedName.java index f53a3a3a42..261cddc6f6 100644 --- a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/metadata/DatasetFullyQualifiedName.java +++ b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/metadata/DatasetFullyQualifiedName.java @@ -48,7 +48,8 @@ public class DatasetFullyQualifiedName implements Serializable { @Override public String toString() { - return dataverseName + "." + datasetName; + return (MetadataConstants.DEFAULT_DATABASE.equals(databaseName) ? "" : datasetName + ".") + dataverseName + "." + + datasetName; } @Override diff --git a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/metadata/MetadataConstants.java b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/metadata/MetadataConstants.java index 02cf6d6d36..044d920991 100644 --- a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/metadata/MetadataConstants.java +++ b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/metadata/MetadataConstants.java @@ -43,6 +43,7 @@ public class MetadataConstants { // Name of the pre-defined default dataverse public static final DataverseName DEFAULT_DATAVERSE_NAME = DataverseName.createBuiltinDataverseName("Default"); + public static final Namespace METADATA_NAMESPACE = new Namespace(SYSTEM_DATABASE, METADATA_DATAVERSE_NAME); public static final Namespace DEFAULT_NAMESPACE = new Namespace(DEFAULT_DATABASE, DEFAULT_DATAVERSE_NAME); // Name of the node group where metadata is stored on. diff --git a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/metadata/MetadataUtil.java b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/metadata/MetadataUtil.java index 06d12fa56b..539b8c4b43 100644 --- a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/metadata/MetadataUtil.java +++ b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/metadata/MetadataUtil.java @@ -46,6 +46,11 @@ public class MetadataUtil { return dataverseName + "." + objectName; } + public static String getFullyQualifiedDisplayName(String databaseName, DataverseName dataverseName, + String objectName) { + return databaseName + "." + dataverseName + "." + objectName; + } + public static String databaseFor(DataverseName dataverse) { if (dataverse == null) { return null; diff --git a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/metadata/NamespacePathResolver.java b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/metadata/NamespacePathResolver.java index 26d1ce06f9..910c3ef68f 100644 --- a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/metadata/NamespacePathResolver.java +++ b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/metadata/NamespacePathResolver.java @@ -19,6 +19,8 @@ package org.apache.asterix.common.metadata; +import java.io.File; + import org.apache.asterix.common.api.INamespacePathResolver; import org.apache.asterix.common.utils.StoragePathUtil; @@ -27,16 +29,32 @@ public class NamespacePathResolver implements INamespacePathResolver { private final boolean usingDatabase; public NamespacePathResolver(boolean usingDatabase) { - this.usingDatabase = false; + this.usingDatabase = usingDatabase; } @Override public String resolve(Namespace namespace) { - return StoragePathUtil.prepareDataverseName(namespace.getDataverseName()); + DataverseName dataverseName = namespace.getDataverseName(); + if (usingDatabase) { + if (MetadataConstants.METADATA_DATAVERSE_NAME.equals(dataverseName)) { + return StoragePathUtil.prepareDataverseName(dataverseName); + } + return namespace.getDatabaseName() + File.separatorChar + + StoragePathUtil.prepareDataverseName(dataverseName); + } else { + return StoragePathUtil.prepareDataverseName(dataverseName); + } } @Override public String resolve(String databaseName, DataverseName dataverseName) { - return StoragePathUtil.prepareDataverseName(dataverseName); + if (usingDatabase) { + if (MetadataConstants.METADATA_DATAVERSE_NAME.equals(dataverseName)) { + return StoragePathUtil.prepareDataverseName(dataverseName); + } + return databaseName + File.separatorChar + StoragePathUtil.prepareDataverseName(dataverseName); + } else { + return StoragePathUtil.prepareDataverseName(dataverseName); + } } } diff --git a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/metadata/NamespaceResolver.java b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/metadata/NamespaceResolver.java index b18562e738..d1d813e84f 100644 --- a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/metadata/NamespaceResolver.java +++ b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/metadata/NamespaceResolver.java @@ -29,7 +29,7 @@ public class NamespaceResolver implements INamespaceResolver { private final boolean usingDatabase; public NamespaceResolver(boolean usingDatabase) { - this.usingDatabase = false; + this.usingDatabase = usingDatabase; } @Override @@ -42,13 +42,49 @@ public class NamespaceResolver implements INamespaceResolver { if (multiIdentifier == null) { return null; } - DataverseName dataverseName = DataverseName.create(multiIdentifier, fromIndex, toIndex); - return new Namespace(MetadataUtil.databaseFor(dataverseName), dataverseName); + if (usingDatabase) { + int partsNum = toIndex - fromIndex; + if (partsNum > 1) { + String databaseName = multiIdentifier.get(fromIndex); + return ofDatabase(databaseName, multiIdentifier, fromIndex + 1, toIndex); + } else { + return ofDataverse(multiIdentifier, fromIndex, toIndex); + } + } else { + return ofDataverse(multiIdentifier, fromIndex, toIndex); + } } @Override public Namespace resolve(String namespace) throws AsterixException { DataverseName dataverseName = DataverseName.createFromCanonicalForm(namespace); + if (usingDatabase) { + List<String> parts = dataverseName.getParts(); + if (parts.size() > 1) { + String databaseName = parts.get(0); + return ofDatabase(databaseName, parts, 1, parts.size()); + } else { + return new Namespace(MetadataUtil.databaseFor(dataverseName), dataverseName); + } + } else { + return new Namespace(MetadataUtil.databaseFor(dataverseName), dataverseName); + } + } + + @Override + public boolean isUsingDatabase() { + return usingDatabase; + } + + private static Namespace ofDatabase(String databaseName, List<String> multiIdentifier, int fromIndex, int toIndex) + throws AsterixException { + DataverseName dataverseName = DataverseName.create(multiIdentifier, fromIndex, toIndex); + return new Namespace(databaseName, dataverseName); + } + + private static Namespace ofDataverse(List<String> multiIdentifier, int fromIndex, int toIndex) + throws AsterixException { + DataverseName dataverseName = DataverseName.create(multiIdentifier, fromIndex, toIndex); return new Namespace(MetadataUtil.databaseFor(dataverseName), dataverseName); } } diff --git a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/storage/DatasetCopyIdentifier.java b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/storage/DatasetCopyIdentifier.java index 6fea755c9b..4533361cf9 100644 --- a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/storage/DatasetCopyIdentifier.java +++ b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/storage/DatasetCopyIdentifier.java @@ -25,19 +25,22 @@ import org.apache.asterix.common.metadata.DataverseName; public class DatasetCopyIdentifier implements Serializable { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 2L; + private final String database; private final DataverseName dataverse; private final String dataset; private final String rebalance; - private DatasetCopyIdentifier(DataverseName dataverse, String datasetName, String rebalance) { + private DatasetCopyIdentifier(String database, DataverseName dataverse, String datasetName, String rebalance) { + this.database = database; this.dataverse = dataverse; this.dataset = datasetName; this.rebalance = rebalance; } - public static DatasetCopyIdentifier of(DataverseName dataverse, String datasetName, String rebalance) { - return new DatasetCopyIdentifier(dataverse, datasetName, rebalance); + public static DatasetCopyIdentifier of(String database, DataverseName dataverse, String datasetName, + String rebalance) { + return new DatasetCopyIdentifier(database, dataverse, datasetName, rebalance); } public String getDataset() { @@ -57,13 +60,13 @@ public class DatasetCopyIdentifier implements Serializable { return false; } DatasetCopyIdentifier that = (DatasetCopyIdentifier) o; - return Objects.equals(dataverse, that.dataverse) && Objects.equals(dataset, that.dataset) - && Objects.equals(rebalance, that.rebalance); + return Objects.equals(database, that.database) && Objects.equals(dataverse, that.dataverse) + && Objects.equals(dataset, that.dataset) && Objects.equals(rebalance, that.rebalance); } @Override public int hashCode() { - return Objects.hash(dataverse, dataset, rebalance); + return Objects.hash(database, dataverse, dataset, rebalance); } public DataverseName getDataverse() { @@ -71,8 +74,8 @@ public class DatasetCopyIdentifier implements Serializable { } public boolean isMatch(ResourceReference resourceReference) { - return resourceReference.getDataverse().equals(dataverse) && resourceReference.getDataset().equals(dataset) - && resourceReference.getRebalance().equals(rebalance); + return resourceReference.getDatabase().equals(database) && resourceReference.getDataverse().equals(dataverse) + && resourceReference.getDataset().equals(dataset) && resourceReference.getRebalance().equals(rebalance); } @Override diff --git a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/storage/ResourceReference.java b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/storage/ResourceReference.java index 7065767cd5..a163ece942 100644 --- a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/storage/ResourceReference.java +++ b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/storage/ResourceReference.java @@ -27,6 +27,7 @@ import java.util.List; import org.apache.asterix.common.exceptions.AsterixException; import org.apache.asterix.common.metadata.DataverseName; +import org.apache.asterix.common.metadata.MetadataUtil; import org.apache.asterix.common.utils.StorageConstants; import org.apache.asterix.common.utils.StoragePathUtil; import org.apache.commons.lang3.ArrayUtils; @@ -40,6 +41,7 @@ public class ResourceReference { private static final Logger LOGGER = LogManager.getLogger(); protected final String root; protected final String partition; + protected final String database; protected final DataverseName dataverse; protected final String dataset; protected final String rebalance; @@ -68,12 +70,19 @@ public class ResourceReference { String probablyPartition = tokens[--offset]; if (dvParts.isEmpty()) { // root/partition/dataverse/dataset/rebalanceCount/index/fileName + // root/partition/database?/dataverse/dataset/rebalanceCount/index/fileName try { dataverse = DataverseName.createSinglePartName(dvPart); } catch (AsterixException e) { throw new IllegalArgumentException("unable to parse path: '" + path + "'!", e); } - partition = probablyPartition; + if (!probablyPartition.startsWith(StorageConstants.PARTITION_DIR_PREFIX)) { + database = probablyPartition; + partition = tokens[--offset]; + } else { + database = MetadataUtil.databaseFor(dataverse); + partition = probablyPartition; + } root = tokens[--offset]; } else if (probablyPartition.startsWith(StorageConstants.PARTITION_DIR_PREFIX)) { // root/partition/dataverse_p1/^dataverse_p2/.../^dataverse_pn/dataset/rebalanceCount/index/fileName @@ -84,6 +93,7 @@ public class ResourceReference { } catch (AsterixException e) { throw new IllegalArgumentException("unable to parse path: '" + path + "'!", e); } + database = MetadataUtil.databaseFor(dataverse); partition = probablyPartition; root = tokens[--offset]; } else if (dvPart.startsWith(StorageConstants.PARTITION_DIR_PREFIX)) { @@ -99,6 +109,7 @@ public class ResourceReference { } LOGGER.info("legacy dataverse starting with ^ found: '{}'; this is not supported for new dataverses", dataverse); + database = MetadataUtil.databaseFor(dataverse); partition = dvPart; root = probablyPartition; } else { @@ -119,6 +130,10 @@ public class ResourceReference { return partition; } + public String getDatabase() { + return database; + } + public DataverseName getDataverse() { return dataverse; } diff --git a/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties b/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties index 3f61b85359..ab77067ca0 100644 --- a/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties +++ b/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties @@ -281,6 +281,8 @@ 1182 = Failed to calculate computed fields: %1$s 1183 = Failed to evaluate computed field. File: '%1$s'. Computed Field Name: '%2$s'. Computed Field Type: '%3$s'. Computed Field Value: '%4$s'. Reason: '%5$s' 1184 = Compilation error: %1$s: %2$s dataset is not supported on datasets with meta records +1185 = Cannot find database with name %1$s +1186 = A database with this name %1$s already exists # Feed Errors 3001 = Illegal state. diff --git a/asterixdb/asterix-common/src/test/java/org/apache/asterix/test/ioopcallbacks/LSMIOOperationCallbackTest.java b/asterixdb/asterix-common/src/test/java/org/apache/asterix/test/ioopcallbacks/LSMIOOperationCallbackTest.java index 33d513f7e4..befdd1a915 100644 --- a/asterixdb/asterix-common/src/test/java/org/apache/asterix/test/ioopcallbacks/LSMIOOperationCallbackTest.java +++ b/asterixdb/asterix-common/src/test/java/org/apache/asterix/test/ioopcallbacks/LSMIOOperationCallbackTest.java @@ -21,6 +21,7 @@ package org.apache.asterix.test.ioopcallbacks; import static org.apache.hyracks.storage.am.lsm.common.impls.LSMComponentId.MIN_VALID_COMPONENT_ID; +import java.io.File; import java.util.HashMap; import java.util.Map; @@ -91,7 +92,9 @@ public class LSMIOOperationCallbackTest extends TestCase { flushMap.put(LSMIOOperationCallback.KEY_NEXT_COMPONENT_ID, nextComponentId); ILSMIndexAccessor firstAccessor = new TestLSMIndexAccessor(new TestLSMIndexOperationContext(mockIndex)); firstAccessor.getOpContext().setParameters(flushMap); - FileReference firstTarget = new FileReference(Mockito.mock(IODeviceHandle.class), getComponentFileName()); + IODeviceHandle mockIoDevice = Mockito.mock(IODeviceHandle.class); + Mockito.when(mockIoDevice.getMount()).thenReturn(new File(getIndexPath())); + FileReference firstTarget = new FileReference(mockIoDevice, getComponentFileName()); LSMComponentFileReferences firstFiles = new LSMComponentFileReferences(firstTarget, firstTarget, firstTarget); FlushOperation firstFlush = new TestFlushOperation(firstAccessor, firstTarget, callback, indexId, firstFiles, new LSMComponentId(0, 0)); @@ -107,7 +110,7 @@ public class LSMIOOperationCallbackTest extends TestCase { flushMap.put(LSMIOOperationCallback.KEY_NEXT_COMPONENT_ID, nextComponentId); ILSMIndexAccessor secondAccessor = new TestLSMIndexAccessor(new TestLSMIndexOperationContext(mockIndex)); secondAccessor.getOpContext().setParameters(flushMap); - FileReference secondTarget = new FileReference(Mockito.mock(IODeviceHandle.class), getComponentFileName()); + FileReference secondTarget = new FileReference(mockIoDevice, getComponentFileName()); LSMComponentFileReferences secondFiles = new LSMComponentFileReferences(secondTarget, secondTarget, secondTarget); FlushOperation secondFlush = new TestFlushOperation(secondAccessor, secondTarget, callback, indexId, @@ -173,6 +176,8 @@ public class LSMIOOperationCallbackTest extends TestCase { callback.recycled(mockComponent); checkMemoryComponent(id, mockComponent); + IODeviceHandle mockIoDevice = Mockito.mock(IODeviceHandle.class); + Mockito.when(mockIoDevice.getMount()).thenReturn(new File(getIndexPath())); Mockito.when(mockIndex.isMemoryComponentsAllocated()).thenReturn(true); for (int i = 0; i < 100; i++) { // schedule a flush @@ -184,7 +189,7 @@ public class LSMIOOperationCallbackTest extends TestCase { flushMap.put(LSMIOOperationCallback.KEY_NEXT_COMPONENT_ID, expectedId); ILSMIndexAccessor accessor = new TestLSMIndexAccessor(new TestLSMIndexOperationContext(mockIndex)); accessor.getOpContext().setParameters(flushMap); - FileReference target = new FileReference(Mockito.mock(IODeviceHandle.class), getComponentFileName()); + FileReference target = new FileReference(mockIoDevice, getComponentFileName()); LSMComponentFileReferences files = new LSMComponentFileReferences(target, target, target); FlushOperation flush = new TestFlushOperation(accessor, target, callback, indexId, files, new LSMComponentId(0, 0)); diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/IQueryRewriter.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/IQueryRewriter.java index 6099cb6d96..12c3b93269 100644 --- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/IQueryRewriter.java +++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/IQueryRewriter.java @@ -21,6 +21,7 @@ package org.apache.asterix.lang.common.base; import java.util.Collection; import java.util.Set; +import org.apache.asterix.common.api.INamespaceResolver; import org.apache.asterix.common.exceptions.CompilationException; import org.apache.asterix.lang.common.expression.AbstractCallExpression; import org.apache.asterix.lang.common.expression.VariableExpr; @@ -64,5 +65,5 @@ public interface IQueryRewriter { Query createFunctionAccessorQuery(FunctionDecl functionDecl); - Query createViewAccessorQuery(ViewDecl viewDecl); + Query createViewAccessorQuery(ViewDecl viewDecl, INamespaceResolver namespaceResolver); } diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppQueryRewriter.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppQueryRewriter.java index 0ce09e54ab..bad48c29b4 100644 --- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppQueryRewriter.java +++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppQueryRewriter.java @@ -28,6 +28,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import org.apache.asterix.common.api.INamespaceResolver; import org.apache.asterix.common.exceptions.CompilationException; import org.apache.asterix.common.exceptions.ErrorCode; import org.apache.asterix.common.functions.FunctionSignature; @@ -603,22 +604,34 @@ public class SqlppQueryRewriter implements IQueryRewriter { } @Override - public Query createViewAccessorQuery(ViewDecl viewDecl) { + public Query createViewAccessorQuery(ViewDecl viewDecl, INamespaceResolver namespaceResolver) { + boolean usingDatabase = namespaceResolver.isUsingDatabase(); // dataverse_name.view_name + String databaseName = viewDecl.getViewName().getDatabaseName(); DataverseName dataverseName = viewDecl.getViewName().getDataverseName(); String viewName = viewDecl.getViewName().getDatasetName(); - Expression vAccessExpr = createDatasetAccessExpression(dataverseName, viewName, viewDecl.getSourceLocation()); + Expression vAccessExpr = createDatasetAccessExpression(databaseName, dataverseName, viewName, + viewDecl.getSourceLocation(), usingDatabase); return ExpressionUtils.createWrappedQuery(vAccessExpr, viewDecl.getSourceLocation()); } - private static Expression createDatasetAccessExpression(DataverseName dataverseName, String datasetName, - SourceLocation sourceLoc) { - AbstractExpression resultExpr = null; + private static Expression createDatasetAccessExpression(String databaseName, DataverseName dataverseName, + String datasetName, SourceLocation sourceLoc, boolean usingDatabase) { + AbstractExpression resultExpr; List<String> dataverseNameParts = dataverseName.getParts(); - for (int i = 0, n = dataverseNameParts.size(); i < n; i++) { + int startIdx; + if (usingDatabase) { + resultExpr = new VariableExpr(new VarIdentifier(SqlppVariableUtil.toInternalVariableName(databaseName))); + startIdx = 0; + } else { + resultExpr = new VariableExpr( + new VarIdentifier(SqlppVariableUtil.toInternalVariableName(dataverseNameParts.get(0)))); + startIdx = 1; + } + resultExpr.setSourceLocation(sourceLoc); + for (int i = startIdx, n = dataverseNameParts.size(); i < n; i++) { String part = dataverseNameParts.get(i); - resultExpr = i == 0 ? new VariableExpr(new VarIdentifier(SqlppVariableUtil.toInternalVariableName(part))) - : new FieldAccessor(resultExpr, new Identifier(part)); + resultExpr = new FieldAccessor(resultExpr, new Identifier(part)); resultExpr.setSourceLocation(sourceLoc); } resultExpr = new FieldAccessor(resultExpr, new Identifier(datasetName)); diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/VariableCheckAndRewriteVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/VariableCheckAndRewriteVisitor.java index 27a63d2d7a..97a41712ad 100644 --- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/VariableCheckAndRewriteVisitor.java +++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/VariableCheckAndRewriteVisitor.java @@ -126,15 +126,16 @@ public class VariableCheckAndRewriteVisitor extends AbstractSqlppExpressionScopi if (resolveAsVariableReference(topVarExpr)) { return fa; } else { - DataverseName dataverseName; + Namespace namespace; try { - dataverseName = DataverseName.create(dataverseNameParts); + namespace = metadataProvider.resolve(dataverseNameParts); } catch (AsterixException e) { throw new CompilationException(ErrorCode.INVALID_DATABASE_OBJECT_NAME, fa.getSourceLocation(), dataverseNameParts.toString()); } //TODO(DB): decide - String databaseName = MetadataUtil.resolveDatabase(null, dataverseName); + String databaseName = namespace.getDatabaseName(); + DataverseName dataverseName = namespace.getDataverseName(); String datasetName = fa.getIdent().getValue(); CallExpr datasetExpr = resolveAsDataset(databaseName, dataverseName, datasetName, parent, topVarExpr); diff --git a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/MetadataNode.java b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/MetadataNode.java index cc1251bd96..5383ac96ba 100644 --- a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/MetadataNode.java +++ b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/MetadataNode.java @@ -40,6 +40,7 @@ import org.apache.asterix.common.exceptions.MetadataException; import org.apache.asterix.common.functions.FunctionSignature; import org.apache.asterix.common.metadata.DataverseName; import org.apache.asterix.common.metadata.DependencyFullyQualifiedName; +import org.apache.asterix.common.metadata.MetadataConstants; import org.apache.asterix.common.metadata.MetadataIndexImmutableProperties; import org.apache.asterix.common.metadata.MetadataUtil; import org.apache.asterix.common.transactions.IRecoveryManager.ResourceType; @@ -63,6 +64,7 @@ import org.apache.asterix.metadata.api.IMetadataExtension; import org.apache.asterix.metadata.api.IMetadataIndex; import org.apache.asterix.metadata.api.IMetadataNode; import org.apache.asterix.metadata.api.IValueExtractor; +import org.apache.asterix.metadata.bootstrap.MetadataBuiltinEntities; import org.apache.asterix.metadata.bootstrap.MetadataIndexesProvider; import org.apache.asterix.metadata.entities.CompactionPolicy; import org.apache.asterix.metadata.entities.Database; @@ -354,13 +356,15 @@ public class MetadataNode implements IMetadataNode { @Override public void addDatabase(TxnId txnId, Database database) throws AlgebricksException, RemoteException { try { + if (!mdIndexesProvider.isUsingDatabase()) { + return; + } DatabaseTupleTranslator tupleReaderWriter = tupleTranslatorProvider.getDatabaseTupleTranslator(true); ITupleReference tuple = tupleReaderWriter.getTupleFromMetadataEntity(database); insertTupleIntoIndex(txnId, mdIndexesProvider.getDatabaseEntity().getIndex(), tuple); } catch (HyracksDataException e) { if (e.matches(ErrorCode.DUPLICATE_KEY)) { - //TODO(DB): change to database - throw new AsterixException(org.apache.asterix.common.exceptions.ErrorCode.DATAVERSE_EXISTS, e, + throw new AsterixException(org.apache.asterix.common.exceptions.ErrorCode.DATABASE_EXISTS, e, database.getDatabaseName()); } else { throw new AlgebricksException(e); @@ -699,6 +703,9 @@ public class MetadataNode implements IMetadataNode { @Override public void dropDatabase(TxnId txnId, String databaseName) throws AlgebricksException, RemoteException { try { + if (!mdIndexesProvider.isUsingDatabase()) { + return; + } //TODO(DB): review confirmDatabaseCanBeDeleted(txnId, databaseName); @@ -1123,6 +1130,9 @@ public class MetadataNode implements IMetadataNode { @Override public Database getDatabase(TxnId txnId, String databaseName) throws AlgebricksException { try { + if (!mdIndexesProvider.isUsingDatabase()) { + return defaultDatabase(databaseName); + } ITupleReference searchKey = createTuple(databaseName); DatabaseTupleTranslator tupleReaderWriter = tupleTranslatorProvider.getDatabaseTupleTranslator(false); IValueExtractor<Database> valueExtractor = new MetadataEntityValueExtractor<>(tupleReaderWriter); @@ -2995,4 +3005,13 @@ public class MetadataNode implements IMetadataNode { public ITxnIdFactory getTxnIdFactory() { return txnIdFactory; } + + private Database defaultDatabase(String databaseName) { + //TODO(DB): review + if (MetadataConstants.SYSTEM_DATABASE.equals(databaseName)) { + return MetadataBuiltinEntities.SYSTEM_DATABASE; + } else { + return MetadataBuiltinEntities.DEFAULT_DATABASE; + } + } } diff --git a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/utils/DatasetUtil.java b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/utils/DatasetUtil.java index 73797d8096..4d1c4a656b 100644 --- a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/utils/DatasetUtil.java +++ b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/utils/DatasetUtil.java @@ -628,6 +628,11 @@ public class DatasetUtil { return MetadataUtil.getFullyQualifiedDisplayName(dataverseName, datasetName); } + public static String getFullyQualifiedDisplayName(String databaseName, DataverseName dataverseName, + String datasetName) { + return MetadataUtil.getFullyQualifiedDisplayName(databaseName, dataverseName, datasetName); + } + /*** * Creates a node group that is associated with a new dataset. *