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"