kaqing 2.0.70__py3-none-any.whl → 2.0.72__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.
adam/sql/sql_completer.py CHANGED
@@ -2,151 +2,30 @@ from typing import Callable, Iterable
2
2
  from prompt_toolkit.completion import CompleteEvent, Completer, Completion
3
3
  from prompt_toolkit.document import Document
4
4
  import sqlparse
5
- from sqlparse.sql import Statement, Token
6
- from sqlparse import tokens as T
5
+ from sqlparse.sql import Statement
7
6
 
7
+ from adam.sql.state_machine import StateMachine, StateTo
8
8
  from adam.sql.term_completer import TermCompleter
9
9
 
10
- columns = TermCompleter(['id', 'x.', 'y.', 'z.'])
10
+ __all__ = [
11
+ "SqlCompleter",
12
+ ]
11
13
 
12
- def fr(*args):
13
- for arg in args:
14
- pass
14
+ DML_COMPLETER = TermCompleter(['select', 'insert', 'delete', 'update'])
15
15
 
16
16
  class SqlCompleter(Completer):
17
- # <select_statement> ::= SELECT <select_list>
18
- # FROM <table_expression>
19
- # [WHERE <search_condition>]
20
- # [<group_by_clause>]
21
- # [<having_clause>]
22
- # [<order_by_clause>]
23
- # [<limit_clause>]
24
-
25
- # <search_condition> ::= <boolean_term>
26
- # | <search_condition> OR <boolean_term>
27
-
28
- # <boolean_term> ::= <boolean_factor>
29
- # | <boolean_term> AND <boolean_factor>
30
-
31
- # <boolean_factor> ::= [NOT] <predicate>
32
- # | ([NOT] <search_condition>)
33
-
34
- # <predicate> ::= <comparison_predicate>
35
- # | <between_predicate>
36
- # | <in_predicate>
37
- # | <like_predicate>
38
- # | <null_predicate>
39
- # | <exists_predicate>
40
- # | <quantified_predicate>
41
- # | <unique_predicate>
42
- # | <match_predicate>
43
- # | <overlaps_predicate>
44
- # | <distinct_predicate>
45
- # | <member_predicate>
46
- # | <submultiset_predicate>
47
- # | <set_predicate>
48
-
49
- # <comparison_predicate> ::= <row_value_expression> <comparison_operator> <row_value_expression>
50
- # <comparison_operator> ::= '=' | '<>' | '<' | '<=' | '>' | '>='
51
-
52
- # <row_value_expression> ::= <value_expression>
53
- # | (<value_expression> [ { <comma> <value_expression> }... ])
54
-
55
- # <value_expression> ::= <numeric_value_expression>
56
- # | <string_value_expression>
57
- # | <datetime_value_expression>
58
- # | <interval_value_expression>
59
- # | <boolean_value_expression>
60
- # | <user_defined_type_value_expression>
61
- # | <reference_value_expression>
62
- # | <collection_value_expression>
63
- # | <row_value_constructor>
64
- # | <case_expression>
65
- # | <cast_expression>
66
- # | <subquery>
67
- # | NULL
68
- # | DEFAULT
69
- # | <identifier>
70
- # | <literal>
71
-
72
- # <insert_statement> ::= INSERT INTO <table_name> [ ( <column_list> ) ]
73
- # VALUES ( <value_list> )
74
- # | INSERT INTO <table_name> [ ( <column_list> ) ]
75
- # <query_expression>
76
-
77
- # <table_name> ::= <identifier>
78
-
79
- # <column_list> ::= <column_name> [ , <column_list> ]
80
-
81
- # <column_name> ::= <identifier>
82
-
83
- # <value_list> ::= <expression> [ , <value_list> ]
84
-
85
- # <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> ]
86
-
87
- # <update_statement> ::= UPDATE <table_name>
88
- # SET <set_clause_list>
89
- # [WHERE <search_condition>]
90
-
91
- # <set_clause_list> ::= <set_clause> { , <set_clause> }
92
-
93
- # <set_clause> ::= <column_name> = <update_value>
94
-
95
- # <update_value> ::= <expression> | NULL | DEFAULT
96
-
97
- # <search_condition> ::= <boolean_expression>
98
-
99
- # <delete_statement> ::= DELETE FROM <table_name> [ WHERE <search_condition> ]
100
-
101
- # <table_name> ::= <identifier>
102
-
103
- # <search_condition> ::= <boolean_expression>
104
-
105
- # <boolean_expression> ::= <predicate>
106
- # | <boolean_expression> AND <predicate>
107
- # | <boolean_expression> OR <predicate>
108
- # | NOT <predicate>
109
- # | ( <boolean_expression> )
110
-
111
- # <predicate> ::= <expression> <comparison_operator> <expression>
112
- # | <expression> IS NULL
113
- # | <expression> IS NOT NULL
114
- # | <expression> LIKE <pattern> [ ESCAPE <escape_character> ]
115
- # | <expression> IN ( <expression_list> )
116
- # | EXISTS ( <select_statement> )
117
- # | ... (other predicates)
118
-
119
- # <comparison_operator> ::= = | <> | != | > | < | >= | <=
120
-
121
- # <expression> ::= <literal>
122
- # | <column_name>
123
- # | <function_call>
124
- # | ( <expression> )
125
- # | <expression> <arithmetic_operator> <expression>
126
- # | ... (other expressions)
127
-
128
- # <literal> ::= <numeric_literal> | <string_literal> | <boolean_literal> | <date_literal> | ...
129
-
130
- # <column_name> ::= <identifier>
131
-
132
- # <identifier> ::= <letter> { <letter> | <digit> | _ }...
133
-
134
- # <pattern> ::= <string_literal>
135
-
136
- # <escape_character> ::= <string_literal> (single character)
137
-
138
- # <expression_list> ::= <expression> { , <expression> }...
139
17
  def __init__(self, tables: Callable[[], list[str]], dml: str = None, debug = False):
