kaqing 2.0.52__py3-none-any.whl → 2.0.184__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.

Potentially problematic release.


This version of kaqing might be problematic. Click here for more details.

Files changed (223) hide show
  1. adam/__init__.py +0 -2
  2. adam/app_session.py +9 -12
  3. adam/apps.py +20 -6
  4. adam/batch.py +15 -19
  5. adam/checks/check_utils.py +19 -49
  6. adam/checks/compactionstats.py +1 -1
  7. adam/checks/cpu.py +9 -3
  8. adam/checks/cpu_metrics.py +52 -0
  9. adam/checks/disk.py +3 -4
  10. adam/checks/gossip.py +1 -1
  11. adam/checks/memory.py +3 -3
  12. adam/checks/status.py +1 -1
  13. adam/columns/columns.py +3 -1
  14. adam/columns/cpu.py +3 -1
  15. adam/columns/cpu_metrics.py +22 -0
  16. adam/columns/memory.py +3 -4
  17. adam/commands/__init__.py +24 -0
  18. adam/commands/alter_tables.py +37 -63
  19. adam/commands/app/app.py +38 -0
  20. adam/commands/{app_ping.py → app/app_ping.py} +8 -14
  21. adam/commands/app/show_app_actions.py +49 -0
  22. adam/commands/{show → app}/show_app_id.py +9 -12
  23. adam/commands/{show → app}/show_app_queues.py +8 -14
  24. adam/commands/app/utils_app.py +98 -0
  25. adam/commands/audit/audit.py +81 -0
  26. adam/commands/audit/audit_repair_tables.py +72 -0
  27. adam/commands/audit/audit_run.py +50 -0
  28. adam/commands/audit/show_last10.py +37 -0
  29. adam/commands/audit/show_slow10.py +36 -0
  30. adam/commands/audit/show_top10.py +36 -0
  31. adam/commands/audit/utils_show_top10.py +71 -0
  32. adam/commands/bash/__init__.py +5 -0
  33. adam/commands/bash/bash.py +36 -0
  34. adam/commands/bash/bash_completer.py +93 -0
  35. adam/commands/bash/utils_bash.py +16 -0
  36. adam/commands/cat.py +36 -0
  37. adam/commands/cd.py +14 -89
  38. adam/commands/check.py +18 -21
  39. adam/commands/cli_commands.py +5 -6
  40. adam/commands/clipboard_copy.py +86 -0
  41. adam/commands/code.py +57 -0
  42. adam/commands/command.py +197 -35
  43. adam/commands/commands_utils.py +15 -31
  44. adam/commands/cql/cql_completions.py +29 -8
  45. adam/commands/cql/cqlsh.py +12 -27
  46. adam/commands/cql/utils_cql.py +297 -0
  47. adam/commands/deploy/code_start.py +7 -10
  48. adam/commands/deploy/code_stop.py +4 -21
  49. adam/commands/deploy/code_utils.py +5 -5
  50. adam/commands/deploy/deploy.py +4 -21
  51. adam/commands/deploy/deploy_frontend.py +14 -17
  52. adam/commands/deploy/deploy_pg_agent.py +3 -6
  53. adam/commands/deploy/deploy_pod.py +71 -79
  54. adam/commands/deploy/deploy_utils.py +16 -26
  55. adam/commands/deploy/undeploy.py +4 -21
  56. adam/commands/deploy/undeploy_frontend.py +4 -7
  57. adam/commands/deploy/undeploy_pg_agent.py +6 -8
  58. adam/commands/deploy/undeploy_pod.py +15 -16
  59. adam/commands/devices/__init__.py +0 -0
  60. adam/commands/devices/device.py +123 -0
  61. adam/commands/devices/device_app.py +163 -0
  62. adam/commands/devices/device_auit_log.py +49 -0
  63. adam/commands/devices/device_cass.py +179 -0
  64. adam/commands/devices/device_export.py +84 -0
  65. adam/commands/devices/device_postgres.py +150 -0
  66. adam/commands/devices/devices.py +25 -0
  67. adam/commands/download_file.py +47 -0
  68. adam/commands/exit.py +1 -4
  69. adam/commands/export/__init__.py +0 -0
  70. adam/commands/export/clean_up_all_export_sessions.py +37 -0
  71. adam/commands/export/clean_up_export_sessions.py +39 -0
  72. adam/commands/export/download_export_session.py +39 -0
  73. adam/commands/export/drop_export_database.py +39 -0
  74. adam/commands/export/drop_export_databases.py +37 -0
  75. adam/commands/export/export.py +53 -0
  76. adam/commands/export/export_databases.py +245 -0
  77. adam/commands/export/export_select.py +59 -0
  78. adam/commands/export/export_select_x.py +54 -0
  79. adam/commands/export/export_sessions.py +209 -0
  80. adam/commands/export/export_use.py +49 -0
  81. adam/commands/export/exporter.py +332 -0
  82. adam/commands/export/import_files.py +44 -0
  83. adam/commands/export/import_session.py +44 -0
  84. adam/commands/export/importer.py +81 -0
  85. adam/commands/export/importer_athena.py +177 -0
  86. adam/commands/export/importer_sqlite.py +67 -0
  87. adam/commands/export/show_column_counts.py +45 -0
  88. adam/commands/export/show_export_databases.py +38 -0
  89. adam/commands/export/show_export_session.py +39 -0
  90. adam/commands/export/show_export_sessions.py +37 -0
  91. adam/commands/export/utils_export.py +343 -0
  92. adam/commands/find_files.py +51 -0
  93. adam/commands/find_processes.py +76 -0
  94. adam/commands/head.py +36 -0
  95. adam/commands/help.py +14 -9
  96. adam/commands/intermediate_command.py +49 -0
  97. adam/commands/issues.py +14 -40
  98. adam/commands/kubectl.py +38 -0
  99. adam/commands/login.py +26 -25
  100. adam/commands/logs.py +5 -7
  101. adam/commands/ls.py +11 -110
  102. adam/commands/medusa/medusa.py +4 -22
  103. adam/commands/medusa/medusa_backup.py +22 -29
  104. adam/commands/medusa/medusa_restore.py +40 -39
  105. adam/commands/medusa/medusa_show_backupjobs.py +19 -20
  106. adam/commands/medusa/medusa_show_restorejobs.py +15 -20
  107. adam/commands/nodetool.py +11 -15
  108. adam/commands/param_get.py +11 -14
  109. adam/commands/param_set.py +8 -12
  110. adam/commands/postgres/postgres.py +45 -46
  111. adam/commands/postgres/postgres_databases.py +269 -0
  112. adam/commands/postgres/postgres_ls.py +4 -8
  113. adam/commands/postgres/postgres_preview.py +5 -9
  114. adam/commands/postgres/psql_completions.py +4 -3
  115. adam/commands/postgres/utils_postgres.py +70 -0
  116. adam/commands/preview_table.py +10 -61
  117. adam/commands/pwd.py +14 -43
  118. adam/commands/reaper/reaper.py +4 -24
  119. adam/commands/reaper/reaper_forward.py +49 -56
  120. adam/commands/reaper/reaper_forward_session.py +6 -0
  121. adam/commands/reaper/reaper_forward_stop.py +10 -16
  122. adam/commands/reaper/reaper_restart.py +8 -15
  123. adam/commands/reaper/reaper_run_abort.py +8 -33
  124. adam/commands/reaper/reaper_runs.py +43 -58
  125. adam/commands/reaper/reaper_runs_abort.py +29 -49
  126. adam/commands/reaper/reaper_schedule_activate.py +9 -32
  127. adam/commands/reaper/reaper_schedule_start.py +9 -32
  128. adam/commands/reaper/reaper_schedule_stop.py +9 -32
  129. adam/commands/reaper/reaper_schedules.py +4 -14
  130. adam/commands/reaper/reaper_status.py +8 -16
  131. adam/commands/reaper/utils_reaper.py +194 -0
  132. adam/commands/repair/repair.py +4 -22
  133. adam/commands/repair/repair_log.py +6 -12
  134. adam/commands/repair/repair_run.py +29 -36
  135. adam/commands/repair/repair_scan.py +33 -39
  136. adam/commands/repair/repair_stop.py +6 -12
  137. adam/commands/report.py +25 -21
  138. adam/commands/restart.py +27 -28
  139. adam/commands/rollout.py +20 -25
  140. adam/commands/shell.py +12 -4
  141. adam/commands/show/show.py +11 -23
  142. adam/commands/show/show_adam.py +3 -3
  143. adam/commands/show/show_cassandra_repairs.py +35 -0
  144. adam/commands/show/show_cassandra_status.py +34 -52
  145. adam/commands/show/show_cassandra_version.py +5 -18
  146. adam/commands/show/show_commands.py +20 -25
  147. adam/commands/show/show_host.py +33 -0
  148. adam/commands/show/show_login.py +23 -27
  149. adam/commands/show/show_params.py +2 -5
  150. adam/commands/show/show_processes.py +16 -20
  151. adam/commands/show/show_storage.py +10 -20
  152. adam/commands/watch.py +27 -30
  153. adam/config.py +7 -15
  154. adam/embedded_params.py +1 -1
  155. adam/log.py +4 -4
  156. adam/pod_exec_result.py +13 -5
  157. adam/repl.py +126 -119
  158. adam/repl_commands.py +63 -29
  159. adam/repl_state.py +320 -71
  160. adam/sql/sql_completer.py +98 -383
  161. adam/sql/sql_state_machine.py +630 -0
  162. adam/sql/term_completer.py +14 -4
  163. adam/sso/authn_ad.py +6 -8
  164. adam/sso/authn_okta.py +4 -6
  165. adam/sso/cred_cache.py +4 -6
  166. adam/sso/idp.py +10 -13
  167. adam/utils.py +511 -10
  168. adam/utils_athena.py +145 -0
  169. adam/utils_audits.py +102 -0
  170. adam/utils_issues.py +32 -0
  171. adam/utils_k8s/__init__.py +0 -0
  172. adam/utils_k8s/app_clusters.py +28 -0
  173. adam/utils_k8s/app_pods.py +36 -0
  174. adam/utils_k8s/cassandra_clusters.py +44 -0
  175. adam/{k8s_utils → utils_k8s}/cassandra_nodes.py +11 -4
  176. adam/{k8s_utils → utils_k8s}/custom_resources.py +16 -17
  177. adam/{k8s_utils → utils_k8s}/deployment.py +2 -2
  178. adam/{k8s_utils → utils_k8s}/ingresses.py +2 -2
  179. adam/{k8s_utils → utils_k8s}/jobs.py +7 -11
  180. adam/utils_k8s/k8s.py +87 -0
  181. adam/{k8s_utils → utils_k8s}/kube_context.py +2 -2
  182. adam/{k8s_utils → utils_k8s}/pods.py +109 -74
  183. adam/{k8s_utils → utils_k8s}/secrets.py +7 -3
  184. adam/{k8s_utils → utils_k8s}/service_accounts.py +5 -4
  185. adam/{k8s_utils → utils_k8s}/services.py +2 -2
  186. adam/{k8s_utils → utils_k8s}/statefulsets.py +3 -14
  187. adam/utils_local.py +4 -0
  188. adam/utils_net.py +24 -0
  189. adam/utils_repl/__init__.py +0 -0
  190. adam/utils_repl/automata_completer.py +48 -0
  191. adam/utils_repl/repl_completer.py +46 -0
  192. adam/utils_repl/state_machine.py +173 -0
  193. adam/utils_sqlite.py +137 -0
  194. adam/version.py +1 -1
  195. {kaqing-2.0.52.dist-info → kaqing-2.0.184.dist-info}/METADATA +1 -1
  196. kaqing-2.0.184.dist-info/RECORD +244 -0
  197. adam/commands/app.py +0 -67
  198. adam/commands/bash.py +0 -87
  199. adam/commands/cp.py +0 -95
  200. adam/commands/cql/cql_table_completer.py +0 -8
  201. adam/commands/cql/cql_utils.py +0 -109
  202. adam/commands/describe/describe.py +0 -46
  203. adam/commands/describe/describe_keyspace.py +0 -60
  204. adam/commands/describe/describe_keyspaces.py +0 -50
  205. adam/commands/describe/describe_table.py +0 -60
  206. adam/commands/describe/describe_tables.py +0 -50
  207. adam/commands/devices.py +0 -89
  208. adam/commands/postgres/postgres_session.py +0 -240
  209. adam/commands/postgres/postgres_utils.py +0 -31
  210. adam/commands/postgres/psql_table_completer.py +0 -11
  211. adam/commands/reaper/reaper_session.py +0 -159
  212. adam/commands/show/show_app_actions.py +0 -53
  213. adam/commands/show/show_repairs.py +0 -47
  214. adam/k8s_utils/cassandra_clusters.py +0 -35
  215. adam/sql/sql_utils.py +0 -5
  216. kaqing-2.0.52.dist-info/RECORD +0 -184
  217. /adam/commands/{describe → app}/__init__.py +0 -0
  218. /adam/{k8s_utils → commands/audit}/__init__.py +0 -0
  219. /adam/{k8s_utils → utils_k8s}/config_maps.py +0 -0
  220. /adam/{k8s_utils → utils_k8s}/volumes.py +0 -0
  221. {kaqing-2.0.52.dist-info → kaqing-2.0.184.dist-info}/WHEEL +0 -0
  222. {kaqing-2.0.52.dist-info → kaqing-2.0.184.dist-info}/entry_points.txt +0 -0
  223. {kaqing-2.0.52.dist-info → kaqing-2.0.184.dist-info}/top_level.txt +0 -0
