Skip to content

Commit 7363d83

Browse files
committed
improve syntax highlighting
1 parent f5b9496 commit 7363d83

File tree

6 files changed

+43
-23
lines changed

6 files changed

+43
-23
lines changed

app/components/plan-node/plan-node.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ <h4>{{node[_planService.NODE_TYPE_PROP] | uppercase}}
1010
</span>
1111
</header>
1212

13-
<button *ngIf="plan.formattedQuery && !viewOptions.showCompactView" tooltip="view corresponding query"
13+
<button *ngIf="plan.query && !viewOptions.showCompactView" tooltip="view corresponding query"
1414
class="btn btn-sm btn-default btn-slim pull-right" (click)="showQuery = !showQuery">
1515
<i class="fa fa-database"></i>
1616
</button>

app/components/plan-node/plan-node.ts

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -74,27 +74,38 @@ export class PlanNode {
7474
}
7575

7676
if (this.currentCompactView !== this.viewOptions.showCompactView) {
77-
this.currentCompactView = this.viewOptions.showCompactView;
78-
this.calculateBar();
77+
this.currentCompactView = this.viewOptions.showCompactView;
78+
this.calculateBar();
7979
}
8080
}
8181

8282
getFormattedQuery() {
8383
var keyItems: Array<string> = [];
8484

85-
var relationName = this.node[this._planService.RELATION_NAME_PROP];
85+
// relation name will be highlighted for SCAN nodes
86+
var relationName: string = this.node[this._planService.RELATION_NAME_PROP];
8687
if (relationName) {
8788
keyItems.push(this.node[this._planService.SCHEMA_PROP] + '.' + relationName);
8889
keyItems.push(' ' + relationName);
8990
keyItems.push(' ' + this.node[this._planService.ALIAS_PROP] + ' ');
9091
}
9192

93+
// group key will be highlighted for AGGREGATE nodes
9294
var groupKey: Array<string> = this.node[this._planService.GROUP_KEY_PROP];
9395
if (groupKey) {
94-
keyItems.push('BY</span> ' + groupKey.join(','));
95-
keyItems.push('BY</span> ' + groupKey.join(', '));
96+
keyItems.push('GROUP BY ' + groupKey.join(','));
97+
}
98+
99+
// hash condition will be highlighted for HASH JOIN nodes
100+
var hashCondition: string = this.node[this._planService.HASH_CONDITION_PROP];
101+
if (hashCondition) {
102+
keyItems.push(hashCondition.replace('(', '').replace(')', ''));
103+
}
104+
105+
if (this.node[this._planService.NODE_TYPE_PROP].toUpperCase() === 'LIMIT') {
106+
keyItems.push('LIMIT');
96107
}
97-
return this._syntaxHighlightService.highlightKeyItems(this.plan.formattedQuery, keyItems);
108+
return this._syntaxHighlightService.highlight(this.plan.query, keyItems);
98109
}
99110