140
18
  super().__init__()
141
19
  self.dml = dml
142
20
  self.tables = tables
143
21
  self.debug = debug
144
- self.machine = self.automata()
22
+ self.machine = StateMachine(debug=self.debug)
145
23
 
146
24
  def get_completions(
147
25
  self, document: Document, complete_event: CompleteEvent
148
26
  ) -> Iterable[Completion]:
149
27
  text = document.text_before_cursor.lstrip()
28
+ state = ''
150
29
  if self.dml:
151
30
  state = f'{self.dml}_'
152
31
  text = f'{self.dml} {text}'
@@ -154,22 +33,20 @@ class SqlCompleter(Completer):
154
33
  completer: Completer = None
155
34
  stmts = sqlparse.parse(text)
156
35
  if not stmts:
157
- completer = TermCompleter(['select', 'insert', 'delete', 'update'])
36
+ completer = DML_COMPLETER
158
37
  else:
159
38
  statement: Statement = stmts[0]
160
- state = self.traverse_tokens(text, statement.tokens)
39
+ state: StateTo = self.machine.traverse_tokens(statement.tokens, StateTo(state))
161
40
  if self.debug:
162
- print('\n =>', state)
41
+ print('\n =>', state.to_s if isinstance(state, StateTo) else '')
163
42
 
164
- if state == '':
165
- completer = TermCompleter(['select', 'insert', 'delete', 'update'])
43
+ if not state or not state.to_s:
44
+ completer = DML_COMPLETER
166
45
 
167
- completers: dict[str, str] = self.machine[1]
168
- if state in completers:
46
+ if state and state.to_s in self.machine.suggestions:
169
47
  terms = []
170
48
 
171
- words = completers[state]
172
- for word in words.strip(' ').split(','):
49
+ for word in self.machine.suggestions[state.to_s].strip(' ').split(','):
173
50
  if word == 'tables':
174
51
  terms.extend(self.tables())
175
52
  elif word == 'single':
@@ -186,302 +63,6 @@ class SqlCompleter(Completer):
186
63
  for c in completer.get_completions(document, complete_event):
187
64
  yield c
188
65
 