adam/sql/sql_completer.py CHANGED
@@ -1,403 +1,118 @@
1
- from typing import Callable, Iterable
2
- from prompt_toolkit.completion import CompleteEvent, Completer, Completion
3
- from prompt_toolkit.document import Document
1
+ from enum import Enum
2
+ from typing import Callable
3
+
4
4
  import sqlparse
5
- from sqlparse.sql import Statement, Token
6
- from sqlparse import tokens as T
5
+ from sqlparse.sql import Token
7
6
 
8
7
  from adam.sql.term_completer import TermCompleter
8
+ from adam.utils_repl.automata_completer import AutomataCompleter
9
+ from adam.sql.sql_state_machine import AthenaStateMachine, CqlStateMachine, SqlStateMachine
10
+ from adam.utils_repl.state_machine import State
9
11
 
10
- class SqlCompleter(Completer):
11
- def __init__(self, tables: Callable[[], list[str]], dml: str = None, debug = False):
12
- super().__init__()
13
- self.dml = dml
14
- self.tables = tables
15
- self.debug = debug
12
+ __all__ = [
13
+ "SqlCompleter",
14
+ ]
16
15
 
17
- def get_completions(
18
- self, document: Document, complete_event: CompleteEvent
19
- ) -> Iterable[Completion]:
20
- text = document.text_before_cursor.lstrip()
21
- if self.dml:
22
- state = f'{self.dml}_'
23
- text = f'{self.dml} {text}'
16
+ def default_columns(x: list[str]):
17
+ return 'id,x.,y.,z.'.split(',')
18
+
19
+ class SqlVariant(Enum):
20
+ SQL = 'sql'
21
+ CQL = 'cql'
22
+ ATHENA = 'athena'
23
+
24
+ class SqlCompleter(AutomataCompleter[Token]):
25
+ def tokens(self, text: str) -> list[Token]:
26
+ tokens = []
24
27
 
