Skip to content

Commit 3595465

Browse files
Merge pull request #1175 from merico-dev/1173-add-content_id-query_id-params-filters-and-context-variables-to-query-interface
1173 add content id query id params filters and context variables to query interface
2 parents 52779d7 + 91623a4 commit 3595465

25 files changed

+1444
-255
lines changed

api/.env.sample

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ SERVER_PORT=31200
33
CORS_ALLOW_ORIGIN=
44
SECRET_KEY="secret key for encrypting datasource passwords"
55
ENABLE_AUTH=0
6+
ENABLE_QUERY_PARSER=0
67
SUPER_ADMIN_PASSWORD=
78
DATABASE_CONNECTION_TIMEOUT_MS=
89
DATABASE_POOL_SIZE=

api/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ Add a `.env` file based on `.env.sample`
1111
- `CORS_ALLOW_ORIGIN` for configuring cors. separate multiple origins by `;`. Defaults to `http://localhost`
1212
- `SECRET_KEY` for encrypting and decrypting passwords used in datasource configurations
1313
- `ENABLE_AUTH` Whether to add authentication and authorization to routes. 0 = disabled, 1 = enabled
14+
- `ENABLE_QUERY_PARSER` Whether to enable Server-Side Query parsing. 0 = disabled, 1 = enabled
1415
- `SUPER_ADMIN_PASSWORD` The password which will be configured for the superadmin account during migration. Must be configured before migration is run. If value is not set, password will be 'secret'
1516
- `DATABASE_CONNECTION_TIMEOUT_MS` for configuration the time after which the db connection will timeout in milliseconds. Default is 30000ms (30 seconds)
1617
- `DATABASE_POOL_SIZE` for configuration the maximum number of clients in the pool

api/src/api_models/dashboard_content.ts

Lines changed: 122 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,118 @@
11
import { ApiModel, ApiModelProperty, SwaggerDefinitionConstant } from 'swagger-express-ts';
2-
import { IsObject, Length, IsString, IsOptional, ValidateNested, IsUUID, IsIn } from 'class-validator';
2+
import { IsObject, Length, IsString, IsOptional, ValidateNested, IsUUID, IsIn, IsArray } from 'class-validator';
33
import { Type } from 'class-transformer';
44
import { Authentication, FilterObject, PaginationRequest, PaginationResponse, SortRequest } from './base';
55