189
- def automata(self):
190
- y = [
191
- ' > select > select',
192
- 'select_ > name|* > select_a ^ *',
193
- 'select_a > , > select_a_comma_',
194
- 'select_a_comma_ > name|* > select_a ^ *',
195
- 'select_a_ > from > select_from ^ from',
196
- 'select_from_ > name > select_from_x ^ (select,tables',
197
- '- > { > select_from_x_lp_',
198
- 'select_from_x_lp_ > select > select',
199
- 'select_from_x > , > select_from_x_comma_',
200
- '- > } > select_from_x_rp_',
201
- 'select_from_x_rp__ > as > select_from_x_as ^ as',
202
- 'select_from_x_comma_ > name > select_from_x ^ tables',
203
- 'select_from_x_ ^ as,where,inner join,left outer join,right outer join,full outer join,group by,limit',
204
- 'select_from_x_as_x_ > , > select_from_x_comma_ ^ where,inner join,left outer join,right outer join,full outer join,group by,limit',
205
- '- > as > select_from_x_as',
206
- '- > where > select_where',
207
- '- > limit > select_where_sc_limit',
208
- '- > group > select_group',
209
- '- > group by > select_group_by',
210
- '- > inner > select_from_x_inner',
211
- '- > inner join > select_join',
212
- '- > left > select_from_x_left',
213
- '- > left join > select_join',
214
- '- > left outer join > select_join',
215
- '- > right > select_from_x_right',
216
- '- > right join > select_join',
217
- '- > right outer join > select_join',
218
- '- > full > select_from_x_full',
219
- '- > full outer join > select_join',
220
- 'select_from_x_as_ > name > select_from_x_as_x ^ x,y,z',
221
- 'select_from_x_as_x > , > select_from_x_as_x_comma_',
222
- '- > } > select_where_sc_re_',
223
- 'select_from_x_as_x_comma_ > name > select_from_x ^ tables',
224
- 'select_where_ > name > select_where_a ^ id,x.,y.,z.',
225
- 'select_where_a > comparison > select_where_a_op ^ =,<,<=,>,>=,<>,like,not,in',
226
- 'select_where_a_ > comparison > select_where_a_op ^ =,<,<=,>,>=,<>,like,not,in',
227
- '- > not > select_where_a_not',
228
- '- > in > select_where_a_in',
229
- 'select_where_a_not_ > comparison > select_where_a_not_op ^ like,in',
230
- '- > in > select_where_a_in',
231
- 'select_where_a_in > ( > select_where_a_in_lp_ ^ (',
232
- 'select_where_a_in_lp_ > name|single|num > select_where_a_in_lp_a ^ single,select',
233
- '- > select > select_where_a_in_lp_select',
234
- 'select_where_a_in_lp_select_ > name > select_a ^ id',
235
- 'select_where_a_in_lp_a > , > select_where_a_in_lp_a_comma_ ^ comma,)',
236
- '- > ) > select_where_sc',
237
- 'select_where_a_in_lp_a_comma_ > name|single|num > select_where_a_in_lp_a ^ single',
238
- 'select_where_a_not_op > name|single|num > select_where_sc ^ single',
239
- 'select_where_a_op > name|single|num > select_where_sc ^ single',
240
- 'select_where_sc > ) > select_where_sc_rp_',
241
- 'select_where_sc > } > select_where_sc_re_',
242
- 'select_where_sc_re__ > as > select_from_x_as ^ as',
243
- 'select_where_sc_rp_ > } > select_where_sc_re_',
244
- 'select_where_sc_rp__ > as > select_from_x_as ^ and,or,group by,limit',
245
- '- > and|or > select_where',
246
- '- > group > select_group',
247
- '- > group by > select_group_by',
248
- '- > limit > select_where_sc_limit',
249
- '- > } > select_where_sc_re_',
250
- 'select_where_sc_ > and|or > select_where ^ and,or,group by,limit',
251
- '- > group > select_group',
252
- '- > group by > select_group_by',
253
- '- > limit > select_where_sc_limit',
254
- 'select_group_ > by > select_group_by ^ by',
255
- 'select_group_by_ > name > select_group_by_a ^ id,x.,y.,z.',
256
- 'select_group_by_a > , > select_group_by_a_comma_',
257
- '- > } > select_where_sc_re_',
258
- 'select_group_by_a_comma_ > name > select_group_by_a ^ id,x.,y.,z.',
259
- 'select_group_by_a_ > limit > select_where_sc_limit ^ limit',
260
- 'select_where_sc_limit_ > num > select_where_sc_limit_num ^ 1',
261
- 'select_where_sc_limit_num > ) > select_where_sc_limit_num_rp_',
262
- 'select_where_sc_limit_num_rp__ > as > select_from_x_as ^ as',
263
- 'select_where_x_inner_ > join > select_join',
264
- 'select_join_ > name > select_x_join_y ^ tables',
265
- 'select_from_x_left_ > join > select_join ^ outer join',
266
- '- > outer > select_from_x_left_outer',
267
- 'select_from_x_left_outer_ > join > select_join ^ join',
268
- 'select_from_x_right_ > join > select_join ^ outer join',
269
- '- > outer > select_from_x_right_outer',
270
- 'select_from_x_right_outer_ > join > select_join ^ join',
271
- 'select_from_x_full_ > join > select_join ^ outer join',
272
- '- > outer > select_from_x_full_outer',
273
- 'select_from_x_full_outer_ > join > select_join ^ join',
274
- 'select_x_join_y_ > as > select_x_join_y_as ^ as,on',
275
- '- > on > select_x_join_y_on ^ as,on',
276
- 'select_x_join_y_as_ > name > select_x_join_y_as_y ^ x,y,z',
277
- 'select_x_join_y_as_y_ > on > select_x_join_y_on ^ on',
278
- 'select_x_join_y_on_ > name > select_x_join_y_on_a ^ id,x.,y.,z.',
279
- 'select_x_join_y_on_a > comparison > select_x_join_y_on_a_op ^ =',
280
- 'select_x_join_y_on_a_op > name > select_x_join_y_on_a_op_b ^ id,x.,y.,z.',
281
- 'select_x_join_y_on_a_op_b > _ > select_from_x_as_x_',
282
- '- > } > select_where_sc_re_',
283
-
284
-
285
- ' > insert > insert',
286
- 'insert_ > into > insert_into ^ into',
287
- 'insert_into_ > name > insert_into_x ^ tables',
288
- 'insert_into_x > ( > insert_into_x_lp_',
289
- 'insert_into_x_ > ( > insert_into_x_lp_ ^ (,values(',
290
- '- > values > insert_values',
291
- 'insert_into_x_lp_ > name > insert_into_x_lp_a ^ id',
292
- 'insert_into_x_lp_a > , > insert_into_x_lp_a_comma_',
293
- '- > ) > insert_into_x_lp_a_rp_',
294
- 'insert_into_x_lp_a_comma_ > name > insert_into_x_lp_a ^ id',
295
- 'insert_into_x_lp_a_rp__ > values > insert_values ^ values(,select',
296
- '- > select > select',
297
- 'insert_values > ( > insert_values_lp_',
298
- 'insert_values_lp_ > name|single|num > insert_values_lp_v ^ single',
299
- 'insert_values_lp_v > , > insert_values_lp_v_comma_',
300
- 'insert_values_lp_v_comma_ > name|single|num > insert_values_lp_v',
301
-
302
-
303
- ' > update > update',
304
- 'update_ > name > update_x ^ tables',
305
- 'update_x_ > set > update_set ^ set',
306
- 'update_set_ > name > update_set_a ^ id',
307
- 'update_set_a > comparison > update_set_a_op',
308
- 'update_set_a_op > name|single|num > update_set_sc ^ single',
309
- 'update_set_sc > , > update_set_sc_comma_',
310
- 'update_set_sc_comma_ > name > update_set_a ^ id',
311
- 'update_set_sc_ > , > update_set_sc_comma_ ^ where',
312
- '- > where > update_where',
313
- 'update_where_ > name > update_where_a ^ id',
314
- 'update_where_a > comparison > update_where_a_op',
315
- 'update_where_a_ > comparison > update_where_a_op ^ =,<,<=,>,>=,<>,like,not,in',
316
- '- > not > update_where_a_not',
317
- '- > in > update_where_a_in',
318
- 'update_where_a_not_ > comparison > update_where_a_not_op ^ like,in',
319
- '- > in > update_where_a_in',
320
- 'update_where_a_in > ( > update_where_a_in_lp_ ^ (',
321
- 'update_where_a_in_lp_ > name|single|num > update_where_a_in_lp_a ^ single,select',
322
- '- > select > update_where_a_in_lp_select',
323
- 'update_where_a_in_lp_select_ > name > select_a ^ id',
324
- 'update_where_a_in_lp_a > , > update_where_a_in_lp_a_comma_ ^ comma,)',
325
- '- > ) > update_where_sc',
326
- 'update_where_a_in_lp_a_comma_ > name|single|num > update_where_a_in_lp_a ^ single',
327
- 'update_where_a_not_op > name|single|num > update_where_sc ^ single',
328
- 'update_where_a_op > name|single|num > update_where_sc ^ single',
329
- 'update_where_sc_ > and|or > update_where ^ and,or',
330
-
331
-
332
- ' > delete > delete',
333
- 'delete_ > from > delete_from ^ from',
334
- 'delete_from_ > name > delete_from_x ^ tables',
335
- 'delete_from_x_ > where > update_where ^ where',
336
- ]
337
-
338
- def add_whitespace_transition(from_s: str):
339
- # add whitespace transition if a state with trailing whitespace is found from from states, for example, select > _ > select_
340
- if from_s.endswith('_') and not from_s.endswith('_comma_') and not from_s.endswith('_lp_') and not from_s.endswith('_rp_'):
341
- if self.debug:
342
- print(f'{from_s[:-1]} > _ = {to_s}')
343
- machine[f'{from_s[:-1]} > _'] = from_s
344
-
345
- machine: dict[str, str] = {}
346
- completers: dict[str, str] = {}
347
-
348
- from_ss_to_add = []
349
- from_ss = ['']
350
- token = None
351
- tokens = []
352
- to_s = None
353
- words: str = None
354
- for l in y:
355
- t_and_w = l.split('^')
356
- if len(t_and_w) > 1:
357
- words = t_and_w[1]
358
- else:
359
- words = None
360
-
361
- tks = t_and_w[0].strip(' ').split('>')
362
- if l.startswith('-'):
363
- token = tks[1].strip(' ')
364
- if len(tks) > 2:
365
- to_s = tks[2].strip(' ')
366
- for from_s in from_ss:
367
- tokens = [token]
368
- if '|' in token:
369
- tokens = token.strip(' ').split('|')
370
-
371
- for t in tokens:
372
- if self.debug:
373
- print(f'{from_s} > {t} = {to_s}')
374
- machine[f'{from_s} > {t}'] = to_s
375
- else:
376
- if words:
377
- completers[tks[0].strip(' ')] = words
378
-
379
- if len(tks) == 1:
380
- from_s = tks[0].strip(' ')
381
- add_whitespace_transition(from_s)
382
- from_ss_to_add.append(f'{from_s}')
383
- continue
384
-
385
- from_ss = []
386
- from_ss.extend(from_ss_to_add)
387
- from_ss_to_add = []
388
- from_ss.append(tks[0].strip(' '))
389
- for from_s in from_ss:
390
- add_whitespace_transition(from_s)
391
- token = tks[1].strip(' ')
392
- tokens = [token]
393
- if len(tks) > 2:
394
- to_s = tks[2].strip(' ')
395
-
396
- if '|' in token:
397
- tokens = token.split('|')
398
-
399
- for t in tokens:
400
- if self.debug:
401
- print(f'{from_s} > {t} = {to_s}')
402
- machine[f'{from_s} > {t}'] = to_s
403
-
404
- return (machine, completers)
405
-
406
- def traverse_tokens(self, text: str, tokens: list[Token], state: str = '', indent=0, lp_level = 0, lp_levels_to_match: set = set()):
407
- keywords = [
408
- 'select', 'from', 'as', 'not', 'in', 'where',
409
- 'and', 'or', 'group', 'by', 'group by', 'limit',
410
- 'inner join', 'on', 'left', 'right', 'full', 'outer', 'left outer join',
411
- 'left join', 'right outer join', 'right join', 'full join', 'full outer join',
412
-
413
- 'insert', 'into', 'values',
414
-
415
- 'update', 'where', 'set',
416
-
417
- 'delete'
418
- ]
419
-
420
- def is_opening_embrace():
421
- if f'{state} > ' + '{' in self.machine[0]:
422
- lp_levels_to_match.add(lp_level)
423
- return '{'
424
-
425
- return '('
426
-
427
- def is_closing_embrace():
428
- if f'{state} > ' + '}' in self.machine[0] and lp_level in lp_levels_to_match:
429
- lp_levels_to_match.remove(lp_level)
430
- return '}'
431
-
432
- return ')'
433
-
434
- for token in tokens:
435
- if self.debug:
436
- if token.ttype == T.Whitespace:
437
- print('_ ', end='')
438
- elif token.ttype in [T.DML, T.Wildcard, T.Punctuation]:
439
- print(f'{token.value} ', end='')
440
- elif token.ttype:
441
- tks = str(token.ttype).split('.')
442
- typ = tks[len(tks) - 1]
443
- if ' ' in token.value:
444
- print(f'"{token.value}:{typ}" ', end='')
445
- else:
446
- print(f'{token.value}:{typ} ', end='')
447
- # print(" " * indent + f"Token: {token.value}, Type: {token.ttype}@{token.ttype.__class__}")
448
-
449
- if token.is_group:
450
- state = self.traverse_tokens(text, token.tokens, state, indent + 1, lp_level)
451
- else:
452
- it = ''
453
- if (t := token.value.lower()) in keywords:
454
- it = t
455
- elif token.ttype == T.Text.Whitespace:
456
- it = '_'
457
- elif token.ttype == T.Name:
458
- it = 'name'
459
- elif token.ttype == T.Literal.String.Single:
460
- it = 'single'
461
- elif token.ttype in [T.Literal.Number.Integer, T.Literal.Number.Float]:
462
- it = 'num'
463
- elif token.ttype == T.Wildcard:
464
- it = '*'
465
- elif token.ttype == T.Punctuation:
466
- if token.value == ',':
467
- it = ','
468
- elif token.value == '(':
469
- it = is_opening_embrace()
470
- lp_level += 1
471
- elif token.value == ')':
472
- lp_level -= 1
473
- it = is_closing_embrace()
474
-
475
- elif token.ttype == T.Operator.Comparison:
476
- it = 'comparison'
477
-
478
- try:
479
- state = self.machine[0][f'{state} > {it}']
480
- except:
481
- pass
482
-
483
- return state
484
-
485
66
  def completions(table_names: Callable[[], list[str]]):