25
- completer = None
26
28
  stmts = sqlparse.parse(text)
27
- if not stmts:
28
- completer = TermCompleter(['select', 'insert', 'delete', 'update'])
29
- else:
30
- statement: Statement = stmts[0]
31
- state = self.traverse_tokens(text, statement.tokens)
32
- if self.debug:
33
- print('\n =>', state)
34
- if state == 'dml_incomplete':
35
- completer = TermCompleter(['select', 'insert', 'delete', 'update'])
29
+ if stmts:
30
+ for stmt in stmts:
31
+ tokens.extend(stmt.tokens)
32
+
33
+ return tokens
34
+
35
+ def __init__(self,
36
+ tables: Callable[[], list[str]],
37
+ dml: str = None,
38
+ expandables: dict = {},
39
+ variant: SqlVariant = SqlVariant.SQL,
40
+ debug = False):
41
+ machine = SqlStateMachine(debug=debug)
42
+ if variant == SqlVariant.CQL:
43
+ machine = CqlStateMachine(debug=debug)
44
+ elif variant == SqlVariant.ATHENA:
45
+ machine = AthenaStateMachine(debug=debug)
46
+ super().__init__(machine, dml, debug)
36
47
 
37
- elif state == 'select_':
38
- completer = TermCompleter(['*'])
39
- elif state == 'select_a':
40
- completer = TermCompleter(['from'])
41
- elif state == 'select_a,':
42
- completer = TermCompleter(['*'])
43
- elif state == 'select_a_':
44
- completer = TermCompleter(['from'])
45
- elif state == "select_a_from_":
46
- completer = TermCompleter(self.tables())
47
- elif state == "select_a_from_x_":
48
- completer = TermCompleter(['where', 'group', 'limit'])
49
- elif state == "select_a_from_x,":
50
- completer = TermCompleter(self.tables())
51
- elif state == "select_a_from_x_where_":
52
- completer = TermCompleter(['id'])
53
- elif state == "select_a_from_x_where_id":
54
- completer = TermCompleter(['=', '<', '<=', '>', '>=', '<>', 'like'])
55
- elif state == "select_a_from_x_where_id=":
56
- completer = TermCompleter(["'"])
57
- elif state == "select_a_from_x_where_id=v_":
58
- completer = TermCompleter(['and', 'or', 'group', 'limit'])
59
- elif state == "select_a_from_x_where_id=v_limit_":
60
- completer = TermCompleter(['1'])
61
- elif state == "select_a_from_x_group_":
62
- completer = TermCompleter(['by'])
63
- elif state == "select_a_from_x_group_by_":
64
- completer = TermCompleter(['id'])
65
- elif state == "select_a_from_x_group_by_a,":
66
- completer = TermCompleter(['id'])
67
- elif state == "select_a_from_x_group_by_a_":
68
- completer = TermCompleter(['limit'])
69
- elif state == "select_a_from_x_group_by_a_limit_":
70
- completer = TermCompleter(['1'])
48
+ self.tables = tables
49
+ if 'columns' not in expandables:
50
+ expandables['columns'] = default_columns
51
+ self.expandables = expandables
52
+ self.variant = variant
53
+ self.debug = debug
71
54
 