100111
calculateBar() {

app/components/plan-view/plan-view.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ export class PlanView {
3434

3535
highlightTypes = HighlightType; // exposing the enum to the view
3636

37-
constructor(private _planService: PlanService, routeParams: RouteParams, private _syntaxHighlightService: SyntaxHighlightService) {
37+
constructor(private _planService: PlanService, routeParams: RouteParams) {
3838
this.id = routeParams.get('id');
3939
}
4040

@@ -56,10 +56,6 @@ export class PlanView {
5656
maxCost: this.rootContainer[this._planService.MAXIMUM_COSTS_PROP] || 0,
5757
maxDuration: this.rootContainer[this._planService.MAXIMUM_DURATION_PROP] || 0
5858
}
59-
60-
// get syntax highlighted query
61-
this._syntaxHighlightService.init();
62-
this.plan.formattedQuery = this._syntaxHighlightService.highlight(this.plan.query);
6359
}
6460

6561
ngOnInit() {

app/services/help-service.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,14 @@ export var NODE_DESCRIPTIONS = {
1212
"NESTED LOOP": `merges two record sets by looping through every record in the first set and
1313
trying to find a match in the second set. All matching records are returned.`,
1414
"MERGE JOIN": `merges two record sets by first sorting them on a <strong>join key</strong>.`,
15+
"HASH": `generates a hash table from the records in the input recordset. Hash is used by
16+
<strong>Hash Join</strong>.`,
17+
"HASH JOIN": `joins to record sets by hashing one of them (using a <strong>Hash Scan</scan>).`,
1518
"AGGREGATE": `groups records together based on a GROUP BY or aggregate function (like <code>sum()</code>).`,
1619
"HASHAGGREGATE": `groups records together based on a GROUP BY or aggregate function (like sum()). Hash Aggregate uses
1720
a hash to first organize the records by a key.`,
18-
"SEQ SCAN": `finds relevant records by sequentially scanning the table. Seq Scans perform a single read operation
19-
(only the table is read).`,
21+
"SEQ SCAN": `finds relevant records by sequentially scanning the input record set. When reading from a table,
22+
Seq Scans (unlike Index Scans) perform a single read operation (only the table is read).`,
2023
"INDEX SCAN": `finds relevant records based on an <strong>Index</strong>. Index Scans perform 2 read operations: one to
2124
read the index and another to read the actual value from the table.`,
2225
"INDEX ONLY SCAN": `finds relevant records based on an <strong>Index</strong>. Index Only Scans perform a single read operation

app/services/plan-service.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ export class PlanService {
1919
SORT_KEY_PROP: string = 'Sort Key';
2020
JOIN_TYPE_PROP: string = 'Join Type';
2121
INDEX_NAME_PROP: string = 'Index Name';
22+
HASH_CONDITION_PROP: string = 'Hash Cond';
2223

2324
// computed by pev
2425
COMPUTED_TAGS_PROP: string = "*Tags";

app/services/syntax-highlight-service.ts

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,29 @@
22
/// <reference path="lodash.d.ts" />
33

44
export class SyntaxHighlightService {
5-
init() {
5+
OPEN_TAG: string = ' _OPEN_TAG_';
6+
CLOSE_TAG: string = '_CLOSE_TAG_';
7+
8+
highlight(code: string, keyItems: Array<string>) {
69
hljs.registerLanguage('sql', LANG_SQL);
7-
}
810

9-
highlight(code) {
1011
hljs.configure({
1112
tabReplace: ' ', // 4 spaces
1213
});
13-
return hljs.highlightAuto(code).value;
14-
}
1514

16-
highlightKeyItems(value: string, keyItems: Array<string>) {
17-
_.each(keyItems, (keyItem) => { value = value.replace(keyItem, `<span class='code-key-item'>${keyItem}</span>`) })
18-
return value;
15+
// prior to syntax highlighting, we want to tag key items in the raw code. making the
16+
// query upper case and ensuring that all comma separated values have a space
17+
// makes it simpler to find the items we're looing for
18+
var result: string = code.toUpperCase().replace(', ', ',');
19+
_.each(keyItems, (keyItem: string) => {
20+
result = result.replace(keyItem.toUpperCase(), `${this.OPEN_TAG}${keyItem}${this.CLOSE_TAG}`)
21+
});
22+
23+
result = hljs.highlightAuto(result).value;
24+
result = result.replace(new RegExp(this.OPEN_TAG, 'g'), "<span class='code-key-item'>")
25+
result = result.replace(new RegExp(this.CLOSE_TAG, 'g'), "</span>");
26+
27+
return result;
1928
}
2029
}
2130

@@ -43,7 +52,7 @@ export var LANG_SQL = function(hljs) {
4352
'authors auto autoallocate autodblink autoextend automatic availability avg backup badfile basicfile ' +
4453
'before begin beginning benchmark between bfile bfile_base big bigfile bin binary_double binary_float ' +
4554
'binlog bit_and bit_count bit_length bit_or bit_xor bitmap blob_base block blocksize body both bound ' +
46-
'buffer_cache buffer_pool build bulk by byte byteordermark bytes c cache caching call calling cancel ' +
55+
'buffer_cache buffer_pool build bulk by byte byteordermark bytes cache caching call calling cancel ' +
4756
'capacity cascade cascaded case cast catalog category ceil ceiling chain change changed char_base ' +
4857
'char_length character_length characters characterset charindex charset charsetform charsetid check ' +
4958
'checksum checksum_agg child choose chr chunk class cleanup clear client clob clob_base clone close ' +

0 commit comments

Comments
 (0)