486
67
  return {
487
68
  'delete': SqlCompleter(table_names, 'delete'),
@@ -0,0 +1,429 @@
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 > select_from_x ^ (select,tables',
138
+ '- > ( > select_from_lp_',
139
+ '- < ) > select_from_ns',
140
+ 'select_from_lp_ > select > select',
141
+ 'select_from_x > , > select_from_x_comma_',
142
+ 'select_from_ns_ > 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,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,limit',
146
+ '- > as > select_from_x_as',
147
+ '- > where > select_where',
148
+ '- > limit > select_where_sc_limit',
149
+ '- > group > select_group',
150
+ '- > group by > select_group_by',
151
+ '- > inner > select_from_x_inner',
152
+ '- > inner join > select_join',
153
+ '- > left > select_from_x_left',
154
+ '- > left join > select_join',
155
+ '- > left outer join > select_join',
156
+ '- > right > select_from_x_right',
157
+ '- > right join > select_join',
158
+ '- > right outer join > select_join',
159
+ '- > full > select_from_x_full',
160
+ '- > full outer join > select_join',
161
+ 'select_from_x_as_ > name > select_from_x_as_x ^ x,y,z',
162
+ 'select_from_x_as_x > , > select_from_x_as_x_comma_',
163
+ 'select_from_x_as_x_comma_ > name > select_from_x ^ tables',
164
+ 'select_where_ > name > select_where_a ^ id,x.,y.,z.',
165
+ 'select_where_a > comparison > select_where_a_op ^ =,<,<=,>,>=,<>,like,not,in',
166
+ 'select_where_a_ > comparison > select_where_a_op ^ =,<,<=,>,>=,<>,like,not,in',
167
+ '- > not > select_where_a_not',
168
+ '- > in > select_where_a_in',
169
+ 'select_where_a_not_ > comparison > select_where_a_not_op ^ like,in',
170
+ '- > in > select_where_a_in',
171
+ 'select_where_a_in > ( > select_where_a_in_lp_ ^ (',
172
+ '- < ) > select_where_sc',
173
+ 'select_where_a_in_lp_ > name|single|num > select_where_a_in_lp_a ^ single,select',
174
+ '- > select > select_where_a_in_lp_select',
175
+ 'select_where_a_in_lp_select_ > name > select_a ^ id',
176
+ 'select_where_a_in_lp_a > , > select_where_a_in_lp_a_comma_ ^ comma,)',
177
+ 'select_where_a_in_lp_a_comma_ > name|single|num > select_where_a_in_lp_a ^ single',
178
+ 'select_where_a_not_op > name|single|num > select_where_sc ^ single',
179
+ 'select_where_a_op > name|single|num > select_where_sc ^ single',
180
+ 'select_where_sc_ > and|or > select_where ^ and,or,group by,limit',
181
+ '- > group > select_group',
182
+ '- > group by > select_group_by',
183
+ '- > limit > select_where_sc_limit',
184
+ 'select_group_ > by > select_group_by ^ by',
185
+ 'select_group_by_ > name > select_group_by_a ^ id,x.,y.,z.',
186
+ 'select_group_by_a > , > select_group_by_a_comma_',
187
+ 'select_group_by_a_comma_ > name > select_group_by_a ^ id,x.,y.,z.',
188
+ 'select_group_by_a_ > limit > select_where_sc_limit ^ limit',
189
+ 'select_where_sc_limit_ > num > select_where_sc_limit_num ^ 1',
190
+ 'select_where_sc_limit_num_rp__ > as > select_from_x_as ^ as',
191
+ 'select_where_x_inner_ > join > select_join',
192
+ 'select_join_ > name > select_x_join_y ^ tables',
193
+ 'select_from_x_left_ > join > select_join ^ outer join',
194
+ '- > outer > select_from_x_left_outer',
195
+ 'select_from_x_left_outer_ > join > select_join ^ join',
196
+ 'select_from_x_right_ > join > select_join ^ outer join',
197
+ '- > outer > select_from_x_right_outer',
198
+ 'select_from_x_right_outer_ > join > select_join ^ join',
199
+ 'select_from_x_full_ > join > select_join ^ outer join',
200
+ '- > outer > select_from_x_full_outer',
201
+ 'select_from_x_full_outer_ > join > select_join ^ join',
202
+ 'select_x_join_y_ > as > select_x_join_y_as ^ as,on',
203
+ '- > on > select_x_join_y_on ^ as,on',
204
+ 'select_x_join_y_as_ > name > select_x_join_y_as_y ^ x,y,z',
205
+ 'select_x_join_y_as_y_ > on > select_x_join_y_on ^ on',
206
+ 'select_x_join_y_on_ > name > select_x_join_y_on_a ^ id,x.,y.,z.',
207
+ 'select_x_join_y_on_a > comparison > select_x_join_y_on_a_op ^ =',
208
+ 'select_x_join_y_on_a_op > name > select_x_join_y_on_a_op_b ^ id,x.,y.,z.',
209
+ 'select_x_join_y_on_a_op_b > _ > select_from_x_as_x_',
210
+
211
+
212
+ ' > insert > insert',
213
+ 'insert_ > into > insert_into ^ into',
214
+ 'insert_into_ > name > insert_into_x ^ tables',
215
+ 'insert_into_x > ( > insert_into_x_lp_',
216
+ 'insert_into_x_ > ( > insert_into_x_lp_ ^ (,values(',
217
+ '- > values > insert_values',
218
+ 'insert_into_x_lp_ > name > insert_into_x_lp_a ^ id',
219
+ 'insert_into_x_lp_a > , > insert_into_x_lp_a_comma_',
220
+ '- > ) > insert_into_x_lp_a_rp_',
221
+ 'insert_into_x_lp_a_comma_ > name > insert_into_x_lp_a ^ id',
222
+ 'insert_into_x_lp_a_rp__ > values > insert_values ^ values(,select',
223
+ '- > select > select',
224
+ 'insert_values > ( > insert_values_lp_',
225
+ 'insert_values_lp_ > name|single|num > insert_values_lp_v ^ single',
226
+ 'insert_values_lp_v > , > insert_values_lp_v_comma_',
227
+ 'insert_values_lp_v_comma_ > name|single|num > insert_values_lp_v',
228
+
229
+
230
+ ' > update > update',
231
+ 'update_ > name > update_x ^ tables',
232
+ 'update_x_ > set > update_set ^ set',
233
+ 'update_set_ > name > update_set_a ^ id',
234
+ 'update_set_a > comparison > update_set_a_op',
235
+ 'update_set_a_op > name|single|num > update_set_sc ^ single',
236
+ 'update_set_sc > , > update_set_sc_comma_',
237
+ 'update_set_sc_comma_ > name > update_set_a ^ id',
238
+ 'update_set_sc_ > , > update_set_sc_comma_ ^ where',
239
+ '- > where > update_where',
240
+ 'update_where_ > name > update_where_a ^ id',
241
+ 'update_where_a > comparison > update_where_a_op',
242
+ 'update_where_a_ > comparison > update_where_a_op ^ =,<,<=,>,>=,<>,like,not,in',
243
+ '- > not > update_where_a_not',
244
+ '- > in > update_where_a_in',
245
+ 'update_where_a_not_ > comparison > update_where_a_not_op ^ like,in',
246
+ '- > in > update_where_a_in',
247
+ 'update_where_a_in > ( > update_where_a_in_lp_ ^ (',
248
+ '- < ) > update_where_sc',
249
+ 'update_where_a_in_lp_ > name|single|num > update_where_a_in_lp_a ^ single,select',
250
+ '- > select > update_where_a_in_lp_select',
251
+ 'update_where_a_in_lp_select_ > name > select_a ^ id',
252
+ 'update_where_a_in_lp_a > , > update_where_a_in_lp_a_comma_ ^ comma,)',
253
+ 'update_where_a_in_lp_a_comma_ > name|single|num > update_where_a_in_lp_a ^ single',
254
+ 'update_where_a_not_op > name|single|num > update_where_sc ^ single',
255
+ 'update_where_a_op > name|single|num > update_where_sc ^ single',
256
+ 'update_where_sc_ > and|or > update_where ^ and,or',
257
+
258
+
259
+ ' > delete > delete',
260
+ 'delete_ > from > delete_from ^ from',
261
+ 'delete_from_ > name > delete_from_x ^ tables',
262
+ 'delete_from_x_ > where > update_where ^ where',
263
+ ]
264
+
265
+ KEYWORDS = [
266
+ 'select', 'from', 'as', 'not', 'in', 'where',
267
+ 'and', 'or', 'group', 'by', 'group by', 'limit',
268
+ 'inner join', 'on', 'left', 'right', 'full', 'outer', 'left outer join',
269
+ 'left join', 'right outer join', 'right join', 'full join', 'full outer join',
270
+ 'insert', 'into', 'values',
271
+ 'update', 'where', 'set',
272
+ 'delete'
273
+ ]
274
+
275
+ class StateTo:
276
+ def __init__(self, to_s: str, comeback_token: str = None, comeback_state: str = None):
277
+ self.to_s = to_s
278
+ self.comeback_token = comeback_token
279
+ self.comeback_state = comeback_state
280
+
281
+ def __str__(self):
282
+ return f'{self.to_s} comeback[{self.comeback_token} {self.comeback_state}]'
283
+
284
+ class StateMachine:
285
+ def __init__(self, indent=0, lp_level = 0, debug = False):
286
+ self.states: dict[str, StateTo] = {}
287
+ self.suggestions: dict[str, str] = {}
288
+
289
+ self.indent = indent
290
+ self.lp_level = lp_level
291
+ self.comebacks: dict[int, str] = {}
292
+ self.debug = debug
293
+
294
+ from_ss_to_add = []
295
+ from_ss = ['']
296
+ words: str = None
297
+ for l in SPEC:
298
+ t_and_w = l.split('^')
299
+ if len(t_and_w) > 1:
300
+ words = t_and_w[1]
301
+ else:
302
+ words = None
303
+
304
+ tks = t_and_w[0].strip(' ').split('>')
305
+ if not l.startswith('-'):
306
+ if words:
307
+ self.suggestions[tks[0].strip(' ')] = words
308
+
309
+ if len(tks) == 1:
310
+ from_ss_to_add.append(tks[0].strip(' '))
311
+ continue
312
+
313
+ from_ss = []
314
+ from_ss.extend(from_ss_to_add)
315
+ from_ss_to_add = []
316
+ from_ss.append(tks[0].strip(' '))
317
+
318
+ self.add_transitions(from_ss, tks)
319
+
320
+ def add_transitions(self, from_ss: list[str], tks: list[str]):
321
+ token = tks[1].strip(' ')
322
+ if len(tks) > 2:
323
+ to_s = tks[2].strip(' ')
324
+ for from_s in from_ss:
325
+ self.add_whitespace_transition(from_s, to_s)
326
+ self.add_transition(from_s, token, to_s)
327
+ elif '<' in tks[0]:
328
+ from_and_token = tks[0].split('<')
329
+ if len(from_and_token) > 1:
330
+ for from_s in from_ss:
331
+ self.add_comeback_transition(from_s, from_and_token[1], tks[1].strip(' '))
332
+
333
+ def add_whitespace_transition(self, from_s: str, to_s: str):
334
+ # add whitespace transition if a state with trailing whitespace is found from from states, for example, select > _ > select_
335
+ if from_s.endswith('_') and not from_s.endswith('_comma_') and not from_s.endswith('_lp_') and not from_s.endswith('_rp_'):
336
+ if self.debug:
337
+ print(f'{from_s[:-1]} > _ = {to_s}')
338
+ self.states[f'{from_s[:-1]} > _'] = StateTo(from_s)
339
+
340
+ def add_transition(self, from_s: str, token: str, to_s: str):
341
+ tokens = [token]
342
+ if '|' in token:
343
+ tokens = token.split('|')
344
+
345
+ for t in tokens:
346
+ if self.debug:
347
+ print(f'{from_s} > {t} = {to_s}')
348
+ self.states[f'{from_s} > {t}'] = StateTo(to_s)
349
+
350
+ def add_comeback_transition(self, from_s: str, token: str, to_s: str):
351
+ orig = self.states[f'{from_s} > (']
352
+ orig.comeback_token = token
353
+ orig.comeback_state = to_s
354
+ self.states[f'{from_s} > ('] = orig
355
+
356
+ def traverse_tokens(self, tokens: list[Token], state: StateTo = StateTo('')):
357
+ def handle_opening_parenthesis():
358
+ if f'{state.to_s} > {it}' in self.states:
359
+ state_test = self.states[f'{state.to_s} > {it}']
360
+ if state_test.comeback_token:
361
+ self.comebacks[self.lp_level] = state_test.comeback_state
362
+
363
+ def handle_closing_parenthesis():
364
+ if self.lp_level in self.comebacks:
365
+ try:
366
+ return StateTo(self.comebacks[self.lp_level])
367
+ finally:
368
+ del self.comebacks[self.lp_level]
369
+
370
+ return None
371
+
372
+ for token in tokens:
373
+ if self.debug:
374
+ if token.ttype == T.Whitespace:
375
+ print('_ ', end='')
376
+ elif token.ttype in [T.DML, T.Wildcard, T.Punctuation]:
377
+ print(f'{token.value} ', end='')
378
+ elif token.ttype:
379
+ tks = str(token.ttype).split('.')
380
+ typ = tks[len(tks) - 1]
381
+ if ' ' in token.value:
382
+ print(f'"{token.value}:{typ}" ', end='')
383
+ else:
384
+ print(f'{token.value}:{typ} ', end='')
385
+ # print(" " * self.indent + f"Token: {token.value}, Type: {token.ttype}@{token.ttype.__class__}")
386
+
387
+ if token.is_group:
388
+ state = self.traverse_tokens(token.tokens, state)
389
+ else:
390
+ comeback_state = None
391
+
392
+ it = ''
393
+ if (t := token.value.lower()) in KEYWORDS:
394
+ it = t
395
+ elif token.ttype == T.Text.Whitespace:
396
+ it = '_'
397
+ elif token.ttype == T.Name:
398
+ it = 'name'
399
+ elif token.ttype == T.Literal.String.Single:
400
+ it = 'single'
401
+ elif token.ttype in [T.Literal.Number.Integer, T.Literal.Number.Float]:
402
+ it = 'num'
403
+ elif token.ttype == T.Wildcard:
404
+ it = '*'
405
+ elif token.ttype == T.Punctuation:
406
+ it = token.value
407
+
408
+ if it == '(':
409
+ handle_opening_parenthesis()
410
+ self.lp_level += 1
411
+ elif it == ')':
412
+ self.lp_level -= 1
413
+ comeback_state = handle_closing_parenthesis()
414
+
415
+ elif token.ttype == T.Operator.Comparison:
416
+ it = 'comparison'
417
+
418
+ try:
419
+ # print(f'\n{state.to_s} > {it} > ', end='')
420
+ if comeback_state:
421
+ state = comeback_state
422
+ else:
423
+ state = self.states[f'{state.to_s} > {it}']
424
+ # print(state)
425
+ except:
426
+ pass
427
+ # print('error')
428
+
429
+ return state
adam/version.py CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env python
2
2
  # -*- coding: utf-8 -*-
3
3
 
4
- __version__ = "2.0.70" #: the working version
4
+ __version__ = "2.0.72" #: the working version
5
5
  __release__ = "1.0.0" #: the release version
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: kaqing
3
- Version: 2.0.70
3
+ Version: 2.0.72
4
4
  Summary: UNKNOWN
5
5
  Home-page: UNKNOWN
6
6
  License: UNKNOWN
@@ -14,7 +14,7 @@ adam/repl_commands.py,sha256=WA90Rl27Juctzr3U3kfCDk5N-oYMKlfWbZeafUgk7k0,4723
14
14
  adam/repl_session.py,sha256=uIogcvWBh7wd8QQ-p_JgLsyJ8YJgINw5vOd6JIsd7Vo,472
15
15
  adam/repl_state.py,sha256=nZO5CucSIGz68f4JreadGphRzMXPUzkTn-4XcoJJOug,8643
16
16
  adam/utils.py,sha256=2DoWsrcaioFFH0-RjT30qelVRPUJqCGTfz_ucfE7F8g,7406
17
- adam/version.py,sha256=yckbK4TX1cs1x8SSakRP16TVFCz-kWBTek3kfgTkIHA,139
17
+ adam/version.py,sha256=sohbp5RAQ9SRwwVEHXQ7sNudaDVpnjYfouyGnn7JNas,139
18
18
  adam/checks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
19
  adam/checks/check.py,sha256=Qopr3huYcMu2bzQgb99dEUYjFzkjKHRI76S6KA9b9Rk,702
20
20
  adam/checks/check_context.py,sha256=FEHkQ32jY1EDopQ2uYWqy9v7aEEX1orLpJWhopwAlh4,402
@@ -164,7 +164,8 @@ adam/k8s_utils/services.py,sha256=EOJJGACVbbRvu5T3rMKqIJqgYic1_MSJ17EA0TJ6UOk,31
164
164
  adam/k8s_utils/statefulsets.py,sha256=5g7KxGRHgEewT8rnZneDTaJDylUf-dHH2edWJEoorr8,4667
165
165
  adam/k8s_utils/volumes.py,sha256=RIBmlOSWM3V3QVXLCFT0owVOyh4rGG1ETp521a-6ndo,1137
166
166
  adam/sql/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
167
- adam/sql/sql_completer.py,sha256=VQfSPgNenkzIPKdER2p7NkU-82yyM-TDiSPHs_NkSJA,26705
167
+ adam/sql/sql_completer.py,sha256=R5boj_bdHlzeJkGEy7XQDz_qtE-VF1yjg8pXn5zYGJA,2510
168
+ adam/sql/state_machine.py,sha256=hsXLGZPI5d4umvaC6QZa0EJLBfh2sXBXLN0HjBgscJY,23029
168
169
  adam/sql/term_completer.py,sha256=bNnHAVf9NZl52xS_BQpikbOK39gDBJADnT9gSvG0iqI,2539
169
170
  adam/sso/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
170
171
  adam/sso/authenticator.py,sha256=BCm16L9zf5aLU47-sTCnudn2zLPwd8M2wwRminJfsqw,615
@@ -176,8 +177,8 @@ adam/sso/idp.py,sha256=fvcwUw_URTgsO6ySaqTIw0zQT2qRO1IPSGhf6rPtybo,5804
176
177
  adam/sso/idp_login.py,sha256=QAtCUeDTVWliJy40RK_oac8Vgybr13xH8wzeBoxPaa8,1754
177
178
  adam/sso/idp_session.py,sha256=9BUHNRf70u4rVKrVY1HKPOEmOviXvkjam8WJxmXSKIM,1735
178
179
  adam/sso/sso_config.py,sha256=5N8WZgIJQBtHUy585XLRWKjpU87_v6QluyNK9E27D5s,2459
179
- kaqing-2.0.70.dist-info/METADATA,sha256=CXfFNyxJYztdM8ZE6MW7MSPJ6LmxM63_fNGPBAH4THU,132
180
- kaqing-2.0.70.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
181
- kaqing-2.0.70.dist-info/entry_points.txt,sha256=SkzhuQJUWsXOzHeZ5TgQ2c3_g53UGK23zzJU_JTZOZI,39
182
- kaqing-2.0.70.dist-info/top_level.txt,sha256=8_2PZkwBb-xDcnc8a2rAbQeJhXKXskc7zTP7pSPa1fw,5
183
- kaqing-2.0.70.dist-info/RECORD,,
180
+ kaqing-2.0.72.dist-info/METADATA,sha256=kQwqFpOI4985VdIsINzktxgotqog31R0i1E-O8ZI7J4,132
181
+ kaqing-2.0.72.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
182
+ kaqing-2.0.72.dist-info/entry_points.txt,sha256=SkzhuQJUWsXOzHeZ5TgQ2c3_g53UGK23zzJU_JTZOZI,39
183
+ kaqing-2.0.72.dist-info/top_level.txt,sha256=8_2PZkwBb-xDcnc8a2rAbQeJhXKXskc7zTP7pSPa1fw,5
184
+ kaqing-2.0.72.dist-info/RECORD,,