72
- elif state == "insert_":
73
- completer = TermCompleter(['into'])
74
- elif state == "insert_into_":
75
- completer = TermCompleter(self.tables())
76
- elif state == "insert_into_x_":
77
- completer = TermCompleter(['values'])
78
- elif state == "insert_into_x(":
79
- completer = TermCompleter(['id'])
80
- elif state == "insert_into_x(a,":
81
- completer = TermCompleter(['id'])
82
- elif state == "insert_into_x(a)_":
83
- completer = TermCompleter(['values('])
84
- elif state == "insert_into_x_values":
85
- completer = TermCompleter(['('])
86
- elif state == "insert_into_x_values(":
87
- completer = TermCompleter(["'"])
55
+ def suggestions_completer(self, state: State, suggestions: str) -> list[str]:
56
+ if not suggestions:
57
+ return None
88
58
 
89
- elif state == "update_":
90
- completer = TermCompleter(self.tables())
91
- elif state == "update_x_":
92
- completer = TermCompleter(['set'])
93
- elif state in ["update_x_set_", "update_x_set_a=v,"]:
94
- completer = TermCompleter(['id'])
95
- elif state == "update_x_set_a":
96
- completer = TermCompleter(['='])
97
- elif state == "update_x_set_a=":
98
- completer = TermCompleter(["'"])
99
- elif state == "update_x_set_a=v_":
100
- completer = TermCompleter(['where'])
101
- elif state == "update_x_set_a=v_where_":
102
- completer = TermCompleter(['id'])
103
- elif state == "update_x_set_a=v_where_id":
104
- completer = TermCompleter(['='])
105
- elif state == "update_x_set_a=v_where_id=v_":
106
- completer = TermCompleter(['and', 'or'])
59
+ terms = []
60
+ for suggestion in suggestions.split(','):
61
+ terms.extend(self._terms(state, suggestion))
107
62
 
