diff --git a/packages/nc-gui/package.json b/packages/nc-gui/package.json
index b8fa48268e..67e5eb682c 100644
--- a/packages/nc-gui/package.json
+++ b/packages/nc-gui/package.json
@@ -29,7 +29,7 @@
"monaco-editor": "^0.19.3",
"monaco-themes": "^0.2.5",
"nano-assign": "^1.0.1",
- "nocodb-sdk": "0.90.5",
+ "nocodb-sdk": "file:../nocodb-sdk",
"nuxt": "^2.14.0",
"odometer": "^0.4.8",
"papaparse": "^5.3.1",
diff --git a/packages/noco-docs/content/en/developer-resources/rest-apis.md b/packages/noco-docs/content/en/developer-resources/rest-apis.md
index 37786d0b4c..71b2d73212 100644
--- a/packages/noco-docs/content/en/developer-resources/rest-apis.md
+++ b/packages/noco-docs/content/en/developer-resources/rest-apis.md
@@ -55,16 +55,18 @@ Currently, the default value for {orgs} is noco. Users will be able to ch
| Data | Patch | dbTableRow | bulkUpdateAll | /api/v1/db/data/bulk/{orgs}/{projectName}/{tableName}/all |
| Data | Delete| dbTableRow | bulkDeleteAll | /api/v1/db/data/bulk/{orgs}/{projectName}/{tableName}/all |
| Data | Get | dbTableRow | list | /api/v1/db/data/{orgs}/{projectName}/{tableName} |
+| Data | Get | dbTableRow | findOne | /api/v1/db/data/{orgs}/{projectName}/{tableName}/find-one |
| Data | Post | dbTableRow | create | /api/v1/db/data/{orgs}/{projectName}/{tableName} |
| Data | Get | dbTableRow | read | /api/v1/db/data/{orgs}/{projectName}/{tableName}/{rowId} |
| Data | Patch | dbTableRow | update | /api/v1/db/data/{orgs}/{projectName}/{tableName}/{rowId} |
| Data | Delete| dbTableRow | delete | /api/v1/db/data/{orgs}/{projectName}/{tableName}/{rowId} |
| Data | Get | dbTableRow | count | /api/v1/db/data/{orgs}/{projectName}/{tableName}/count |
-| Data | Get | dbViewRow | list | /api/v1/db/data/{orgs}/{projectName}/{tableName}/view/{viewName} |
-| Data | Post | dbViewRow | create | /api/v1/db/data/{orgs}/{projectName}/{tableName}/view/{viewName} |
-| Data | Get | dbViewRow | read | /api/v1/db/data/{orgs}/{projectName}/{tableName}/view/{viewName}/{rowId} |
-| Data | Patch | dbViewRow | update | /api/v1/db/data/{orgs}/{projectName}/{tableName}/view/{viewName}/{rowId} |
-| Data | Delete| dbViewRow | delete | /api/v1/db/data/{orgs}/{projectName}/{tableName}/view/{viewName}/{rowId} |
+| Data | Get | dbViewRow | list | /api/v1/db/data/{orgs}/{projectName}/{tableName}/views/{viewName} |
+| Data | Get | dbViewRow | findOne | /api/v1/db/data/{orgs}/{projectName}/{tableName}/views/{viewName}/find-one |
+| Data | Post | dbViewRow | create | /api/v1/db/data/{orgs}/{projectName}/{tableName}/views/{viewName} |
+| Data | Get | dbViewRow | read | /api/v1/db/data/{orgs}/{projectName}/{tableName}/views/{viewName}/{rowId} |
+| Data | Patch | dbViewRow | update | /api/v1/db/data/{orgs}/{projectName}/{tableName}/views/{viewName}/{rowId} |
+| Data | Delete| dbViewRow | delete | /api/v1/db/data/{orgs}/{projectName}/{tableName}/views/{viewName}/{rowId} |
| Data | Get | dbViewRow | count | /api/v1/db/data/{orgs}/{projectName}/{tableName}/views/{viewName}/count |
### Meta APIs
diff --git a/packages/nocodb-sdk/src/lib/Api.ts b/packages/nocodb-sdk/src/lib/Api.ts
index a8dbeb7f4f..ee6bb65487 100644
--- a/packages/nocodb-sdk/src/lib/Api.ts
+++ b/packages/nocodb-sdk/src/lib/Api.ts
@@ -1097,7 +1097,7 @@ export class Api<
* @request GET:/api/v1/db/meta/projects/{projectId}/info
* @response `200` `{ Node?: string, Arch?: string, Platform?: string, Docker?: boolean, Database?: string, ProjectOnRootDB?: string, RootDB?: string, PackageVersion?: string }` OK
*/
- metaGet: (projectId: string, params: RequestParams = {}) =>
+ metaGet: (projectId: string, params: RequestParams = {}, query: object) =>
this.request<
{
Node?: string;
@@ -1113,6 +1113,7 @@ export class Api<
>({
path: `/api/v1/db/meta/projects/${projectId}/info`,
method: 'GET',
+ query: query,
format: 'json',
...params,
}),
@@ -2233,6 +2234,30 @@ export class Api<
...params,
}),
+ /**
+ * No description
+ *
+ * @tags DB table row
+ * @name FindOne
+ * @summary Table row FindOne
+ * @request GET:/api/v1/db/data/{orgs}/{projectName}/{tableName}/find-one
+ * @response `200` `any` OK
+ */
+ findOne: (
+ orgs: string,
+ projectName: string,
+ tableName: string,
+ query?: { fields?: any[]; sort?: any[]; where?: string },
+ params: RequestParams = {}
+ ) =>
+ this.request({
+ path: `/api/v1/db/data/${orgs}/${projectName}/${tableName}/find-one`,
+ method: 'GET',
+ query: query,
+ format: 'json',
+ ...params,
+ }),
+
/**
* No description
*
@@ -2636,6 +2661,31 @@ export class Api<
...params,
}),
+ /**
+ * No description
+ *
+ * @tags DB view row
+ * @name FindOne
+ * @summary Table view row FindOne
+ * @request GET:/api/v1/db/data/{orgs}/{projectName}/{tableName}/views/{viewName}/find-one
+ * @response `200` `any` OK
+ */
+ findOne: (
+ orgs: string,
+ projectName: string,
+ tableName: string,
+ viewName: string,
+ query?: { fields?: any[]; sort?: any[]; where?: string; nested?: any },
+ params: RequestParams = {}
+ ) =>
+ this.request({
+ path: `/api/v1/db/data/${orgs}/${projectName}/${tableName}/views/${viewName}/find-one`,
+ method: 'GET',
+ query: query,
+ format: 'json',
+ ...params,
+ }),
+
/**
* No description
*
diff --git a/packages/nocodb/package.json b/packages/nocodb/package.json
index 94a85f1d19..9c8bf23835 100644
--- a/packages/nocodb/package.json
+++ b/packages/nocodb/package.json
@@ -154,7 +154,7 @@
"nc-lib-gui": "0.90.5",
"nc-plugin": "^0.1.1",
"ncp": "^2.0.0",
- "nocodb-sdk": "0.90.5",
+ "nocodb-sdk": "file:../nocodb-sdk",
"nodemailer": "^6.4.10",
"openapi-to-postmanv2": "^3.1.0",
"ora": "^4.0.4",
diff --git a/packages/nocodb/src/lib/dataMapper/lib/sql/BaseModelSqlv2.ts b/packages/nocodb/src/lib/dataMapper/lib/sql/BaseModelSqlv2.ts
index c2227f0ec2..0af3c47f01 100644
--- a/packages/nocodb/src/lib/dataMapper/lib/sql/BaseModelSqlv2.ts
+++ b/packages/nocodb/src/lib/dataMapper/lib/sql/BaseModelSqlv2.ts
@@ -90,6 +90,45 @@ class BaseModelSqlv2 {
return data;
}
+ public async findOne(
+ args: {
+ where?: string;
+ filterArr?: Filter[];
+ } = {}
+ ): Promise {
+ const qb = this.dbDriver(this.model.table_name);
+ await this.selectObject({ qb });
+
+ const aliasColObjMap = await this.model.getAliasColObjMap();
+ const filterObj = extractFilterFromXwhere(args?.where, aliasColObjMap);
+
+ await conditionV2(
+ [
+ new Filter({
+ children: args.filterArr || [],
+ is_group: true,
+ logical_op: 'and'
+ }),
+ new Filter({
+ children: filterObj,
+ is_group: true,
+ logical_op: 'and'
+ }),
+ ...(args.filterArr || [])
+ ],
+ qb,
+ this.dbDriver
+ );
+
+ const data = await qb.first();
+
+ if (data) {
+ const proto = await this.getProto();
+ data.__proto__ = proto;
+ }
+ return data;
+ }
+
public async list(
args: {
where?: string;
diff --git a/packages/nocodb/src/lib/noco/meta/api/dataApis/dataAliasApis.ts b/packages/nocodb/src/lib/noco/meta/api/dataApis/dataAliasApis.ts
index c3e8c31987..82ff1d2a4c 100644
--- a/packages/nocodb/src/lib/noco/meta/api/dataApis/dataAliasApis.ts
+++ b/packages/nocodb/src/lib/noco/meta/api/dataApis/dataAliasApis.ts
@@ -13,6 +13,11 @@ async function dataList(req: Request, res: Response) {
res.json(await getDataList(model, view, req));
}
+async function dataFindOne(req: Request, res: Response) {
+ const { model, view } = await getViewAndModelFromRequestByAliasOrId(req);
+ res.json(await getFindOne(model, view, req));
+}
+
async function dataCount(req: Request, res: Response) {
const { model, view } = await getViewAndModelFromRequestByAliasOrId(req);
@@ -106,6 +111,31 @@ async function getDataList(model, view: View, req) {
});
}
+async function getFindOne(model, view: View, req) {
+ const base = await Base.get(model.base_id);
+
+ const baseModel = await Model.getBaseModelSQL({
+ id: model.id,
+ viewId: view?.id,
+ dbDriver: NcConnectionMgrv2.get(base)
+ });
+
+ const args: any = { ...req.query };
+ try {
+ args.filterArr = JSON.parse(args.filterArrJson);
+ } catch (e) {}
+ try {
+ args.sortArr = JSON.parse(args.sortArrJson);
+ } catch (e) {}
+
+ return await nocoExecute(
+ await baseModel.defaultResolverReq(),
+ await baseModel.findOne(args),
+ {},
+ {}
+ );
+}
+
async function dataRead(req: Request, res: Response) {
const { model, view } = await getViewAndModelFromRequestByAliasOrId(req);
@@ -135,6 +165,11 @@ router.get(
ncMetaAclMw(dataList, 'dataList')
);
+router.get(
+ '/api/v1/db/data/:orgs/:projectName/:tableName/find-one',
+ ncMetaAclMw(dataFindOne, 'dataFindOne')
+);
+
router.get(
'/api/v1/db/data/:orgs/:projectName/:tableName/count',
ncMetaAclMw(dataCount, 'dataCount')
@@ -168,6 +203,11 @@ router.get(
ncMetaAclMw(dataList, 'dataList')
);
+router.get(
+ '/api/v1/db/data/:orgs/:projectName/:tableName/views/:viewName/find-one',
+ ncMetaAclMw(dataFindOne, 'dataFindOne')
+);
+
router.post(
'/api/v1/db/data/:orgs/:projectName/:tableName',
ncMetaAclMw(dataInsert, 'dataInsert')
diff --git a/scripts/sdk/swagger.json b/scripts/sdk/swagger.json
index d63ba0e38d..091505e9a9 100644
--- a/scripts/sdk/swagger.json
+++ b/scripts/sdk/swagger.json
@@ -573,6 +573,16 @@
},
"tags": [
"Project"
+ ],
+ "parameters": [
+ {
+ "schema": {
+ "type": "number",
+ "minimum": 1,
+ "multipleOf": 1
+ },
+ "in": "query"
+ }
]
}
},
@@ -2521,6 +2531,75 @@
}
}
},
+ "/api/v1/db/data/{orgs}/{projectName}/{tableName}/find-one": {
+ "parameters": [
+ {
+ "schema": {
+ "type": "string"
+ },
+ "name": "orgs",
+ "in": "path",
+ "required": true
+ },
+ {
+ "schema": {
+ "type": "string"
+ },
+ "name": "projectName",
+ "in": "path",
+ "required": true
+ },
+ {
+ "schema": {
+ "type": "string"
+ },
+ "name": "tableName",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "get": {
+ "summary": "Table row FindOne",
+ "operationId": "db-table-row-find-one",
+ "description": "",
+ "tags": [
+ "DB table row"
+ ],
+ "parameters": [
+ {
+ "schema": {
+ "type": "array"
+ },
+ "in": "query",
+ "name": "fields"
+ },
+ {
+ "schema": {
+ "type": "array"
+ },
+ "in": "query",
+ "name": "sort"
+ },
+ {
+ "schema": {
+ "type": "string"
+ },
+ "in": "query",
+ "name": "where"
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "OK",
+ "content": {
+ "application/json": {
+ "schema": {}
+ }
+ }
+ }
+ }
+ }
+ },
"/api/v1/db/data/{orgs}/{projectName}/{tableName}/count": {
"parameters": [
{
@@ -2689,6 +2768,89 @@
}
}
},
+ "/api/v1/db/data/{orgs}/{projectName}/{tableName}/views/{viewName}/find-one": {
+ "parameters": [
+ {
+ "schema": {
+ "type": "string"
+ },
+ "name": "orgs",
+ "in": "path",
+ "required": true
+ },
+ {
+ "schema": {
+ "type": "string"
+ },
+ "name": "projectName",
+ "in": "path",
+ "required": true
+ },
+ {
+ "schema": {
+ "type": "string"
+ },
+ "name": "tableName",
+ "in": "path",
+ "required": true
+ },
+ {
+ "schema": {
+ "type": "string"
+ },
+ "name": "viewName",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "get": {
+ "summary": "Table view row FindOne",
+ "operationId": "db-view-row-find-one",
+ "description": "",
+ "tags": [
+ "DB view row"
+ ],
+ "parameters": [
+ {
+ "schema": {
+ "type": "array"
+ },
+ "in": "query",
+ "name": "fields"
+ },
+ {
+ "schema": {
+ "type": "array"
+ },
+ "in": "query",
+ "name": "sort"
+ },
+ {
+ "schema": {
+ "type": "string"
+ },
+ "in": "query",
+ "name": "where"
+ },
+ {
+ "schema": {},
+ "in": "query",
+ "name": "nested",
+ "description": "Query params for nested data"
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "OK",
+ "content": {
+ "application/json": {
+ "schema": {}
+ }
+ }
+ }
+ }
+ }
+ },
"/api/v1/db/data/{orgs}/{projectName}/{tableName}/views/{viewName}/count": {
"parameters": [
{