From 8154fe3445efaefa5d7b243f42bcb01a5f3dd251 Mon Sep 17 00:00:00 2001 From: Mel O'Hagan Date: Wed, 22 Jun 2022 15:58:15 +0100 Subject: [PATCH 1/4] Use raw sql to get money type as numeric --- packages/server/src/definitions/common.ts | 1 + packages/server/src/integrations/base/sql.ts | 22 ++++++++++++++++-- packages/server/yarn.lock | 24 ++++++++++++-------- 3 files changed, 36 insertions(+), 11 deletions(-) diff --git a/packages/server/src/definitions/common.ts b/packages/server/src/definitions/common.ts index 4aec0d103d..f7e5a9a049 100644 --- a/packages/server/src/definitions/common.ts +++ b/packages/server/src/definitions/common.ts @@ -12,6 +12,7 @@ export interface Application extends Base { export interface FieldSchema { // TODO: replace with field types enum when done type: string + externalType?: string fieldName?: string name: string tableId?: string diff --git a/packages/server/src/integrations/base/sql.ts b/packages/server/src/integrations/base/sql.ts index 782f61e49e..6b054b2872 100644 --- a/packages/server/src/integrations/base/sql.ts +++ b/packages/server/src/integrations/base/sql.ts @@ -89,6 +89,24 @@ function parseFilters(filters: SearchFilters | undefined): SearchFilters { return filters } +function generateSelectStatement(json: QueryJson, knex: Knex): any[] { + const { resource, meta } = json + const schema = meta?.table?.schema + return resource.fields.map(field => { + const shortFieldName = field.match(/(?<=\.).*$/g)?.[0] + if (shortFieldName) { + const externalType = schema?.[shortFieldName].externalType + if (externalType?.includes("money")) { + const fieldName = field.split(/\./g) + return knex.raw( + `"${fieldName?.[0]}"."${fieldName?.[1]}"::money::numeric as "${field}"` + ) + } + } + return `${field} as ${field}` + }) +} + class InternalBuilder { private readonly client: string @@ -323,12 +341,12 @@ class InternalBuilder { if (!resource) { resource = { fields: [] } } - let selectStatement: string | string[] = "*" + let selectStatement: string | any[] = "*" // handle select if (resource.fields && resource.fields.length > 0) { // select the resources as the format "table.columnName" - this is what is provided // by the resource builder further up - selectStatement = resource.fields.map(field => `${field} as ${field}`) + selectStatement = generateSelectStatement(json, knex) } let foundLimit = limit || BASE_LIMIT // handle pagination diff --git a/packages/server/yarn.lock b/packages/server/yarn.lock index 2c61b9aa49..e8277b88b5 100644 --- a/packages/server/yarn.lock +++ b/packages/server/yarn.lock @@ -1094,11 +1094,12 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== -"@budibase/backend-core@1.0.207-alpha.3": - version "1.0.207-alpha.3" - resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-1.0.207-alpha.3.tgz#98bced0575ec4e2b158239a8c73b39ca2d816719" - integrity sha512-DU4X6jJ+DfhzOv4TTa1w4Dk5ZEdlK/z1joCTruT+SGM5qI75bXrGeol5OX2OaEbNKtXFKJ1zeVTmBCYcu7OFUg== +"@budibase/backend-core@1.0.207-alpha.6": + version "1.0.207-alpha.6" + resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-1.0.207-alpha.6.tgz#47fed5cc78686e23951a050479c777673f725c17" + integrity sha512-mB3i9TyNbdlE8TmsAWGXhphwLRlrBd2bDfvOYTz3CP7xzql1FXGoWfOqA87vNaGBDrtOyQQnmbYeTc3Tn2OHcg== dependencies: + "@budibase/types" "^1.0.207-alpha.6" "@techpass/passport-openidconnect" "0.3.2" aws-sdk "2.1030.0" bcrypt "5.0.1" @@ -1175,12 +1176,12 @@ svelte-flatpickr "^3.2.3" svelte-portal "^1.0.0" -"@budibase/pro@1.0.207-alpha.3": - version "1.0.207-alpha.3" - resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-1.0.207-alpha.3.tgz#9bde845ceb685f1b43286a124620c21fdf891a01" - integrity sha512-WFEMujpKTVAMvAgLBnMdw8ou9PxsbM4Oa9Dq+DAUsWpPACsMWOProyHLsdRxJyvHlgGfwVjo5MEusvStjI4j6g== +"@budibase/pro@1.0.207-alpha.6": + version "1.0.207-alpha.6" + resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-1.0.207-alpha.6.tgz#04a81281beeb230c0c1a1f48237a94e1150a7851" + integrity sha512-IDQdKHaojfGlL8xLSQ1gYrLyipgUYPJ6Mjrrp8TcWnpwTOA2Wtzen31E5HG6YxZU8g8rN6k9S0Nsp88JKOGSrg== dependencies: - "@budibase/backend-core" "1.0.207-alpha.3" + "@budibase/backend-core" "1.0.207-alpha.6" node-fetch "^2.6.1" "@budibase/standard-components@^0.9.139": @@ -1201,6 +1202,11 @@ svelte-apexcharts "^1.0.2" svelte-flatpickr "^3.1.0" +"@budibase/types@^1.0.207-alpha.6": + version "1.0.208" + resolved "https://registry.yarnpkg.com/@budibase/types/-/types-1.0.208.tgz#c45cb494fb5b85229e15a34c6ac1805bae5be867" + integrity sha512-zKIHg6TGK+soVxMNZNrGypP3DCrd3jhlUQEFeQ+rZR6/tCue1G74bjzydY5FjnLEsXeLH1a0hkS5HulTmvQ2bA== + "@bull-board/api@3.7.0": version "3.7.0" resolved "https://registry.yarnpkg.com/@bull-board/api/-/api-3.7.0.tgz#231f687187c0cb34e0b97f463917b6aaeb4ef6af" From 9603a92c2c86b4b7ce0c93d1735068dad9a27551 Mon Sep 17 00:00:00 2001 From: Mel O'Hagan Date: Wed, 22 Jun 2022 16:13:02 +0100 Subject: [PATCH 2/4] Only cast money as numeric for Postgres --- packages/server/src/integrations/base/sql.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/server/src/integrations/base/sql.ts b/packages/server/src/integrations/base/sql.ts index 6b054b2872..87243c073e 100644 --- a/packages/server/src/integrations/base/sql.ts +++ b/packages/server/src/integrations/base/sql.ts @@ -94,7 +94,7 @@ function generateSelectStatement(json: QueryJson, knex: Knex): any[] { const schema = meta?.table?.schema return resource.fields.map(field => { const shortFieldName = field.match(/(?<=\.).*$/g)?.[0] - if (shortFieldName) { + if (shortFieldName && knex.client.config.client === "pg") { const externalType = schema?.[shortFieldName].externalType if (externalType?.includes("money")) { const fieldName = field.split(/\./g) From ece1e7533d71106d27fc2d476a7ba001b291940d Mon Sep 17 00:00:00 2001 From: Mel O'Hagan Date: Thu, 23 Jun 2022 09:41:43 +0100 Subject: [PATCH 3/4] Refactor - simplify regex and use enum --- packages/server/src/integrations/base/sql.ts | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/server/src/integrations/base/sql.ts b/packages/server/src/integrations/base/sql.ts index 87243c073e..c9841347a6 100644 --- a/packages/server/src/integrations/base/sql.ts +++ b/packages/server/src/integrations/base/sql.ts @@ -93,13 +93,14 @@ function generateSelectStatement(json: QueryJson, knex: Knex): any[] { const { resource, meta } = json const schema = meta?.table?.schema return resource.fields.map(field => { - const shortFieldName = field.match(/(?<=\.).*$/g)?.[0] - if (shortFieldName && knex.client.config.client === "pg") { - const externalType = schema?.[shortFieldName].externalType + const fieldNames = field.split(/\./g) + const tableName = fieldNames[0] + const columnName = fieldNames[1] + if (columnName && knex.client.config.client === SqlClients.POSTGRES) { + const externalType = schema?.[columnName].externalType if (externalType?.includes("money")) { - const fieldName = field.split(/\./g) return knex.raw( - `"${fieldName?.[0]}"."${fieldName?.[1]}"::money::numeric as "${field}"` + `"${tableName}"."${columnName}"::money::numeric as "${field}"` ) } } From 633a701b0ce56bcd3139a23768cf7e8ccfe0eca5 Mon Sep 17 00:00:00 2001 From: Mel O'Hagan Date: Thu, 23 Jun 2022 13:09:22 +0100 Subject: [PATCH 4/4] Added Knex.Raw to return type --- packages/server/src/integrations/base/sql.ts | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/packages/server/src/integrations/base/sql.ts b/packages/server/src/integrations/base/sql.ts index c9841347a6..2758b6f1f1 100644 --- a/packages/server/src/integrations/base/sql.ts +++ b/packages/server/src/integrations/base/sql.ts @@ -89,7 +89,10 @@ function parseFilters(filters: SearchFilters | undefined): SearchFilters { return filters } -function generateSelectStatement(json: QueryJson, knex: Knex): any[] { +function generateSelectStatement( + json: QueryJson, + knex: Knex +): (string | Knex.Raw)[] { const { resource, meta } = json const schema = meta?.table?.schema return resource.fields.map(field => { @@ -235,9 +238,7 @@ class InternalBuilder { } addRelationships( - knex: Knex, query: KnexQuery, - fields: string | string[], fromTable: string, relationships: RelationshipsJson[] | undefined ): KnexQuery { @@ -342,7 +343,7 @@ class InternalBuilder { if (!resource) { resource = { fields: [] } } - let selectStatement: string | any[] = "*" + let selectStatement: string | (string | Knex.Raw)[] = "*" // handle select if (resource.fields && resource.fields.length > 0) { // select the resources as the format "table.columnName" - this is what is provided @@ -382,13 +383,7 @@ class InternalBuilder { preQuery = this.addSorting(preQuery, json) } // handle joins - query = this.addRelationships( - knex, - preQuery, - selectStatement, - tableName, - relationships - ) + query = this.addRelationships(preQuery, tableName, relationships) return this.addFilters(query, filters, { relationship: true }) }