108
- elif state == "delete_":
109
- completer = TermCompleter(['from'])
110
- elif state == "delete_from_":
111
- completer = TermCompleter(self.tables())
112
- elif state == "delete_from_x_":
113
- completer = TermCompleter(['where'])
114
- elif state == "delete_from_x_where_":
115
- completer = TermCompleter(['id'])
116
- elif state == "delete_from_x_where_id":
117
- completer = TermCompleter(['='])
118
- elif state == "delete_from_x_where_id=":
119
- completer = TermCompleter(["'"])
120
- elif state == "delete_from_x_where_id=v_":
121
- completer = TermCompleter(['and', 'or'])
63
+ return TermCompleter(terms)
122
64
 
123
- if completer:
124
- for c in completer.get_completions(document, complete_event):
125
- yield c
65
+ def _terms(self, state: State, word: str) -> list[str]:
66
+ terms = []
126
67
 
127
- def traverse_tokens(self, text: str, tokens: list[Token], state: str = None, indent=0):
128
- # state: str = None
129
- for token in tokens:
130
- if self.debug:
131
- if token.ttype == T.Whitespace:
132
- print('_ ', end='')
133
- elif token.ttype in [T.DML, T.Wildcard, T.Punctuation]:
134
- print(f'{token.value} ', end='')
135
- elif token.ttype:
136
- tks = str(token.ttype).split('.')
137
- typ = tks[len(tks) - 1]
138
- if ' ' in token.value:
139
- print(f'"{token.value}:{typ}" ', end='')
140
- else:
141
- print(f'{token.value}:{typ} ', end='')
142
- # print(" " * indent + f"Token: {token.value}, Type: {token.ttype}@{token.ttype.__class__}")
143
- node: str = None
144
- if token.is_group:
145
- state = self.traverse_tokens(text, token.tokens, state, indent + 1)
68
+ if word.startswith('`') and word.endswith('`'):
69
+ terms.append(word.strip('`'))
70
+ elif word == 'tables':
71
+ terms.extend(self.tables())
72
+ elif word == 'columns':
73
+ if 'last_name' in state.context and (n := state.context['last_name']):
74
+ if 'last_namespace' in state.context and (ns := state.context['last_namespace']):
75
+ n = f'{ns}.{n}'
76
+ terms.extend(self._call_expandable(word, [n]))
146
77
  else:
