From e80fd6b9b37696c41f5d4c40971c7def72b9c665 Mon Sep 17 00:00:00 2001
From: buczekp <buczekp>
Date: Wed, 12 May 2010 09:08:06 +0000
Subject: [PATCH] [LMS-1495] extended GUI - added query database selection
 widget

SVN: 15935
---
 .../generic/shared/basic/dto/NewQuery.java    | 14 ++++
 .../openbis/generic/shared/dto/QueryPE.java   |  6 +-
 .../web/client/IQueryClientService.java       | 12 ++-
 .../web/client/IQueryClientServiceAsync.java  | 17 ++--
 .../client/web/client/application/Dict.java   |  3 +-
 .../web/client/application/QueryModule.java   | 24 +++---
 .../application/module/IQueryProvider.java    |  3 +
 .../module/QueryDatabaseModel.java            | 58 +++++++++++++
 .../module/QueryDatabaseSelectionWidget.java  | 81 +++++++++++++++++++
 .../application/module/QueryEditor.java       | 11 ++-
 .../module/QueryModuleDatabaseMenuItem.java   |  5 +-
 .../application/module/QueryViewer.java       | 10 ++-
 .../module/RunCannedQueryToolbar.java         |  7 ++
 .../module/RunCustomQueryToolbar.java         | 12 +++
 .../client/web/public/query-dictionary.js     |  2 +-
 .../client/web/server/QueryClientService.java | 21 ++++-
 .../plugin/query/server/QueryServer.java      | 50 ++++++------
 .../query/server/QueryServerLogger.java       | 24 +++++-
 .../plugin/query/shared/IQueryServer.java     |  9 ++-
 .../query/shared/basic/dto/QueryDatabase.java | 75 +++++++++++++++++
 .../shared/basic/dto/QueryExpression.java     | 15 ++--
 .../shared/translator/QueryTranslator.java    |  8 +-
 .../query/shared/IQueryServer.java.expected   |  9 ++-
 .../plugin/query/QueryEditingTest.java        | 16 +++-
 24 files changed, 414 insertions(+), 78 deletions(-)
 create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/client/web/client/application/module/QueryDatabaseModel.java
 create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/client/web/client/application/module/QueryDatabaseSelectionWidget.java
 create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/shared/basic/dto/QueryDatabase.java

diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/NewQuery.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/NewQuery.java
index c9687708806..2855c516f8b 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/NewQuery.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/NewQuery.java
@@ -16,6 +16,8 @@
 
 package ch.systemsx.cisd.openbis.generic.shared.basic.dto;
 
+import ch.systemsx.cisd.openbis.plugin.query.shared.basic.dto.QueryDatabase;
+
 /**
  * @author Izabela Adamczyk
  */
@@ -25,6 +27,8 @@ public class NewQuery extends NewExpression
 
     private QueryType queryType;
 
+    private QueryDatabase queryDatabase;
+
     public QueryType getQueryType()
     {
         return queryType;
@@ -35,4 +39,14 @@ public class NewQuery extends NewExpression
         this.queryType = queryType;
     }
 
+    public QueryDatabase getQueryDatabase()
+    {
+        return queryDatabase;
+    }
+
+    public void setQueryDatabase(QueryDatabase queryDatabase)
+    {
+        this.queryDatabase = queryDatabase;
+    }
+
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/QueryPE.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/QueryPE.java
index cc375faf17d..591e410f323 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/QueryPE.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/QueryPE.java
@@ -40,7 +40,9 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ServiceVersionHolder;
 public class QueryPE extends AbstractExpressionPE<QueryPE>
 {
     private static final long serialVersionUID = ServiceVersionHolder.VERSION;
-    private String queryDatabaseKey = "1"; // FIXME
+
+    // FIXME get rid of this "1" when LMS-1495 is finished
+    private String queryDatabaseKey = "1";
 
     private String name;
 
@@ -100,7 +102,7 @@ public class QueryPE extends AbstractExpressionPE<QueryPE>
         final EqualsBuilder builder = new EqualsBuilder();
         builder.append(getName(), that.getName());
         builder.append(getDatabaseInstance(), that.getDatabaseInstance());
-                builder.append(getQueryDatabaseKey(), that.getQueryDatabaseKey());
+        builder.append(getQueryDatabaseKey(), that.getQueryDatabaseKey());
         return builder.isEquals();
     }
 
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/client/web/client/IQueryClientService.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/client/web/client/IQueryClientService.java
index 7b43abcd4da..851a6debeda 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/client/web/client/IQueryClientService.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/client/web/client/IQueryClientService.java
@@ -27,6 +27,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureE
 import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IQueryUpdates;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewQuery;
+import ch.systemsx.cisd.openbis.plugin.query.shared.basic.dto.QueryDatabase;
 import ch.systemsx.cisd.openbis.plugin.query.shared.basic.dto.QueryExpression;
 import ch.systemsx.cisd.openbis.plugin.query.shared.basic.dto.QueryParameterBindings;
 
