[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 <mhubail@apache.org>
Integration-Tests: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Tested-by: Ali Alsuliman <ali.al.solaiman@gmail.com>
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 24b4856..6ea7aeb 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.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 @@
     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 @@
             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 @@
         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 ab6a62a..a439fe5 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.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 @@
     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 @@
                 .createResourceIdFactory();
         persistedResourceRegistry = ncServiceContext.getPersistedResourceRegistry();
         cacheManager = new CacheManager();
-        namespacePathResolver = new NamespacePathResolver(isCloudDeployment());
+        this.namespacePathResolver = namespacePathResolver;
         this.namespaceResolver = namespaceResolver;
     }
 
@@ -205,7 +205,8 @@
             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 4b19200..f404ca5 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 @@
                     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 @@
         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 @@
         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 @@
         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 @@
         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 @@
             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 de3cb82..c93a23b 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.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.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.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 @@
                 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 @@
         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 @@
             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 eea87d8..4acc039 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.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.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 @@
         }
         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 @@
 
     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 a45a1bf..a23da8c 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 @@
 @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 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 @@
 
     @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 2860813..9498979 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 @@
     protected int loopIteration;
 
     protected String deltaPath = null;
+    public String stripSubstring = null;
 
     public TestExecutor() {
         this(Collections.singletonList(
@@ -861,6 +862,9 @@
         }
 
         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 @@
         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 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 @@
         }
     }
 
-    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 @@
                 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 @@
         }
     }
 
+    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 cb28d2f..33130f2 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 18a98e3..e7c2769 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 3580ae9..923c81b 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 910b6df..e657e61 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 1089bc3..e6c06f9 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 6b01a11..fea7c0a 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 ffe81d6..0f537d7 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 3179280..8c7cd8a 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.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 @@
 
 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 @@
     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 @@
 
     @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 6ba31db..f325f41 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 @@
     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 b1f88cb..d0b982c 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.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 @@
 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 97a6173..6ecd201 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.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 @@
     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 7f9bde6..fb30509 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 @@
 
     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 01f9509..85b80a6 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 @@
         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 @@
 
         @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 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 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 ff00aef..83418a4 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 @@
     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 f53a3a3..261cddc 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 @@
 
     @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 02cf6d6..044d920 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 @@
     // 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 06d12fa..539b8c4 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 @@
         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 26d1ce0..910c3ef 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 @@
     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 b18562e..d1d813e 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 @@
     private final boolean usingDatabase;
 
     public NamespaceResolver(boolean usingDatabase) {
-        this.usingDatabase = false;
+        this.usingDatabase = usingDatabase;
     }
 
     @Override
@@ -42,13 +42,49 @@
         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 6fea755..4533361 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 @@
 
 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 @@
             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 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 7065767..a163ece 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 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 @@
     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 @@
         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 @@
             } 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 @@
             }
             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 @@
         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 3f61b85..ab77067 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 33d513f..befdd1a 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 @@
 
 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 @@
         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 @@
         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 @@
         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 @@
             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 6099cb6..12c3b93 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 @@
 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 @@
 
     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 0ce09e5..bad48c2 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.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 @@
     }
 
     @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 27a63d2..97a4171 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 @@
                 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 cc1251b..5383ac9 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.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.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 @@
     @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 @@
     @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 @@
     @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 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 73797d8..4d1c4a6 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 @@
         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.
      *