147
- if not state:
148
- if token.ttype == T.Keyword.DML and token.value.lower() == 'select':
149
- state = 'select'
150
- if token.ttype == T.Keyword.DML and token.value.lower() == 'insert':
151
- state = 'insert'
152
- if token.ttype == T.Keyword.DML and token.value.lower() == 'update':
153
- state = 'update'
154
- if token.ttype == T.Keyword.DML and token.value.lower() == 'delete':
155
- state = 'delete'
156
- elif token.ttype == T.Name:
157
- state = 'dml_incomplete'
158
-
159
- elif state == 'select':
160
- if token.ttype == T.Text.Whitespace:
161
- state = 'select_'
162
- elif state == 'select_':
163
- if token.ttype == T.Name or token.ttype == T.Wildcard:
164
- state = 'select_a'
165
- elif state == 'select_a':
166
- if token.ttype == T.Text.Whitespace:
167
- state = 'select_a_'
168
- elif token.ttype == T.Punctuation and token.value == ',':
169
- state = 'select_a,'
170
- elif state == 'select_a,':
171
- if token.ttype == T.Name or token.ttype == T.Wildcard:
172
- state = 'select_a'
173
- elif state == 'select_a_':
174
- if token.ttype == T.Keyword and token.value.lower() == 'from':
175
- state = 'select_a_from'
176
- elif state == 'select_a_from':
177
- if token.ttype == T.Text.Whitespace:
178
- state = 'select_a_from_'
179
- elif state == 'select_a_from_':
180
- if token.ttype == T.Name:
181
- state = 'select_a_from_x'
182
- elif state == 'select_a_from_x':
183
- if token.ttype == T.Text.Whitespace:
184
- state = 'select_a_from_x_'
185
- elif token.ttype == T.Punctuation and token.value == ',':
186
- state = 'select_a_from_x,'
187
- elif state == 'select_a_from_x,':
188
- if token.ttype == T.Name:
189
- state = 'select_a_from_x'
190
- elif state == 'select_a_from_x_':
191
- if token.ttype == T.Keyword and token.value.lower() == 'where':
192
- state = 'select_a_from_x_where'
193
- elif token.ttype == T.Keyword and token.value.lower() == 'limit':
194
- state = 'select_a_from_x_where_id=v_limit'
195
- elif token.ttype == T.Keyword and token.value.lower() == 'group':
196
- state = 'select_a_from_x_group'
197
- elif token.ttype == T.Keyword and token.value.lower() == 'group by':
198
- state = 'select_a_from_x_group_by'
199
- elif state == 'select_a_from_x_where':
200
- if token.ttype == T.Text.Whitespace:
201
- state = 'select_a_from_x_where_'
202
- elif state == 'select_a_from_x_where_':
203
- if token.ttype == T.Name:
204
- state = 'select_a_from_x_where_id'
205
- elif state == 'select_a_from_x_where_id':
206
- if token.ttype == T.Operator.Comparison:
207
- state = 'select_a_from_x_where_id='
208
- elif state == 'select_a_from_x_where_id=':
209
- if token.ttype in [T.Literal.String.Single, T.Name]:
210
- state = 'select_a_from_x_where_id=v'
211
- elif state == 'select_a_from_x_where_id=v':
212
- if token.ttype == T.Text.Whitespace:
213
- state = 'select_a_from_x_where_id=v_'
214
- elif state == 'select_a_from_x_where_id=v_':
215
- if token.ttype == T.Keyword and token.value.lower() in ['and', 'or']:
216
- state = 'select_a_from_x_where'
217
- elif token.ttype == T.Keyword and token.value.lower() == 'group':
218
- state = 'select_a_from_x_group'
219
- elif token.ttype == T.Keyword and token.value.lower() == 'limit':
220
- state = 'select_a_from_x_where_id=v_limit'
221
- elif state == 'select_a_from_x_group':
222
- if token.ttype == T.Text.Whitespace:
223
- state = 'select_a_from_x_group_'
224
- elif state == 'select_a_from_x_group_':
225
- if token.ttype == T.Keyword and token.value.lower() == 'by':
226
- state = 'select_a_from_x_group_by'
227
- elif state == 'select_a_from_x_group_by':
228
- if token.ttype == T.Text.Whitespace:
229
- state = 'select_a_from_x_group_by_'
230
- elif state == 'select_a_from_x_group_by_':
231
- if token.ttype == T.Name:
232
- state = 'select_a_from_x_group_by_a'
233
- elif state == 'select_a_from_x_group_by_a':
234
- if token.ttype == T.Text.Whitespace:
235
- state = 'select_a_from_x_group_by_a_'
236
- elif token.ttype == T.Punctuation and token.value == ',':
237
- state = 'select_a_from_x_group_by_a,'
238
- elif state == 'select_a_from_x_group_by_a,':
239
- if token.ttype == T.Name:
240
- state = 'select_a_from_x_group_by_a'
241
- elif state == 'select_a_from_x_group_by_a_':
242
- if token.ttype == T.Keyword and token.value.lower() == 'limit':
243
- state = 'select_a_from_x_where_id=v_limit'
244
- elif state == 'select_a_from_x_where_id=v_limit':
245
- if token.ttype == T.Text.Whitespace:
246
- state = 'select_a_from_x_where_id=v_limit_'
78
+ terms.extend(self._call_expandable(word, []))
79
+ elif word == 'partition-columns':
80
+ terms.extend(self._call_expandable(word, []))
81
+ elif word == 'table-props':
82
+ terms.extend(self._call_expandable(word).keys())
83
+ elif word == 'table-prop-values':
84
+ if 'last_name' in state.context and state.context['last_name']:
85
+ table_props = self._call_expandable('table-props')
86
+ terms.extend(table_props[state.context['last_name']])
87
+ elif word == 'single':
88
+ terms.append("'")
89
+ elif word == 'comma':
90
+ terms.append(",")
91
+ elif word in self.machine.expandable_names():
92
+ terms.extend(self._call_expandable(word))
93
+ else:
94
+ terms.append(word)
247
95
 
