kaqing 2.0.98__py3-none-any.whl → 2.0.171__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (194) hide show
  1. adam/__init__.py +0 -2
  2. adam/app_session.py +9 -7
  3. adam/batch.py +4 -18
  4. adam/checks/check_utils.py +14 -46
  5. adam/checks/cpu.py +7 -1
  6. adam/checks/cpu_metrics.py +52 -0
  7. adam/columns/columns.py +3 -1
  8. adam/columns/cpu.py +3 -1
  9. adam/columns/cpu_metrics.py +22 -0
  10. adam/commands/__init__.py +15 -0
  11. adam/commands/alter_tables.py +50 -61
  12. adam/commands/app_cmd.py +38 -0
  13. adam/commands/app_ping.py +8 -14
  14. adam/commands/audit/audit.py +43 -30
  15. adam/commands/audit/audit_repair_tables.py +26 -46
  16. adam/commands/audit/audit_run.py +50 -0
  17. adam/commands/audit/show_last10.py +48 -0
  18. adam/commands/audit/show_slow10.py +47 -0
  19. adam/commands/audit/show_top10.py +45 -0
  20. adam/commands/audit/utils_show_top10.py +59 -0
  21. adam/commands/bash/__init__.py +5 -0
  22. adam/commands/bash/bash.py +36 -0
  23. adam/commands/bash/bash_completer.py +93 -0
  24. adam/commands/bash/utils_bash.py +16 -0
  25. adam/commands/cat.py +50 -0
  26. adam/commands/cd.py +15 -91
  27. adam/commands/check.py +23 -18
  28. adam/commands/cli_commands.py +2 -3
  29. adam/commands/code.py +57 -0
  30. adam/commands/command.py +96 -40
  31. adam/commands/commands_utils.py +9 -19
  32. adam/commands/cp.py +33 -39
  33. adam/commands/cql/cql_completions.py +30 -8
  34. adam/commands/cql/cqlsh.py +12 -27
  35. adam/commands/cql/utils_cql.py +343 -0
  36. adam/commands/deploy/code_start.py +7 -10
  37. adam/commands/deploy/code_stop.py +4 -21
  38. adam/commands/deploy/code_utils.py +3 -3
  39. adam/commands/deploy/deploy.py +4 -21
  40. adam/commands/deploy/deploy_frontend.py +14 -17
  41. adam/commands/deploy/deploy_pg_agent.py +3 -6
  42. adam/commands/deploy/deploy_pod.py +67 -73
  43. adam/commands/deploy/deploy_utils.py +14 -24
  44. adam/commands/deploy/undeploy.py +4 -21
  45. adam/commands/deploy/undeploy_frontend.py +4 -7
  46. adam/commands/deploy/undeploy_pg_agent.py +6 -8
  47. adam/commands/deploy/undeploy_pod.py +11 -12
  48. adam/commands/devices/device.py +118 -0
  49. adam/commands/devices/device_app.py +173 -0
  50. adam/commands/devices/device_auit_log.py +49 -0
  51. adam/commands/devices/device_cass.py +185 -0
  52. adam/commands/devices/device_export.py +86 -0
  53. adam/commands/devices/device_postgres.py +144 -0
  54. adam/commands/devices/devices.py +25 -0
  55. adam/commands/exit.py +1 -4
  56. adam/commands/export/__init__.py +0 -0
  57. adam/commands/export/clean_up_all_export_sessions.py +37 -0
  58. adam/commands/export/clean_up_export_sessions.py +51 -0
  59. adam/commands/export/drop_export_database.py +55 -0
  60. adam/commands/export/drop_export_databases.py +43 -0
  61. adam/commands/export/export.py +53 -0
  62. adam/commands/export/export_databases.py +170 -0
  63. adam/commands/export/export_handlers.py +71 -0
  64. adam/commands/export/export_select.py +81 -0
  65. adam/commands/export/export_select_x.py +54 -0
  66. adam/commands/export/export_use.py +52 -0
  67. adam/commands/export/exporter.py +352 -0
  68. adam/commands/export/import_session.py +40 -0
  69. adam/commands/export/importer.py +67 -0
  70. adam/commands/export/importer_athena.py +80 -0
  71. adam/commands/export/importer_sqlite.py +47 -0
  72. adam/commands/export/show_column_counts.py +54 -0
  73. adam/commands/export/show_export_databases.py +36 -0
  74. adam/commands/export/show_export_session.py +48 -0
  75. adam/commands/export/show_export_sessions.py +44 -0
  76. adam/commands/export/utils_export.py +314 -0
  77. adam/commands/help.py +10 -6
  78. adam/commands/intermediate_command.py +49 -0
  79. adam/commands/issues.py +14 -40
  80. adam/commands/kubectl.py +38 -0
  81. adam/commands/login.py +28 -24
  82. adam/commands/logs.py +4 -6
  83. adam/commands/ls.py +11 -116
  84. adam/commands/medusa/medusa.py +4 -22
  85. adam/commands/medusa/medusa_backup.py +20 -24
  86. adam/commands/medusa/medusa_restore.py +30 -32
  87. adam/commands/medusa/medusa_show_backupjobs.py +16 -17
  88. adam/commands/medusa/medusa_show_restorejobs.py +12 -17
  89. adam/commands/nodetool.py +11 -17
  90. adam/commands/param_get.py +11 -12
  91. adam/commands/param_set.py +9 -10
  92. adam/commands/postgres/postgres.py +43 -36
  93. adam/commands/postgres/{postgres_session.py → postgres_context.py} +80 -46
  94. adam/commands/postgres/postgres_ls.py +4 -8
  95. adam/commands/postgres/postgres_preview.py +5 -9
  96. adam/commands/postgres/psql_completions.py +2 -2
  97. adam/commands/postgres/utils_postgres.py +66 -0
  98. adam/commands/preview_table.py +8 -61
  99. adam/commands/pwd.py +14 -44
  100. adam/commands/reaper/reaper.py +4 -24
  101. adam/commands/reaper/reaper_forward.py +48 -55
  102. adam/commands/reaper/reaper_forward_session.py +6 -0
  103. adam/commands/reaper/reaper_forward_stop.py +10 -16
  104. adam/commands/reaper/reaper_restart.py +7 -14
  105. adam/commands/reaper/reaper_run_abort.py +11 -30
  106. adam/commands/reaper/reaper_runs.py +42 -57
  107. adam/commands/reaper/reaper_runs_abort.py +29 -49
  108. adam/commands/reaper/reaper_schedule_activate.py +11 -30
  109. adam/commands/reaper/reaper_schedule_start.py +10 -29
  110. adam/commands/reaper/reaper_schedule_stop.py +10 -29
  111. adam/commands/reaper/reaper_schedules.py +4 -14
  112. adam/commands/reaper/reaper_status.py +8 -16
  113. adam/commands/reaper/utils_reaper.py +196 -0
  114. adam/commands/repair/repair.py +4 -22
  115. adam/commands/repair/repair_log.py +4 -7
  116. adam/commands/repair/repair_run.py +27 -29
  117. adam/commands/repair/repair_scan.py +31 -34
  118. adam/commands/repair/repair_stop.py +4 -7
  119. adam/commands/report.py +25 -21
  120. adam/commands/restart.py +25 -26
  121. adam/commands/rollout.py +19 -24
  122. adam/commands/shell.py +5 -4
  123. adam/commands/show/show.py +6 -19
  124. adam/commands/show/show_app_actions.py +26 -22
  125. adam/commands/show/show_app_id.py +8 -11
  126. adam/commands/show/show_app_queues.py +7 -10
  127. adam/commands/show/{show_repairs.py → show_cassandra_repairs.py} +8 -17
  128. adam/commands/show/show_cassandra_status.py +29 -33
  129. adam/commands/show/show_cassandra_version.py +4 -14
  130. adam/commands/show/show_commands.py +19 -21
  131. adam/commands/show/show_host.py +1 -1
  132. adam/commands/show/show_login.py +26 -24
  133. adam/commands/show/show_processes.py +16 -18
  134. adam/commands/show/show_storage.py +10 -20
  135. adam/commands/watch.py +26 -29
  136. adam/config.py +5 -14
  137. adam/embedded_params.py +1 -1
  138. adam/pod_exec_result.py +7 -1
  139. adam/repl.py +95 -131
  140. adam/repl_commands.py +48 -20
  141. adam/repl_state.py +270 -61
  142. adam/sql/sql_completer.py +105 -63
  143. adam/sql/sql_state_machine.py +618 -0
  144. adam/sql/term_completer.py +3 -0
  145. adam/sso/authn_ad.py +6 -5
  146. adam/sso/authn_okta.py +3 -3
  147. adam/sso/cred_cache.py +3 -2
  148. adam/sso/idp.py +3 -3
  149. adam/utils.py +439 -3
  150. adam/utils_app.py +98 -0
  151. adam/utils_athena.py +140 -87
  152. adam/utils_audits.py +106 -0
  153. adam/utils_issues.py +32 -0
  154. adam/utils_k8s/app_clusters.py +28 -0
  155. adam/utils_k8s/app_pods.py +33 -0
  156. adam/utils_k8s/cassandra_clusters.py +22 -20
  157. adam/utils_k8s/cassandra_nodes.py +4 -4
  158. adam/utils_k8s/custom_resources.py +5 -0
  159. adam/utils_k8s/ingresses.py +2 -2
  160. adam/utils_k8s/k8s.py +87 -0
  161. adam/utils_k8s/pods.py +77 -68
  162. adam/utils_k8s/secrets.py +4 -4
  163. adam/utils_k8s/service_accounts.py +5 -4
  164. adam/utils_k8s/services.py +2 -2
  165. adam/utils_k8s/statefulsets.py +1 -12
  166. adam/utils_net.py +4 -4
  167. adam/utils_repl/__init__.py +0 -0
  168. adam/utils_repl/automata_completer.py +48 -0
  169. adam/utils_repl/repl_completer.py +46 -0
  170. adam/utils_repl/state_machine.py +173 -0
  171. adam/utils_sqlite.py +109 -0
  172. adam/version.py +1 -1
  173. {kaqing-2.0.98.dist-info → kaqing-2.0.171.dist-info}/METADATA +1 -1
  174. kaqing-2.0.171.dist-info/RECORD +236 -0
  175. adam/commands/app.py +0 -67
  176. adam/commands/bash.py +0 -92
  177. adam/commands/cql/cql_table_completer.py +0 -8
  178. adam/commands/cql/cql_utils.py +0 -115
  179. adam/commands/describe/describe.py +0 -47
  180. adam/commands/describe/describe_keyspace.py +0 -60
  181. adam/commands/describe/describe_keyspaces.py +0 -49
  182. adam/commands/describe/describe_schema.py +0 -49
  183. adam/commands/describe/describe_table.py +0 -60
  184. adam/commands/describe/describe_tables.py +0 -49
  185. adam/commands/devices.py +0 -118
  186. adam/commands/postgres/postgres_utils.py +0 -31
  187. adam/commands/postgres/psql_table_completer.py +0 -11
  188. adam/commands/reaper/reaper_session.py +0 -159
  189. adam/sql/state_machine.py +0 -460
  190. kaqing-2.0.98.dist-info/RECORD +0 -191
  191. /adam/commands/{describe → devices}/__init__.py +0 -0
  192. {kaqing-2.0.98.dist-info → kaqing-2.0.171.dist-info}/WHEEL +0 -0
  193. {kaqing-2.0.98.dist-info → kaqing-2.0.171.dist-info}/entry_points.txt +0 -0
  194. {kaqing-2.0.98.dist-info → kaqing-2.0.171.dist-info}/top_level.txt +0 -0
