Merge branch 'METAMODEL-1159-composite-query'
diff --git a/core/src/main/java/org/apache/metamodel/membrane/app/DataContextSupplier.java b/core/src/main/java/org/apache/metamodel/membrane/app/DataContextSupplier.java
deleted file mode 100644
index 7ce0cc0..0000000
--- a/core/src/main/java/org/apache/metamodel/membrane/app/DataContextSupplier.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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 org.apache.metamodel.membrane.app;
-
-import java.util.function.Supplier;
-
-import org.apache.metamodel.DataContext;
-import org.apache.metamodel.factory.DataContextFactoryRegistryImpl;
-import org.apache.metamodel.factory.DataContextProperties;
-
-public class DataContextSupplier implements Supplier<DataContext> {
-
- private final String dataSourceName;
- private final DataContextProperties dataContextProperties;
-
- public DataContextSupplier(String dataSourceName, DataContextProperties dataContextProperties) {
- this.dataSourceName = dataSourceName;
- this.dataContextProperties = dataContextProperties;
- }
-
- @Override
- public DataContext get() {
- final DataContext dataContext = DataContextFactoryRegistryImpl.getDefaultInstance().createDataContext(
- dataContextProperties);
- return dataContext;
- }
-
- @Override
- public String toString() {
- return "DataContextSupplier[" + dataSourceName + "]";
- }
-}
diff --git a/core/src/main/java/org/apache/metamodel/membrane/app/federation/FederatedDataContextFactory.java b/core/src/main/java/org/apache/metamodel/membrane/app/federation/FederatedDataContextFactory.java
new file mode 100644
index 0000000..db70942
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/membrane/app/federation/FederatedDataContextFactory.java
@@ -0,0 +1,92 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.metamodel.membrane.app.federation;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import org.apache.metamodel.CompositeDataContext;
+import org.apache.metamodel.ConnectionException;
+import org.apache.metamodel.DataContext;
+import org.apache.metamodel.factory.DataContextFactory;
+import org.apache.metamodel.factory.DataContextProperties;
+import org.apache.metamodel.factory.ResourceFactoryRegistry;
+import org.apache.metamodel.factory.UnsupportedDataContextPropertiesException;
+import org.apache.metamodel.membrane.app.registry.DataSourceRegistry;
+import org.apache.metamodel.membrane.app.registry.TenantContext;
+
+public class FederatedDataContextFactory implements DataContextFactory {
+
+ public static final String DATA_CONTEXT_TYPE = "federated";
+ public static final String PROPERTY_DATA_SOURCES = "datasources";
+
+ private final TenantContext tenant;
+
+ public FederatedDataContextFactory(TenantContext tenant) {
+ this.tenant = tenant;
+ }
+
+ @Override
+ public boolean accepts(DataContextProperties properties, ResourceFactoryRegistry resourceFactoryRegistry) {
+ return DATA_CONTEXT_TYPE.equals(properties.getDataContextType());
+ }
+
+ @Override
+ public DataContext create(DataContextProperties properties, ResourceFactoryRegistry resourceFactoryRegistry)
+ throws UnsupportedDataContextPropertiesException, ConnectionException {
+
+ final Object dataSourcesPropertyValue = properties.toMap().get(PROPERTY_DATA_SOURCES);
+ final Collection<String> dataSourceNames = toDataSourceNames(dataSourcesPropertyValue);
+ final DataSourceRegistry dataSourceRegistry = tenant.getDataSourceRegistry();
+ final List<DataContext> dataContexts =
+ dataSourceNames.stream().map(dataSourceRegistry::openDataContext).collect(Collectors.toList());
+ return new CompositeDataContext(dataContexts);
+ }
+
+ @SuppressWarnings("unchecked")
+ private Collection<String> toDataSourceNames(Object dataSourcesPropertyValue) {
+ if (dataSourcesPropertyValue == null) {
+ return Collections.emptyList();
+ }
+ if ("*".equals(dataSourcesPropertyValue)) {
+ return tenant.getDataSourceRegistry().getDataSourceNames();
+ }
+ if (dataSourcesPropertyValue instanceof String) {
+ final String str = (String) dataSourcesPropertyValue;
+ return Collections.singleton(str);
+ }
+ if (dataSourcesPropertyValue instanceof Collection) {
+ return new HashSet<>((Collection<String>)dataSourcesPropertyValue);
+ }
+ if (dataSourcesPropertyValue.getClass().isArray()) {
+ final Set<String> result = new HashSet<>();
+ final Object[] arr = (Object[]) dataSourcesPropertyValue;
+ for (Object item : arr) {
+ result.addAll(toDataSourceNames(item));
+ }
+ return result;
+ }
+ throw new IllegalArgumentException("Bad '" + PROPERTY_DATA_SOURCES + "' value: " + dataSourcesPropertyValue);
+ }
+
+}
diff --git a/core/src/main/java/org/apache/metamodel/membrane/app/registry/AbstractDataSourceRegistry.java b/core/src/main/java/org/apache/metamodel/membrane/app/registry/AbstractDataSourceRegistry.java
new file mode 100644
index 0000000..b83a509
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/membrane/app/registry/AbstractDataSourceRegistry.java
@@ -0,0 +1,45 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.metamodel.membrane.app.registry;
+
+import org.apache.metamodel.DataContext;
+import org.apache.metamodel.factory.DataContextProperties;
+
+public abstract class AbstractDataSourceRegistry implements DataSourceRegistry {
+
+ private final TenantContext tenantContext;
+
+ public AbstractDataSourceRegistry(TenantContext tenantContext) {
+ this.tenantContext = tenantContext;
+ }
+
+ protected DataContextSupplier createDataContextSupplier(String name, DataContextProperties properties) {
+ final DataContextSupplier supplier = new DataContextSupplier(tenantContext, name, properties);
+ return supplier;
+ }
+
+ @Override
+ public DataContext openDataContext(DataContextProperties properties) {
+ return createDataContextSupplier(null, properties).get();
+ }
+
+ protected TenantContext getTenantContext() {
+ return tenantContext;
+ }
+}
diff --git a/core/src/main/java/org/apache/metamodel/membrane/app/registry/DataContextSupplier.java b/core/src/main/java/org/apache/metamodel/membrane/app/registry/DataContextSupplier.java
new file mode 100644
index 0000000..2297dca
--- /dev/null
+++ b/core/src/main/java/org/apache/metamodel/membrane/app/registry/DataContextSupplier.java
@@ -0,0 +1,74 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.metamodel.membrane.app.registry;
+
+import java.util.Collection;
+import java.util.function.Supplier;
+
+import org.apache.metamodel.DataContext;
+import org.apache.metamodel.factory.DataContextFactory;
+import org.apache.metamodel.factory.DataContextFactoryRegistry;
+import org.apache.metamodel.factory.DataContextFactoryRegistryImpl;
+import org.apache.metamodel.factory.DataContextProperties;
+import org.apache.metamodel.factory.ResourceFactoryRegistry;
+import org.apache.metamodel.factory.ResourceFactoryRegistryImpl;
+import org.apache.metamodel.membrane.app.federation.FederatedDataContextFactory;
+
+public class DataContextSupplier implements Supplier<DataContext> {
+
+ private final String dataSourceName;
+ private final DataContextProperties dataContextProperties;
+ private final TenantContext tenantContext;
+
+ public DataContextSupplier(TenantContext tenantContext, String dataSourceName,
+ DataContextProperties dataContextProperties) {
+ this.tenantContext = tenantContext;
+ this.dataSourceName = dataSourceName;
+ this.dataContextProperties = dataContextProperties;
+ }
+
+ @Override
+ public DataContext get() {
+ final DataContextFactoryRegistry registry = getRegistryForTenant();
+ final DataContext dataContext = registry.createDataContext(dataContextProperties);
+ return dataContext;
+ }
+
+ private DataContextFactoryRegistry getRegistryForTenant() {
+ final ResourceFactoryRegistry resourceFactoryRegistry = ResourceFactoryRegistryImpl.getDefaultInstance();
+ final DataContextFactoryRegistry registry = new DataContextFactoryRegistryImpl(resourceFactoryRegistry);
+
+ // Add default/standard factories. This is pretty cumbersome. New constructor/cloning options in MetaModel
+ // should make this easier: https://github.com/apache/metamodel/pull/192
+ final DataContextFactoryRegistry defaultRegistry = DataContextFactoryRegistryImpl.getDefaultInstance();
+ final Collection<DataContextFactory> defaultFactories = defaultRegistry.getFactories();
+ for (DataContextFactory factory : defaultFactories) {
+ registry.addFactory(factory);
+ }
+
+ // add tenant-specific factories
+ registry.addFactory(new FederatedDataContextFactory(tenantContext));
+ return registry;
+ }
+
+ @Override
+ public String toString() {
+ return "DataContextSupplier[" + dataSourceName + "]";
+ }
+}
diff --git a/core/src/main/java/org/apache/metamodel/membrane/app/registry/file/FileBasedDataSourceRegistry.java b/core/src/main/java/org/apache/metamodel/membrane/app/registry/file/FileBasedDataSourceRegistry.java
index 60c77ae..b7a2d31 100644
--- a/core/src/main/java/org/apache/metamodel/membrane/app/registry/file/FileBasedDataSourceRegistry.java
+++ b/core/src/main/java/org/apache/metamodel/membrane/app/registry/file/FileBasedDataSourceRegistry.java
@@ -28,17 +28,18 @@
import org.apache.metamodel.DataContext;
import org.apache.metamodel.factory.DataContextProperties;
-import org.apache.metamodel.membrane.app.DataContextSupplier;
import org.apache.metamodel.membrane.app.config.JacksonConfig;
import org.apache.metamodel.membrane.app.exceptions.DataSourceAlreadyExistException;
import org.apache.metamodel.membrane.app.exceptions.NoSuchDataSourceException;
-import org.apache.metamodel.membrane.app.registry.DataSourceRegistry;
+import org.apache.metamodel.membrane.app.registry.AbstractDataSourceRegistry;
+import org.apache.metamodel.membrane.app.registry.DataContextSupplier;
+import org.apache.metamodel.membrane.app.registry.TenantContext;
import org.apache.metamodel.membrane.controllers.model.RestDataSourceDefinition;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Strings;
-public class FileBasedDataSourceRegistry implements DataSourceRegistry {
+public class FileBasedDataSourceRegistry extends AbstractDataSourceRegistry {
private static final ObjectMapper OBJECT_MAPPER = JacksonConfig.getObjectMapper();
private static final String DATASOURCE_FILE_SUFFIX = ".json";
@@ -46,7 +47,8 @@
private final File directory;
- public FileBasedDataSourceRegistry(File directory) {
+ public FileBasedDataSourceRegistry(TenantContext tenantContext, File directory) {
+ super(tenantContext);
this.directory = directory;
}
@@ -115,7 +117,7 @@
}
final DataContextSupplier supplier =
- new DataContextSupplier(dataSourceName, dataSource.toDataContextProperties());
+ createDataContextSupplier(dataSourceName, dataSource.toDataContextProperties());
return supplier.get();
}
@@ -134,9 +136,4 @@
throw new UncheckedIOException(new IOException("Unable to delete file: " + file));
}
}
-
- public DataContext openDataContext(DataContextProperties properties) {
- final DataContextSupplier supplier = new DataContextSupplier(null, properties);
- return supplier.get();
- }
}
diff --git a/core/src/main/java/org/apache/metamodel/membrane/app/registry/file/FileBasedTenantContext.java b/core/src/main/java/org/apache/metamodel/membrane/app/registry/file/FileBasedTenantContext.java
index d830125..7e64d3d 100644
--- a/core/src/main/java/org/apache/metamodel/membrane/app/registry/file/FileBasedTenantContext.java
+++ b/core/src/main/java/org/apache/metamodel/membrane/app/registry/file/FileBasedTenantContext.java
@@ -31,7 +31,8 @@
public FileBasedTenantContext(File directory) {
this.directory = directory;
- this.dataContextRegistry = new CachedDataSourceRegistryWrapper(new FileBasedDataSourceRegistry(directory));
+ this.dataContextRegistry =
+ new CachedDataSourceRegistryWrapper(new FileBasedDataSourceRegistry(this, directory));
}
@Override
diff --git a/core/src/main/java/org/apache/metamodel/membrane/app/registry/memory/InMemoryDataSourceRegistry.java b/core/src/main/java/org/apache/metamodel/membrane/app/registry/memory/InMemoryDataSourceRegistry.java
index a457ec0..bff3a73 100644
--- a/core/src/main/java/org/apache/metamodel/membrane/app/registry/memory/InMemoryDataSourceRegistry.java
+++ b/core/src/main/java/org/apache/metamodel/membrane/app/registry/memory/InMemoryDataSourceRegistry.java
@@ -26,16 +26,17 @@
import org.apache.metamodel.DataContext;
import org.apache.metamodel.factory.DataContextProperties;
-import org.apache.metamodel.membrane.app.DataContextSupplier;
import org.apache.metamodel.membrane.app.exceptions.DataSourceAlreadyExistException;
import org.apache.metamodel.membrane.app.exceptions.NoSuchDataSourceException;
-import org.apache.metamodel.membrane.app.registry.DataSourceRegistry;
+import org.apache.metamodel.membrane.app.registry.AbstractDataSourceRegistry;
+import org.apache.metamodel.membrane.app.registry.TenantContext;
-public class InMemoryDataSourceRegistry implements DataSourceRegistry {
+public class InMemoryDataSourceRegistry extends AbstractDataSourceRegistry {
private final Map<String, Supplier<DataContext>> dataSources;
- public InMemoryDataSourceRegistry() {
+ public InMemoryDataSourceRegistry(final TenantContext tenantContext) {
+ super(tenantContext);
dataSources = new LinkedHashMap<>();
}
@@ -46,7 +47,7 @@
throw new DataSourceAlreadyExistException(name);
}
- dataSources.put(name, new DataContextSupplier(name, dataContextProperties));
+ dataSources.put(name, createDataContextSupplier(name, dataContextProperties));
return name;
}
@@ -71,9 +72,4 @@
}
dataSources.remove(dataSourceName);
}
-
- public DataContext openDataContext(DataContextProperties properties) {
- final DataContextSupplier supplier = new DataContextSupplier(null, properties);
- return supplier.get();
- }
}
diff --git a/core/src/main/java/org/apache/metamodel/membrane/app/registry/memory/InMemoryTenantContext.java b/core/src/main/java/org/apache/metamodel/membrane/app/registry/memory/InMemoryTenantContext.java
index 08b2fa9..330f3b4 100644
--- a/core/src/main/java/org/apache/metamodel/membrane/app/registry/memory/InMemoryTenantContext.java
+++ b/core/src/main/java/org/apache/metamodel/membrane/app/registry/memory/InMemoryTenantContext.java
@@ -29,7 +29,7 @@
public InMemoryTenantContext(String tenantIdentifier) {
this.tenantIdentifier = tenantIdentifier;
- this.dataContextRegistry = new CachedDataSourceRegistryWrapper(new InMemoryDataSourceRegistry());
+ this.dataContextRegistry = new CachedDataSourceRegistryWrapper(new InMemoryDataSourceRegistry(this));
}
@Override
diff --git a/postman-tests/Membrane.postman_collection.json b/postman-tests/Membrane.postman_collection.json
index e249ead..78a8f29 100644
--- a/postman-tests/Membrane.postman_collection.json
+++ b/postman-tests/Membrane.postman_collection.json
@@ -1,10 +1,8 @@
{
- "variables": [],
"info": {
+ "_postman_id": "b07b47aa-5a8c-4be5-bbc3-0fd98040ee92",
"name": "Membrane",
- "_postman_id": "fc875392-a36c-6ff7-46fb-53eab9cd3c3e",
- "description": "",
- "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json"
+ "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
},
"item": [
{
@@ -24,14 +22,21 @@
}
],
"request": {
- "url": "{{baseUrl}}/swagger.json",
"method": "GET",
"header": [],
"body": {
"mode": "raw",
"raw": ""
},
- "description": ""
+ "url": {
+ "raw": "{{baseUrl}}/swagger.json",
+ "host": [
+ "{{baseUrl}}"
+ ],
+ "path": [
+ "swagger.json"
+ ]
+ }
},
"response": []
},
@@ -58,20 +63,26 @@
}
],
"request": {
- "url": "{{baseUrl}}/my-tenant",
"method": "PUT",
"header": [
{
"key": "Content-Type",
- "value": "application/json",
- "description": ""
+ "value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \n}"
},
- "description": ""
+ "url": {
+ "raw": "{{baseUrl}}/my-tenant",
+ "host": [
+ "{{baseUrl}}"
+ ],
+ "path": [
+ "my-tenant"
+ ]
+ }
},
"response": []
},
@@ -92,14 +103,21 @@
}
],
"request": {
- "url": "{{baseUrl}}/{{membrane_tenant}}",
"method": "GET",
"header": [],
"body": {
"mode": "raw",
"raw": ""
},
- "description": ""
+ "url": {
+ "raw": "{{baseUrl}}/{{membrane_tenant}}",
+ "host": [
+ "{{baseUrl}}"
+ ],
+ "path": [
+ "{{membrane_tenant}}"
+ ]
+ }
},
"response": []
},
@@ -124,20 +142,27 @@
}
],
"request": {
- "url": "{{baseUrl}}/{{membrane_tenant}}/example-postgres",
"method": "PUT",
"header": [
{
"key": "Content-Type",
- "value": "application/json",
- "description": ""
+ "value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"type\":\"jdbc\",\n \"url\": \"jdbc:postgresql://example-postgres/membrane\",\n \"username\": \"membrane\",\n \"password\": \"secret\"\n}"
},
- "description": ""
+ "url": {
+ "raw": "{{baseUrl}}/{{membrane_tenant}}/example-postgres",
+ "host": [
+ "{{baseUrl}}"
+ ],
+ "path": [
+ "{{membrane_tenant}}",
+ "example-postgres"
+ ]
+ }
},
"response": []
},
@@ -162,20 +187,27 @@
}
],
"request": {
- "url": "{{baseUrl}}/{{membrane_tenant}}/example-couchdb",
"method": "PUT",
"header": [
{
"key": "Content-Type",
- "value": "application/json",
- "description": ""
+ "value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"type\":\"couchdb\",\n \"hostname\": \"example-couchdb\",\n \"username\": \"membrane\",\n \"password\": \"secret\"\n}"
},
- "description": ""
+ "url": {
+ "raw": "{{baseUrl}}/{{membrane_tenant}}/example-couchdb",
+ "host": [
+ "{{baseUrl}}"
+ ],
+ "path": [
+ "{{membrane_tenant}}",
+ "example-couchdb"
+ ]
+ }
},
"response": []
},
@@ -202,20 +234,27 @@
}
],
"request": {
- "url": "{{baseUrl}}/{{membrane_tenant}}/example-pojo",
"method": "PUT",
"header": [
{
"key": "Content-Type",
- "value": "application/json",
- "description": ""
+ "value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"type\":\"pojo\",\n \"table-defs\":\"hello_world (greeting VARCHAR, who VARCHAR); foo (bar INTEGER, baz DATE);\"\n}"
},
- "description": ""
+ "url": {
+ "raw": "{{baseUrl}}/{{membrane_tenant}}/example-pojo",
+ "host": [
+ "{{baseUrl}}"
+ ],
+ "path": [
+ "{{membrane_tenant}}",
+ "example-pojo"
+ ]
+ }
},
"response": []
},
@@ -246,20 +285,27 @@
}
],
"request": {
- "url": "{{baseUrl}}/{{membrane_tenant}}/{{membrane_data_source}}",
"method": "GET",
"header": [
{
"key": "Content-Type",
- "value": "application/json",
- "description": ""
+ "value": "application/json"
}
],
"body": {
"mode": "raw",
- "raw": "{\n \"type\":\"pojo\",\n \"table-defs\":\"hello_world (greeting VARCHAR, who VARCHAR); foo (bar INTEGER, baz DATE);\"\n}"
+ "raw": ""
},
- "description": ""
+ "url": {
+ "raw": "{{baseUrl}}/{{membrane_tenant}}/{{membrane_data_source}}",
+ "host": [
+ "{{baseUrl}}"
+ ],
+ "path": [
+ "{{membrane_tenant}}",
+ "{{membrane_data_source}}"
+ ]
+ }
},
"response": []
},
@@ -288,20 +334,29 @@
}
],
"request": {
- "url": "{{baseUrl}}/{{membrane_tenant}}/{{membrane_data_source}}/s/{{membrane_schema}}",
"method": "GET",
"header": [
{
"key": "Content-Type",
- "value": "application/json",
- "description": ""
+ "value": "application/json"
}
],
"body": {
"mode": "raw",
- "raw": "{\n \"type\":\"pojo\",\n \"table-defs\":\"hello_world (greeting VARCHAR, who VARCHAR); foo (bar INTEGER, baz DATE);\"\n}"
+ "raw": ""
},
- "description": ""
+ "url": {
+ "raw": "{{baseUrl}}/{{membrane_tenant}}/{{membrane_data_source}}/s/{{membrane_schema}}",
+ "host": [
+ "{{baseUrl}}"
+ ],
+ "path": [
+ "{{membrane_tenant}}",
+ "{{membrane_data_source}}",
+ "s",
+ "{{membrane_schema}}"
+ ]
+ }
},
"response": []
},
@@ -332,20 +387,31 @@
}
],
"request": {
- "url": "{{baseUrl}}/{{membrane_tenant}}/{{membrane_data_source}}/s/{{membrane_schema}}/t/{{membrane_table}}",
"method": "GET",
"header": [
{
"key": "Content-Type",
- "value": "application/json",
- "description": ""
+ "value": "application/json"
}
],
"body": {
"mode": "raw",
- "raw": "{\n \"type\":\"pojo\",\n \"table-defs\":\"hello_world (greeting VARCHAR, who VARCHAR); foo (bar INTEGER, baz DATE);\"\n}"
+ "raw": ""
},
- "description": ""
+ "url": {
+ "raw": "{{baseUrl}}/{{membrane_tenant}}/{{membrane_data_source}}/s/{{membrane_schema}}/t/{{membrane_table}}",
+ "host": [
+ "{{baseUrl}}"
+ ],
+ "path": [
+ "{{membrane_tenant}}",
+ "{{membrane_data_source}}",
+ "s",
+ "{{membrane_schema}}",
+ "t",
+ "{{membrane_table}}"
+ ]
+ }
},
"response": []
},
@@ -367,20 +433,32 @@
}
],
"request": {
- "url": "{{baseUrl}}/{{membrane_tenant}}/{{membrane_data_source}}/s/{{membrane_schema}}/t/{{membrane_table}}/d",
"method": "POST",
"header": [
{
"key": "Content-Type",
- "value": "application/json",
- "description": ""
+ "value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n\t\"insert\": [\n\t\t{\n\t\t\t\"bar\": 42,\n\t\t\t\"baz\": null\n\t\t}\n\t]\n}"
},
- "description": ""
+ "url": {
+ "raw": "{{baseUrl}}/{{membrane_tenant}}/{{membrane_data_source}}/s/{{membrane_schema}}/t/{{membrane_table}}/d",
+ "host": [
+ "{{baseUrl}}"
+ ],
+ "path": [
+ "{{membrane_tenant}}",
+ "{{membrane_data_source}}",
+ "s",
+ "{{membrane_schema}}",
+ "t",
+ "{{membrane_table}}",
+ "d"
+ ]
+ }
},
"response": []
},
@@ -402,20 +480,32 @@
}
],
"request": {
- "url": "{{baseUrl}}/{{membrane_tenant}}/{{membrane_data_source}}/s/{{membrane_schema}}/t/{{membrane_table}}/d",
"method": "GET",
"header": [
{
"key": "Content-Type",
- "value": "application/json",
- "description": ""
+ "value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": ""
},
- "description": ""
+ "url": {
+ "raw": "{{baseUrl}}/{{membrane_tenant}}/{{membrane_data_source}}/s/{{membrane_schema}}/t/{{membrane_table}}/d",
+ "host": [
+ "{{baseUrl}}"
+ ],
+ "path": [
+ "{{membrane_tenant}}",
+ "{{membrane_data_source}}",
+ "s",
+ "{{membrane_schema}}",
+ "t",
+ "{{membrane_table}}",
+ "d"
+ ]
+ }
},
"response": []
},
@@ -437,6 +527,17 @@
}
],
"request": {
+ "method": "GET",
+ "header": [
+ {
+ "key": "Content-Type",
+ "value": "application/json"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": ""
+ },
"url": {
"raw": "{{baseUrl}}/{{membrane_tenant}}/{{membrane_data_source}}/q?sql=SELECT * FROM {{membrane_table}}",
"host": [
@@ -450,26 +551,10 @@
"query": [
{
"key": "sql",
- "value": "SELECT * FROM {{membrane_table}}",
- "equals": true,
- "description": ""
+ "value": "SELECT * FROM {{membrane_table}}"
}
- ],
- "variable": []
- },
- "method": "GET",
- "header": [
- {
- "key": "Content-Type",
- "value": "application/json",
- "description": ""
- }
- ],
- "body": {
- "mode": "raw",
- "raw": ""
- },
- "description": ""
+ ]
+ }
},
"response": []
},
@@ -491,20 +576,128 @@
}
],
"request": {
- "url": "{{baseUrl}}/{{membrane_tenant}}/{{membrane_data_source}}/s/{{membrane_schema}}/t/{{membrane_table}}/c/{{membrane_column}}",
"method": "GET",
"header": [
{
"key": "Content-Type",
- "value": "application/json",
- "description": ""
+ "value": "application/json"
}
],
"body": {
"mode": "raw",
- "raw": "{\n \"type\":\"pojo\",\n \"table-defs\":\"hello_world (greeting VARCHAR, who VARCHAR); foo (bar INTEGER, baz DATE);\"\n}"
+ "raw": ""
},
- "description": ""
+ "url": {
+ "raw": "{{baseUrl}}/{{membrane_tenant}}/{{membrane_data_source}}/s/{{membrane_schema}}/t/{{membrane_table}}/c/{{membrane_column}}",
+ "host": [
+ "{{baseUrl}}"
+ ],
+ "path": [
+ "{{membrane_tenant}}",
+ "{{membrane_data_source}}",
+ "s",
+ "{{membrane_schema}}",
+ "t",
+ "{{membrane_table}}",
+ "c",
+ "{{membrane_column}}"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "Create data source - federated",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "id": "9d1f41d7-12f9-44b0-8730-6e869b22e7d2",
+ "exec": [
+ "tests[\"Status code is 200\"] = responseCode.code === 200;",
+ "",
+ "var jsonData = JSON.parse(responseBody);",
+ "tests[\"type is datasource\"] = jsonData.type === \"datasource\";",
+ "tests[\"is NOT updateable\"] = !jsonData.updateable;",
+ "",
+ "tests[\"has > 3 schemas\"] = jsonData.schemas.length > 3;"
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "PUT",
+ "header": [
+ {
+ "key": "Content-Type",
+ "value": "application/json"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": "{\n \"type\": \"federated\",\n \"datasources\": [\n \"example-pojo\",\n \"example-couchdb\",\n \"example-postgres\"\n ]\n}"
+ },
+ "url": {
+ "raw": "{{baseUrl}}/{{membrane_tenant}}/example-federated",
+ "host": [
+ "{{baseUrl}}"
+ ],
+ "path": [
+ "{{membrane_tenant}}",
+ "example-federated"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "Query federated datasource",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "id": "689cf505-4bca-49b1-95a6-a861b026e31b",
+ "exec": [
+ "tests[\"Status code is 200\"] = responseCode.code === 200;",
+ "",
+ "var jsonData = JSON.parse(responseBody);",
+ "tests[\"type is dataset\"] = jsonData.type === \"dataset\";",
+ ""
+ ],
+ "type": "text/javascript"
+ }
+ }
+ ],
+ "request": {
+ "method": "GET",
+ "header": [
+ {
+ "key": "Content-Type",
+ "value": "application/json"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": ""
+ },
+ "url": {
+ "raw": "{{baseUrl}}/{{membrane_tenant}}/example-federated/q?sql=SELECT * FROM {{membrane_schema}}.{{membrane_table}}",
+ "host": [
+ "{{baseUrl}}"
+ ],
+ "path": [
+ "{{membrane_tenant}}",
+ "example-federated",
+ "q"
+ ],
+ "query": [
+ {
+ "key": "sql",
+ "value": "SELECT * FROM {{membrane_schema}}.{{membrane_table}}"
+ }
+ ]
+ }
},
"response": []
},
@@ -527,14 +720,22 @@
}
],
"request": {
- "url": "{{baseUrl}}/{{membrane_tenant}}/{{membrane_data_source}}",
"method": "DELETE",
"header": [],
"body": {
"mode": "raw",
"raw": ""
},
- "description": ""
+ "url": {
+ "raw": "{{baseUrl}}/{{membrane_tenant}}/{{membrane_data_source}}",
+ "host": [
+ "{{baseUrl}}"
+ ],
+ "path": [
+ "{{membrane_tenant}}",
+ "{{membrane_data_source}}"
+ ]
+ }
},
"response": []
},
@@ -557,11 +758,21 @@
}
],
"request": {
- "url": "{{baseUrl}}/{{membrane_tenant}}",
"method": "DELETE",
"header": [],
- "body": {},
- "description": ""
+ "body": {
+ "mode": "raw",
+ "raw": ""
+ },
+ "url": {
+ "raw": "{{baseUrl}}/{{membrane_tenant}}",
+ "host": [
+ "{{baseUrl}}"
+ ],
+ "path": [
+ "{{membrane_tenant}}"
+ ]
+ }
},
"response": []
}