248
- elif state == 'insert':
249
- if token.ttype == T.Text.Whitespace:
250
- state = 'insert_'
251
- elif state == 'insert_':
252
- if token.ttype == T.Keyword and token.value.lower() == 'into':
253
- state = 'insert_into'
254
- elif state == 'insert_into':
255
- if token.ttype == T.Text.Whitespace:
256
- state = 'insert_into_'
257
- elif state == 'insert_into_':
258
- if token.ttype == T.Name:
259
- state = 'insert_into_x'
260
- elif state == 'insert_into_x':
261
- if token.ttype == T.Text.Whitespace:
262
- state = 'insert_into_x_'
263
- elif token.ttype == T.Punctuation and token.value == '(':
264
- state = 'insert_into_x('
265
- elif state == 'insert_into_x_':
266
- if token.ttype == T.Punctuation and token.value == '(':
267
- state = 'insert_into_x('
268
- elif token.ttype == T.Keyword and token.value.lower() == 'values':
269
- state = 'insert_into_x_values'
270
- elif state == 'insert_into_x(':
271
- if token.ttype == T.Name:
272
- state = 'insert_into_x(a'
273
- elif state == 'insert_into_x(a':
274
- if token.ttype == T.Punctuation and token.value == ',':
275
- state = 'insert_into_x(a,'
276
- elif token.ttype == T.Punctuation and token.value == ')':
277
- state = 'insert_into_x(a)'
278
- elif state == 'insert_into_x(a,':
279
- if token.ttype == T.Name:
280
- state = 'insert_into_x(a'
281
- elif state == 'insert_into_x(a)':
282
- if token.ttype == T.Text.Whitespace:
283
- state = 'insert_into_x(a)_'
284
- elif state == 'insert_into_x(a)_':
285
- if token.ttype == T.Keyword and token.value.lower() == 'values':
286
- state = 'insert_into_x_values'
287
- elif state == 'insert_into_x_values':
288
- if token.ttype == T.Punctuation and token.value == '(':
289
- state = 'insert_into_x_values('
290
- elif state == 'insert_into_x_values(':
291
- if token.ttype in [T.Literal.String.Single, T.Name]:
292
- state = 'insert_into_x_values(v'
293
- elif state == 'insert_into_x_values(v':
294
- if token.ttype == T.Punctuation and token.value == ',':
295
- state = 'insert_into_x_values(v,'
296
- elif token.ttype == T.Punctuation and token.value == ')':
297
- state = 'insert_into_x_values(v)'
298
- elif state == 'insert_into_x_values(v,':
299
- if token.ttype in [T.Literal.String.Single, T.Name]:
300
- state = 'insert_into_x_values(v'
96
+ return terms
301
97
 