6+
@ApiModel({
7+
description: 'Definition Query object',
8+
name: 'Query',
9+
})
10+
export class Query {
11+
@IsString()
12+
@ApiModelProperty({
13+
description: 'Query ID',
14+
required: true,
15+
})
16+
id: string;
17+
18+
@IsIn(['postgresql', 'mysql', 'http'])
19+
@ApiModelProperty({
20+
description: 'Datasource type',
21+
required: true,
22+
})
23+
type: 'postgresql' | 'mysql' | 'http';
24+
25+
@IsString()
26+
@ApiModelProperty({
27+
description: 'Datasource key',
28+
required: true,
29+
})
30+
key: string;
31+
32+
@IsString()
33+
@ApiModelProperty({
34+
description: 'Query SQL',
35+
required: true,
36+
})
37+
sql: string;
38+
39+
@IsString()
40+
@ApiModelProperty({
41+
description: 'Query pre-processing',
42+
required: true,
43+
})
44+
pre_process: string;
45+
}
46+
47+
@ApiModel({
48+
description: 'Definition SQL Snippets object',
49+
name: 'Snippet',
50+
})
51+
export class Snippet {
52+
@IsString()
53+
@ApiModelProperty({
54+
description: 'Snippet ID',
55+
required: true,
56+
})
57+
key: string;
58+
59+
@IsString()
60+
@ApiModelProperty({
61+
description: 'Snippet definition',
62+
required: true,
63+
})
64+
value: string;
65+
}
66+
67+
@ApiModel({
68+
description: 'Content definition object',
69+
name: 'ContentDefinition',
70+
})
71+
export class ContentDefinition {
72+
@IsArray()
73+
@Type(() => Query)
74+
@ValidateNested({ each: true })
75+
@ApiModelProperty({
76+
description: 'Content query definitions',
77+
required: true,
78+
model: 'Query',
79+
})
80+
queries: Query[];
81+
82+
@IsArray()
83+
@Type(() => Snippet)
84+
@ValidateNested({ each: true })
85+
@ApiModelProperty({
86+
description: 'Content sql snippet definitions',
87+
required: true,
88+
model: 'Snippet',
89+
})
90+
sqlSnippets: Snippet[];
91+
}
92+
93+
@ApiModel({
94+
description: 'Content object',
95+
name: 'Content',
96+
})
97+
export class Content {
98+
@IsObject()
99+
@Type(() => ContentDefinition)
100+
@ValidateNested({ each: true })
101+
@ApiModelProperty({
102+
description: 'Content definitions',
103+
required: true,
104+
model: 'ContentDefinition',
105+
})
106+
definition: ContentDefinition;
107+
108+
@IsString()
109+
@ApiModelProperty({
110+
description: 'Content schema version',
111+
required: true,
112+
})
113+
version: string;
114+
}
115+
6116
@ApiModel({
7117
description: 'Dashboard content entity',
8118
name: 'DashboardContent',
@@ -23,11 +133,12 @@ export class DashboardContent {
23133
})
24134
name: string;
25135

136+
@Type(() => Content)
26137
@ApiModelProperty({
27138
description: 'content of the dashboard stored in json object format',
28-
type: SwaggerDefinitionConstant.JSON,
139+
model: 'Content',
29140
})
30-
content: object | null;
141+
content: Content;
31142

32143
@ApiModelProperty({
33144
description: 'Create time',
@@ -176,12 +287,14 @@ export class DashboardContentCreateRequest {
176287
name: string;
177288

178289
@IsObject()
290+
@Type(() => Content)
291+
@ValidateNested({ each: true })
179292
@ApiModelProperty({
180293
description: 'content stored in json object format',
181294
required: true,
182-
type: SwaggerDefinitionConstant.JSON,
295+
model: 'Content',
183296
})
184-
content: Record<string, any>;
297+
content: Content;
185298

186299
@IsOptional()
187300
@Type(() => Authentication)
@@ -217,12 +330,14 @@ export class DashboardContentUpdateRequest {
217330

218331
@IsOptional()
219332
@IsObject()
333+
@Type(() => Content)
334+
@ValidateNested({ each: true })
220335
@ApiModelProperty({
221336
description: 'content of the dashboard stored in json object format',
222337
required: false,
223-
type: SwaggerDefinitionConstant.JSON,
338+
model: 'Content',
224339
})
225-
content?: Record<string, any>;
340+
content?: Content;
226341

227342
@IsOptional()
228343
@Type(() => Authentication)

api/src/api_models/index.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ import {
4545
ApiKeyIDRequest,
4646
} from './api';
4747
import { Role, RolePermission, RoleCreateOrUpdateRequest, RoleIDRequest } from './role';
48-
import { QueryRequest, HttpParams } from './query';
48+
import { QueryParams, QueryRequest, HttpParams, QueryStructureRequest } from './query';
4949
import { Job, JobFilterObject, JobListRequest, JobPaginationResponse, JobSortObject, JobRunRequest } from './job';
5050
import { Config, ConfigDescription, ConfigGetRequest, ConfigUpdateRequest } from './config';
5151
import {
@@ -74,6 +74,10 @@ import {
7474
DashboardContentSortObject,
7575
DashboardContentIDRequest,
7676
DashboardContentUpdateRequest,
77+
Content,
78+
ContentDefinition,
79+
Query,
80+
Snippet,
7781
} from './dashboard_content';
7882
import {
7983
DashboardContentChangelog,
@@ -154,8 +158,10 @@ export default {
154158
RoleCreateOrUpdateRequest,
155159
RoleIDRequest,
156160

161+
QueryParams,
157162
QueryRequest,
158163
HttpParams,
164+
QueryStructureRequest,
159165

160166
Job,
161167
JobFilterObject,
@@ -192,6 +198,10 @@ export default {
192198
DashboardContentSortObject,
193199
DashboardContentIDRequest,
194200
DashboardContentUpdateRequest,
201+
Content,
202+
ContentDefinition,
203+
Query,
204+
Snippet,
195205

196206
DashboardContentChangelog,
197207
DashboardContentChangelogFilterObject,

api/src/api_models/query.ts

Lines changed: 111 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,30 @@
11
import { Type } from 'class-transformer';
2-
import { IsBoolean, IsIn, IsObject, IsOptional, IsString, ValidateNested } from 'class-validator';
2+
import { IsBoolean, IsIn, IsNumber, IsObject, IsOptional, IsString, ValidateNested } from 'class-validator';
33
import { ApiModel, ApiModelProperty, SwaggerDefinitionConstant } from 'swagger-express-ts';
44
import { Authentication } from './base';
55

6+
@ApiModel({
7+
description: 'Query params object',
8+
name: 'QueryParams',
9+
})
10+
export class QueryParams {
11+
@IsObject()
12+
@ApiModelProperty({
13+
description: 'Query filter params',
14+
required: true,
15+
type: SwaggerDefinitionConstant.JSON,
16+
})
17+
filters: Record<string, any>;
18+
19+
@IsObject()
20+
@ApiModelProperty({
21+
description: 'Query context params',
22+
required: true,
23+
type: SwaggerDefinitionConstant.JSON,
24+
})
25+
context: Record<string, any>;
26+
}
27+
628
@ApiModel({
729
description: 'Query object',
830
name: 'QueryRequest',
@@ -31,6 +53,30 @@ export class QueryRequest {
3153
})
3254
query: string;
3355

56+
@IsString()
57+
@ApiModelProperty({
58+
description: 'id of the dashboard content',
59+
required: true,
60+
})
61+
content_id: string;
62+
63+
@IsString()
64+
@ApiModelProperty({
65+
description: 'id of the query defined in dashboard content',
66+
required: true,
67+
})
68+
query_id: string;
69+
70+
@IsObject()
71+
@Type(() => QueryParams)
72+
@ValidateNested({ each: true })
73+
@ApiModelProperty({
74+
description: 'Query params',
75+
required: true,
76+
model: 'QueryParams',
77+
})
78+
params: QueryParams;
79+
3480
@IsOptional()
3581
@IsObject()
3682
@ApiModelProperty({
@@ -109,3 +155,67 @@ export class HttpParams {
109155
})
110156
url: string;
111157
}
158+
159+
@ApiModel({
160+
description: 'Query Structure object',
161+
name: 'QueryStructureRequest',
162+
})
163+
export class QueryStructureRequest {
164+
@IsIn(['TABLES', 'COLUMNS', 'DATA', 'INDEXES', 'COUNT'])
165+
@ApiModelProperty({
166+
description: `type of query.
167+
TABLES = get all tables in database
168+
COLUMNS = get column structure of table
169+
DATA = get data of table
170+
INDEXES = get indexes of table
171+
COUNT = get total number of rows in table`,
172+
required: true,
173+
enum: ['TABLES', 'COLUMNS', 'DATA', 'INDEXES', 'COUNT'],
174+
})
175+
query_type: 'TABLES' | 'COLUMNS' | 'DATA' | 'INDEXES' | 'COUNT';
176+
177+
@IsIn(['postgresql', 'mysql'])
178+
@ApiModelProperty({
179+
description: 'datasource type of query',
180+
required: true,
181+
enum: ['postgresql', 'mysql'],
182+
})
183+
type: 'postgresql' | 'mysql';
184+
185+
@IsString()
186+
@ApiModelProperty({
187+
description: 'datasource key',
188+
required: true,
189+
})
190+
key: string;
191+
192+
@IsString()
193+
@ApiModelProperty({
194+
description: 'table schema',
195+
required: true,
196+
})
197+
table_schema: string;
198+
199+
@IsString()
200+
@ApiModelProperty({
201+
description: 'table schema',
202+
required: true,
203+
})
204+
table_name: string;
205+
206+
@IsNumber()
207+
@IsOptional()
208+
@ApiModelProperty({
209+
description: 'Limit of query results. Default = 20',
210+
required: false,
211+
})
212+
limit?: number;
213+
214+
@IsNumber()
215+
@IsOptional()
216+
@ApiModelProperty({
217+
description: 'Offset of query results, Default = 0',
218+
required: false,
219+
})
220+
offset?: number;
221+
}

0 commit comments

Comments
 (0)