@@ -36,16 +37,19 @@ import ch.systemsx.cisd.openbis.plugin.query.shared.basic.dto.QueryParameterBind
 public interface IQueryClientService extends IClientService
 {
 
-    /** Returns label of the database used for queries or null if it is not configured. */
-    public String tryToGetQueryDatabaseLabel() throws UserFailureException;
+    /** Returns number of databases configured for queries. */
+    public int initDatabases() throws UserFailureException;
+
+    /** Returns databases used for queries. */
+    public List<QueryDatabase> listQueryDatabases() throws UserFailureException;
 
     /** Returns results of the query with specified id. */
     public TableModelReference createQueryResultsReport(TechId queryId,
             QueryParameterBindings bindingsOrNull) throws UserFailureException;
 
     /** Returns results of the specified SQL query. */
-    public TableModelReference createQueryResultsReport(String sqlQuery,
-            QueryParameterBindings bindingsOrNull) throws UserFailureException;
+    public TableModelReference createQueryResultsReport(QueryDatabase queryDatabase,
+            String sqlQuery, QueryParameterBindings bindingsOrNull) throws UserFailureException;
 
     /** Returns a list of all the canned custom queries created so far. */
     public List<QueryExpression> listQueries() throws UserFailureException;
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/client/web/client/IQueryClientServiceAsync.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/client/web/client/IQueryClientServiceAsync.java
index 021e2682ccb..e6247400d7b 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/client/web/client/IQueryClientServiceAsync.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/client/web/client/IQueryClientServiceAsync.java
@@ -29,6 +29,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureE
 import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IQueryUpdates;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewQuery;
+import ch.systemsx.cisd.openbis.plugin.query.shared.basic.dto.QueryDatabase;
 import ch.systemsx.cisd.openbis.plugin.query.shared.basic.dto.QueryExpression;
 import ch.systemsx.cisd.openbis.plugin.query.shared.basic.dto.QueryParameterBindings;
 
@@ -38,16 +39,22 @@ import ch.systemsx.cisd.openbis.plugin.query.shared.basic.dto.QueryParameterBind
 public interface IQueryClientServiceAsync extends IClientServiceAsync
 {
 
-    /** @see IQueryClientService#tryToGetQueryDatabaseLabel() */
-    public void tryToGetQueryDatabaseLabel(AsyncCallback<String> callback);
+    /** @see IQueryClientService#initDatabases() */
+    public void initDatabases(AsyncCallback<Integer> callback);
+
+    /** @see IQueryClientService#listQueryDatabases() */
+    public void listQueryDatabases(AsyncCallback<List<QueryDatabase>> callback);
 
     /** @see IQueryClientService#createQueryResultsReport(TechId, QueryParameterBindings) */
     public void createQueryResultsReport(TechId techId, QueryParameterBindings bindingsOrNull,
             AsyncCallback<TableModelReference> callback);
 
-    /** @see IQueryClientService#createQueryResultsReport(String, QueryParameterBindings) */
-    public void createQueryResultsReport(String sqlQuery, QueryParameterBindings bindingsOrNull,
-            AsyncCallback<TableModelReference> callback);
+    /**
+     * @see IQueryClientService#createQueryResultsReport(QueryDatabase, String,
+     *      QueryParameterBindings)
+     */
+    public void createQueryResultsReport(QueryDatabase queryDatabase, String sqlQuery,
+            QueryParameterBindings bindingsOrNull, AsyncCallback<TableModelReference> callback);
 
     /** @see IQueryClientService#listQueries(IResultSetConfig) */
     public void listQueries(IResultSetConfig<String, QueryExpression> resultSetConfig,
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/client/web/client/application/Dict.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/client/web/client/application/Dict.java
index 50698c483a4..021569be5c6 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/client/web/client/application/Dict.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/client/web/client/application/Dict.java
@@ -26,8 +26,7 @@ public final class Dict extends ch.systemsx.cisd.openbis.generic.client.web.clie
 {
     public static final String MODULE_MENU_TITLE = "module_menu_title";
 
-    public static final String QUERY_DATABASE_MENU_TITLE_TEMPLATE =
-            "query_database_menu_title_template";
+    public static final String QUERY_DATABASE_MENU_TITLE = "query_database_menu_title";
 
     public static final String BUTTON_ADD_QUERY = "button_add_query";
 
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/client/web/client/application/QueryModule.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/client/web/client/application/QueryModule.java
index 41b4de9553d..c1ebd4c46b3 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/client/web/client/application/QueryModule.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/client/web/client/application/QueryModule.java
@@ -39,9 +39,9 @@ public class QueryModule implements IModule
 
     private final IViewContext<IQueryClientServiceAsync> viewContext;
 
-    // If after initialization is finished this is still null it means that DB was not configured
-    // and this module shouldn't provide any functionality.
-    private String databaseLabelOrNull;
+    // number of configured and initialized DBs
+    // (0 means that this module shouldn't provide any functionality)
+    private int databases;
 
     QueryModule(IViewContext<IQueryClientServiceAsync> viewContext)
     {
@@ -55,27 +55,26 @@ public class QueryModule implements IModule
 
     public void initialize(AsyncCallback<Void> callback)
     {
-        viewContext.getService().tryToGetQueryDatabaseLabel(
-                new DatabaseLabelCallback(viewContext, callback));
+        viewContext.getService().initDatabases(
+                new DatabasesInitializationCallback(viewContext, callback));
     }
 
     public List<? extends MenuItem> getMenuItems()
     {
-        if (databaseLabelOrNull == null)
+        if (databases == 0)
         {
             return Collections.emptyList();
         } else
         {
-            return Collections.singletonList(new QueryModuleDatabaseMenuItem(viewContext,
-                    databaseLabelOrNull));
+            return Collections.singletonList(new QueryModuleDatabaseMenuItem(viewContext));
         }
     }
 
-    private final class DatabaseLabelCallback extends AbstractAsyncCallback<String>
+    private final class DatabasesInitializationCallback extends AbstractAsyncCallback<Integer>
     {
         private final AsyncCallback<Void> delegate;
 
-        public DatabaseLabelCallback(final IViewContext<?> viewContext,
+        public DatabasesInitializationCallback(final IViewContext<?> viewContext,
                 final AsyncCallback<Void> delegate)
         {
             super(viewContext);
@@ -83,9 +82,10 @@ public class QueryModule implements IModule
         }
 
         @Override
-        protected void process(String result)
+        protected void process(Integer result)
         {
-            databaseLabelOrNull = result;
+            viewContext.log(" query database(s) configured:" + result);
+            databases = result;
             delegate.onSuccess(null);
         }
 
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/client/web/client/application/module/IQueryProvider.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/client/web/client/application/module/IQueryProvider.java
index 34369263ac7..5eefd6b2876 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/client/web/client/application/module/IQueryProvider.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/client/web/client/application/module/IQueryProvider.java
@@ -17,6 +17,7 @@
 package ch.systemsx.cisd.openbis.plugin.query.client.web.client.application.module;
 
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.IDatabaseModificationObserver;
+import ch.systemsx.cisd.openbis.plugin.query.shared.basic.dto.QueryDatabase;
 import ch.systemsx.cisd.openbis.plugin.query.shared.basic.dto.QueryParameterBindings;
 
 /**
@@ -26,6 +27,8 @@ public interface IQueryProvider extends IDatabaseModificationObserver
 {
     Long tryGetQueryId();
 
+    QueryDatabase tryGetQueryDatabase();
+
     String tryGetSQLQuery();
 
     QueryParameterBindings tryGetQueryParameterBindings();
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/client/web/client/application/module/QueryDatabaseModel.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/client/web/client/application/module/QueryDatabaseModel.java
new file mode 100644
index 00000000000..3bd9eec6ef7
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/client/web/client/application/module/QueryDatabaseModel.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2008 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.plugin.query.client.web.client.application.module;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.extjs.gxt.ui.client.data.ModelData;
+
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.model.ModelDataPropertyNames;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.model.NonHierarchicalBaseModelData;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.model.renderer.TooltipRenderer;
+import ch.systemsx.cisd.openbis.plugin.query.shared.basic.dto.QueryDatabase;
+
+/**
+ * {@link ModelData} for {@link QueryDatabase}.
+ * 
+ * @author Piotr Buczek
+ */
+public class QueryDatabaseModel extends NonHierarchicalBaseModelData
+{
+    private static final long serialVersionUID = 1L;
+
+    public QueryDatabaseModel(final QueryDatabase database)
+    {
+        set(ModelDataPropertyNames.NAME, database.getLabel());
+        set(ModelDataPropertyNames.DESCRIPTION, database.getKey());
+        set(ModelDataPropertyNames.OBJECT, database);
+        set(ModelDataPropertyNames.TOOLTIP, TooltipRenderer.renderAsTooltip(database.getLabel(),
+                "key: " + database.getKey()));
+    }
+
+    public final static List<QueryDatabaseModel> convert(final List<QueryDatabase> databases)
+    {
+        final List<QueryDatabaseModel> result = new ArrayList<QueryDatabaseModel>();
+
+        for (final QueryDatabase database : databases)
+        {
+            result.add(new QueryDatabaseModel(database));
+        }
+
+        return result;
+    }
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/client/web/client/application/module/QueryDatabaseSelectionWidget.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/client/web/client/application/module/QueryDatabaseSelectionWidget.java
new file mode 100644
index 00000000000..bdc16c16bac
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/client/web/client/application/module/QueryDatabaseSelectionWidget.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2008 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.plugin.query.client.web.client.application.module;
+
+import java.util.List;
+
+import com.extjs.gxt.ui.client.widget.form.ComboBox;
+
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.AbstractAsyncCallback;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.IViewContext;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.model.ModelDataPropertyNames;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.DropDownList;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.GWTUtils;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.ObjectKind;
+import ch.systemsx.cisd.openbis.plugin.query.client.web.client.IQueryClientServiceAsync;
+import ch.systemsx.cisd.openbis.plugin.query.client.web.client.application.Dict;
+import ch.systemsx.cisd.openbis.plugin.query.shared.basic.dto.QueryDatabase;
+
+/**
+ * {@link ComboBox} containing list of databases loaded from the server.
+ * 
+ * @author Piotr Buczek
+ */
+public final class QueryDatabaseSelectionWidget extends
+        DropDownList<QueryDatabaseModel, QueryDatabase>
+{
+    private static final String LIST_ITEMS_CALLBACK = "ListItemsCallback";
+
+    public static final String SUFFIX = "database";
+
+    private final IViewContext<IQueryClientServiceAsync> viewContext;
+
+    public QueryDatabaseSelectionWidget(final IViewContext<IQueryClientServiceAsync> viewContext)
+    {
+        super(viewContext, SUFFIX, Dict.QUERY_DATABASE, ModelDataPropertyNames.NAME, Dict.QUERY,
+                "databases");
+        setEditable(false);
+        this.viewContext = viewContext;
+        setCallbackId(createCallbackId());
+        setTemplate(GWTUtils.getTooltipTemplate(ModelDataPropertyNames.NAME,
+                ModelDataPropertyNames.TOOLTIP));
+    }
+
+    public static String createCallbackId()
+    {
+        return QueryDatabaseSelectionWidget.class + LIST_ITEMS_CALLBACK;
+    }
+
+    @Override
+    protected List<QueryDatabaseModel> convertItems(List<QueryDatabase> result)
+    {
+        return QueryDatabaseModel.convert(result);
+    }
+
+    @Override
+    protected void loadData(AbstractAsyncCallback<List<QueryDatabase>> callback)
+    {
+        viewContext.getService().listQueryDatabases(callback);
+    }
+
+    public DatabaseModificationKind[] getRelevantModifications()
+    {
+        return DatabaseModificationKind.any(ObjectKind.QUERY);
+    }
+
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/client/web/client/application/module/QueryEditor.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/client/web/client/application/module/QueryEditor.java
index 98c0f89e9da..86f7f285c2a 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/client/web/client/application/module/QueryEditor.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/client/web/client/application/module/QueryEditor.java
@@ -58,6 +58,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.QueryType;
 import ch.systemsx.cisd.openbis.plugin.query.client.web.client.IQueryClientServiceAsync;
 import ch.systemsx.cisd.openbis.plugin.query.client.web.client.application.Constants;
 import ch.systemsx.cisd.openbis.plugin.query.client.web.client.application.Dict;
+import ch.systemsx.cisd.openbis.plugin.query.shared.basic.dto.QueryDatabase;
 import ch.systemsx.cisd.openbis.plugin.query.shared.basic.dto.QueryExpression;
 import ch.systemsx.cisd.openbis.plugin.query.shared.basic.dto.QueryParameterBindings;
 
@@ -162,6 +163,8 @@ public class QueryEditor extends Dialog
 
     private final SimpleComboBox<QueryType> queryTypeField;
 
+    private final QueryDatabaseSelectionWidget queryDatabaseSelectionWidget;
+
     public QueryEditor(final IViewContext<IQueryClientServiceAsync> viewContext,
             QueryExpression queryOrNull, IDelegatedAction refreshAction, int parentWidth,
             int parentHeight)
@@ -188,6 +191,7 @@ public class QueryEditor extends Dialog
         statementField = createStatementField();
         isPublicField = new CheckBoxField(viewContext.getMessage(Dict.IS_PUBLIC), false);
         queryTypeField = new QueryTypeComboBox(viewContext);
+        queryDatabaseSelectionWidget = new QueryDatabaseSelectionWidget(viewContext);
         queryTypeField.addListener(Events.SelectionChange, statementField);
         if (queryOrNull != null)
         {
@@ -196,8 +200,11 @@ public class QueryEditor extends Dialog
             statementField.setValue(StringEscapeUtils.unescapeHtml(queryOrNull.getExpression()));
             isPublicField.setValue(queryOrNull.isPublic());
             queryTypeField.setSimpleValue(queryOrNull.getQueryType());
+            queryDatabaseSelectionWidget.setValue(new QueryDatabaseModel(queryOrNull
+                    .getQueryDatabase()));
         }
         form.add(nameField, FORM_DATA);
+        form.add(queryDatabaseSelectionWidget, FORM_DATA);
         form.add(queryTypeField, FORM_DATA);
         form.add(descriptionField, FORM_DATA);
         form.add(statementField, FORM_DATA);
@@ -333,9 +340,11 @@ public class QueryEditor extends Dialog
     private void runQuery(QueryParameterBindings parameterBindings)
     {
         String sqlStatement = statementField.getValue();
-        if (sqlStatement != null && sqlStatement.length() > 0)
+        QueryDatabase queryDatabase = queryDatabaseSelectionWidget.tryGetSelected();
+        if (sqlStatement != null && sqlStatement.length() > 0 && queryDatabase != null)
         {
             viewContext.getService().createQueryResultsReport(
+                    queryDatabase,
                     sqlStatement,
                     parameterBindings,
                     ReportGeneratedCallback.create(viewContext.getCommonViewContext(),
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/client/web/client/application/module/QueryModuleDatabaseMenuItem.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/client/web/client/application/module/QueryModuleDatabaseMenuItem.java
index 7489152ce7f..4e5f6af73ab 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/client/web/client/application/module/QueryModuleDatabaseMenuItem.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/client/web/client/application/module/QueryModuleDatabaseMenuItem.java
@@ -37,10 +37,9 @@ public class QueryModuleDatabaseMenuItem extends MenuItem
 {
     public static final String ID = GenericConstants.ID_PREFIX;
 
-    public QueryModuleDatabaseMenuItem(IViewContext<IQueryClientServiceAsync> viewContext,
-            String databaseLabel)
+    public QueryModuleDatabaseMenuItem(IViewContext<IQueryClientServiceAsync> viewContext)
     {
-        super(viewContext.getMessage(Dict.QUERY_DATABASE_MENU_TITLE_TEMPLATE, databaseLabel));
+        super(viewContext.getMessage(Dict.QUERY_DATABASE_MENU_TITLE));
 
         Menu submenu = new Menu();
         ActionMenuDefinition[] values = ActionMenuDefinition.values();
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/client/web/client/application/module/QueryViewer.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/client/web/client/application/module/QueryViewer.java
index 27dbb34db79..1a1d6bd4a5b 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/client/web/client/application/module/QueryViewer.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/client/web/client/application/module/QueryViewer.java
@@ -37,6 +37,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind;
 import ch.systemsx.cisd.openbis.plugin.query.client.web.client.IQueryClientServiceAsync;
 import ch.systemsx.cisd.openbis.plugin.query.client.web.client.application.Constants;
+import ch.systemsx.cisd.openbis.plugin.query.shared.basic.dto.QueryDatabase;
 import ch.systemsx.cisd.openbis.plugin.query.shared.basic.dto.QueryParameterBindings;
 
 /**
@@ -91,8 +92,9 @@ public class QueryViewer extends ContentPanel implements IDatabaseModificationOb
     {
         Long queryIdOrNull = queryProvider.tryGetQueryId();
         String sqlQueryOrNull = queryProvider.tryGetSQLQuery();
+        QueryDatabase queryDatabaseOrNull = queryProvider.tryGetQueryDatabase();
         QueryParameterBindings bindingsOrNull = queryProvider.tryGetQueryParameterBindings();
-        if (queryIdOrNull == null && sqlQueryOrNull == null)
+        if (queryIdOrNull == null && (sqlQueryOrNull == null || queryDatabaseOrNull == null))
         {
             return;
         }
@@ -104,10 +106,10 @@ public class QueryViewer extends ContentPanel implements IDatabaseModificationOb
         {
             viewContext.getService().createQueryResultsReport(new TechId(queryIdOrNull),
                     bindingsOrNull, callback);
-        } else if (sqlQueryOrNull != null)
+        } else if (sqlQueryOrNull != null && queryDatabaseOrNull != null)
         {
-            viewContext.getService().createQueryResultsReport(sqlQueryOrNull, bindingsOrNull,
-                    callback);
+            viewContext.getService().createQueryResultsReport(queryDatabaseOrNull, sqlQueryOrNull,
+                    bindingsOrNull, callback);
         }
     }
 
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/client/web/client/application/module/RunCannedQueryToolbar.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/client/web/client/application/module/RunCannedQueryToolbar.java
index 7f1e0eaec1a..2baa45c2008 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/client/web/client/application/module/RunCannedQueryToolbar.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/client/web/client/application/module/RunCannedQueryToolbar.java
@@ -39,6 +39,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ParameterWithValue
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind;
 import ch.systemsx.cisd.openbis.plugin.query.client.web.client.IQueryClientServiceAsync;
 import ch.systemsx.cisd.openbis.plugin.query.client.web.client.application.Dict;
+import ch.systemsx.cisd.openbis.plugin.query.shared.basic.dto.QueryDatabase;
 import ch.systemsx.cisd.openbis.plugin.query.shared.basic.dto.QueryExpression;
 import ch.systemsx.cisd.openbis.plugin.query.shared.basic.dto.QueryParameterBindings;
 
@@ -224,6 +225,12 @@ public class RunCannedQueryToolbar extends AbstractQueryProviderToolbar
         return selectedQueryOrNull == null ? null : selectedQueryOrNull.getExpression();
     }
 
+    public QueryDatabase tryGetQueryDatabase()
+    {
+        QueryExpression selectedQueryOrNull = querySelectionWidget.tryGetSelected();
+        return selectedQueryOrNull == null ? null : selectedQueryOrNull.getQueryDatabase();
+    }
+
     public QueryParameterBindings tryGetQueryParameterBindings()
     {
         QueryParameterBindings bindings = new QueryParameterBindings();
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/client/web/client/application/module/RunCustomQueryToolbar.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/client/web/client/application/module/RunCustomQueryToolbar.java
index 8c0555e8ef6..5afcb260d04 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/client/web/client/application/module/RunCustomQueryToolbar.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/client/web/client/application/module/RunCustomQueryToolbar.java
@@ -27,6 +27,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.IViewConte
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind;
 import ch.systemsx.cisd.openbis.plugin.query.client.web.client.IQueryClientServiceAsync;
 import ch.systemsx.cisd.openbis.plugin.query.client.web.client.application.Dict;
+import ch.systemsx.cisd.openbis.plugin.query.shared.basic.dto.QueryDatabase;
 import ch.systemsx.cisd.openbis.plugin.query.shared.basic.dto.QueryParameterBindings;
 
 /**
@@ -41,14 +42,20 @@ public class RunCustomQueryToolbar extends AbstractQueryProviderToolbar
 
     private final TextArea queryField;
 
+    private final QueryDatabaseSelectionWidget queryDatabaseSelectionWidget;
+
     public RunCustomQueryToolbar(final IViewContext<IQueryClientServiceAsync> viewContext)
     {
         super(viewContext);
         setAlignment(HorizontalAlignment.CENTER);
         this.queryField = createQueryField();
+        this.queryDatabaseSelectionWidget = new QueryDatabaseSelectionWidget(viewContext);
         add(new LabelToolItem(viewContext.getMessage(Dict.SQL_QUERY)
                 + GenericConstants.LABEL_SEPARATOR));
         add(queryField);
+        add(new LabelToolItem(viewContext.getMessage(Dict.QUERY_DATABASE)
+                + GenericConstants.LABEL_SEPARATOR));
+        add(queryDatabaseSelectionWidget);
         add(executeButton);
     }
 
@@ -79,6 +86,11 @@ public class RunCustomQueryToolbar extends AbstractQueryProviderToolbar
         return queryField.getValue();
     }
 
+    public QueryDatabase tryGetQueryDatabase()
+    {
+        return queryDatabaseSelectionWidget.tryGetSelected();
+    }
+
     public QueryParameterBindings tryGetQueryParameterBindings()
     {
         return null;
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/client/web/public/query-dictionary.js b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/client/web/public/query-dictionary.js
index 396862b1cf3..3f91cc13c41 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/client/web/public/query-dictionary.js
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/client/web/public/query-dictionary.js
@@ -11,7 +11,7 @@ var query = {
 	
 	module_menu_title: "Queries",
 	
-	query_database_menu_title_template: "Query {0}",
+	query_database_menu_title: "Queries",
 	query_execute: "Execute",
 	
 	RUN_CUSTOM_QUERY_menu_item: "Run Custom SQL Query",
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/client/web/server/QueryClientService.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/client/web/server/QueryClientService.java
index 6c40ecfa64a..e7869ae6499 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/client/web/server/QueryClientService.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/client/web/server/QueryClientService.java
@@ -40,6 +40,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModel;
 import ch.systemsx.cisd.openbis.plugin.query.client.web.client.IQueryClientService;
 import ch.systemsx.cisd.openbis.plugin.query.shared.IQueryServer;
 import ch.systemsx.cisd.openbis.plugin.query.shared.ResourceNames;
+import ch.systemsx.cisd.openbis.plugin.query.shared.basic.dto.QueryDatabase;
 import ch.systemsx.cisd.openbis.plugin.query.shared.basic.dto.QueryExpression;
 import ch.systemsx.cisd.openbis.plugin.query.shared.basic.dto.QueryParameterBindings;
 
@@ -79,26 +80,38 @@ public class QueryClientService extends AbstractClientService implements IQueryC
     // IQueryClientService
     //
 
-    public String tryToGetQueryDatabaseLabel()
+    public int initDatabases()
     {
         try
         {
             final String sessionToken = getSessionToken();
-            return queryServer.tryToGetQueryDatabaseLabel(sessionToken);
+            return queryServer.initDatabases(sessionToken);
         } catch (final UserFailureException e)
         {
             throw UserFailureExceptionTranslator.translate(e);
         }
     }
 
-    public TableModelReference createQueryResultsReport(String sqlQuery,
+    public List<QueryDatabase> listQueryDatabases()
+    {
+        try
+        {
+            final String sessionToken = getSessionToken();
+            return queryServer.listQueryDatabases(sessionToken);
+        } catch (final UserFailureException e)
+        {
+            throw UserFailureExceptionTranslator.translate(e);
+        }
+    }
+
+    public TableModelReference createQueryResultsReport(QueryDatabase database, String sqlQuery,
             QueryParameterBindings bindingsOrNull)
     {
         try
         {
             final String sessionToken = getSessionToken();
             final TableModel tableModel =
-                    queryServer.queryDatabase(sessionToken, sqlQuery, bindingsOrNull);
+                    queryServer.queryDatabase(sessionToken, database, sqlQuery, bindingsOrNull);
             return createTableModelReference(tableModel);
         } catch (final UserFailureException e)
         {
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/server/QueryServer.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/server/QueryServer.java
index fc586a9c7f3..6a315d70735 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/server/QueryServer.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/server/QueryServer.java
@@ -16,6 +16,8 @@
 
 package ch.systemsx.cisd.openbis.plugin.query.server;
 
+import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -49,6 +51,7 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.QueryPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.Session;
 import ch.systemsx.cisd.openbis.plugin.query.shared.IQueryServer;
 import ch.systemsx.cisd.openbis.plugin.query.shared.ResourceNames;
+import ch.systemsx.cisd.openbis.plugin.query.shared.basic.dto.QueryDatabase;
 import ch.systemsx.cisd.openbis.plugin.query.shared.basic.dto.QueryExpression;
 import ch.systemsx.cisd.openbis.plugin.query.shared.basic.dto.QueryParameterBindings;
 import ch.systemsx.cisd.openbis.plugin.query.shared.translator.QueryTranslator;
@@ -73,8 +76,6 @@ public class QueryServer extends AbstractServer<IQueryServer> implements IQueryS
     @Resource(name = "propertyConfigurer")
     private ExposablePropertyPaceholderConfigurer configurer;
 
-    private DatabaseDefinition databaseDefinition;
-
     /**
      * map from dbKey to IDAO
      * 
@@ -104,12 +105,25 @@ public class QueryServer extends AbstractServer<IQueryServer> implements IQueryS
         return new QueryServerLogger(getSessionManager(), context);
     }
 
-    public String tryToGetQueryDatabaseLabel(String sessionToken)
+    public int initDatabases(String sessionToken)
+    {
+        checkSession(sessionToken);
+        initDatabaseDefinitions();
+        return getDatabaseDefinitions().size();
+    }
+
+    public List<QueryDatabase> listQueryDatabases(String sessionToken)
     {
         checkSession(sessionToken);
 
-        DatabaseDefinition definition = tryToGetDatabaseDefinition();
-        return definition == null ? null : definition.getLabel();
+        initDatabaseDefinitions();
+        final List<QueryDatabase> results = new ArrayList<QueryDatabase>();
+        for (DatabaseDefinition definition : definitions.values())
+        {
+            results.add(new QueryDatabase(definition.getKey(), definition.getLabel()));
+        }
+        Collections.sort(results);
+        return results;
     }
 
     public List<QueryExpression> listQueries(String sessionToken)
@@ -187,14 +201,13 @@ public class QueryServer extends AbstractServer<IQueryServer> implements IQueryS
         }
     }
 
-    public TableModel queryDatabase(String sessionToken, String sqlQuery,
+    public TableModel queryDatabase(String sessionToken, QueryDatabase database, String sqlQuery,
             QueryParameterBindings bindings)
     {
         checkSession(sessionToken);
         try
         {
-            // FIXME
-            return queryDatabaseWithKey("1", sqlQuery, bindings);
+            return queryDatabaseWithKey(database.getKey(), sqlQuery, bindings);
         } catch (DataAccessException ex)
         {
             throw new UserFailureException(ex.getMostSpecificCause().getMessage(), ex);
@@ -239,19 +252,6 @@ public class QueryServer extends AbstractServer<IQueryServer> implements IQueryS
         return result;
     }
 
-    // FIXME add support for multiple DBs
-    private DatabaseDefinition tryToGetDatabaseDefinition()
-    {
-        if (databaseDefinition == null)
-        {
-            if (getDatabaseDefinitions().size() > 0)
-            {
-                databaseDefinition = getDatabaseDefinitions().values().iterator().next();
-            }
-        }
-        return databaseDefinition;
-    }
-
     private Map<String, DatabaseDefinition> getDatabaseDefinitions()
     {
         if (definitions == null)
@@ -263,12 +263,16 @@ public class QueryServer extends AbstractServer<IQueryServer> implements IQueryS
 
     private void initDatabaseDefinitions()
     {
-        assert definitions == null;
+        if (definitions != null)
+        {
+            return;
+        }
 
         definitions = new HashMap<String, DatabaseDefinition>();
         Properties resolvedProps = configurer.getResolvedProps();
         SectionProperties[] sectionsProperties =
-                PropertyParametersUtil.extractSectionProperties(resolvedProps, DATABASE_KEYS, true);
+                PropertyParametersUtil
+                        .extractSectionProperties(resolvedProps, DATABASE_KEYS, false);
         for (int i = 0; i < sectionsProperties.length; i++)
         {
             final String databaseKey = sectionsProperties[i].getKey();
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/server/QueryServerLogger.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/server/QueryServerLogger.java
index a0f3bf31c45..5f920d9a716 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/server/QueryServerLogger.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/server/QueryServerLogger.java
@@ -27,6 +27,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewQuery;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModel;
 import ch.systemsx.cisd.openbis.generic.shared.dto.Session;
 import ch.systemsx.cisd.openbis.plugin.query.shared.IQueryServer;
+import ch.systemsx.cisd.openbis.plugin.query.shared.basic.dto.QueryDatabase;
 import ch.systemsx.cisd.openbis.plugin.query.shared.basic.dto.QueryExpression;
 import ch.systemsx.cisd.openbis.plugin.query.shared.basic.dto.QueryParameterBindings;
 
@@ -41,12 +42,30 @@ class QueryServerLogger extends AbstractServerLogger implements IQueryServer
         super(sessionManager, context);
     }
 
+    public int initDatabases(String sessionToken)
+    {
+        logAccess(sessionToken, "init_databases");
+        return 0;
+    }
+
     public String tryToGetQueryDatabaseLabel(String sessionToken)
     {
         logAccess(sessionToken, "try_to_get_query_database_label");
         return null;
     }
 
+    public List<String> listQueryDatabaseLabels(String sessionToken)
+    {
+        logAccess(sessionToken, "list_query_database_labels");
+        return null;
+    }
+
+    public List<QueryDatabase> listQueryDatabases(String sessionToken)
+    {
+        logAccess(sessionToken, "list_query_databases");
+        return null;
+    }
+
     public List<QueryExpression> listQueries(String sessionToken)
     {
         logAccess(sessionToken, "list_queries");
@@ -69,10 +88,11 @@ class QueryServerLogger extends AbstractServerLogger implements IQueryServer
                 .getName());
     }
 
-    public TableModel queryDatabase(String sessionToken, String sqlQuery,
+    public TableModel queryDatabase(String sessionToken, QueryDatabase database, String sqlQuery,
             QueryParameterBindings bindings)
     {
-        logAccess(sessionToken, "query_database", "SQL(%s) BINDINGS(%s)", sqlQuery, bindings);
+        logAccess(sessionToken, "query_database", "DB(%s) SQL(%s) BINDINGS(%s)", database,
+                sqlQuery, bindings);
         return null;
 
     }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/shared/IQueryServer.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/shared/IQueryServer.java
index 0c0b88ca250..7a5a2a5e924 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/shared/IQueryServer.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/shared/IQueryServer.java
@@ -35,6 +35,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModel;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.ObjectKind;
 import ch.systemsx.cisd.openbis.plugin.query.shared.authorization.predicate.DeleteQueryPredicate;
 import ch.systemsx.cisd.openbis.plugin.query.shared.authorization.predicate.UpdateQueryPredicate;
+import ch.systemsx.cisd.openbis.plugin.query.shared.basic.dto.QueryDatabase;
 import ch.systemsx.cisd.openbis.plugin.query.shared.basic.dto.QueryExpression;
 import ch.systemsx.cisd.openbis.plugin.query.shared.basic.dto.QueryParameterBindings;
 
@@ -46,11 +47,15 @@ public interface IQueryServer extends IServer
 
     @Transactional(readOnly = true)
     @RolesAllowed(RoleSet.OBSERVER)
-    public String tryToGetQueryDatabaseLabel(String sessionToken);
+    public int initDatabases(String sessionToken);
+
+    @Transactional(readOnly = true)
+    @RolesAllowed(RoleSet.OBSERVER)
+    public List<QueryDatabase> listQueryDatabases(String sessionToken);
 
     @Transactional(readOnly = true)
     @RolesAllowed(RoleSet.POWER_USER)
-    public TableModel queryDatabase(String sessionToken, String sqlQuery,
+    public TableModel queryDatabase(String sessionToken, QueryDatabase database, String sqlQuery,
             QueryParameterBindings bindings);
 
     @Transactional(readOnly = true)
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/shared/basic/dto/QueryDatabase.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/shared/basic/dto/QueryDatabase.java
new file mode 100644
index 00000000000..27c8294b008
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/shared/basic/dto/QueryDatabase.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2010 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.plugin.query.shared.basic.dto;
+
+import com.google.gwt.user.client.rpc.IsSerializable;
+
+/**
+ * @author Piotr Buczek
+ */
+public class QueryDatabase implements IsSerializable, Comparable<QueryDatabase>
+{
+    private String key;
+
+    private String label;
+
+    public QueryDatabase()
+    {
+    }
+
+    public QueryDatabase(String key, String label)
+    {
+        this.key = key;
+        this.label = label;
+    }
+
+    public String getKey()
+    {
+        return key;
+    }
+
+    public void setKey(String key)
+    {
+        this.key = key;
+    }
+
+    public String getLabel()
+    {
+        return label;
+    }
+
+    public void setLabel(String label)
+    {
+        this.label = label;
+    }
+
+    // 
+    // Object
+    // 
+
+    @Override
+    public String toString()
+    {
+        return label + " [" + key + "]";
+    }
+
+    public int compareTo(QueryDatabase o)
+    {
+        return key.compareTo(o.key);
+    }
+
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/shared/basic/dto/QueryExpression.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/shared/basic/dto/QueryExpression.java
index e878de31be8..ffd3ae625f7 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/shared/basic/dto/QueryExpression.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/shared/basic/dto/QueryExpression.java
@@ -32,7 +32,7 @@ public class QueryExpression extends AbstractExpressionWithParameters implements
 
     private QueryType queryType;
 
-    private String queryDatabaseLabel;
+    private QueryDatabase queryDatabase;
 
     public QueryExpression()
     {
@@ -53,14 +53,19 @@ public class QueryExpression extends AbstractExpressionWithParameters implements
         return queryType;
     }
 
-    public String getQueryDatabaseLabel()
+    public QueryDatabase getQueryDatabase()
     {
-        return queryDatabaseLabel;
+        return queryDatabase;
     }
 
-    public void setQueryDatabaseLabel(String queryDatabaseLabel)
+    public void setQueryDatabase(QueryDatabase queryDatabase)
+    {
+        this.queryDatabase = queryDatabase;
+    }
+
+    public String getQueryDatabaseLabel()
     {
-        this.queryDatabaseLabel = queryDatabaseLabel;
+        return queryDatabase == null ? null : queryDatabase.getLabel();
     }
 
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/shared/translator/QueryTranslator.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/shared/translator/QueryTranslator.java
index c93a118e797..f61d2db282b 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/shared/translator/QueryTranslator.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/shared/translator/QueryTranslator.java
@@ -26,6 +26,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.ExpressionUtil;
 import ch.systemsx.cisd.openbis.generic.shared.dto.QueryPE;
 import ch.systemsx.cisd.openbis.generic.shared.translator.GridCustomExpressionTranslator;
 import ch.systemsx.cisd.openbis.plugin.query.server.DatabaseDefinition;
+import ch.systemsx.cisd.openbis.plugin.query.shared.basic.dto.QueryDatabase;
 import ch.systemsx.cisd.openbis.plugin.query.shared.basic.dto.QueryExpression;
 
 /**
@@ -48,12 +49,13 @@ public final class QueryTranslator
         for (final QueryPE query : queries)
         {
             result.add(QueryTranslator.translate(query, definitions
-                    .get(query.getQueryDatabaseKey()).getLabel()));
+                    .get(query.getQueryDatabaseKey())));
         }
         return result;
     }
 
-    public final static QueryExpression translate(final QueryPE original, final String databaseLabel)
+    public final static QueryExpression translate(final QueryPE original,
+            final DatabaseDefinition database)
     {
         if (original == null)
         {
@@ -61,7 +63,7 @@ public final class QueryTranslator
         }
         final QueryExpression result = new QueryExpression();
         result.setName(escapeHtml(original.getName()));
-        result.setQueryDatabaseLabel(databaseLabel);
+        result.setQueryDatabase(new QueryDatabase(database.getKey(), database.getLabel()));
         result.setQueryType(original.getQueryType());
         result.setupParameters(ExpressionUtil.extractParameters(original.getExpression()));
 
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/plugin/query/shared/IQueryServer.java.expected b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/plugin/query/shared/IQueryServer.java.expected
index 6d10dab4049..57415b43dbd 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/plugin/query/shared/IQueryServer.java.expected
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/plugin/query/shared/IQueryServer.java.expected
@@ -35,6 +35,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModel;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.ObjectKind;
 import ch.systemsx.cisd.openbis.plugin.query.shared.authorization.predicate.DeleteQueryPredicate;
 import ch.systemsx.cisd.openbis.plugin.query.shared.authorization.predicate.UpdateQueryPredicate;
+import ch.systemsx.cisd.openbis.plugin.query.shared.basic.dto.QueryDatabase;
 import ch.systemsx.cisd.openbis.plugin.query.shared.basic.dto.QueryExpression;
 import ch.systemsx.cisd.openbis.plugin.query.shared.basic.dto.QueryParameterBindings;
 
@@ -46,11 +47,15 @@ public interface IQueryServer extends IServer
 
     @Transactional(readOnly = true)
     @RolesAllowed(RoleSet.OBSERVER)
-    public String tryToGetQueryDatabaseLabel(String sessionToken);
+    public int initDatabases(String sessionToken);
+
+    @Transactional(readOnly = true)
+    @RolesAllowed(RoleSet.OBSERVER)
+    public List<QueryDatabase> listQueryDatabases(String sessionToken);
 
     @Transactional(readOnly = true)
     @RolesAllowed(RoleSet.POWER_USER)
-    public TableModel queryDatabase(String sessionToken, String sqlQuery,
+    public TableModel queryDatabase(String sessionToken, QueryDatabase database, String sqlQuery,
             QueryParameterBindings bindings);
 
     @Transactional(readOnly = true)
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/plugin/query/QueryEditingTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/plugin/query/QueryEditingTest.java
index 1b0e1eed16a..fb319b12a05 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/plugin/query/QueryEditingTest.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/plugin/query/QueryEditingTest.java
@@ -41,6 +41,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewQuery;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.QueryType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModelColumnHeader;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModelRow;
+import ch.systemsx.cisd.openbis.plugin.query.shared.basic.dto.QueryDatabase;
 import ch.systemsx.cisd.openbis.plugin.query.shared.basic.dto.QueryExpression;
 import ch.systemsx.cisd.openbis.plugin.query.shared.basic.dto.QueryParameterBindings;
 
@@ -63,11 +64,19 @@ public class QueryEditingTest extends QuerySystemTestCase
     }
 
     @Test
-    public void testGetQueryDatabaseLabel()
+    public void testInitDatabases()
     {
         logIntoCommonClientService();
 
-        assertEquals("openBIS meta data", queryClientService.tryToGetQueryDatabaseLabel());
+        assertEquals(1, queryClientService.initDatabases());
+    }
+
+    @Test
+    public void testGetQueryDatabases()
+    {
+        logIntoCommonClientService();
+
+        assertEquals("openBIS meta data", queryClientService.listQueryDatabases().get(0).getLabel());
     }
 
     @Test
@@ -165,10 +174,11 @@ public class QueryEditingTest extends QuerySystemTestCase
     {
         logIntoCommonClientService();
 
+        QueryDatabase database = new QueryDatabase("1", "label");
         QueryParameterBindings bindings = new QueryParameterBindings();
         bindings.addBinding("id", "1");
         TableModelReference table =
-                queryClientService.createQueryResultsReport(
+                queryClientService.createQueryResultsReport(database,
                         "select id, code from sample_types where id = ${id}", bindings);
         checkTable(table);
     }
-- 
GitLab