302
- elif state == 'update':
303
- if token.ttype == T.Text.Whitespace:
304
- state = 'update_'
305
- elif state == 'update_':
306
- if token.ttype == T.Name:
307
- state = 'update_x'
308
- elif state == 'update_x':
309
- if token.ttype == T.Text.Whitespace:
310
- state = 'update_x_'
311
- elif state == 'update_x_':
312
- if token.ttype == T.Keyword and token.value.lower() == 'set':
313
- state = 'update_x_set'
314
- elif state == 'update_x_set':
315
- if token.ttype == T.Text.Whitespace:
316
- state = 'update_x_set_'
317
- elif state == 'update_x_set_':
318
- if token.ttype == T.Name:
319
- state = 'update_x_set_a'
320
- elif state == 'update_x_set_a':
321
- if token.ttype == T.Operator.Comparison:
322
- state = 'update_x_set_a='
323
- elif state == 'update_x_set_a=':
324
- if token.ttype in [T.Literal.String.Single, T.Name]:
325
- state = 'update_x_set_a=v'
326
- elif state == 'update_x_set_a=v':
327
- if token.ttype == T.Punctuation and token.value == ',':
328
- state = 'update_x_set_a=v,'
329
- elif token.ttype == T.Text.Whitespace:
330
- state = 'update_x_set_a=v_'
331
- elif state == 'update_x_set_a=v,':
332
- if token.ttype == T.Name:
333
- state = 'update_x_set_a'
334
- elif state == 'update_x_set_a=v_':
335
- if token.ttype == T.Punctuation and token.value == ',':
336
- state = 'update_x_set_a=v,'
337
- elif token.ttype == T.Keyword and token.value.lower() == 'where':
338
- state = 'update_x_set_a=v_where'
339
- elif state == 'update_x_set_a=v_where':
340
- if token.ttype == T.Text.Whitespace:
341
- state = 'update_x_set_a=v_where_'
342
- elif state == 'update_x_set_a=v_where_':
343
- if token.ttype == T.Name:
344
- state = 'update_x_set_a=v_where_id'
345
- elif state == 'update_x_set_a=v_where_id':
346
- if token.ttype == T.Operator.Comparison:
347
- state = 'update_x_set_a=v_where_id='
348
- elif state == 'update_x_set_a=v_where_id=':
349
- if token.ttype in [T.Literal.String.Single, T.Name]:
350
- state = 'update_x_set_a=v_where_id=v'
351
- elif state == 'update_x_set_a=v_where_id=v':
352
- if token.ttype == T.Text.Whitespace:
353
- state = 'update_x_set_a=v_where_id=v_'
354
- elif state == 'update_x_set_a=v_where_id=v_':
355
- if token.ttype == T.Keyword and token.value.lower() in ['and', 'or']:
356
- state = 'update_x_set_a=v_where'
98
+ def _call_expandable(self, name: str, *args):
99
+ if name in self.expandables:
100
+ c = self.expandables[name]
101
+ if args:
102
+ return c(args)
103
+ else:
104
+ return c()
357
105
 
358
- elif state == 'delete':
359
- if token.ttype == T.Text.Whitespace:
360
- state = 'delete_'
361
- elif state == 'delete_':
362
- if token.ttype == T.Keyword and token.value.lower() == 'from':
363
- state = 'delete_from'
364
- elif state == 'delete_from':
365
- if token.ttype == T.Text.Whitespace:
366
- state = 'delete_from_'
367
- elif state == 'delete_from_':
368
- if token.ttype == T.Name:
369
- state = 'delete_from_x'
370
- elif state == 'delete_from_x':
371
- if token.ttype == T.Text.Whitespace:
372
- state = 'delete_from_x_'
373
- elif state == 'delete_from_x_':
374
- if token.ttype == T.Keyword and token.value.lower() == 'where':
375
- state = 'delete_from_x_where'
376
- elif state == 'delete_from_x_where':
377
- if token.ttype == T.Text.Whitespace:
378
- state = 'delete_from_x_where_'
379
- elif state == 'delete_from_x_where_':
380
- if token.ttype == T.Name:
381
- state = 'delete_from_x_where_id'
382
- elif state == 'delete_from_x_where_id':
383
- if token.ttype == T.Operator.Comparison:
384
- state = 'delete_from_x_where_id='
385
- elif state == 'delete_from_x_where_id=':
386
- if token.ttype in [T.Literal.String.Single, T.Name]:
387
- state = 'delete_from_x_where_id=v'
388
- elif state == 'delete_from_x_where_id=v':
389
- if token.ttype == T.Text.Whitespace:
390
- state = 'delete_from_x_where_id=v_'
391
- elif state == 'delete_from_x_where_id=v_':
392
- if token.ttype == T.Keyword and token.value.lower() in ['and', 'or']:
393
- state = 'delete_from_x_where'
106
+ return []
394
107
 
395
- return state
108
+ def completions_for_nesting(self, dml: str = None):
109
+ if dml:
110
+ return {dml: SqlCompleter(self.tables, dml, expandables=self.expandables, variant=self.variant)}
396
111
 
397
- def completions(table_names: Callable[[], list[str]]):
398
112
  return {
399
- 'delete': SqlCompleter(table_names, 'delete'),
400
- 'insert': SqlCompleter(table_names, 'insert'),
401
- 'select': SqlCompleter(table_names, 'select'),
402
- 'update': SqlCompleter(table_names, 'update'),
403
- }
113
+ word: SqlCompleter(self.tables, word, expandables=self.expandables, variant=self.variant)
114
+ for word in self.machine.suggestions[''].strip(' ').split(',')
115
+ }
116
+
117
+ def __str__(self):
118
+ return f'{self.variant}, {self.first_term}'