diff --git a/packages/server/src/api/controllers/datasource.js b/packages/server/src/api/controllers/datasource.js index 5e5151f76e..f248d1957a 100644 --- a/packages/server/src/api/controllers/datasource.js +++ b/packages/server/src/api/controllers/datasource.js @@ -68,10 +68,11 @@ exports.query = async function (ctx) { const datasourceId = queryJson.endpoint.datasourceId const database = new CouchDB(ctx.appId) const datasource = await database.get(datasourceId) - const source = integrations[datasource.source] + const Integration = integrations[datasource.source] // query is the opinionated function - if (source.query) { - ctx.body = await source.query(queryJson) + if (Integration.prototype.query) { + const integration = new Integration(datasource.config) + ctx.body = await integration.query(queryJson) } else { ctx.throw(400, "Datasource does not support query.") } diff --git a/packages/server/src/api/routes/tests/datasource.spec.js b/packages/server/src/api/routes/tests/datasource.spec.js index c1448894b1..94235f8d35 100644 --- a/packages/server/src/api/routes/tests/datasource.spec.js +++ b/packages/server/src/api/routes/tests/datasource.spec.js @@ -2,6 +2,9 @@ let setup = require("./utilities") let { basicDatasource } = setup.structures let { checkBuilderEndpoint } = require("./utilities/TestFunctions") +jest.mock("pg") +const pg = require("pg") + describe("/datasources", () => { let request = setup.getRequest() let config = setup.getConfig() @@ -66,6 +69,37 @@ describe("/datasources", () => { }) }) + describe("query", () => { + it("should be able to query a pg datasource", async () => { + const res = await request + .post(`/api/datasources/query`) + .send({ + endpoint: { + datasourceId: datasource._id, + operation: "READ", + // table name below + entityId: "users", + }, + resource: { + fields: ["name", "age"], + }, + filters: { + string: { + name: "John", + }, + }, + }) + .set(config.defaultHeaders()) + .expect(200) + // this is mock data, can't test it + expect(res.body).toBeDefined() + expect(pg.queryMock).toHaveBeenCalledWith({ + bindings: ["John%", 5000], + sql: `select "name", "age" from "users" where "name" like $1 limit $2` + }) + }) + }) + describe("destroy", () => { it("deletes queries for the datasource after deletion and returns a success message", async () => { await config.createQuery() diff --git a/packages/server/src/db/utils.js b/packages/server/src/db/utils.js index 43a6056b9f..3af943cb8c 100644 --- a/packages/server/src/db/utils.js +++ b/packages/server/src/db/utils.js @@ -281,7 +281,7 @@ exports.getWebhookParams = (webhookId = null, otherProps = {}) => { * Generates a new datasource ID. * @returns {string} The new datasource ID which the webhook doc can be stored under. */ -exports.generateDatasourceID = ({ plus = false }) => { +exports.generateDatasourceID = ({ plus = false } = {}) => { return `${ plus ? DocumentTypes.DATASOURCE_PLUS : DocumentTypes.DATASOURCE }${SEPARATOR}${newid()}` diff --git a/packages/server/src/integrations/base/sql.js b/packages/server/src/integrations/base/sql.js index 61d18656ce..0d40e85f3e 100644 --- a/packages/server/src/integrations/base/sql.js +++ b/packages/server/src/integrations/base/sql.js @@ -11,6 +11,9 @@ function addFilters(query, filters) { fn(key, value) } } + if (!filters) { + return query + } if (filters.string) { iterate(filters.string, (key, value) => { query = query.where(key, "like", `${value}%`) @@ -72,11 +75,11 @@ function buildRead(knex, json, limit) { } } // handle pagination - if (paginate.page && paginate.limit) { + if (paginate && paginate.page && paginate.limit) { const page = paginate.page <= 1 ? 0 : paginate.page - 1 const offset = page * paginate.limit query = query.offset(offset).limit(paginate.limit) - } else if (paginate.limit) { + } else if (paginate && paginate.limit) { query = query.limit(paginate.limit) } else { query.limit(limit)