-
Notifications
You must be signed in to change notification settings - Fork 0
/
encode_to_hint.py
125 lines (101 loc) · 3.48 KB
/
encode_to_hint.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
'''
Encode the result from psql_explain_decoder.py to readable hints of pg_plan_hints
e.g.
input:
'Hash Join(c,Nested Loop(Nested Loop(Hash Join(v,p), Merge Join (a,u)),b))'
['Seq Scan(u)', 'Index Scan(p)', 'Index Scan(v)', 'Index Scan(b)', 'Index Only Scan(c)']
output:
['HashJoin ( v p )', 'MergeJoin ( a u )', 'NestLoop ( v p a u )', 'NestLoop ( v p a u b )', 'HashJoin ( c v p a u b )'] Leading ( ( c ( ( ( v p ) ( a u ) ) b ) ) )
['SeqScan(u)', 'IndexScan(p)', 'IndexScan(v)', 'IndexScan(b)', 'IndexOnlyScan(c)']
'''
def split_string(tmp, d):
tmp = tmp.split(d)
tmp_list = []
for k in range(len(tmp)):
tmp_list.append(tmp[k])
if k < len(tmp) - 1:
tmp_list.append(d)
return tmp_list
def parse_string(new_list, d):
final_list = []
for i in range(len(new_list)):
if d in new_list[i]:
tmp_list = split_string(new_list[i], d)
final_list += tmp_list
else:
final_list.append(new_list[i])
return final_list
join_type = ['Merge Join', 'Hash Join', 'Nested Loop']
hint_type_dict = {
'Merge Join': 'MergeJoin',
'Hash Join': 'HashJoin',
'Nested Loop': 'NestLoop'
}
def gen_join_hints(str):
new_list = []
tmp = str.split('(')
for i in range(len(tmp)):
new_list.append(tmp[i])
if i < len(tmp) - 1:
new_list.append('(')
# print(new_list)
final_list = parse_string(new_list, ')')
final_list = parse_string(final_list, ',')
# print(final_list)
for i in final_list:
if i == '':
final_list.remove('')
for i in final_list:
if i == ',':
final_list.remove(',')
for i in range(len(final_list)):
final_list[i] = final_list[i].lstrip().rstrip()
lead = 'Leading ( '
for i in final_list:
if i not in join_type:
lead += i + ' '
lead = lead + ')'
# print(final_list)
visited = [0] * len(final_list)
join_hints = []
for i in range(len(final_list)):
if final_list[i] == ')' and visited[i] == 0:
# print("i=", i , " ", final_list[i])
# 找到前面第一个没有visited的左括号
tmp_rst = ')'
visited[i] == 1
for j in range(i-1, -1, -1):
if final_list[j] not in ['(', ')'] and final_list[j] not in join_type:
tmp_rst = final_list[j] + ' ' + tmp_rst
if final_list[j] == '(' and visited[j] == 0:
tmp_rst = hint_type_dict[final_list[j-1]] + ' ' + final_list[j] + ' ' + tmp_rst
visited[j] = 1
visited[j-1] = 1
break
join_hints.append(tmp_rst)
continue
return join_hints, lead
def gen_scan_hints(scan_mtd):
scan_hints = []
for scan in scan_mtd:
scan = scan.split(' ')
tmp = ''
for i in scan:
tmp += i
scan_hints.append(tmp)
return scan_hints
def gen_final_hint(str, scan_mtd):
result = '/*+'
for i in gen_scan_hints(scan_mtd):
result += '\n' + i
join_hints, leading = gen_join_hints(str)
for i in join_hints:
result += '\n' + i
result += '\n' + leading
result += ' */'
return result
str = 'Hash Join(c,Nested Loop(Nested Loop(Hash Join(v,p), Merge Join (a,u)),b))'
scan_mtd = ['Seq Scan(u)', 'Index Scan(p)', 'Index Scan(v)', 'Index Scan(b)', 'Index Only Scan(c)']
a, b = gen_join_hints(str)
print(a, b)
print(gen_scan_hints(scan_mtd))