diff --git a/fda-gateway-service/src/main/java/at/tuwien/gatewayservice/config/GatewayConfig.java b/fda-gateway-service/src/main/java/at/tuwien/gatewayservice/config/GatewayConfig.java
index 54063f12a9a528713100db7f732dcb4ff210429f..47182f176a71de21fdeff19d20b58ca70ff28b8d 100644
--- a/fda-gateway-service/src/main/java/at/tuwien/gatewayservice/config/GatewayConfig.java
+++ b/fda-gateway-service/src/main/java/at/tuwien/gatewayservice/config/GatewayConfig.java
@@ -31,6 +31,11 @@ public class GatewayConfig {
                         .method("POST","GET","PUT","DELETE")
                         .and()
                         .uri("lb://fda-query-service"))
+                .route("fda-query-service", r -> r.path("/api/database/**/querystore/**")
+                        .and()
+                        .method("POST","GET","PUT","DELETE")
+                        .and()
+                        .uri("lb://fda-query-service"))
                 .route("fda-table-service", r -> r.path("/api/database/**/table/**")
                         .and()
                         .method("POST","GET","PUT","DELETE")
diff --git a/fda-ui/components/DBToolbar.vue b/fda-ui/components/DBToolbar.vue
index efdad60e18758a397eddf526d3d7d19466463d06..cd0a5769e97a0577ff06d4ca449b347258a11dc0 100644
--- a/fda-ui/components/DBToolbar.vue
+++ b/fda-ui/components/DBToolbar.vue
@@ -9,6 +9,9 @@
       <v-btn :to="`/databases/${$route.params.database_id}/tables/import`" class="mr-2">
         <v-icon left>mdi-cloud-upload</v-icon> Import CSV
       </v-btn>
+      <v-btn color="blue-grey" :to="`/databases/${$route.params.database_id}/queries/create`" class="mr-2 white--text">
+        <v-icon left>mdi-wrench</v-icon> Query Builder
+      </v-btn>
       <v-btn color="primary" :to="`/databases/${$route.params.database_id}/tables/create`">
         <v-icon left>mdi-table-large-plus</v-icon> Create Table
       </v-btn>
diff --git a/fda-ui/components/QueryList.vue b/fda-ui/components/QueryList.vue
new file mode 100644
index 0000000000000000000000000000000000000000..4e2c5a6eb8e3a4b328634b21261794dab3356637
--- /dev/null
+++ b/fda-ui/components/QueryList.vue
@@ -0,0 +1,123 @@
+<template>
+  <div>
+    <v-card v-if="queries.length === 0" flat>
+      <v-card-title>
+        (no queries)
+      </v-card-title>
+    </v-card>
+    <v-expansion-panels v-if="queries.length > 0" accordion>
+      <v-expansion-panel v-for="(item, i) in queries" :key="i" @click="details(item)">
+        <v-expansion-panel-header>
+          {{ item.query }}
+        </v-expansion-panel-header>
+        <v-expansion-panel-content>
+          <v-row dense>
+            <v-col>
+              <v-list dense>
+                <v-list-item>
+                  <v-list-item-icon>
+                    <v-icon>mdi-information-variant</v-icon>
+                  </v-list-item-icon>
+                  <v-list-item-content>
+                    <v-list-item-title>
+                      ID: {{ queryDetails.id }}
+                    </v-list-item-title>
+                  </v-list-item-content>
+                </v-list-item>
+                <v-list-item>
+                  <v-list-item-icon>
+                    <v-icon>mdi-fingerprint</v-icon>
+                  </v-list-item-icon>
+                  <v-list-item-content>
+                    <v-list-item-title>
+                      DOI: <code v-if="queryDetails.doi">{{ queryDetails.doi }}</code>
+                      <span v-if="!queryDetails.doi">(no identifier issued)</span>
+                    </v-list-item-title>
+                  </v-list-item-content>
+                </v-list-item>
+                <v-list-item>
+                  <v-list-item-icon>
+                    <v-icon>mdi-api</v-icon>
+                  </v-list-item-icon>
+                  <v-list-item-content>
+                    <v-list-item-title>
+                      Query Hash: <code>{{ queryDetails.queryHash }}</code>
+                    </v-list-item-title>
+                  </v-list-item-content>
+                </v-list-item>
+                <v-list-item>
+                  <v-list-item-icon>
+                    <v-icon>mdi-clock-outline</v-icon>
+                  </v-list-item-icon>
+                  <v-list-item-content>
+                    <v-list-item-title>
+                      Execution Timestamp: {{ queryDetails.executionTimestamp }}
+                    </v-list-item-title>
+                  </v-list-item-content>
+                </v-list-item>
+                <v-list-item>
+                  <v-list-item-icon>
+                    <v-icon>mdi-content-save</v-icon>
+                  </v-list-item-icon>
+                  <v-list-item-content>
+                    <v-list-item-title>
+                      Query: <code>{{ queryDetails.query }}</code>
+                    </v-list-item-title>
+                  </v-list-item-content>
+                </v-list-item>
+              </v-list>
+            </v-col>
+          </v-row>
+          <v-row dense>
+            <v-col>
+              <v-btn color="primary" :to="`/databases/${$route.params.database_id}/tables/${item.id}`" disabled>
+                <v-icon left>mdi-run</v-icon> Execute Again
+              </v-btn>
+            </v-col>
+          </v-row>
+        </v-expansion-panel-content>
+      </v-expansion-panel>
+    </v-expansion-panels>
+  </div>
+</template>
+
+<script>
+export default {
+  data () {
+    return {
+      queries: [],
+      queryDetails: {
+        id: null,
+        doi: null,
+        queryHash: null,
+        executionTimestamp: null,
+        columns: []
+      }
+    }
+  },
+  mounted () {
+    this.$root.$on('query-create', this.refresh)
+    this.refresh()
+  },
+  methods: {
+    async refresh () {
+      // XXX same as in QueryBuilder
+      let res
+      try {
+        res = await this.$axios.get(`/api/database/${this.$route.params.database_id}/querystore`)
+        console.debug('queries', res)
+        this.queries = res.data
+      } catch (err) {
+        this.$toast.error('Could not list queries.')
+      }
+    },
+    details (query) {
+      this.queryDetails = query
+    }
+  }
+}
+</script>
+
+<style>
+
+</style>
diff --git a/fda-ui/components/query/Builder.vue b/fda-ui/components/query/Builder.vue
index a45d278c5d8185c5e4f49ce3affce848f49f2eb3..aa2a9f7c60206e620e0bb20e4725867818eef213 100644
--- a/fda-ui/components/query/Builder.vue
+++ b/fda-ui/components/query/Builder.vue
@@ -22,21 +22,32 @@
           @change="buildQuery" />
       </v-col>
     </v-row>
-    <QueryFilters
-      v-if="table"
-      v-model="clauses"
-      :columns="columnNames" />
+    <!--    <QueryFilters-->
+    <!--      v-if="table"-->
+    <!--      v-model="clauses"-->
+    <!--      :columns="columnNames" />-->
     <v-row v-if="query.formatted">
       <v-col>
         <highlightjs autodetect :code="query.formatted" />
       </v-col>
       <v-col cols="3" class="actions">
-        <v-btn class="execute" color="primary">
+        <v-btn class="execute" color="primary" @click="execute">
           <v-icon>mdi-refresh</v-icon>
           Execute
         </v-btn>
       </v-col>
     </v-row>
+    <v-row>
+      <v-col>
+        <p>Results</p>
+        <v-data-table
+          :headers="result.headers"
+          :items="result.rows"
+          :loading="loading"
+          :items-per-page="30"
+          class="elevation-1" />
+      </v-col>
+    </v-row>
   </div>
 </template>
 
@@ -49,7 +60,12 @@ export default {
       tableDetails: null,
       query: {},
       select: [],
-      clauses: []
+      clauses: [],
+      result: {
+        headers: [],
+        rows: []
+      },
+      loading: false
     }
   },
   computed: {
@@ -80,6 +96,26 @@ export default {
     }
   },
   methods: {
+    async execute () {
+      const query = this.query.sql.replaceAll('"', '')
+      this.loading = true
+      try {
+        const res = await this.$axios.put(`/api/database/${this.$route.params.database_id}/query`, {
+          Query: query
+        })
+        console.debug('query result', res)
+        this.$toast.success('Successfully executed query')
+        this.loading = false
+        this.result.headers = this.select.map((s) => {
+          return { text: s.name, value: 'mdb_' + s.name, sortable: false }
+        })
+        this.result.rows = res.data.result
+      } catch (err) {
+        console.error('query execute', err)
+        this.$toast.error('Could not execute query')
+        this.loading = false
+      }
+    },
     async buildQuery () {
       if (!this.table) {
         return
@@ -87,7 +123,7 @@ export default {
       const url = '/server-middleware/query/build'
       const data = {
         table: this.table.internalName,
-        select: this.select.map(s => s.name),
+        select: this.select.map(s => 'mdb_' + s.name),
         clauses: this.clauses
       }
       try {
diff --git a/fda-ui/pages/databases/_database_id/queries/create.vue b/fda-ui/pages/databases/_database_id/queries/create.vue
new file mode 100644
index 0000000000000000000000000000000000000000..c2390fb100fc31aae393c887670de537524e16b0
--- /dev/null
+++ b/fda-ui/pages/databases/_database_id/queries/create.vue
@@ -0,0 +1,20 @@
+<template>
+  <div>
+    <v-card class="pb-2">
+      <v-card-title class="pb-0">
+        Query Builder
+      </v-card-title>
+      <v-card-text>
+        <QueryBuilder />
+      </v-card-text>
+    </v-card>
+  </div>
+</template>
+
+<script>
+export default {
+  data () {
+    return {}
+  }
+}
+</script>
diff --git a/fda-ui/pages/databases/_database_id/queries/index.vue b/fda-ui/pages/databases/_database_id/queries/index.vue
index a0bcd835956bfabbd7095b7438d747da8ef9b09e..ff90d731ff4275336480f3eb528518a66b4b00f0 100644
--- a/fda-ui/pages/databases/_database_id/queries/index.vue
+++ b/fda-ui/pages/databases/_database_id/queries/index.vue
@@ -1,14 +1,7 @@
 <template>
   <div>
     <DBToolbar v-model="db" />
-    <v-card>
-      <v-card-title>
-        Query Builder
-      </v-card-title>
-      <v-card-text>
-        <QueryBuilder />
-      </v-card-text>
-    </v-card>
+    <QueryList />
   </div>
 </template>
 
diff --git a/fda-ui/yarn.lock b/fda-ui/yarn.lock
index 31a4d9d4314ca3fbc11c5f9b5efe49ffa62d9520..31dcd208e937faeed12a5ae9100e93489dede6a8 100644
--- a/fda-ui/yarn.lock
+++ b/fda-ui/yarn.lock
@@ -1622,7 +1622,7 @@
     "webpack-node-externals" "^3.0.0"
     "webpackbar" "^4.0.0"
 
-"@nuxtjs/axios@^5.12.2":
+"@nuxtjs/axios@^5.13.6":
   "integrity" "sha512-XS+pOE0xsDODs1zAIbo95A0LKlilvJi8YW0NoXYuq3/jjxGgWDxizZ6Yx0AIIjZOoGsXJOPc0/BcnSEUQ2mFBA=="
   "resolved" "https://registry.npmjs.org/@nuxtjs/axios/-/axios-5.13.6.tgz"
   "version" "5.13.6"
@@ -8579,7 +8579,7 @@
     "ufo" "^0.7.7"
     "vue-i18n" "^8.25.0"
 
-"nuxt@^2.12.2":
+"nuxt@^2.15.8":
   "integrity" "sha512-ceK3qLg/Baj7J8mK9bIxqw9AavrF+LXqwYEreBdY/a4Sj8YV4mIvhqea/6E7VTCNNGvKT2sJ/TTJjtfQ597lTA=="
   "resolved" "https://registry.npmjs.org/nuxt/-/nuxt-2.15.8.tgz"
   "version" "2.15.8"