diff --git a/.run/Run NocoDB Sqlite.run.xml b/.run/Run NocoDB Sqlite.run.xml index 19996f59ba..e7b120a2af 100644 --- a/.run/Run NocoDB Sqlite.run.xml +++ b/.run/Run NocoDB Sqlite.run.xml @@ -12,4 +12,4 @@ - \ No newline at end of file + diff --git a/packages/nc-gui/components/dashboard/settings/data-sources/CreateBase.vue b/packages/nc-gui/components/dashboard/settings/data-sources/CreateBase.vue index bb4f6d56d8..296f0bced1 100644 --- a/packages/nc-gui/components/dashboard/settings/data-sources/CreateBase.vue +++ b/packages/nc-gui/components/dashboard/settings/data-sources/CreateBase.vue @@ -495,7 +495,7 @@ watch(
- + {{ $t('activity.useConnectionUrl') }}
@@ -611,7 +611,7 @@ watch(
- + {{ $t('activity.testDbConn') }} diff --git a/packages/nc-gui/lang/fr.json b/packages/nc-gui/lang/fr.json index 28d5266003..402c97bd4f 100644 --- a/packages/nc-gui/lang/fr.json +++ b/packages/nc-gui/lang/fr.json @@ -260,7 +260,7 @@ "barcodeFormat": "Format du code-barres", "qrCodeValueTooLong": "Trop de caractères pour un code QR", "barcodeValueTooLong": "Trop de caractères pour un code-barres", - "currentLocation": "Current Location", + "currentLocation": "Emplacement actuel", "lng": "Lng", "lat": "Lat", "aggregateFunction": "Fonction agrégée", @@ -385,12 +385,12 @@ "nextRecord": "Ligne suivante", "previousRecord": "Ligne précédente", "copyApiURL": "Copier l'URL de l'API", - "createTable": "Create New Table", + "createTable": "Créer une nouvelle table", "refreshTable": "Actualiser le tableau", - "renameTable": "Rename Table", - "deleteTable": "Delete Table", + "renameTable": "Renommer la table", + "deleteTable": "Supprimer la table", "addField": "Ajouter un nouveau champ à ce tableau", - "setDisplay": "Set as Display value", + "setDisplay": "Définir comme valeur d'affichage", "addRow": "Ajouter une nouvelle ligne", "saveRow": "Enregistrer la ligne", "saveAndExit": "Enregistrer et quitter", diff --git a/packages/nc-gui/package-lock.json b/packages/nc-gui/package-lock.json index 4a50a2051b..db8ca28452 100644 --- a/packages/nc-gui/package-lock.json +++ b/packages/nc-gui/package-lock.json @@ -110,7 +110,7 @@ } }, "../nocodb-sdk": { - "version": "0.107.4", + "version": "0.107.5", "license": "AGPL-3.0-or-later", "dependencies": { "axios": "^0.21.1", diff --git a/packages/nc-lib-gui/package.json b/packages/nc-lib-gui/package.json index 34d5efbf1b..c480b45bae 100644 --- a/packages/nc-lib-gui/package.json +++ b/packages/nc-lib-gui/package.json @@ -1,6 +1,6 @@ { "name": "nc-lib-gui", - "version": "0.107.4", + "version": "0.107.5", "description": "NocoDB GUI", "author": { "name": "NocoDB", diff --git a/packages/nocodb-sdk/package-lock.json b/packages/nocodb-sdk/package-lock.json index bc7fc27f3c..3eeec3c695 100644 --- a/packages/nocodb-sdk/package-lock.json +++ b/packages/nocodb-sdk/package-lock.json @@ -1,12 +1,12 @@ { "name": "nocodb-sdk", - "version": "0.107.4", + "version": "0.107.5", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "nocodb-sdk", - "version": "0.107.4", + "version": "0.107.5", "license": "AGPL-3.0-or-later", "dependencies": { "axios": "^0.21.1", diff --git a/packages/nocodb-sdk/package.json b/packages/nocodb-sdk/package.json index 9709ad7d86..eafc8a6866 100644 --- a/packages/nocodb-sdk/package.json +++ b/packages/nocodb-sdk/package.json @@ -1,6 +1,6 @@ { "name": "nocodb-sdk", - "version": "0.107.4", + "version": "0.107.5", "description": "NocoDB SDK", "main": "build/main/index.js", "typings": "build/main/index.d.ts", diff --git a/packages/nocodb-sdk/src/lib/Api.ts b/packages/nocodb-sdk/src/lib/Api.ts index 3d0a0e92f3..8903a6d481 100644 --- a/packages/nocodb-sdk/src/lib/Api.ts +++ b/packages/nocodb-sdk/src/lib/Api.ts @@ -1603,7 +1603,7 @@ export interface NormalColumnRequestType { /** Data Type Extra */ dtx?: StringOrNullType; /** Data Type Extra Precision */ - dtxp?: StringOrNullType | number; + dtxp?: string | number | null; /** Data Type Extra Scale */ dtxs?: StringOrNullType | number; /** Numeric Precision */ diff --git a/packages/nocodb/package-lock.json b/packages/nocodb/package-lock.json index 6095a65621..de526510b2 100644 --- a/packages/nocodb/package-lock.json +++ b/packages/nocodb/package-lock.json @@ -1,12 +1,12 @@ { "name": "nocodb", - "version": "0.107.4", + "version": "0.107.5", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "nocodb", - "version": "0.107.4", + "version": "0.107.5", "license": "AGPL-3.0-or-later", "dependencies": { "@google-cloud/storage": "^5.7.2", @@ -80,7 +80,7 @@ "mysql2": "^3.2.0", "nanoid": "^3.1.20", "nc-help": "^0.2.87", - "nc-lib-gui": "0.107.4", + "nc-lib-gui": "0.107.5", "nc-plugin": "^0.1.3", "ncp": "^2.0.0", "nocodb-sdk": "file:../nocodb-sdk", @@ -190,7 +190,7 @@ } }, "../nocodb-sdk": { - "version": "0.107.4", + "version": "0.107.5", "license": "AGPL-3.0-or-later", "dependencies": { "axios": "^0.21.1", @@ -13157,9 +13157,9 @@ } }, "node_modules/nc-lib-gui": { - "version": "0.107.4", - "resolved": "https://registry.npmjs.org/nc-lib-gui/-/nc-lib-gui-0.107.4.tgz", - "integrity": "sha512-+e0jjJgrBfgLGTTShkcu1QQ2I0QxE/NUCCJ5L8KeZibm71pvgxL/P2hfatSz8PvzSDU/YwXnyXZQkeaSDBzNyA==", + "version": "0.107.5", + "resolved": "https://registry.npmjs.org/nc-lib-gui/-/nc-lib-gui-0.107.5.tgz", + "integrity": "sha512-bFmKo6qDmrHY7a3itHMnp1A8qFecHyNKZABWK4GIdA8xCeSx6rLL8LGzxDRsD3fIXFwTCzSd8iPJECHaF5fcFg==", "dependencies": { "express": "^4.17.1" } @@ -28442,9 +28442,9 @@ } }, "nc-lib-gui": { - "version": "0.107.4", - "resolved": "https://registry.npmjs.org/nc-lib-gui/-/nc-lib-gui-0.107.4.tgz", - "integrity": "sha512-+e0jjJgrBfgLGTTShkcu1QQ2I0QxE/NUCCJ5L8KeZibm71pvgxL/P2hfatSz8PvzSDU/YwXnyXZQkeaSDBzNyA==", + "version": "0.107.5", + "resolved": "https://registry.npmjs.org/nc-lib-gui/-/nc-lib-gui-0.107.5.tgz", + "integrity": "sha512-bFmKo6qDmrHY7a3itHMnp1A8qFecHyNKZABWK4GIdA8xCeSx6rLL8LGzxDRsD3fIXFwTCzSd8iPJECHaF5fcFg==", "requires": { "express": "^4.17.1" } diff --git a/packages/nocodb/package.json b/packages/nocodb/package.json index 1b8701a2e6..d9dc9b67c7 100644 --- a/packages/nocodb/package.json +++ b/packages/nocodb/package.json @@ -1,6 +1,6 @@ { "name": "nocodb", - "version": "0.107.4", + "version": "0.107.5", "description": "NocoDB Backend", "main": "dist/bundle.js", "author": { @@ -113,7 +113,7 @@ "mysql2": "^3.2.0", "nanoid": "^3.1.20", "nc-help": "^0.2.87", - "nc-lib-gui": "0.107.4", + "nc-lib-gui": "0.107.5", "nc-plugin": "^0.1.3", "ncp": "^2.0.0", "nocodb-sdk": "file:../nocodb-sdk", diff --git a/packages/nocodb/src/Noco.ts b/packages/nocodb/src/Noco.ts index 1b93161bb7..048901ac47 100644 --- a/packages/nocodb/src/Noco.ts +++ b/packages/nocodb/src/Noco.ts @@ -1,6 +1,6 @@ +import path from 'path'; import Sentry, { Handlers } from '@sentry/node'; import { Logger } from '@nestjs/common'; -import path from 'path'; import { NestFactory } from '@nestjs/core'; import clear from 'clear'; import * as express from 'express'; diff --git a/packages/nocodb/src/db/BaseModelSqlv2.ts b/packages/nocodb/src/db/BaseModelSqlv2.ts index b82ced126d..1d8dd24a1f 100644 --- a/packages/nocodb/src/db/BaseModelSqlv2.ts +++ b/packages/nocodb/src/db/BaseModelSqlv2.ts @@ -144,10 +144,24 @@ class BaseModelSqlv2 { autoBind(this); } - public async readByPk(id?: any, validateFormula = false): Promise { + public async readByPk( + id?: any, + validateFormula = false, + query: any = {}, + ): Promise { const qb = this.dbDriver(this.tnPath); - await this.selectObject({ qb, validateFormula }); + const { ast, dependencyFields } = await getAst({ + query, + model: this.model, + view: this.viewId && (await View.get(this.viewId)), + }); + + await this.selectObject({ + ...(dependencyFields ?? {}), + qb, + validateFormula, + }); qb.where(_wherePk(this.model.primaryKeys, id)); @@ -167,14 +181,7 @@ class BaseModelSqlv2 { data.__proto__ = proto; } - // retrieve virtual column data as well - const project = await Project.get(this.model.project_id); - const { model, view } = await getViewAndModelByAliasOrId({ - projectName: project.title, - tableName: this.model.title, - }); - const { ast } = await getAst({ model, view }); - return data ? await nocoExecute(ast, data, {}) : {}; + return data ? await nocoExecute(ast, data, {}, query) : {}; } public async exist(id?: any): Promise { @@ -204,7 +211,7 @@ class BaseModelSqlv2 { ): Promise { const { where, ...rest } = this._getListArgs(args as any); const qb = this.dbDriver(this.tnPath); - await this.selectObject({ qb, validateFormula }); + await this.selectObject({ ...args, qb, validateFormula }); const aliasColObjMap = await this.model.getAliasColObjMap(); const sorts = extractSortsObject(rest?.sort, aliasColObjMap); @@ -2188,6 +2195,7 @@ class BaseModelSqlv2 { raw?: boolean; } = {}, ) { + let trx; try { // TODO: ag column handling for raw bulk insert const insertDatas = raw @@ -2216,7 +2224,7 @@ class BaseModelSqlv2 { // refer : https://www.sqlite.org/limits.html const chunkSize = this.isSqlite ? 10 : _chunkSize; - const trx = await this.dbDriver.transaction(); + trx = await this.dbDriver.transaction(); if (!foreign_key_checks) { if (this.isPg) { @@ -2247,6 +2255,7 @@ class BaseModelSqlv2 { return response; } catch (e) { + await trx?.rollback(); // await this.errorInsertb(e, data, null); throw e; } diff --git a/packages/nocodb/src/schema/swagger.json b/packages/nocodb/src/schema/swagger.json index 2912be1cb4..690c3ce3bb 100644 --- a/packages/nocodb/src/schema/swagger.json +++ b/packages/nocodb/src/schema/swagger.json @@ -17834,10 +17834,13 @@ "dtxp": { "oneOf": [ { - "$ref": "#/components/schemas/StringOrNull" + "type": "string" }, { "type": "number" + }, + { + "type": "null" } ], "description": "Data Type Extra Precision" diff --git a/packages/nocodb/src/services/app-init.service.ts b/packages/nocodb/src/services/app-init.service.ts index c913fcaefb..e1050d480c 100644 --- a/packages/nocodb/src/services/app-init.service.ts +++ b/packages/nocodb/src/services/app-init.service.ts @@ -4,7 +4,7 @@ import { Connection } from '../connection/connection'; import initAdminFromEnv from '../helpers/initAdminFromEnv'; import NcPluginMgrv2 from '../helpers/NcPluginMgrv2'; import { MetaService } from '../meta/meta.service'; -import { User } from '../models' +import { User } from '../models'; import Noco from '../Noco'; import getInstance from '../utils/getInstance'; import NcConfigFactory from '../utils/NcConfigFactory'; diff --git a/packages/nocodb/src/services/datas.service.ts b/packages/nocodb/src/services/datas.service.ts index 1e1aa78d24..c41609f6c0 100644 --- a/packages/nocodb/src/services/datas.service.ts +++ b/packages/nocodb/src/services/datas.service.ts @@ -185,8 +185,8 @@ export class DatasService { view, }); - const data = await baseModel.findOne({ ...args, dependencyFields }); - return data ? await nocoExecute(ast, data, {}, {}) : {}; + const data = await baseModel.findOne({ ...args, ...dependencyFields }); + return data ? await nocoExecute(ast, data, {}, dependencyFields) : {}; } async getDataGroupBy(param: { model: Model; view: View; query?: any }) { @@ -221,15 +221,13 @@ export class DatasService { dbDriver: await NcConnectionMgrv2.get(base), }); - const row = await baseModel.readByPk(param.rowId); + const row = await baseModel.readByPk(param.rowId, false, param.query); if (!row) { NcError.notFound('Row not found'); } - const { ast } = await getAst({ model, query: param.query, view }); - - return await nocoExecute(ast, row, {}, param.query); + return row; } async dataExist(param: PathParams & { rowId: string; query: any }) { @@ -274,9 +272,9 @@ export class DatasService { dbDriver: await NcConnectionMgrv2.get(base), }); - const { ast } = await getAst({ model, query, view }); + const { ast, dependencyFields } = await getAst({ model, query, view }); - const listArgs: any = { ...query }; + const listArgs: any = { ...dependencyFields }; try { listArgs.filterArr = JSON.parse(listArgs.filterArrJson); } catch (e) {} @@ -637,13 +635,16 @@ export class DatasService { dbDriver: await NcConnectionMgrv2.get(base), }); - const { ast } = await getAst({ model, query: param.query }); + const { ast, dependencyFields } = await getAst({ + model, + query: param.query, + }); return await nocoExecute( ast, - await baseModel.readByPk(param.rowId), - {}, + await baseModel.readByPk(param.rowId, false), {}, + dependencyFields, ); } catch (e) { console.log(e); diff --git a/packages/nocodb/tests/unit/rest/tests/tableRow.test.ts b/packages/nocodb/tests/unit/rest/tests/tableRow.test.ts index 02af981a57..488bb50493 100644 --- a/packages/nocodb/tests/unit/rest/tests/tableRow.test.ts +++ b/packages/nocodb/tests/unit/rest/tests/tableRow.test.ts @@ -1106,7 +1106,9 @@ function tableTest() { ); const nestedFields = { - 'Rental List': ['RentalDate', 'ReturnDate'], + 'Rental List': { + f: 'RentalDate,ReturnDate', + }, }; const nestedFilter = [ @@ -1276,6 +1278,39 @@ function tableTest() { } }); + it('Read table row with nested fields', async () => { + const rowId = 1; + const actorTable = await getTable({ + project: sakilaProject, + name: 'actor', + }); + const response = await request(context.app) + .get( + `/api/v1/db/data/noco/${sakilaProject.id}/${actorTable.id}/${rowId}/`, + ) + .set('xc-auth', context.token) + .query({ + 'nested[Film List][fields]': 'Title,ReleaseYear,Language', + }) + .expect(200); + + const record = response.body; + expect(record['Film List']).length(19); + expect(record['Film List'][0]).to.have.all.keys( + 'Title', + 'ReleaseYear', + 'Language', + ); + + // for SQLite Sakila, Language is null + if (isPg(context)) { + expect(record['Film List'][0]['Language']).to.have.all.keys( + 'Name', + 'LanguageId', + ); + } + }); + it('Update table row', async function () { const table = await createTable(context, project); const row = await createRow(context, { project, table }); diff --git a/packages/nocodb/tests/unit/rest/tests/viewRow.test.ts b/packages/nocodb/tests/unit/rest/tests/viewRow.test.ts index 971c471879..3473c79bcf 100644 --- a/packages/nocodb/tests/unit/rest/tests/viewRow.test.ts +++ b/packages/nocodb/tests/unit/rest/tests/viewRow.test.ts @@ -901,7 +901,7 @@ function viewRowTests() { ); const nestedFields = { - 'Rental List': ['RentalDate', 'ReturnDate'], + 'Rental List': { f: 'RentalDate,ReturnDate' }, }; const nestedFilter = [