@@ -1,11 +0,0 @@
1
- from adam.commands.postgres.postgres_utils import pg_table_names
2
- from adam.sql.term_completer import TermCompleter
3
-
4
- class PsqlTableNameCompleter(TermCompleter):
5
- def __init__(self, namespace: str, pg_path: str, ignore_case: bool = True):
6
- super().__init__(pg_table_names(namespace, pg_path), ignore_case=ignore_case)
7
- self.namespace = namespace
8
- self.pg_path = pg_path
9
-
10
- def __repr__(self) -> str:
11
- return "PsqlTableCompleter(%r, pg_path=%r)" % (self.namespace, self.pg_path)
@@ -1,159 +0,0 @@
1
- from collections.abc import Callable
2
- import threading
3
- from kubernetes import client
4
- import portforward
5
- import re
6
- import requests
7
- from typing import List, cast
8
-
9
- from adam.config import Config
10
- from adam.utils_k8s.kube_context import KubeContext
11
- from adam.repl_state import ReplState
12
- from adam.utils import lines_to_tabular, log2
13
-
14
- class ReaperSession:
15
- is_forwarding = False
16
- stopping = threading.Event()
17
- schedules_ids_by_cluster: dict[str, list[str]] = {}
18
-
19
- def __init__(self, pod: str, headers: dict[str, str] = None):
20
- self.pod = pod
21
- self.headers = headers
22
-
23
- def login(self, state: ReplState, local_addr: str, remote_addr: str, show_output = True) -> str :
24
- user, pw = state.user_pass(secret_path='reaper.secret')
25
-
26
- response = requests.post(f'http://{local_addr}/login', headers={
27
- 'Accept': '*'
28
- },data={
29
- 'username':user,
30
- 'password':pw})
31
- if show_output:
32
- log2(f'POST {remote_addr}/login')
33
- log2(f' username={user}&password={pw}')
34
-
35
- if int(response.status_code / 100) != 2:
36
- if show_output:
37
- log2("login failed")
38
- return None
39
-
40
- return response.headers['Set-Cookie']
41
-
42
- def port_forwarded(self, state: ReplState, path: str, body: Callable[[str, dict[str, str]], requests.Response], method: str = None, show_output = True):
43
- local_port = Config().get('reaper.port-forward.local-port', 9001)
44
- target_port = 8080
45
-
46
- def f(local_addr: str, remote_addr: str):
47
- if not self.headers:
48
- self.headers = self.cookie_header(state, local_addr, remote_addr, show_output=show_output)
49
-
50
- if show_output and method:
51
- log2(f'{method} {remote_addr}/{path}')
52
- response = body(f'http://{local_addr}/{path}', self.headers)
53
-
54
- if response:
55
- if int(response.status_code / 100) != 2:
56
- if show_output:
57
- log2(response.status_code)
58
- return response
59
-
60
- if show_output:
61
- log2()
62
-
63
- return response if response else 'no-response'
64
-
65
- if KubeContext.in_cluster():
66
- # cs-a526330d23-cs-a526330d23-default-sts-0 ->
67
- # curl http://cs-a526330d23-cs-a526330d23-reaper-service.stgawsscpsr.svc.cluster.local:8080
68
- groups = re.match(r'^(.*?-.*?-.*?-.*?-).*', state.sts)
69
- if groups:
70
- svc_name = Config().get('reaper.service-name', 'reaper-service')
71
- svc = f'{groups[1]}{svc_name}.{state.namespace}.svc.cluster.local:{target_port}'
72
- return f(local_addr=svc, remote_addr=svc)
73
- else:
74
- return None
75
- else:
76
- with portforward.forward(state.namespace, self.pod, local_port, target_port):
77
- return f(local_addr=f'localhost:{local_port}', remote_addr=f'{self.pod}:{target_port}')
78
-
79
- def cookie_header(self, state: ReplState, local_addr, remote_addr, show_output = True):
80
- return {'Cookie': self.login(state, local_addr, remote_addr, show_output=show_output)}
81
-
82
- def create(state: ReplState) -> 'ReaperSession':
83
- pods = ReaperSession.list_reaper_pods(state.sts if state.sts else state.pod, state.namespace)
84
- if pods:
85
- return ReaperSession(pods[0].metadata.name)
86
- else:
87
- log2('No reaper found.')
88
-
89
- return None
90
-
91
- def list_reaper_pods(sts_name: str, namespace: str) -> List[client.V1Pod]:
92
- v1 = client.CoreV1Api()
93
-
94
- # k8ssandra.io/reaper: cs-d0767a536f-cs-d0767a536f-reaper
95
- groups = re.match(Config().get('reaper.pod.cluster-regex', r'(.*?-.*?-.*?-.*?)-.*'), sts_name)
96
- label_selector = Config().get('reaper.pod.label-selector', 'k8ssandra.io/reaper={cluster}-reaper').replace('{cluster}', groups[1])
97
-
98
- return cast(List[client.V1Pod], v1.list_namespaced_pod(namespace, label_selector=label_selector).items)
99
-
100
- def show_schedules(self, state: ReplState, filter: Callable[[list[dict]], dict] = None):
101
- schedules = self.list_schedules(state, filter=filter)
102
- # forced refresh of schedule list
103
- if not filter:
104
- self.schedules_ids_by_cluster[state.sts] = [schedule['id'] for schedule in schedules]
105
- self.show_schedules_tabular(schedules)
106
-
107
- def schedule_ids(self, state: ReplState, show_output = True, filter: Callable[[list[dict]], dict] = None):
108
- schedules = self.list_schedules(state, show_output=show_output, filter=filter)
109
- return [schedule['id'] for schedule in schedules]
110
-
111
- def list_schedules(self, state: ReplState, show_output = True, filter: Callable[[list[dict]], dict] = None) -> list[dict]:
112
- def body(uri: str, headers: dict[str, str]):
113
- return requests.get(uri, headers=headers)
114
-
115
- response = self.port_forwarded(state, 'repair_schedule', body, method='GET', show_output=show_output)
116
- if not response:
117
- return
118
-
119
- res = response.json()
120
- if filter:
121
- res = filter(res)
122
-
123
- return res
124
-
125
- def show_schedules_tabular(self, schedules: list[dict]):
126
- log2(lines_to_tabular([f"{schedule['id']} {schedule['state']} {schedule['cluster_name']} {schedule['keyspace_name']}" for schedule in schedules], 'ID STATE CLUSTER KEYSPACE'))
127
-
128
- def show_schedule(self, state: ReplState, schedule_id: str):
129
- def filter(schedules: list[dict]):
130
- return [schedule for schedule in schedules if schedule['id'] == schedule_id]
131
-
132
- self.show_schedules(state, filter)
133
-
134
- def reaper_spec(self, state: ReplState) -> dict[str, any]:
135
- user, pw = state.user_pass(secret_path='reaper.secret')
136
- local_port = Config().get('reaper.port-forward.local-port', 9001)
137
-
138
- return {
139
- 'pod': self.pod,
140
- 'exec': f'kubectl exec -it {self.pod} -n {state.namespace} -- bash',
141
- 'forward': f'kubectl port-forward pods/{self.pod} -n {state.namespace} {local_port}:8080',
142
- 'web-uri': f'http://localhost:{local_port}/webui',
143
- 'username': user,
144
- 'password': pw
145
- }
146
-
147
- def cached_schedule_ids(state: ReplState) -> list[str]:
148
- if state.sts in ReaperSession.schedules_ids_by_cluster:
149
- return ReaperSession.schedules_ids_by_cluster[state.sts]
150
-
151
- if reaper := ReaperSession.create(state):
152
- Config().wait_log('Inspecting Cassandra Reaper...')
153
-
154
- schedules = reaper.schedule_ids(state, show_output = False)
155
- ReaperSession.schedules_ids_by_cluster[state.sts] = schedules
156
-
157
- return schedules
158
-
159
- return []
adam/sql/state_machine.py DELETED
@@ -1,460 +0,0 @@
1
- # <select_statement> ::= SELECT <select_list>
2
- # FROM <table_expression>
3
- # [WHERE <search_condition>]
4
- # [<group_by_clause>]
5
- # [<having_clause>]
6
- # [<order_by_clause>]
7
- # [<limit_clause>]
8
-
9
- # <search_condition> ::= <boolean_term>
10
- # | <search_condition> OR <boolean_term>
11
-
12
- # <boolean_term> ::= <boolean_factor>
13
- # | <boolean_term> AND <boolean_factor>
14
-
15
- # <boolean_factor> ::= [NOT] <predicate>
16
- # | ([NOT] <search_condition>)
17
-
18
- # <predicate> ::= <comparison_predicate>
19
- # | <between_predicate>
20
- # | <in_predicate>
21
- # | <like_predicate>
22
- # | <null_predicate>
23
- # | <exists_predicate>
24
- # | <quantified_predicate>
25
- # | <unique_predicate>
26
- # | <match_predicate>
27
- # | <overlaps_predicate>
28
- # | <distinct_predicate>
29
- # | <member_predicate>
30
- # | <submultiset_predicate>
31
- # | <set_predicate>
32
-
33
- # <comparison_predicate> ::= <row_value_expression> <comparison_operator> <row_value_expression>
34
- # <comparison_operator> ::= '=' | '<>' | '<' | '<=' | '>' | '>='
35
-
36
- # <row_value_expression> ::= <value_expression>
37
- # | (<value_expression> [ { <comma> <value_expression> }... ])
38
-
39
- # <value_expression> ::= <numeric_value_expression>
40
- # | <string_value_expression>
41
- # | <datetime_value_expression>
42
- # | <interval_value_expression>
43
- # | <boolean_value_expression>
44
- # | <user_defined_type_value_expression>
45
- # | <reference_value_expression>
46
- # | <collection_value_expression>
47
- # | <row_value_constructor>
48
- # | <case_expression>
49
- # | <cast_expression>
50
- # | <subquery>
51
- # | NULL
52
- # | DEFAULT
53
- # | <identifier>
54
- # | <literal>
55
-
56
- # <insert_statement> ::= INSERT INTO <table_name> [ ( <column_list> ) ]
57
- # VALUES ( <value_list> )
58
- # | INSERT INTO <table_name> [ ( <column_list> ) ]
59
- # <query_expression>
60
-
61
- # <table_name> ::= <identifier>
62
-
63
- # <column_list> ::= <column_name> [ , <column_list> ]
64
-
65
- # <column_name> ::= <identifier>
66
-
67
- # <value_list> ::= <expression> [ , <value_list> ]
68
-
69
- # <query_expression> ::= SELECT <select_list> FROM <table_reference_list> [ WHERE <search_condition> ] [ GROUP BY <grouping_column_list> ] [ HAVING <search_condition> ] [ ORDER BY <sort_specification_list> ]
70
-
71
- # <update_statement> ::= UPDATE <table_name>
72
- # SET <set_clause_list>
73
- # [WHERE <search_condition>]
74
-
75
- # <set_clause_list> ::= <set_clause> { , <set_clause> }
76
-
77
- # <set_clause> ::= <column_name> = <update_value>
78
-
79
- # <update_value> ::= <expression> | NULL | DEFAULT
80
-
81
- # <search_condition> ::= <boolean_expression>
82
-
83
- # <delete_statement> ::= DELETE FROM <table_name> [ WHERE <search_condition> ]
84
-
85
- # <table_name> ::= <identifier>
86
-
87
- # <search_condition> ::= <boolean_expression>
88
-
89
- # <boolean_expression> ::= <predicate>
90
- # | <boolean_expression> AND <predicate>
91
- # | <boolean_expression> OR <predicate>
92
- # | NOT <predicate>
93
- # | ( <boolean_expression> )
94
-
95
- # <predicate> ::= <expression> <comparison_operator> <expression>
96
- # | <expression> IS NULL
97
- # | <expression> IS NOT NULL
98
- # | <expression> LIKE <pattern> [ ESCAPE <escape_character> ]
99
- # | <expression> IN ( <expression_list> )
100
- # | EXISTS ( <select_statement> )
101
- # | ... (other predicates)
102
-
103
- # <comparison_operator> ::= = | <> | != | > | < | >= | <=
104
-
105
- # <expression> ::= <literal>
106
- # | <column_name>
107
- # | <function_call>
108
- # | ( <expression> )
109
- # | <expression> <arithmetic_operator> <expression>
110
- # | ... (other expressions)
111
-
112
- # <literal> ::= <numeric_literal> | <string_literal> | <boolean_literal> | <date_literal> | ...
113
-
114
- # <column_name> ::= <identifier>
115
-
116
- # <identifier> ::= <letter> { <letter> | <digit> | _ }...
117
-
118
- # <pattern> ::= <string_literal>
119
-
120
- # <escape_character> ::= <string_literal> (single character)
121
-
122
- # <expression_list> ::= <expression> { , <expression> }...
123
-
124
- from sqlparse.sql import Token
125
- from sqlparse import tokens as T
126
-
127
- __all__ = [
128
- "StateMachine",
129
- ]
130
-
131
- SPEC = [
132
- ' > select > select',
133
- 'select_ > name|* > select_a ^ *',
134
- 'select_a > , > select_a_comma_',
135
- 'select_a_comma_ > name|* > select_a ^ *',
136
- 'select_a_ > from > select_from ^ from',
137
- 'select_from_ > name|audit > select_from_x ^ (select,tables',
138
- '- > ( > select_from_lp_',
139
- '- < ) > select_from_sq',
140
- 'select_from_lp_ > select > select',
141
- 'select_from_x > , > select_from_x_comma_ ^ (select,tables',
142
- 'select_from_sq_ > as > select_from_x_as ^ as',
143
- 'select_from_x_comma_ > name > select_from_x ^ tables',
144
- 'select_from_x_ ^ as,where,inner join,left outer join,right outer join,full outer join,group by,order by,limit',
145
- 'select_from_x_as_x_ > , > select_from_x_comma_ ^ where,inner join,left outer join,right outer join,full outer join,group by,order by,limit',
146
- '- > as > select_from_x_as',
147
- '- > where > select_where',
148
- '- > order > select_order',
149
- '- > order by > select_order_by',
150
- '- > limit > select_where_sc_limit',
151
- '- > group > select_group',
152
- '- > group by > select_group_by',
153
- '- > inner > select_from_x_inner',
154
- '- > inner join > select_join',
155
- '- > left > select_from_x_left',
156
- '- > left join > select_join',
157
- '- > left outer join > select_join',
158
- '- > right > select_from_x_right',
159
- '- > right join > select_join',
160
- '- > right outer join > select_join',
161
- '- > full > select_from_x_full',
162
- '- > full outer join > select_join',
163
- 'select_from_x_as_ > name > select_from_x_as_x ^ x,y,z',
164
- 'select_from_x_as_x > , > select_from_x_as_x_comma_',
165
- 'select_from_x_as_x_comma_ > name > select_from_x ^ tables',
166
- 'select_where_ > name > select_where_a ^ columns',
167
- 'select_where_a > name > select_where_a ^ columns,=,<,<=,>,>=,<>',
168
- '- > comparison > select_where_a_op',
169
- 'select_where_a_ > comparison > select_where_a_op ^ =,<,<=,>,>=,<>,like,not,in',
170
- '- > not > select_where_a_not',
171
- '- > in > select_where_a_in',
172
- 'select_where_a_not_ > comparison > select_where_a_not_op ^ like,in',
173
- '- > in > select_where_a_in',
174
- 'select_where_a_in > ( > select_where_a_in_lp_ ^ (',
175
- '- < ) > select_where_sc',
176
- 'select_where_a_in_lp_ > name|single|num > select_where_a_in_lp_a ^ single,select',
177
- '- > select > select_where_a_in_lp_select',
178
- 'select_where_a_in_lp_select_ > name > select_a ^ id',
179
- 'select_where_a_in_lp_a > , > select_where_a_in_lp_a_comma_ ^ comma,)',
180
- 'select_where_a_in_lp_a_comma_ > name|single|num > select_where_a_in_lp_a ^ single',
181
- 'select_where_a_not_op > name|single|num > select_where_sc ^ single',
182
- 'select_where_a_op > name|single|num > select_where_sc ^ single',
183
- 'select_where_sc_ > and|or > select_where ^ and,or,order by,group by,limit',
184
- '- > group > select_group',
185
- '- > group by > select_group_by',
186
- '- > order > select_order',
187
- '- > order by > select_order_by',
188
- '- > limit > select_where_sc_limit',
189
- 'select_group_ > by > select_group_by ^ by',
190
- 'select_group_by_ > name > select_group_by_a ^ columns',
191
- 'select_group_by_a > name > select_group_by_a ^ columns',
192
- '- > , > select_group_by_a_comma_ ^ columns',
193
- 'select_group_by_a_comma_ > name > select_group_by_a ^ columns',
194
- 'select_group_by_a_ > limit > select_where_sc_limit ^ limit,order by',
195
- '- > order > select_order',
196
- '- > order by > select_order_by',
197
- 'select_order_ > by > select_order_by ^ by',
198
- 'select_order_by_ > name > select_order_by_a ^ columns',
199
- 'select_order_by_a > name > select_order_by_a ^ columns',
200
- '- > , > select_order_by_a_comma_',
201
- 'select_order_by_a_comma_ > name > select_order_by_a ^ columns',
202
- 'select_order_by_a_ > desc|asc > select_order_by_a_desc ^ desc,asc,limit',
203
- '- > limit > select_where_sc_limit',
204
- 'select_order_by_a_desc > , > select_order_by_a_comma_',
205
- 'select_order_by_a_desc_ > limit > select_where_sc_limit ^ limit',
206
- 'select_where_sc_limit_ > num > select_where_sc_limit_num ^ 1',
207
- 'select_where_sc_limit_num_rp__ > as > select_from_x_as ^ as',
208
- 'select_where_x_inner_ > join > select_join',
209
- 'select_join_ > name > select_x_join_y ^ tables',
210
- 'select_from_x_left_ > join > select_join ^ outer join',
211
- '- > outer > select_from_x_left_outer',
212
- 'select_from_x_left_outer_ > join > select_join ^ join',
213
- 'select_from_x_right_ > join > select_join ^ outer join',
214
- '- > outer > select_from_x_right_outer',
215
- 'select_from_x_right_outer_ > join > select_join ^ join',
216
- 'select_from_x_full_ > join > select_join ^ outer join',
217
- '- > outer > select_from_x_full_outer',
218
- 'select_from_x_full_outer_ > join > select_join ^ join',
219
- 'select_x_join_y > name > select_x_join_y ^ tables',
220
- 'select_x_join_y_ > as > select_x_join_y_as ^ as,on',
221
- '- > on > select_x_join_y_on ^ as,on',
222
- 'select_x_join_y_as_ > name > select_x_join_y_as_y ^ x,y,z',
223
- 'select_x_join_y_as_y_ > on > select_x_join_y_on ^ on',
224
- 'select_x_join_y_on_ > name > select_x_join_y_on_a ^ columns',
225
- 'select_x_join_y_on_a > name > select_x_join_y_on_a ^ columns,=',
226
- '- > comparison > select_x_join_y_on_a_op',
227
- 'select_x_join_y_on_a_ > comparison > select_x_join_y_on_a_op ^ =',
228
- 'select_x_join_y_on_a_op > name > select_x_join_y_on_a_op_b ^ columns',
229
- 'select_x_join_y_on_a_op_b > name > select_x_join_y_on_a_op_b ^ columns',
230
- '- > _ > select_from_x_as_x_',
231
-
232
-
233
- ' > insert > insert',
234
- 'insert_ > into > insert_into ^ into',
235
- 'insert_into_ > name > insert_into_x ^ tables',
236
- 'insert_into_x > name > insert_into_x ^ tables',
237
- '- > ( > insert_into_x_lp_',
238
- 'insert_into_x_ > ( > insert_into_x_lp_ ^ (,values(',
239
- '- > values > insert_values',
240
- 'insert_into_x_lp_ > name > insert_into_x_lp_a ^ id',
241
- 'insert_into_x_lp_a > , > insert_into_x_lp_a_comma_',
242
- '- > ) > insert_into_x_lp_a_rp_',
243
- 'insert_into_x_lp_a_comma_ > name > insert_into_x_lp_a ^ id',
244
- 'insert_into_x_lp_a_rp__ > values > insert_values ^ values(,select',
245
- '- > select > select',
246
- 'insert_values > ( > insert_values_lp_',
247
- 'insert_values_lp_ > name|single|num > insert_values_lp_v ^ single',
248
- 'insert_values_lp_v > , > insert_values_lp_v_comma_',
249
- 'insert_values_lp_v_comma_ > name|single|num > insert_values_lp_v',
250
-
251
-
252
- ' > update > update',
253
- 'update_ > name > update_x ^ tables',
254
- 'update_x > name > update_x ^ tables',
255
- 'update_x_ > set > update_set ^ set',
256
- 'update_set_ > name > update_set_a ^ id',
257
- 'update_set_a > comparison > update_set_a_op',
258
- 'update_set_a_op > name|single|num > update_set_sc ^ single',
259
- 'update_set_sc > , > update_set_sc_comma_',
260
- 'update_set_sc_comma_ > name > update_set_a ^ id',
261
- 'update_set_sc_ > , > update_set_sc_comma_ ^ where',
262
- '- > where > update_where',
263
- 'update_where_ > name > update_where_a ^ id',
264
- 'update_where_a > comparison > update_where_a_op',
265
- 'update_where_a_ > comparison > update_where_a_op ^ =,<,<=,>,>=,<>,like,not,in',
266
- '- > not > update_where_a_not',
267
- '- > in > update_where_a_in',
268
- 'update_where_a_not_ > comparison > update_where_a_not_op ^ like,in',
269
- '- > in > update_where_a_in',
270
- 'update_where_a_in > ( > update_where_a_in_lp_ ^ (',
271
- '- < ) > update_where_sc',
272
- 'update_where_a_in_lp_ > name|single|num > update_where_a_in_lp_a ^ single,select',
273
- '- > select > update_where_a_in_lp_select',
274
- 'update_where_a_in_lp_select_ > name > select_a ^ id',
275
- 'update_where_a_in_lp_a > , > update_where_a_in_lp_a_comma_ ^ comma,)',
276
- 'update_where_a_in_lp_a_comma_ > name|single|num > update_where_a_in_lp_a ^ single',
277
- 'update_where_a_not_op > name|single|num > update_where_sc ^ single',
278
- 'update_where_a_op > name|single|num > update_where_sc ^ single',
279
- 'update_where_sc_ > and|or > update_where ^ and,or',
280
-
281
-
282
- ' > delete > delete',
283
- 'delete_ > from > delete_from ^ from',
284
- 'delete_from_ > name > delete_from_x ^ tables',
285
- 'delete_from_x > name > delete_from_x ^ tables',
286
- 'delete_from_x_ > where > update_where ^ where',
287
- ]
288
-
289
- KEYWORDS = [
290
- 'select', 'from', 'as', 'not', 'in', 'where',
291
- 'and', 'or', 'group', 'by', 'group by', 'order', 'order by', 'limit', 'asc', 'desc',
292
- 'inner join', 'on', 'left', 'right', 'full', 'outer', 'left outer join',
293
- 'left join', 'right outer join', 'right join', 'full join', 'full outer join',
294
- 'insert', 'into', 'values',
295
- 'update', 'where', 'set',
296
- 'delete',
297
- 'audit'
298
- ]
299
-
300
- class StateTo:
301
- def __init__(self, to_s: str, comeback_token: str = None, comeback_state: str = None):
302
- self.to_s = to_s
303
- self.comeback_token = comeback_token
304
- self.comeback_state = comeback_state
305
-
306
- def __str__(self):
307
- return f'{self.to_s} comeback[{self.comeback_token} {self.comeback_state}]'
308
-
309
- class StateMachine:
310
- def __init__(self, indent=0, lp_level = 0, debug = False):
311
- self.states: dict[str, StateTo] = {}
312
- self.suggestions: dict[str, str] = {}
313
-
314
- self.indent = indent
315
- self.lp_level = lp_level
316
- self.comebacks: dict[int, str] = {}
317
- self.debug = debug
318
-
319
- from_ss_to_add = []
320
- from_ss = ['']
321
- words: str = None
322
- for l in SPEC:
323
- t_and_w = l.split('^')
324
- if len(t_and_w) > 1:
325
- words = t_and_w[1]
326
- else:
327
- words = None
328
-
329
- tks = t_and_w[0].strip(' ').split('>')
330
- if not l.startswith('-'):
331
- if words:
332
- self.suggestions[tks[0].strip(' ')] = words
333
-
334
- if len(tks) == 1:
335
- from_ss_to_add.append(tks[0].strip(' '))
336
- continue
337
-
338
- from_ss = []
339
- from_ss.extend(from_ss_to_add)
340
- from_ss_to_add = []
341
- from_ss.append(tks[0].strip(' '))
342
-
343
- self.add_transitions(from_ss, tks)
344
-
345
- def add_transitions(self, from_ss: list[str], tks: list[str]):
346
- token = tks[1].strip(' ')
347
- if len(tks) > 2:
348
- to_s = tks[2].strip(' ')
349
- for from_s in from_ss:
350
- self.add_whitespace_transition(from_s, to_s)
351
- self.add_transition(from_s, token, to_s)
352
- elif '<' in tks[0]:
353
- from_and_token = tks[0].split('<')
354
- if len(from_and_token) > 1:
355
- for from_s in from_ss:
356
- self.add_comeback_transition(from_s, from_and_token[1], tks[1].strip(' '))
357
-
358
- def add_whitespace_transition(self, from_s: str, to_s: str):
359
- # add whitespace transition if a state with trailing whitespace is found from from states, for example, select > _ > select_
360
- if from_s.endswith('_') and not from_s.endswith('_comma_') and not from_s.endswith('_lp_') and not from_s.endswith('_rp_'):
361
- if self.debug:
362
- print(f'{from_s[:-1]} > _ = {to_s}')
363
- self.states[f'{from_s[:-1]} > _'] = StateTo(from_s)
364
-
365
- def add_transition(self, from_s: str, token: str, to_s: str):
366
- tokens = [token]
367
- if '|' in token:
368
- tokens = token.split('|')
369
-
370
- for t in tokens:
371
- if self.debug:
372
- print(f'{from_s} > {t} = {to_s}')
373
- self.states[f'{from_s} > {t}'] = StateTo(to_s)
374
-
375
- def add_comeback_transition(self, from_s: str, token: str, to_s: str):
376
- key = f'{from_s} > ('
377
- orig = self.states[key]
378
- if not orig:
379
- raise Exception(f'from state not found for {key}')
380
-
381
- orig.comeback_token = token
382
- orig.comeback_state = to_s
383
- if self.debug:
384
- print(f'{from_s} > ) = {to_s}')
385
- self.states[key] = orig
386
-
387
- def traverse_tokens(self, tokens: list[Token], state: StateTo = StateTo('')):
388
- def handle_opening_parenthesis():
389
- if f'{state.to_s} > {it}' in self.states:
390
- state_test = self.states[f'{state.to_s} > {it}']
391
- if state_test.comeback_token:
392
- self.comebacks[self.lp_level] = state_test.comeback_state
393
-
394
- def handle_closing_parenthesis():
395
- if self.lp_level in self.comebacks:
396
- try:
397
- return StateTo(self.comebacks[self.lp_level])
398
- finally:
399
- del self.comebacks[self.lp_level]
400
-
401
- return None
402
-
403
- for token in tokens:
404
- if self.debug:
405
- if token.ttype == T.Whitespace:
406
- print('_ ', end='')
407
- elif token.ttype in [T.DML, T.Wildcard, T.Punctuation]:
408
- print(f'{token.value} ', end='')
409
- elif token.ttype:
410
- tks = str(token.ttype).split('.')
411
- typ = tks[len(tks) - 1]
412
- if ' ' in token.value:
413
- print(f'"{token.value}:{typ}" ', end='')
414
- else:
415
- print(f'{token.value}:{typ} ', end='')
416
- # print(" " * self.indent + f"Token: {token.value}, Type: {token.ttype}@{token.ttype.__class__}")
417
-
418
- if token.is_group:
419
- state = self.traverse_tokens(token.tokens, state)
420
- else:
421
- comeback_state = None
422
-
423
- it = ''
424
- if (t := token.value.lower()) in KEYWORDS:
425
- it = t
426
- elif token.ttype == T.Text.Whitespace:
427
- it = '_'
428
- elif token.ttype == T.Name:
429
- it = 'name'
430
- elif token.ttype == T.Literal.String.Single:
431
- it = 'single'
432
- elif token.ttype in [T.Literal.Number.Integer, T.Literal.Number.Float]:
433
- it = 'num'
434
- elif token.ttype == T.Wildcard:
435
- it = '*'
436
- elif token.ttype == T.Punctuation:
437
- it = token.value
438
-
439
- if it == '(':
440
- handle_opening_parenthesis()
441
- self.lp_level += 1
442
- elif it == ')':
443
- self.lp_level -= 1
444
- comeback_state = handle_closing_parenthesis()
445
-
446
- elif token.ttype == T.Operator.Comparison:
447
- it = 'comparison'
448
-
449
- try:
450
- # print(f'\n{state.to_s} > {it} > ', end='')
451
- if comeback_state:
452
- state = comeback_state
453
- else:
454
- state = self.states[f'{state.to_s} > {it}']
455
- # print(state)
456
- except:
457
- pass
458
- # print('error')
459
-
460
- return state