diff --git a/.github/workflows/budibase_ci.yml b/.github/workflows/budibase_ci.yml index a17ca352cc..1b236caab5 100644 --- a/.github/workflows/budibase_ci.yml +++ b/.github/workflows/budibase_ci.yml @@ -147,7 +147,7 @@ jobs: fi test-server: - runs-on: budi-tubby-tornado-quad-core-150gb + runs-on: budi-tubby-tornado-quad-core-300gb steps: - name: Checkout repo uses: actions/checkout@v4 diff --git a/README.md b/README.md index 4979f0ee8e..64492b97e4 100644 --- a/README.md +++ b/README.md @@ -116,7 +116,7 @@ As with anything that we build in Budibase, our new public API is simple to use, You can learn more about the Budibase API at the following places: - [General documentation](https://docs.budibase.com/docs/public-api): Learn how to get your API key, how to use spec, and how to use Postman -- [Interactive API documentation](https://docs.budibase.com/reference/post_applications) : Learn how to interact with the API +- [Interactive API documentation](https://docs.budibase.com/reference/appcreate) : Learn how to interact with the API

diff --git a/i18n/README.es.md b/i18n/README.es.md index a7d1112914..ee92ca24d5 100644 --- a/i18n/README.es.md +++ b/i18n/README.es.md @@ -144,7 +144,7 @@ del sistema. Budibase API ofrece: Puedes aprender mas acerca de Budibase API en los siguientes documentos: - [Documentacion general](https://docs.budibase.com/docs/public-api) : Como optener tu clave para la API, usar Insomnia y Postman -- [API Interactiva](https://docs.budibase.com/reference/post_applications) : Aprende como trabajar con la API +- [API Interactiva](https://docs.budibase.com/reference/appcreate) : Aprende como trabajar con la API #### Guias diff --git a/packages/server/package.json b/packages/server/package.json index 48ab0685d9..b835477489 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -80,7 +80,7 @@ "dotenv": "8.2.0", "form-data": "4.0.0", "global-agent": "3.0.0", - "google-spreadsheet": "npm:@budibase/google-spreadsheet@4.1.2", + "google-spreadsheet": "npm:@budibase/google-spreadsheet@4.1.3", "ioredis": "5.3.2", "isolated-vm": "^4.7.2", "jimp": "0.22.12", diff --git a/packages/server/src/api/routes/tests/datasource.spec.ts b/packages/server/src/api/routes/tests/datasource.spec.ts index 4ca766247b..237133e639 100644 --- a/packages/server/src/api/routes/tests/datasource.spec.ts +++ b/packages/server/src/api/routes/tests/datasource.spec.ts @@ -17,9 +17,14 @@ import { SupportedSqlTypes, JsonFieldSubType, } from "@budibase/types" -import { DatabaseName, getDatasource } from "../../../integrations/tests/utils" +import { + DatabaseName, + getDatasource, + knexClient, +} from "../../../integrations/tests/utils" import { tableForDatasource } from "../../../tests/utilities/structures" import nock from "nock" +import { Knex } from "knex" describe("/datasources", () => { const config = setup.getConfig() @@ -164,11 +169,15 @@ describe("/datasources", () => { [DatabaseName.MYSQL, getDatasource(DatabaseName.MYSQL)], [DatabaseName.SQL_SERVER, getDatasource(DatabaseName.SQL_SERVER)], [DatabaseName.MARIADB, getDatasource(DatabaseName.MARIADB)], + [DatabaseName.ORACLE, getDatasource(DatabaseName.ORACLE)], ])("%s", (_, dsProvider) => { let rawDatasource: Datasource + let client: Knex + beforeEach(async () => { rawDatasource = await dsProvider datasource = await config.api.datasource.create(rawDatasource) + client = await knexClient(rawDatasource) }) describe("get", () => { @@ -285,9 +294,6 @@ describe("/datasources", () => { [FieldType.STRING]: { name: stringName, type: FieldType.STRING, - constraints: { - presence: true, - }, }, [FieldType.LONGFORM]: { name: "longform", @@ -381,10 +387,6 @@ describe("/datasources", () => { ), schema: Object.entries(table.schema).reduce( (acc, [fieldName, field]) => { - // the constraint will be unset - as the DB doesn't recognise it as not null - if (fieldName === stringName) { - field.constraints = {} - } acc[fieldName] = expect.objectContaining({ ...field, }) @@ -441,20 +443,49 @@ describe("/datasources", () => { }) describe("info", () => { - it("should fetch information about postgres datasource", async () => { - const table = await config.api.table.save( - tableForDatasource(datasource, { - schema: { - name: { - name: "name", - type: FieldType.STRING, - }, - }, - }) - ) + it("should fetch information about a datasource with a single table", async () => { + const existingTableNames = ( + await config.api.datasource.info(datasource) + ).tableNames + + const tableName = generator.guid() + await client.schema.createTable(tableName, table => { + table.increments("id").primary() + table.string("name") + }) const info = await config.api.datasource.info(datasource) - expect(info.tableNames).toContain(table.name) + expect(info.tableNames).toEqual( + expect.arrayContaining([tableName, ...existingTableNames]) + ) + expect(info.tableNames).toHaveLength(existingTableNames.length + 1) + }) + + it("should fetch information about a datasource with multiple tables", async () => { + const existingTableNames = ( + await config.api.datasource.info(datasource) + ).tableNames + + const tableNames = [ + generator.guid(), + generator.guid(), + generator.guid(), + generator.guid(), + ] + for (const tableName of tableNames) { + await client.schema.createTable(tableName, table => { + table.increments("id").primary() + table.string("name") + }) + } + + const info = await config.api.datasource.info(datasource) + expect(info.tableNames).toEqual( + expect.arrayContaining([...tableNames, ...existingTableNames]) + ) + expect(info.tableNames).toHaveLength( + existingTableNames.length + tableNames.length + ) }) }) }) diff --git a/packages/server/src/integrations/oracle.ts b/packages/server/src/integrations/oracle.ts index d1c0978b89..6139b18844 100644 --- a/packages/server/src/integrations/oracle.ts +++ b/packages/server/src/integrations/oracle.ts @@ -400,7 +400,9 @@ class OracleIntegration extends Sql implements DatasourcePlus { if (oracleConstraint.type === OracleContraintTypes.PRIMARY) { table.primary!.push(columnName) } else if ( - oracleConstraint.type === OracleContraintTypes.NOT_NULL_OR_CHECK + oracleConstraint.type === + OracleContraintTypes.NOT_NULL_OR_CHECK && + oracleConstraint.searchCondition?.endsWith("IS NOT NULL") ) { table.schema[columnName].constraints = { presence: true, @@ -421,7 +423,11 @@ class OracleIntegration extends Sql implements DatasourcePlus { const columnsResponse = await this.internalQuery({ sql: OracleIntegration.COLUMNS_SQL, }) - return (columnsResponse.rows || []).map(row => row.TABLE_NAME) + const tableNames = new Set() + for (const row of columnsResponse.rows || []) { + tableNames.add(row.TABLE_NAME) + } + return Array.from(tableNames) } async testConnection() { diff --git a/yarn.lock b/yarn.lock index 607db0b7bb..0195f19a2a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12072,10 +12072,10 @@ google-p12-pem@^4.0.0: dependencies: node-forge "^1.3.1" -"google-spreadsheet@npm:@budibase/google-spreadsheet@4.1.2": - version "4.1.2" - resolved "https://registry.yarnpkg.com/@budibase/google-spreadsheet/-/google-spreadsheet-4.1.2.tgz#90548ccba2284b3042b08d2974ef3caeaf772ad9" - integrity sha512-dxoY3rQGGnuNeZiXhNc9oYPduzU8xnIjWujFwNvaRRv3zWeUV7mj6HE2o/OJOeekPGt7o44B+w6DfkiaoteZgg== +"google-spreadsheet@npm:@budibase/google-spreadsheet@4.1.3": + version "4.1.3" + resolved "https://registry.yarnpkg.com/@budibase/google-spreadsheet/-/google-spreadsheet-4.1.3.tgz#bcee7bd9d90f82c54b16a9aca963b87aceb050ad" + integrity sha512-03VX3/K5NXIh6+XAIDZgcHPmR76xwd8vIDL7RedMpvM2IcXK0Iq/KU7FmLY0t/mKqORAGC7+0rajd0jLFezC4w== dependencies: axios "^1.4.0" lodash "^4.17.21"