Skip to content

Commit 7714e8c

Browse files
committed
Merge branch 'develop' into feature/update-doc
2 parents bb35e60 + bc00c09 commit 7714e8c

File tree

6 files changed

+232
-2
lines changed

6 files changed

+232
-2
lines changed

packages/core/src/lib/cache-layer/cacheLayerLoader.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,19 @@ export class CacheLayerLoader implements ICacheLayerLoader {
6262
if (!fs.existsSync(directory!)) {
6363
fs.mkdirSync(directory!, { recursive: true });
6464
}
65+
// remove the files in other subfolder before export, cause we will not reuse cache files
66+
const folderPath = path.resolve(
67+
this.options.folderPath!,
68+
templateName,
69+
profile,
70+
cacheTableName
71+
);
72+
const folders = fs
73+
.readdirSync(folderPath)
74+
.filter((file) =>
75+
fs.statSync(path.resolve(folderPath, file)).isDirectory()
76+
);
77+
this.removeParquetFiles(folders, folderPath);
6578
// 1. export to cache files according to each schema set the cache value
6679
this.logger.debug(`Start to export to ${type} file in "${directory}"`);
6780
await dataSource.export({
@@ -97,4 +110,14 @@ export class CacheLayerLoader implements ICacheLayerLoader {
97110
const parquetFiles = files.filter((file) => /\.parquet$/.test(file));
98111
return parquetFiles;
99112
}
113+
114+
private removeParquetFiles(folders: string[], folderPath: string) {
115+
folders.forEach((folder) => {
116+
const directory = path.resolve(folderPath, folder);
117+
const parquetFiles = this.getParquetFiles(directory);
118+
parquetFiles.forEach((file) => {
119+
fs.unlinkSync(path.resolve(directory, file));
120+
});
121+
});
122+
}
100123
}

packages/core/src/lib/template-engine/built-in-extensions/cache/cacheTagRunner.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,9 @@ export class CacheTagRunner extends TagRunner {
4444
query = query
4545
.split(/\r?\n/)
4646
.filter((line) => line.trim().length > 0)
47-
.join('\n');
47+
.join('\n')
48+
.replace(/--.*(?:\n|$)|\/\*[\s\S]*?\*\//g, ''); // remove single-line comments and multi-line comments
49+
4850
// Set the default vulcan created cache table schema, so we could query the cache table directly, not need user to type schema in the SQL.
4951
query = `set schema=${vulcanCacheSchemaName};`.concat('\n').concat(query);
5052
// Create the builder which access "vulcan.cache" data source for cache layer query

packages/core/src/lib/template-engine/built-in-extensions/query-builder/reqTagRunner.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,12 @@ export class ReqTagRunner extends TagRunner {
4040
for (let index = 0; index < contentArgs.length; index++) {
4141
query += await contentArgs[index]();
4242
}
43+
4344
query = query
4445
.split(/\r?\n/)
4546
.filter((line) => line.trim().length > 0)
46-
.join('\n');
47+
.join('\n')
48+
.replace(/--.*(?:\n|$)|\/\*[\s\S]*?\*\//g, ''); // remove single-line comments and multi-line comments
4749

4850
let builder: IDataQueryBuilder | undefined;
4951
// Replace to put the directly query cache builder to original query main builder of "__wrapper__builder",

packages/core/test/cache-layer/cacheLayerLoader.spec.ts

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,114 @@ describe('Test cache layer loader', () => {
169169
// Set 50s timeout to test cache loader export and load data
170170
50 * 10000
171171
);
172+
it(
173+
'Should remove the other parquet files after executing export',
174+
async () => {
175+
// Arrange
176+
const templateName = 'template-1';
177+
const cache = {
178+
cacheTableName: 'employees',
179+
sql: sinon.default.stub() as any,
180+
profile: profiles[0].name,
181+
folderSubpath: '2023',
182+
} as CacheLayerInfo;
183+
const { profile, cacheTableName, folderSubpath } = cache;
184+
const dir = path.resolve(
185+
folderPath,
186+
templateName,
187+
profile,
188+
cacheTableName,
189+
folderSubpath!
190+
);
191+
const loader = new CacheLayerLoader(options, stubFactory as any);
192+
await loader.load(templateName, cache);
193+
expect(fs.readdirSync(dir).length).toBeGreaterThan(0);
194+
195+
// Act
196+
cache.folderSubpath = '2024';
197+
await loader.load(templateName, cache);
198+
199+
// Assert
200+
const newDir = path.resolve(
201+
folderPath,
202+
templateName,
203+
profile,
204+
cacheTableName,
205+
'2024'!
206+
);
207+
expect(fs.readdirSync(dir).length).toEqual(0);
208+
expect(fs.readdirSync(newDir).length).toBeGreaterThan(0);
209+
},
210+
// Set 50s timeout to test cache loader export and load data
211+
50 * 10000
212+
);
213+
it(
214+
'Should not remove files if parquet files were reused',
215+
async () => {
216+
const templateName = 'template-1';
217+
const cache = {
218+
cacheTableName: 'employees',
219+
sql: sinon.default.stub() as any,
220+
profile: profiles[0].name,
221+
folderSubpath: '2023',
222+
} as CacheLayerInfo;
223+
// Arrange
224+
const { profile, cacheTableName, folderSubpath } = cache;
225+
const dir = path.resolve(
226+
folderPath,
227+
templateName,
228+
profile,
229+
cacheTableName,
230+
folderSubpath!
231+
);
232+
const loader = new CacheLayerLoader(options, stubFactory as any);
233+
await loader.load(templateName, cache);
234+
const parquetFiles = fs.readdirSync(dir);
235+
236+
// Act
237+
await loader.load(templateName, cache);
238+
239+
// Assert
240+
// expect parquetFiles is the same
241+
expect(fs.readdirSync(dir)).toEqual(parquetFiles);
242+
},
243+
// Set 50s timeout to test cache loader export and load data
244+
50 * 10000
245+
);
246+
247+
it(
248+
'Should remove parquet files of its own folder.',
249+
async () => {
250+
// Arrange
251+
const templateName = 'template-1';
252+
const cache = {
253+
cacheTableName: 'employees',
254+
sql: sinon.default.stub() as any,
255+
profile: profiles[0].name,
256+
folderSubpath: '2023',
257+
} as CacheLayerInfo;
258+
const { profile, cacheTableName, folderSubpath } = cache;
259+
const loader = new CacheLayerLoader(options, stubFactory as any);
260+
await loader.load(templateName, cache);
261+
const dirPath = path.resolve(
262+
folderPath,
263+
templateName,
264+
profile,
265+
cacheTableName,
266+
folderSubpath!
267+
);
268+
expect(fs.readdirSync(dirPath).length).toBeGreaterThan(0);
269+
270+
// Act :load another cache table
271+
cache.cacheTableName = 'another_employees';
272+
await loader.load(templateName, cache);
273+
274+
// Assert
275+
expect(fs.readdirSync(dirPath).length).toBeGreaterThan(0);
276+
},
277+
// Set 50s timeout to test cache loader export and load data
278+
50 * 10000
279+
);
172280
});
173281

174282
async function createParquetFile(path: string, fileName: string) {

packages/core/test/template-engine/built-in-extensions/cache/cache.spec.ts

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,3 +174,48 @@ select count(*) as count from vulcan.user where user.id = {{ context.params.user
174174
expect(binding[0].get('$1')).toBe(`user-id`);
175175
expect(resultData).toEqual([{ count: 1 }]);
176176
});
177+
178+
it('Extension should remove comments in sql statements', async () => {
179+
// Arrange
180+
const {
181+
compiler,
182+
loader,
183+
builder,
184+
executeTemplate,
185+
getCreatedQueries,
186+
getCreatedBinding,
187+
} = await createTestCompiler();
188+
const { compiledData } = await compiler.compile(`
189+
-- this is comment1
190+
/*
191+
this is multiline comments
192+
*/
193+
{% cache %} -- this is comment2
194+
select count(*) as count from vulcan.user where user.id = {{ context.params.userId }}; -- this is comment3
195+
{% endcache %} -- this is comment4
196+
-- this is comment5
197+
198+
/*
199+
this is multiline comments
200+
*/
201+
`);
202+
builder.value.onFirstCall().resolves({
203+
getColumns: () => [],
204+
getData: () => arrayToStream([{ count: 1 }]),
205+
});
206+
// Action
207+
loader.setSource('test', compiledData);
208+
const result = await executeTemplate('test', {
209+
userId: 'user-id',
210+
});
211+
const resultData = await streamToArray(result.getData());
212+
const queries = await getCreatedQueries();
213+
const binding = await getCreatedBinding();
214+
215+
// Assert, cache tag runner add the "set schema=vulcan;" in the prefix sql statement to make query could get correct cache table of schema.
216+
expect(queries[0].trim()).toBe(
217+
`set schema=vulcan;\n select count(*) as count from vulcan.user where user.id = $1;`
218+
);
219+
expect(binding[0].get('$1')).toBe(`user-id`);
220+
expect(resultData).toEqual([{ count: 1 }]);
221+
});

packages/core/test/template-engine/built-in-extensions/query-builder/builder.spec.ts

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,3 +167,53 @@ it('Extension should throw error when no profile defined', async () => {
167167
`No profile name found`
168168
);
169169
});
170+
171+
it('Extension should remove comments in sql statements', async () => {
172+
// Arrange
173+
const {
174+
compiler,
175+
loader,
176+
builder,
177+
executeTemplate,
178+
getCreatedQueries,
179+
getCreatedBinding,
180+
} = await createTestCompiler();
181+
const { compiledData } = await compiler.compile(`
182+
-- this is comment1
183+
/*
184+
this is multiline comments
185+
*/
186+
{% req userCount main %} -- this is comment2
187+
/*
188+
this is multiline comments
189+
*/
190+
-- this is comment3
191+
select count(*) as count from user where user.id = {{ context.params.userId }}; -- this is comment4
192+
-- this is comment5
193+
{% endreq %}
194+
195+
/*
196+
this is multiline comments
197+
*/
198+
199+
-- this is comment6
200+
`);
201+
builder.value.onFirstCall().resolves({
202+
getColumns: () => [],
203+
getData: () => arrayToStream([{ count: 1 }]),
204+
});
205+
// Action
206+
loader.setSource('test', compiledData);
207+
const result = await executeTemplate('test', {
208+
userId: 'user-id',
209+
});
210+
const resultData = await streamToArray(result.getData());
211+
const queries = await getCreatedQueries();
212+
const binding = await getCreatedBinding();
213+
// Assert
214+
expect(queries[0].trim()).toBe(
215+
`select count(*) as count from user where user.id = $1;`
216+
);
217+
expect(binding[0].get('$1')).toBe(`user-id`);
218+
expect(resultData).toEqual([{ count: 1 }]);
219+
});

0 commit comments

Comments
 (0)