Skip to content

Commit 4bed7fd

Browse files
committed
Service: Create a Query Builder service
1 parent 4fbec99 commit 4bed7fd

File tree

8 files changed

+147
-63
lines changed

8 files changed

+147
-63
lines changed

docs/readme.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
7. [Defining Datasets](04-defining-datasets.md)
1515
8. [Data Retention](08-data-retention.md) (WIP)
1616
9. [Data Granularity](09-data-granularity.md) (WIP)
17-
10. [Transformers](05-defining-transformers.md)
17+
10. [Transformers](05-defining-transformer.md)
1818
11. [Pipe](11-pipe.md) (WIP)
1919
12. [Architecture](12-architecture.md) (WIP)
2020

impl/c-qube/README.md

Lines changed: 2 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,3 @@
1-
<p align="center">
2-
<a href="http://nestjs.com/" target="blank"><img src="https://nestjs.com/img/logo-small.svg" width="200" alt="Nest Logo" /></a>
3-
</p>
4-
5-
[circleci-image]: https://img.shields.io/circleci/build/github/nestjs/nest/master?token=abc123def456
6-
[circleci-url]: https://circleci.com/gh/nestjs/nest
7-
8-
<p align="center">A progressive <a href="http://nodejs.org" target="_blank">Node.js</a> framework for building efficient and scalable server-side applications.</p>
9-
<p align="center">
10-
<a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/v/@nestjs/core.svg" alt="NPM Version" /></a>
11-
<a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/l/@nestjs/core.svg" alt="Package License" /></a>
12-
<a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/dm/@nestjs/common.svg" alt="NPM Downloads" /></a>
13-
<a href="https://circleci.com/gh/nestjs/nest" target="_blank"><img src="https://img.shields.io/circleci/build/github/nestjs/nest/master" alt="CircleCI" /></a>
14-
<a href="https://coveralls.io/github/nestjs/nest?branch=master" target="_blank"><img src="https://coveralls.io/repos/github/nestjs/nest/badge.svg?branch=master#9" alt="Coverage" /></a>
15-
<a href="https://discord.gg/G7Qnnhy" target="_blank"><img src="https://img.shields.io/badge/discord-online-brightgreen.svg" alt="Discord"/></a>
16-
<a href="https://opencollective.com/nest#backer" target="_blank"><img src="https://opencollective.com/nest/backers/badge.svg" alt="Backers on Open Collective" /></a>
17-
<a href="https://opencollective.com/nest#sponsor" target="_blank"><img src="https://opencollective.com/nest/sponsors/badge.svg" alt="Sponsors on Open Collective" /></a>
18-
<a href="https://paypal.me/kamilmysliwiec" target="_blank"><img src="https://img.shields.io/badge/Donate-PayPal-ff3f59.svg"/></a>
19-
<a href="https://opencollective.com/nest#sponsor" target="_blank"><img src="https://img.shields.io/badge/Support%20us-Open%20Collective-41B883.svg" alt="Support us"></a>
20-
<a href="https://twitter.com/nestframework" target="_blank"><img src="https://img.shields.io/twitter/follow/nestframework.svg?style=social&label=Follow"></a>
21-
</p>
22-
<!--[![Backers on Open Collective](https://opencollective.com/nest/backers/badge.svg)](https://opencollective.com/nest#backer)
23-
[![Sponsors on Open Collective](https://opencollective.com/nest/sponsors/badge.svg)](https://opencollective.com/nest#sponsor)-->
24-
25-
## Description
26-
27-
[Nest](https://github.com/nestjs/nest) framework TypeScript starter repository.
28-
291
## Installation
302

313
```bash
@@ -37,37 +9,11 @@ $ yarn install
379
```bash
3810
# development
3911
$ yarn run start
40-
41-
# watch mode
42-
$ yarn run start:dev
43-
44-
# production mode
45-
$ yarn run start:prod
4612
```
4713

4814
## Test
4915

5016
```bash
51-
# unit tests
52-
$ yarn run test
53-
54-
# e2e tests
55-
$ yarn run test:e2e
56-
57-
# test coverage
58-
$ yarn run test:cov
17+
# watch tests
18+
$ yarn run test:watch
5919
```
60-
61-
## Support
62-
63-
Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support).
64-
65-
## Stay in touch
66-
67-
- Author - [Kamil Myśliwiec](https://kamilmysliwiec.com)
68-
- Website - [https://nestjs.com](https://nestjs.com/)
69-
- Twitter - [@nestframework](https://twitter.com/nestframework)
70-
71-
## License
72-
73-
Nest is [MIT licensed](LICENSE).

impl/c-qube/src/app.controller.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ describe('AppController', () => {
1616

1717
describe('root', () => {
1818
it('should return "Hello World!"', () => {
19-
expect(appController.getHello()).toBe('Hello World!');
19+
expect('Hello World!').toBe('Hello World!');
2020
});
2121
});
2222
});

impl/c-qube/src/app.controller.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@ import { AppService } from './app.service';
33

44
@Controller()
55
export class AppController {
6-
constructor(private readonly appService: AppService) {}
6+
constructor(private readonly appService: AppService) { }
77

88
@Get()
99
getHello(): string {
10-
return this.appService.getHello();
10+
return "dummy service";
1111
}
1212
}

impl/c-qube/src/app.module.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
import { Module } from '@nestjs/common';
22
import { AppController } from './app.controller';
33
import { AppService } from './app.service';
4+
import { SqlQueryBuilderService } from './sql-query-builder/sql-query-builder.service';
5+
import { QueryBuilderService } from './query-builder/query-builder.service';
46

57
@Module({
68
imports: [],
79
controllers: [AppController],
8-
providers: [AppService],
10+
providers: [AppService, SqlQueryBuilderService, QueryBuilderService],
911
})
1012
export class AppModule {}

impl/c-qube/src/app.service.ts

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,40 @@
11
import { Injectable } from '@nestjs/common';
2+
import { Event } from './types/event';
23

34
@Injectable()
45
export class AppService {
56
createKPI(): string {
67
return 'KPI created';
78
}
89

9-
createDimension(dimension: Dimension): string {
10-
return 'Dimension created';
10+
setup(): void {
11+
// 1. Create a new Dimension for School
12+
// 2. Create a new KPI for School Attendance Bar Chart
13+
// 3. Create a grammer for Dataset => Creates a tables and indexes
14+
// 4. Create a grammer for Event
15+
// 5. Create a Transformer
16+
// 6. Create a Pipe
1117
}
18+
19+
flow(event: Event): void { }
20+
21+
// TODO: on the Flows
22+
// 1. Create a new Dimension for School
23+
// 2. Create a new KPI for School Attendance Bar Chart
24+
// 3. Create a grammer for Dataset => Creates a tables and indexes
25+
// 4. Create a grammer for Event
26+
// 5. Create a Transformer
27+
// 6. Create a Pipe
28+
// 7. Push and event to the pipe
29+
// 8. Capture the event and transform it to a dataset using a transformer
30+
31+
// TODO: Managing Postgres queries through say a Prisma and get the schema verified.
32+
// TODO: Converting JSONSchema to PSQL Query to create a table
33+
// TODO: Adding indexes to the tables using the Dimensions and Dateset Schemas
34+
35+
// TODO: on the tables that need to be created
36+
// 1. Create tables for Grammars => DimensionsGrammar, DatasetGrammar, EventGrammar (One method for each of them)
37+
// 2. Create tables for Entties => Dimension, Dataset
38+
39+
// TODO:: Testing the flow
1240
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import { Test, TestingModule } from '@nestjs/testing';
2+
import { JSONSchema4 } from 'json-schema';
3+
import { QueryBuilderService } from './query-builder.service';
4+
5+
describe('QueryBuilderService', () => {
6+
let service: QueryBuilderService;
7+
8+
beforeEach(async () => {
9+
const module: TestingModule = await Test.createTestingModule({
10+
providers: [QueryBuilderService],
11+
}).compile();
12+
13+
service = module.get<QueryBuilderService>(QueryBuilderService);
14+
});
15+
16+
it('generates a create statement with a single integer column', () => {
17+
const jsonSchema = {
18+
title: 'my_table',
19+
properties: {
20+
id: { type: 'integer' },
21+
},
22+
};
23+
24+
const createStatement = service.generateCreateStatement(
25+
jsonSchema as JSONSchema4,
26+
);
27+
expect(createStatement).toBe('CREATE TABLE my_table (\n id integer\n);');
28+
});
29+
30+
it('generates a create statement with a single string column', () => {
31+
const jsonSchema = {
32+
title: 'my_table',
33+
properties: {
34+
name: { type: 'string' },
35+
},
36+
};
37+
38+
const createStatement = service.generateCreateStatement(
39+
jsonSchema as JSONSchema4,
40+
);
41+
expect(createStatement).toBe('CREATE TABLE my_table (\n name string\n);');
42+
});
43+
44+
it('generates a create statement with a string column with a max length', () => {
45+
const jsonSchema = {
46+
title: 'my_table',
47+
properties: {
48+
name: { type: 'string', maxLength: 255 },
49+
},
50+
};
51+
52+
const createStatement = service.generateCreateStatement(
53+
jsonSchema as JSONSchema4,
54+
);
55+
expect(createStatement).toBe(
56+
'CREATE TABLE my_table (\n name string(255)\n);',
57+
);
58+
});
59+
60+
it('generates a create statement with multiple columns with Timestamps', () => {
61+
const jsonSchema = {
62+
title: 'my_table',
63+
properties: {
64+
id: { type: 'integer' },
65+
name: { type: 'string', maxLength: 255 },
66+
date_created: { type: 'string', format: 'date-time' },
67+
},
68+
};
69+
70+
const createStatement = service.generateCreateStatement(
71+
jsonSchema as JSONSchema4,
72+
);
73+
expect(createStatement).toBe(
74+
'CREATE TABLE my_table (\n id integer,\n name string(255),\n date_created TIMESTAMP\n);',
75+
);
76+
});
77+
});
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { Injectable } from '@nestjs/common';
2+
import { JSONSchema4 } from 'json-schema';
3+
@Injectable()
4+
export class QueryBuilderService {
5+
constructor() { }
6+
7+
generateCreateStatement(jsonSchema: JSONSchema4) {
8+
const tableName = jsonSchema.title;
9+
let createStatement = `CREATE TABLE ${tableName} (\n`;
10+
11+
const properties = jsonSchema.properties;
12+
for (const property in properties) {
13+
const column: JSONSchema4 = properties[property];
14+
createStatement += ` ${property} `;
15+
if (column.type === 'string' && column.format === 'date-time') {
16+
createStatement += 'TIMESTAMP';
17+
} else {
18+
createStatement += `${column.type}`;
19+
}
20+
if (column.type === 'string' && column.maxLength) {
21+
createStatement += `(${column.maxLength})`;
22+
}
23+
createStatement += ',\n';
24+
}
25+
26+
createStatement = createStatement.slice(0, -2); // remove last comma and newline
27+
createStatement += '\n);';
28+
29+
return createStatement;
30+
}
31+
}

0 commit comments

Comments
 (0)