Skip to content

Commit

Permalink
Merge pull request #123 from dalibo/costs_off_plans
Browse files Browse the repository at this point in the history
Don't fail to parse plans without costs nor analyze
  • Loading branch information
pgiraud authored Nov 29, 2019
2 parents baf3e40 + fb37be1 commit 23f399b
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 23 deletions.
16 changes: 16 additions & 0 deletions src/services/__tests__/08-plan-without-cost.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,19 @@ Seq Scan on pg_class (actual time=0.013..0.181 rows=645 loops=1)
});
});


describe('PlanService', () => {
test('Can parse plan without analyze nor costs', () => {
const planService = new PlanService();
const source = `
Bitmap Heap Scan on a
Recheck Cond: ((id = 42) OR (id = 4711))
-> BitmapOr
-> Bitmap Index Scan on a_pkey
Index Cond: (id = 42)
-> Bitmap Index Scan on a_pkey
Index Cond: (id = 4711)
`;
const r: any = planService.fromSource(source);
});
});
15 changes: 14 additions & 1 deletion src/services/__tests__/1-parse-error-line-break.spec.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,24 @@
import { PlanService } from '@/services/plan-service';

describe('PlanService', () => {
test('Can`t parse plan with line break from text', () => {
test('Can`t parse plan with line break', () => {
const planService = new PlanService();
const planText = `
Seq Scan on ref (cost=0.00..14425.02 rows=1000002 width=8) (actual
`;
expect(() => { planService.fromText(planText); }).toThrow();
});

test('Can`t parse plan with line break', () => {
const planService = new PlanService();
// tslint:disable:max-line-length
const source = `
Nested Loop Left Join (cost=11.95..28.52 rows=5 width=157) (actual time=0.010..0.010 rows=0 loops=1)
Output: rel_users_exams.user_username, rel_users_exams.exam_id, rel_users_exams.started_at, rel_users_exams.finished_at, exam_1.id, exam_1.title, ex
here is a line break
Planning Time: 1.110 ms
Execution Time: 0.170 ms`;
expect(() => { planService.fromText(source); }).toThrow();
});

});
14 changes: 0 additions & 14 deletions src/services/__tests__/plan-service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -229,18 +229,4 @@ Result (cost=0.31..0.32 rows=1 width=4)
expect(r.Plan.Plans[0]['Shared Hit Blocks']).toEqual(16230);
expect(r.Plan.Plans[0]['Shared Read Blocks']).toEqual(67104);
});

test('correctly parses line breaks', () => {
const planService = new PlanService();
// tslint:disable:max-line-length
const source = `
Nested Loop Left Join (cost=11.95..28.52 rows=5 width=157) (actual time=0.010..0.010 rows=0 loops=1)
Output: rel_users_exams.user_username, rel_users_exams.exam_id, rel_users_exams.started_at, rel_users_exams.finished_at, exam_1.id, exam_1.title, ex
here is a line break
Planning Time: 1.110 ms
Execution Time: 0.170 ms`;
// tslint:enable:max-line-length
const r: any = planService.fromSource(source);
expect(r['Execution Time']).toEqual(0.17);
});
});
20 changes: 12 additions & 8 deletions src/services/plan-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -285,8 +285,11 @@ export class PlanService {
// Remove any begining "
line = line.replace(/^\s*"/, '');


const emptyLineRegex = '^\s*$';
const headerRegex = '^\\s*(QUERY|---|#).*$';
const prefixRegex = '^(\\s*->\\s*|\\s*)';
const typeRegex = '(\\S.*?)';
const typeRegex = '([^\\r\\n\\t\\f\\v\\:\\(]*?)';
// tslint:disable-next-line:max-line-length
const estimationRegex = '\\(cost=(\\d+\\.\\d+)\\.\\.(\\d+\\.\\d+)\\s+rows=(\\d+)\\s+width=(\\d+)\\)';
const nonCapturingGroupOpen = '(?:';
Expand All @@ -297,10 +300,9 @@ export class PlanService {
const actualRegex = '(?:actual\\stime=(\\d+\\.\\d+)\\.\\.(\\d+\\.\\d+)\\srows=(\\d+)\\sloops=(\\d+)|actual\\srows=(\\d+)\\sloops=(\\d+)|(never\\s+executed))';
const optionalGroup = '?';

const a = new RegExp(
prefixRegex,
'gm',
);
const emptyLineMatches = new RegExp(emptyLineRegex).exec(line);
const headerMatches = new RegExp(headerRegex).exec(line);

/*
* Groups
* 1: prefix
Expand Down Expand Up @@ -328,7 +330,7 @@ export class PlanService {
const nodeRegex = new RegExp(
prefixRegex +
typeRegex +
'\\s+' +
'\\s*' +
nonCapturingGroupOpen +
(nonCapturingGroupOpen + estimationRegex + '\\s+' +
openParenthesisRegex + actualRegex + closeParenthesisRegex +
Expand All @@ -337,7 +339,7 @@ export class PlanService {
nonCapturingGroupOpen + estimationRegex + nonCapturingGroupClose +
'|' +
nonCapturingGroupOpen + openParenthesisRegex + actualRegex + closeParenthesisRegex + nonCapturingGroupClose +
nonCapturingGroupClose +
nonCapturingGroupClose + '*' +
'\\s*$',
'gm',
);
Expand Down Expand Up @@ -386,7 +388,9 @@ export class PlanService {
const extraRegex = /^(\s*)(\S.*\S)\s*$/g;
const extraMatches = extraRegex.exec(line);

if (nodeMatches) {
if (emptyLineMatches || headerMatches) {
return;
} else if (nodeMatches && !cteMatches && !subMatches) {
const prefix = nodeMatches[1];
const neverExecuted = nodeMatches[13];
const newNode: Node = new Node(nodeMatches[2]);
Expand Down

0 comments on commit 23f399b

Please sign in to comment.