scylla-cqlsh 6.0.29__cp310-cp310-win_amd64.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.
- copyutil.cp310-win_amd64.pyd +0 -0
- cqlsh/__init__.py +1 -0
- cqlsh/__main__.py +11 -0
- cqlsh/cqlsh.py +2736 -0
- cqlshlib/__init__.py +90 -0
- cqlshlib/_version.py +34 -0
- cqlshlib/authproviderhandling.py +176 -0
- cqlshlib/copyutil.py +2762 -0
- cqlshlib/cql3handling.py +1670 -0
- cqlshlib/cqlhandling.py +333 -0
- cqlshlib/cqlshhandling.py +314 -0
- cqlshlib/displaying.py +128 -0
- cqlshlib/formatting.py +601 -0
- cqlshlib/helptopics.py +190 -0
- cqlshlib/pylexotron.py +562 -0
- cqlshlib/saferscanner.py +91 -0
- cqlshlib/sslhandling.py +109 -0
- cqlshlib/tracing.py +90 -0
- cqlshlib/util.py +183 -0
- cqlshlib/wcwidth.py +379 -0
- scylla_cqlsh-6.0.29.dist-info/METADATA +108 -0
- scylla_cqlsh-6.0.29.dist-info/RECORD +26 -0
- scylla_cqlsh-6.0.29.dist-info/WHEEL +5 -0
- scylla_cqlsh-6.0.29.dist-info/entry_points.txt +2 -0
- scylla_cqlsh-6.0.29.dist-info/licenses/LICENSE.txt +204 -0
- scylla_cqlsh-6.0.29.dist-info/top_level.txt +3 -0
cqlshlib/cql3handling.py
ADDED
|
@@ -0,0 +1,1670 @@
|
|
|
1
|
+
# Licensed to the Apache Software Foundation (ASF) under one
|
|
2
|
+
# or more contributor license agreements. See the NOTICE file
|
|
3
|
+
# distributed with this work for additional information
|
|
4
|
+
# regarding copyright ownership. The ASF licenses this file
|
|
5
|
+
# to you under the Apache License, Version 2.0 (the
|
|
6
|
+
# "License"); you may not use this file except in compliance
|
|
7
|
+
# with the License. You may obtain a copy of the License at
|
|
8
|
+
#
|
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
#
|
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
# See the License for the specific language governing permissions and
|
|
15
|
+
# limitations under the License.
|
|
16
|
+
|
|
17
|
+
from cassandra.metadata import maybe_escape_name
|
|
18
|
+
from cqlshlib import helptopics
|
|
19
|
+
from cqlshlib.cqlhandling import CqlParsingRuleSet, Hint
|
|
20
|
+
|
|
21
|
+
simple_cql_types = {'ascii', 'bigint', 'blob', 'boolean', 'counter', 'date', 'decimal', 'double', 'duration', 'float',
|
|
22
|
+
'inet', 'int', 'smallint', 'text', 'time', 'timestamp', 'timeuuid', 'tinyint', 'uuid', 'varchar',
|
|
23
|
+
'varint'}
|
|
24
|
+
simple_cql_types.difference_update(('set', 'map', 'list'))
|
|
25
|
+
|
|
26
|
+
cqldocs = helptopics.CQL3HelpTopics()
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class UnexpectedTableStructure(UserWarning):
|
|
30
|
+
|
|
31
|
+
def __init__(self, msg):
|
|
32
|
+
self.msg = msg
|
|
33
|
+
|
|
34
|
+
def __str__(self):
|
|
35
|
+
return 'Unexpected table structure; may not translate correctly to CQL. ' + self.msg
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
SYSTEM_KEYSPACES = ('system', 'system_schema', 'system_traces', 'system_auth', 'system_distributed', 'system_views',
|
|
39
|
+
'system_virtual_schema', 'system_distributed_everywhere', 'system_replicated_keys')
|
|
40
|
+
NONALTERBALE_KEYSPACES = ('system', 'system_schema', 'system_views', 'system_virtual_schema', 'system_distributed_everywhere', 'system_replicated_keys')
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class Cql3ParsingRuleSet(CqlParsingRuleSet):
|
|
44
|
+
|
|
45
|
+
columnfamily_layout_options = (
|
|
46
|
+
('bloom_filter_fp_chance', None),
|
|
47
|
+
('comment', None),
|
|
48
|
+
('gc_grace_seconds', None),
|
|
49
|
+
('min_index_interval', None),
|
|
50
|
+
('max_index_interval', None),
|
|
51
|
+
('default_time_to_live', None),
|
|
52
|
+
('speculative_retry', None),
|
|
53
|
+
('additional_write_policy', None),
|
|
54
|
+
('memtable_flush_period_in_ms', None),
|
|
55
|
+
('cdc', None),
|
|
56
|
+
('read_repair', None),
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
columnfamily_layout_map_options = (
|
|
60
|
+
# (CQL3 option name, schema_columnfamilies column name (or None if same),
|
|
61
|
+
# list of known map keys)
|
|
62
|
+
('compaction', 'compaction_strategy_options',
|
|
63
|
+
('class', 'max_threshold', 'tombstone_compaction_interval', 'tombstone_threshold', 'enabled',
|
|
64
|
+
'unchecked_tombstone_compaction', 'only_purge_repaired_tombstones', 'provide_overlapping_tombstones')),
|
|
65
|
+
('compression', 'compression_parameters',
|
|
66
|
+
('sstable_compression', 'chunk_length_kb', 'crc_check_chance')),
|
|
67
|
+
('caching', None,
|
|
68
|
+
('rows_per_partition', 'keys')),
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
obsolete_cf_options = ()
|
|
72
|
+
|
|
73
|
+
consistency_levels = (
|
|
74
|
+
'ANY',
|
|
75
|
+
'ONE',
|
|
76
|
+
'TWO',
|
|
77
|
+
'THREE',
|
|
78
|
+
'QUORUM',
|
|
79
|
+
'ALL',
|
|
80
|
+
'LOCAL_QUORUM',
|
|
81
|
+
'EACH_QUORUM',
|
|
82
|
+
'SERIAL'
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
size_tiered_compaction_strategy_options = (
|
|
86
|
+
'min_sstable_size',
|
|
87
|
+
'min_threshold',
|
|
88
|
+
'bucket_high',
|
|
89
|
+
'bucket_low'
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
leveled_compaction_strategy_options = (
|
|
93
|
+
'sstable_size_in_mb',
|
|
94
|
+
'fanout_size'
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
date_tiered_compaction_strategy_options = (
|
|
98
|
+
'base_time_seconds',
|
|
99
|
+
'max_sstable_age_days',
|
|
100
|
+
'min_threshold',
|
|
101
|
+
'max_window_size_seconds',
|
|
102
|
+
'timestamp_resolution'
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
time_window_compaction_strategy_options = (
|
|
106
|
+
'compaction_window_unit',
|
|
107
|
+
'compaction_window_size',
|
|
108
|
+
'min_threshold',
|
|
109
|
+
'timestamp_resolution'
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
@classmethod
|
|
113
|
+
def escape_value(cls, value):
|
|
114
|
+
if value is None:
|
|
115
|
+
return 'NULL' # this totally won't work
|
|
116
|
+
if isinstance(value, bool):
|
|
117
|
+
value = str(value).lower()
|
|
118
|
+
elif isinstance(value, float):
|
|
119
|
+
return '%f' % value
|
|
120
|
+
elif isinstance(value, int):
|
|
121
|
+
return str(value)
|
|
122
|
+
return "'%s'" % value.replace("'", "''")
|
|
123
|
+
|
|
124
|
+
@classmethod
|
|
125
|
+
def escape_name(cls, name):
|
|
126
|
+
if name is None:
|
|
127
|
+
return 'NULL'
|
|
128
|
+
return "'%s'" % name.replace("'", "''")
|
|
129
|
+
|
|
130
|
+
@staticmethod
|
|
131
|
+
def dequote_name(name):
|
|
132
|
+
name = name.strip()
|
|
133
|
+
if name == '':
|
|
134
|
+
return name
|
|
135
|
+
if name[0] == '"' and name[-1] == '"':
|
|
136
|
+
return name[1:-1].replace('""', '"')
|
|
137
|
+
else:
|
|
138
|
+
return name.lower()
|
|
139
|
+
|
|
140
|
+
@staticmethod
|
|
141
|
+
def dequote_value(cqlword):
|
|
142
|
+
cqlword = cqlword.strip()
|
|
143
|
+
if cqlword == '':
|
|
144
|
+
return cqlword
|
|
145
|
+
if cqlword[0] == "'" and cqlword[-1] == "'":
|
|
146
|
+
cqlword = cqlword[1:-1].replace("''", "'")
|
|
147
|
+
return cqlword
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
CqlRuleSet = Cql3ParsingRuleSet()
|
|
151
|
+
|
|
152
|
+
# convenience for remainder of module
|
|
153
|
+
completer_for = CqlRuleSet.completer_for
|
|
154
|
+
explain_completion = CqlRuleSet.explain_completion
|
|
155
|
+
dequote_value = CqlRuleSet.dequote_value
|
|
156
|
+
dequote_name = CqlRuleSet.dequote_name
|
|
157
|
+
escape_value = CqlRuleSet.escape_value
|
|
158
|
+
|
|
159
|
+
# BEGIN SYNTAX/COMPLETION RULE DEFINITIONS
|
|
160
|
+
|
|
161
|
+
syntax_rules = r'''
|
|
162
|
+
<Start> ::= <CQL_Statement>*
|
|
163
|
+
;
|
|
164
|
+
|
|
165
|
+
<CQL_Statement> ::= [statements]=<statementBody> ";"
|
|
166
|
+
;
|
|
167
|
+
|
|
168
|
+
# the order of these terminal productions is significant:
|
|
169
|
+
<endline> ::= /\n/ ;
|
|
170
|
+
|
|
171
|
+
JUNK ::= /([ \t\r\f\v]+|(--|[/][/])[^\n\r]*([\n\r]|$)|[/][*].*?[*][/])/ ;
|
|
172
|
+
|
|
173
|
+
<stringLiteral> ::= <quotedStringLiteral>
|
|
174
|
+
| <pgStringLiteral> ;
|
|
175
|
+
<quotedStringLiteral> ::= /'([^']|'')*'/ ;
|
|
176
|
+
<pgStringLiteral> ::= /\$\$(?:(?!\$\$).)*\$\$/;
|
|
177
|
+
<quotedName> ::= /"([^"]|"")*"/ ;
|
|
178
|
+
<float> ::= /-?[0-9]+\.[0-9]+/ ;
|
|
179
|
+
<uuid> ::= /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/ ;
|
|
180
|
+
<blobLiteral> ::= /0x[0-9a-f]+/ ;
|
|
181
|
+
<wholenumber> ::= /[0-9]+/ ;
|
|
182
|
+
<identifier> ::= /[a-z][a-z0-9_]*/ ;
|
|
183
|
+
<colon> ::= ":" ;
|
|
184
|
+
<star> ::= "*" ;
|
|
185
|
+
<endtoken> ::= ";" ;
|
|
186
|
+
<op> ::= /[-+=%/,().]/ ;
|
|
187
|
+
<cmp> ::= /[<>!]=?/ ;
|
|
188
|
+
<brackets> ::= /[][{}]/ ;
|
|
189
|
+
|
|
190
|
+
<integer> ::= "-"? <wholenumber> ;
|
|
191
|
+
<boolean> ::= "true"
|
|
192
|
+
| "false"
|
|
193
|
+
;
|
|
194
|
+
|
|
195
|
+
<unclosedPgString>::= /\$\$(?:(?!\$\$).)*/ ;
|
|
196
|
+
<unclosedString> ::= /'([^']|'')*/ ;
|
|
197
|
+
<unclosedName> ::= /"([^"]|"")*/ ;
|
|
198
|
+
<unclosedComment> ::= /[/][*].*$/ ;
|
|
199
|
+
|
|
200
|
+
<term> ::= <stringLiteral>
|
|
201
|
+
| <integer>
|
|
202
|
+
| <float>
|
|
203
|
+
| <uuid>
|
|
204
|
+
| <boolean>
|
|
205
|
+
| <blobLiteral>
|
|
206
|
+
| <collectionLiteral>
|
|
207
|
+
| <functionLiteral> <functionArguments>
|
|
208
|
+
| "NULL"
|
|
209
|
+
;
|
|
210
|
+
|
|
211
|
+
<functionLiteral> ::= (<identifier> ( "." <identifier> )?)
|
|
212
|
+
| "TOKEN"
|
|
213
|
+
;
|
|
214
|
+
|
|
215
|
+
<functionArguments> ::= "(" ( <term> ( "," <term> )* )? ")"
|
|
216
|
+
;
|
|
217
|
+
|
|
218
|
+
<tokenDefinition> ::= token="TOKEN" "(" <term> ( "," <term> )* ")"
|
|
219
|
+
| <term>
|
|
220
|
+
;
|
|
221
|
+
<cident> ::= <quotedName>
|
|
222
|
+
| <identifier>
|
|
223
|
+
| <unreservedKeyword>
|
|
224
|
+
;
|
|
225
|
+
<colname> ::= <cident> ; # just an alias
|
|
226
|
+
|
|
227
|
+
<collectionLiteral> ::= <listLiteral>
|
|
228
|
+
| <setLiteral>
|
|
229
|
+
| <mapLiteral>
|
|
230
|
+
;
|
|
231
|
+
<listLiteral> ::= "[" ( <term> ( "," <term> )* )? "]"
|
|
232
|
+
;
|
|
233
|
+
<setLiteral> ::= "{" ( <term> ( "," <term> )* )? "}"
|
|
234
|
+
;
|
|
235
|
+
<mapLiteral> ::= "{" <term> ":" <term> ( "," <term> ":" <term> )* "}"
|
|
236
|
+
;
|
|
237
|
+
|
|
238
|
+
<anyFunctionName> ::= ( ksname=<cfOrKsName> dot="." )? udfname=<cfOrKsName> ;
|
|
239
|
+
|
|
240
|
+
<userFunctionName> ::= ( ksname=<nonSystemKeyspaceName> dot="." )? udfname=<cfOrKsName> ;
|
|
241
|
+
|
|
242
|
+
<refUserFunctionName> ::= udfname=<cfOrKsName> ;
|
|
243
|
+
|
|
244
|
+
<userAggregateName> ::= ( ksname=<nonSystemKeyspaceName> dot="." )? udaname=<cfOrKsName> ;
|
|
245
|
+
|
|
246
|
+
<functionAggregateName> ::= ( ksname=<nonSystemKeyspaceName> dot="." )? functionname=<cfOrKsName> ;
|
|
247
|
+
|
|
248
|
+
<aggregateName> ::= <userAggregateName>
|
|
249
|
+
;
|
|
250
|
+
|
|
251
|
+
<functionName> ::= <functionAggregateName>
|
|
252
|
+
| "TOKEN"
|
|
253
|
+
;
|
|
254
|
+
|
|
255
|
+
<statementBody> ::= <useStatement>
|
|
256
|
+
| <selectStatement>
|
|
257
|
+
| <dataChangeStatement>
|
|
258
|
+
| <schemaChangeStatement>
|
|
259
|
+
| <authenticationStatement>
|
|
260
|
+
| <authorizationStatement>
|
|
261
|
+
;
|
|
262
|
+
|
|
263
|
+
<dataChangeStatement> ::= <insertStatement>
|
|
264
|
+
| <updateStatement>
|
|
265
|
+
| <deleteStatement>
|
|
266
|
+
| <truncateStatement>
|
|
267
|
+
| <batchStatement>
|
|
268
|
+
;
|
|
269
|
+
|
|
270
|
+
<schemaChangeStatement> ::= <createKeyspaceStatement>
|
|
271
|
+
| <createColumnFamilyStatement>
|
|
272
|
+
| <createIndexStatement>
|
|
273
|
+
| <createMaterializedViewStatement>
|
|
274
|
+
| <createUserTypeStatement>
|
|
275
|
+
| <createFunctionStatement>
|
|
276
|
+
| <createAggregateStatement>
|
|
277
|
+
| <createTriggerStatement>
|
|
278
|
+
| <dropKeyspaceStatement>
|
|
279
|
+
| <dropColumnFamilyStatement>
|
|
280
|
+
| <dropIndexStatement>
|
|
281
|
+
| <dropMaterializedViewStatement>
|
|
282
|
+
| <dropUserTypeStatement>
|
|
283
|
+
| <dropFunctionStatement>
|
|
284
|
+
| <dropAggregateStatement>
|
|
285
|
+
| <dropTriggerStatement>
|
|
286
|
+
| <alterTableStatement>
|
|
287
|
+
| <alterKeyspaceStatement>
|
|
288
|
+
| <alterUserTypeStatement>
|
|
289
|
+
;
|
|
290
|
+
|
|
291
|
+
<authenticationStatement> ::= <createUserStatement>
|
|
292
|
+
| <alterUserStatement>
|
|
293
|
+
| <dropUserStatement>
|
|
294
|
+
| <listUsersStatement>
|
|
295
|
+
| <createRoleStatement>
|
|
296
|
+
| <alterRoleStatement>
|
|
297
|
+
| <dropRoleStatement>
|
|
298
|
+
| <listRolesStatement>
|
|
299
|
+
| <createSlaStatement>
|
|
300
|
+
| <alterSlaStatement>
|
|
301
|
+
| <dropSlaStatement>
|
|
302
|
+
| <listSlaStatement>
|
|
303
|
+
| <attachSlaStatement>
|
|
304
|
+
| <detachRSlaStatement>
|
|
305
|
+
;
|
|
306
|
+
|
|
307
|
+
<authorizationStatement> ::= <grantStatement>
|
|
308
|
+
| <grantRoleStatement>
|
|
309
|
+
| <revokeStatement>
|
|
310
|
+
| <revokeRoleStatement>
|
|
311
|
+
| <listPermissionsStatement>
|
|
312
|
+
;
|
|
313
|
+
|
|
314
|
+
# timestamp is included here, since it's also a keyword
|
|
315
|
+
<simpleStorageType> ::= typename=( <identifier> | <stringLiteral> | "timestamp" ) ;
|
|
316
|
+
|
|
317
|
+
<userType> ::= utname=<cfOrKsName> ;
|
|
318
|
+
|
|
319
|
+
<storageType> ::= <simpleStorageType> | <collectionType> | <frozenCollectionType> | <userType> ;
|
|
320
|
+
|
|
321
|
+
# Note: autocomplete for frozen collection types does not handle nesting past depth 1 properly,
|
|
322
|
+
# but that's a lot of work to fix for little benefit.
|
|
323
|
+
<collectionType> ::= "map" "<" <simpleStorageType> "," ( <simpleStorageType> | <userType> ) ">"
|
|
324
|
+
| "list" "<" ( <simpleStorageType> | <userType> ) ">"
|
|
325
|
+
| "set" "<" ( <simpleStorageType> | <userType> ) ">"
|
|
326
|
+
;
|
|
327
|
+
|
|
328
|
+
<frozenCollectionType> ::= "frozen" "<" "map" "<" <storageType> "," <storageType> ">" ">"
|
|
329
|
+
| "frozen" "<" "list" "<" <storageType> ">" ">"
|
|
330
|
+
| "frozen" "<" "set" "<" <storageType> ">" ">"
|
|
331
|
+
;
|
|
332
|
+
|
|
333
|
+
<columnFamilyName> ::= ( ksname=<cfOrKsName> dot="." )? cfname=<cfOrKsName> ;
|
|
334
|
+
|
|
335
|
+
<materializedViewName> ::= ( ksname=<cfOrKsName> dot="." )? mvname=<cfOrKsName> ;
|
|
336
|
+
|
|
337
|
+
<userTypeName> ::= ( ksname=<cfOrKsName> dot="." )? utname=<cfOrKsName> ;
|
|
338
|
+
|
|
339
|
+
<keyspaceName> ::= ksname=<cfOrKsName> ;
|
|
340
|
+
|
|
341
|
+
<nonSystemKeyspaceName> ::= ksname=<cfOrKsName> ;
|
|
342
|
+
|
|
343
|
+
<alterableKeyspaceName> ::= ksname=<cfOrKsName> ;
|
|
344
|
+
|
|
345
|
+
<cfOrKsName> ::= <identifier>
|
|
346
|
+
| <quotedName>
|
|
347
|
+
| <unreservedKeyword>;
|
|
348
|
+
|
|
349
|
+
<unreservedKeyword> ::= nocomplete=
|
|
350
|
+
( "key"
|
|
351
|
+
| "clustering"
|
|
352
|
+
# | "count" -- to get count(*) completion, treat count as reserved
|
|
353
|
+
| "ttl"
|
|
354
|
+
| "compact"
|
|
355
|
+
| "storage"
|
|
356
|
+
| "type"
|
|
357
|
+
| "values" )
|
|
358
|
+
;
|
|
359
|
+
|
|
360
|
+
<property> ::= [propname]=<cident> propeq="=" [propval]=<propertyValue>
|
|
361
|
+
;
|
|
362
|
+
<propertyValue> ::= propsimpleval=( <stringLiteral>
|
|
363
|
+
| <identifier>
|
|
364
|
+
| <integer>
|
|
365
|
+
| <float>
|
|
366
|
+
| <unreservedKeyword> )
|
|
367
|
+
# we don't use <mapLiteral> here so we can get more targeted
|
|
368
|
+
# completions:
|
|
369
|
+
| propsimpleval="{" [propmapkey]=<term> ":" [propmapval]=<term>
|
|
370
|
+
( ender="," [propmapkey]=<term> ":" [propmapval]=<term> )*
|
|
371
|
+
ender="}"
|
|
372
|
+
;
|
|
373
|
+
|
|
374
|
+
'''
|
|
375
|
+
|
|
376
|
+
|
|
377
|
+
def prop_equals_completer(ctxt, cass):
|
|
378
|
+
if not working_on_keyspace(ctxt):
|
|
379
|
+
# we know if the thing in the property name position is "compact" or
|
|
380
|
+
# "clustering" that there won't actually be an equals sign, because
|
|
381
|
+
# there are no properties by those names. there are, on the other hand,
|
|
382
|
+
# table properties that start with those keywords which don't have
|
|
383
|
+
# equals signs at all.
|
|
384
|
+
curprop = ctxt.get_binding('propname')[-1].upper()
|
|
385
|
+
if curprop in ('COMPACT', 'CLUSTERING'):
|
|
386
|
+
return ()
|
|
387
|
+
return ['=']
|
|
388
|
+
|
|
389
|
+
|
|
390
|
+
completer_for('property', 'propeq')(prop_equals_completer)
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
@completer_for('property', 'propname')
|
|
394
|
+
def prop_name_completer(ctxt, cass):
|
|
395
|
+
if working_on_keyspace(ctxt):
|
|
396
|
+
return ks_prop_name_completer(ctxt, cass)
|
|
397
|
+
else:
|
|
398
|
+
return cf_prop_name_completer(ctxt, cass)
|
|
399
|
+
|
|
400
|
+
|
|
401
|
+
@completer_for('propertyValue', 'propsimpleval')
|
|
402
|
+
def prop_val_completer(ctxt, cass):
|
|
403
|
+
if working_on_keyspace(ctxt):
|
|
404
|
+
return ks_prop_val_completer(ctxt, cass)
|
|
405
|
+
else:
|
|
406
|
+
return cf_prop_val_completer(ctxt, cass)
|
|
407
|
+
|
|
408
|
+
|
|
409
|
+
@completer_for('propertyValue', 'propmapkey')
|
|
410
|
+
def prop_val_mapkey_completer(ctxt, cass):
|
|
411
|
+
if working_on_keyspace(ctxt):
|
|
412
|
+
return ks_prop_val_mapkey_completer(ctxt, cass)
|
|
413
|
+
else:
|
|
414
|
+
return cf_prop_val_mapkey_completer(ctxt, cass)
|
|
415
|
+
|
|
416
|
+
|
|
417
|
+
@completer_for('propertyValue', 'propmapval')
|
|
418
|
+
def prop_val_mapval_completer(ctxt, cass):
|
|
419
|
+
if working_on_keyspace(ctxt):
|
|
420
|
+
return ks_prop_val_mapval_completer(ctxt, cass)
|
|
421
|
+
else:
|
|
422
|
+
return cf_prop_val_mapval_completer(ctxt, cass)
|
|
423
|
+
|
|
424
|
+
|
|
425
|
+
@completer_for('propertyValue', 'ender')
|
|
426
|
+
def prop_val_mapender_completer(ctxt, cass):
|
|
427
|
+
if working_on_keyspace(ctxt):
|
|
428
|
+
return ks_prop_val_mapender_completer(ctxt, cass)
|
|
429
|
+
else:
|
|
430
|
+
return cf_prop_val_mapender_completer(ctxt, cass)
|
|
431
|
+
|
|
432
|
+
|
|
433
|
+
def ks_prop_name_completer(ctxt, cass):
|
|
434
|
+
optsseen = ctxt.get_binding('propname', ())
|
|
435
|
+
if 'replication' not in optsseen:
|
|
436
|
+
return ['replication']
|
|
437
|
+
return ["durable_writes"]
|
|
438
|
+
|
|
439
|
+
|
|
440
|
+
def ks_prop_val_completer(ctxt, cass):
|
|
441
|
+
optname = ctxt.get_binding('propname')[-1]
|
|
442
|
+
if optname == 'durable_writes':
|
|
443
|
+
return ["'true'", "'false'"]
|
|
444
|
+
if optname == 'replication':
|
|
445
|
+
return ["{'class': 'NetworkTopologyStrategy'"]
|
|
446
|
+
return ()
|
|
447
|
+
|
|
448
|
+
|
|
449
|
+
def ks_prop_val_mapkey_completer(ctxt, cass):
|
|
450
|
+
optname = ctxt.get_binding('propname')[-1]
|
|
451
|
+
if optname != 'replication':
|
|
452
|
+
return ()
|
|
453
|
+
keysseen = list(map(dequote_value, ctxt.get_binding('propmapkey', ())))
|
|
454
|
+
valsseen = list(map(dequote_value, ctxt.get_binding('propmapval', ())))
|
|
455
|
+
for k, v in zip(keysseen, valsseen):
|
|
456
|
+
if k == 'class':
|
|
457
|
+
repclass = v
|
|
458
|
+
break
|
|
459
|
+
else:
|
|
460
|
+
return ["'class'"]
|
|
461
|
+
if repclass == 'SimpleStrategy':
|
|
462
|
+
opts = {'replication_factor'}
|
|
463
|
+
elif repclass == 'NetworkTopologyStrategy':
|
|
464
|
+
return [Hint('<dc_name>')]
|
|
465
|
+
return list(map(escape_value, opts.difference(keysseen)))
|
|
466
|
+
|
|
467
|
+
|
|
468
|
+
def ks_prop_val_mapval_completer(ctxt, cass):
|
|
469
|
+
optname = ctxt.get_binding('propname')[-1]
|
|
470
|
+
if optname != 'replication':
|
|
471
|
+
return ()
|
|
472
|
+
currentkey = dequote_value(ctxt.get_binding('propmapkey')[-1])
|
|
473
|
+
if currentkey == 'class':
|
|
474
|
+
partial = ctxt.get_binding('partial', '')
|
|
475
|
+
if partial == '':
|
|
476
|
+
return [escape_value('NetworkTopologyStrategy')]
|
|
477
|
+
return [s for s in CqlRuleSet.replication_strategies if s.startswith(partial)]
|
|
478
|
+
return [Hint('<term>')]
|
|
479
|
+
|
|
480
|
+
|
|
481
|
+
def ks_prop_val_mapender_completer(ctxt, cass):
|
|
482
|
+
optname = ctxt.get_binding('propname')[-1]
|
|
483
|
+
if optname != 'replication':
|
|
484
|
+
return [',']
|
|
485
|
+
keysseen = list(map(dequote_value, ctxt.get_binding('propmapkey', ())))
|
|
486
|
+
valsseen = list(map(dequote_value, ctxt.get_binding('propmapval', ())))
|
|
487
|
+
for k, v in zip(keysseen, valsseen):
|
|
488
|
+
if k == 'class':
|
|
489
|
+
repclass = v
|
|
490
|
+
break
|
|
491
|
+
else:
|
|
492
|
+
return [',']
|
|
493
|
+
if repclass == 'SimpleStrategy':
|
|
494
|
+
if 'replication_factor' not in keysseen:
|
|
495
|
+
return [',']
|
|
496
|
+
if repclass == 'NetworkTopologyStrategy' and len(keysseen) == 1:
|
|
497
|
+
return [',']
|
|
498
|
+
return ['}']
|
|
499
|
+
|
|
500
|
+
|
|
501
|
+
def cf_prop_name_completer(ctxt, cass):
|
|
502
|
+
return [c[0] for c in (CqlRuleSet.columnfamily_layout_options
|
|
503
|
+
+ CqlRuleSet.columnfamily_layout_map_options)]
|
|
504
|
+
|
|
505
|
+
|
|
506
|
+
def cf_prop_val_completer(ctxt, cass):
|
|
507
|
+
exist_opts = ctxt.get_binding('propname')
|
|
508
|
+
this_opt = exist_opts[-1]
|
|
509
|
+
if this_opt == 'compression':
|
|
510
|
+
return ["{'sstable_compression': '"]
|
|
511
|
+
if this_opt == 'compaction':
|
|
512
|
+
return ["{'class': '"]
|
|
513
|
+
if this_opt == 'caching':
|
|
514
|
+
return ["{'keys': '"]
|
|
515
|
+
if any(this_opt == opt[0] for opt in CqlRuleSet.obsolete_cf_options):
|
|
516
|
+
return ["'<obsolete_option>'"]
|
|
517
|
+
if this_opt == 'bloom_filter_fp_chance':
|
|
518
|
+
return [Hint('<float_between_0_and_1>')]
|
|
519
|
+
if this_opt in ('min_compaction_threshold', 'max_compaction_threshold',
|
|
520
|
+
'gc_grace_seconds', 'min_index_interval', 'max_index_interval'):
|
|
521
|
+
return [Hint('<integer>')]
|
|
522
|
+
if this_opt in ('cdc'):
|
|
523
|
+
return [Hint('<true|false>')]
|
|
524
|
+
if this_opt in ('read_repair'):
|
|
525
|
+
return [Hint('<\'none\'|\'blocking\'>')]
|
|
526
|
+
return [Hint('<option_value>')]
|
|
527
|
+
|
|
528
|
+
|
|
529
|
+
def cf_prop_val_mapkey_completer(ctxt, cass):
|
|
530
|
+
optname = ctxt.get_binding('propname')[-1]
|
|
531
|
+
for cql3option, _, subopts in CqlRuleSet.columnfamily_layout_map_options:
|
|
532
|
+
if optname == cql3option:
|
|
533
|
+
break
|
|
534
|
+
else:
|
|
535
|
+
return ()
|
|
536
|
+
keysseen = list(map(dequote_value, ctxt.get_binding('propmapkey', ())))
|
|
537
|
+
valsseen = list(map(dequote_value, ctxt.get_binding('propmapval', ())))
|
|
538
|
+
pairsseen = dict(list(zip(keysseen, valsseen)))
|
|
539
|
+
if optname == 'compression':
|
|
540
|
+
return list(map(escape_value, set(subopts).difference(keysseen)))
|
|
541
|
+
if optname == 'caching':
|
|
542
|
+
return list(map(escape_value, set(subopts).difference(keysseen)))
|
|
543
|
+
if optname == 'compaction':
|
|
544
|
+
opts = set(subopts)
|
|
545
|
+
try:
|
|
546
|
+
csc = pairsseen['class']
|
|
547
|
+
except KeyError:
|
|
548
|
+
return ["'class'"]
|
|
549
|
+
csc = csc.split('.')[-1]
|
|
550
|
+
if csc == 'SizeTieredCompactionStrategy':
|
|
551
|
+
opts = opts.union(set(CqlRuleSet.size_tiered_compaction_strategy_options))
|
|
552
|
+
elif csc == 'LeveledCompactionStrategy':
|
|
553
|
+
opts = opts.union(set(CqlRuleSet.leveled_compaction_strategy_options))
|
|
554
|
+
elif csc == 'DateTieredCompactionStrategy':
|
|
555
|
+
opts = opts.union(set(CqlRuleSet.date_tiered_compaction_strategy_options))
|
|
556
|
+
elif csc == 'TimeWindowCompactionStrategy':
|
|
557
|
+
opts = opts.union(set(CqlRuleSet.time_window_compaction_strategy_options))
|
|
558
|
+
|
|
559
|
+
return list(map(escape_value, opts))
|
|
560
|
+
return ()
|
|
561
|
+
|
|
562
|
+
|
|
563
|
+
def cf_prop_val_mapval_completer(ctxt, cass):
|
|
564
|
+
opt = ctxt.get_binding('propname')[-1]
|
|
565
|
+
key = dequote_value(ctxt.get_binding('propmapkey')[-1])
|
|
566
|
+
if opt == 'compaction':
|
|
567
|
+
if key == 'class':
|
|
568
|
+
return list(map(escape_value, CqlRuleSet.available_compaction_classes))
|
|
569
|
+
if key == 'provide_overlapping_tombstones':
|
|
570
|
+
return [Hint('<NONE|ROW|CELL>')]
|
|
571
|
+
return [Hint('<option_value>')]
|
|
572
|
+
elif opt == 'compression':
|
|
573
|
+
if key == 'sstable_compression':
|
|
574
|
+
return list(map(escape_value, CqlRuleSet.available_compression_classes))
|
|
575
|
+
return [Hint('<option_value>')]
|
|
576
|
+
elif opt == 'caching':
|
|
577
|
+
if key == 'rows_per_partition':
|
|
578
|
+
return ["'ALL'", "'NONE'", Hint('#rows_per_partition')]
|
|
579
|
+
elif key == 'keys':
|
|
580
|
+
return ["'ALL'", "'NONE'"]
|
|
581
|
+
return ()
|
|
582
|
+
|
|
583
|
+
|
|
584
|
+
def cf_prop_val_mapender_completer(ctxt, cass):
|
|
585
|
+
return [',', '}']
|
|
586
|
+
|
|
587
|
+
|
|
588
|
+
@completer_for('tokenDefinition', 'token')
|
|
589
|
+
def token_word_completer(ctxt, cass):
|
|
590
|
+
return ['token(']
|
|
591
|
+
|
|
592
|
+
|
|
593
|
+
@completer_for('simpleStorageType', 'typename')
|
|
594
|
+
def storagetype_completer(ctxt, cass):
|
|
595
|
+
return simple_cql_types
|
|
596
|
+
|
|
597
|
+
|
|
598
|
+
@completer_for('keyspaceName', 'ksname')
|
|
599
|
+
def ks_name_completer(ctxt, cass):
|
|
600
|
+
return list(map(maybe_escape_name, cass.get_keyspace_names()))
|
|
601
|
+
|
|
602
|
+
|
|
603
|
+
@completer_for('nonSystemKeyspaceName', 'ksname')
|
|
604
|
+
def non_system_ks_name_completer(ctxt, cass):
|
|
605
|
+
ksnames = [n for n in cass.get_keyspace_names() if n not in SYSTEM_KEYSPACES]
|
|
606
|
+
return list(map(maybe_escape_name, ksnames))
|
|
607
|
+
|
|
608
|
+
|
|
609
|
+
@completer_for('alterableKeyspaceName', 'ksname')
|
|
610
|
+
def alterable_ks_name_completer(ctxt, cass):
|
|
611
|
+
ksnames = [n for n in cass.get_keyspace_names() if n not in NONALTERBALE_KEYSPACES]
|
|
612
|
+
return list(map(maybe_escape_name, ksnames))
|
|
613
|
+
|
|
614
|
+
|
|
615
|
+
def cf_ks_name_completer(ctxt, cass):
|
|
616
|
+
return [maybe_escape_name(ks) + '.' for ks in cass.get_keyspace_names()]
|
|
617
|
+
|
|
618
|
+
|
|
619
|
+
completer_for('columnFamilyName', 'ksname')(cf_ks_name_completer)
|
|
620
|
+
completer_for('materializedViewName', 'ksname')(cf_ks_name_completer)
|
|
621
|
+
|
|
622
|
+
|
|
623
|
+
def cf_ks_dot_completer(ctxt, cass):
|
|
624
|
+
name = dequote_name(ctxt.get_binding('ksname'))
|
|
625
|
+
if name in cass.get_keyspace_names():
|
|
626
|
+
return ['.']
|
|
627
|
+
return []
|
|
628
|
+
|
|
629
|
+
|
|
630
|
+
completer_for('columnFamilyName', 'dot')(cf_ks_dot_completer)
|
|
631
|
+
completer_for('materializedViewName', 'dot')(cf_ks_dot_completer)
|
|
632
|
+
|
|
633
|
+
|
|
634
|
+
@completer_for('columnFamilyName', 'cfname')
|
|
635
|
+
def cf_name_completer(ctxt, cass):
|
|
636
|
+
ks = ctxt.get_binding('ksname', None)
|
|
637
|
+
if ks is not None:
|
|
638
|
+
ks = dequote_name(ks)
|
|
639
|
+
try:
|
|
640
|
+
cfnames = cass.get_columnfamily_names(ks)
|
|
641
|
+
except Exception:
|
|
642
|
+
if ks is None:
|
|
643
|
+
return ()
|
|
644
|
+
raise
|
|
645
|
+
return list(map(maybe_escape_name, cfnames))
|
|
646
|
+
|
|
647
|
+
|
|
648
|
+
@completer_for('materializedViewName', 'mvname')
|
|
649
|
+
def mv_name_completer(ctxt, cass):
|
|
650
|
+
ks = ctxt.get_binding('ksname', None)
|
|
651
|
+
if ks is not None:
|
|
652
|
+
ks = dequote_name(ks)
|
|
653
|
+
try:
|
|
654
|
+
mvnames = cass.get_materialized_view_names(ks)
|
|
655
|
+
except Exception:
|
|
656
|
+
if ks is None:
|
|
657
|
+
return ()
|
|
658
|
+
raise
|
|
659
|
+
return list(map(maybe_escape_name, mvnames))
|
|
660
|
+
|
|
661
|
+
|
|
662
|
+
completer_for('userTypeName', 'ksname')(cf_ks_name_completer)
|
|
663
|
+
|
|
664
|
+
completer_for('userTypeName', 'dot')(cf_ks_dot_completer)
|
|
665
|
+
|
|
666
|
+
|
|
667
|
+
def ut_name_completer(ctxt, cass):
|
|
668
|
+
ks = ctxt.get_binding('ksname', None)
|
|
669
|
+
if ks is not None:
|
|
670
|
+
ks = dequote_name(ks)
|
|
671
|
+
try:
|
|
672
|
+
utnames = cass.get_usertype_names(ks)
|
|
673
|
+
except Exception:
|
|
674
|
+
if ks is None:
|
|
675
|
+
return ()
|
|
676
|
+
raise
|
|
677
|
+
return list(map(maybe_escape_name, utnames))
|
|
678
|
+
|
|
679
|
+
|
|
680
|
+
completer_for('userTypeName', 'utname')(ut_name_completer)
|
|
681
|
+
completer_for('userType', 'utname')(ut_name_completer)
|
|
682
|
+
|
|
683
|
+
|
|
684
|
+
@completer_for('unreservedKeyword', 'nocomplete')
|
|
685
|
+
def unreserved_keyword_completer(ctxt, cass):
|
|
686
|
+
# we never want to provide completions through this production;
|
|
687
|
+
# this is always just to allow use of some keywords as column
|
|
688
|
+
# names, CF names, property values, etc.
|
|
689
|
+
return ()
|
|
690
|
+
|
|
691
|
+
|
|
692
|
+
def get_table_meta(ctxt, cass):
|
|
693
|
+
ks = ctxt.get_binding('ksname', None)
|
|
694
|
+
if ks is not None:
|
|
695
|
+
ks = dequote_name(ks)
|
|
696
|
+
cf = dequote_name(ctxt.get_binding('cfname'))
|
|
697
|
+
return cass.get_table_meta(ks, cf)
|
|
698
|
+
|
|
699
|
+
|
|
700
|
+
def get_ut_layout(ctxt, cass):
|
|
701
|
+
ks = ctxt.get_binding('ksname', None)
|
|
702
|
+
if ks is not None:
|
|
703
|
+
ks = dequote_name(ks)
|
|
704
|
+
ut = dequote_name(ctxt.get_binding('utname'))
|
|
705
|
+
return cass.get_usertype_layout(ks, ut)
|
|
706
|
+
|
|
707
|
+
|
|
708
|
+
def working_on_keyspace(ctxt):
|
|
709
|
+
wat = ctxt.get_binding('wat').upper()
|
|
710
|
+
if wat in ('KEYSPACE', 'SCHEMA'):
|
|
711
|
+
return True
|
|
712
|
+
return False
|
|
713
|
+
|
|
714
|
+
|
|
715
|
+
syntax_rules += r'''
|
|
716
|
+
<useStatement> ::= "USE" <keyspaceName>
|
|
717
|
+
;
|
|
718
|
+
<selectStatement> ::= "SELECT" ( "JSON" )? <selectClause>
|
|
719
|
+
"FROM" (cf=<columnFamilyName> | mv=<materializedViewName>)
|
|
720
|
+
( "WHERE" <whereClause> )?
|
|
721
|
+
( "GROUP" "BY" <groupByClause> ( "," <groupByClause> )* )?
|
|
722
|
+
( "ORDER" "BY" <orderByClause> ( "," <orderByClause> )* )?
|
|
723
|
+
( "PER" "PARTITION" "LIMIT" perPartitionLimit=<wholenumber> )?
|
|
724
|
+
( "LIMIT" limit=<wholenumber> )?
|
|
725
|
+
( "ALLOW" "FILTERING" )?
|
|
726
|
+
;
|
|
727
|
+
<whereClause> ::= <relation> ( "AND" <relation> )*
|
|
728
|
+
;
|
|
729
|
+
<relation> ::= [rel_lhs]=<cident> ( "[" <term> "]" )? ( "=" | "<" | ">" | "<=" | ">=" | "CONTAINS" ( "KEY" )? ) <term>
|
|
730
|
+
| token="TOKEN" "(" [rel_tokname]=<cident>
|
|
731
|
+
( "," [rel_tokname]=<cident> )*
|
|
732
|
+
")" ("=" | "<" | ">" | "<=" | ">=") <tokenDefinition>
|
|
733
|
+
| [rel_lhs]=<cident> "IN" "(" <term> ( "," <term> )* ")"
|
|
734
|
+
;
|
|
735
|
+
<selectClause> ::= "DISTINCT"? <selector> ("AS" <cident>)? ("," <selector> ("AS" <cident>)?)*
|
|
736
|
+
| "*"
|
|
737
|
+
;
|
|
738
|
+
<udtSubfieldSelection> ::= <identifier> "." <identifier>
|
|
739
|
+
;
|
|
740
|
+
<selector> ::= [colname]=<cident> ( "[" ( <term> ( ".." <term> "]" )? | <term> ".." ) )?
|
|
741
|
+
| <udtSubfieldSelection>
|
|
742
|
+
| "WRITETIME" "(" [colname]=<cident> ")"
|
|
743
|
+
| "MAXWRITETIME" "(" [colname]=<cident> ")"
|
|
744
|
+
| "TTL" "(" [colname]=<cident> ")"
|
|
745
|
+
| "COUNT" "(" star=( "*" | "1" ) ")"
|
|
746
|
+
| "CAST" "(" <selector> "AS" <storageType> ")"
|
|
747
|
+
| <functionName> <selectionFunctionArguments>
|
|
748
|
+
| <term>
|
|
749
|
+
;
|
|
750
|
+
<selectionFunctionArguments> ::= "(" ( <selector> ( "," <selector> )* )? ")"
|
|
751
|
+
;
|
|
752
|
+
<orderByClause> ::= [ordercol]=<cident> ( "ASC" | "DESC" )?
|
|
753
|
+
;
|
|
754
|
+
<groupByClause> ::= [groupcol]=<cident>
|
|
755
|
+
| <functionName><groupByFunctionArguments>
|
|
756
|
+
;
|
|
757
|
+
<groupByFunctionArguments> ::= "(" ( <groupByFunctionArgument> ( "," <groupByFunctionArgument> )* )? ")"
|
|
758
|
+
;
|
|
759
|
+
<groupByFunctionArgument> ::= [groupcol]=<cident>
|
|
760
|
+
| <term>
|
|
761
|
+
;
|
|
762
|
+
'''
|
|
763
|
+
|
|
764
|
+
|
|
765
|
+
def udf_name_completer(ctxt, cass):
|
|
766
|
+
ks = ctxt.get_binding('ksname', None)
|
|
767
|
+
if ks is not None:
|
|
768
|
+
ks = dequote_name(ks)
|
|
769
|
+
try:
|
|
770
|
+
udfnames = cass.get_userfunction_names(ks)
|
|
771
|
+
except Exception:
|
|
772
|
+
if ks is None:
|
|
773
|
+
return ()
|
|
774
|
+
raise
|
|
775
|
+
return list(map(maybe_escape_name, udfnames))
|
|
776
|
+
|
|
777
|
+
|
|
778
|
+
def uda_name_completer(ctxt, cass):
|
|
779
|
+
ks = ctxt.get_binding('ksname', None)
|
|
780
|
+
if ks is not None:
|
|
781
|
+
ks = dequote_name(ks)
|
|
782
|
+
try:
|
|
783
|
+
udanames = cass.get_useraggregate_names(ks)
|
|
784
|
+
except Exception:
|
|
785
|
+
if ks is None:
|
|
786
|
+
return ()
|
|
787
|
+
raise
|
|
788
|
+
return list(map(maybe_escape_name, udanames))
|
|
789
|
+
|
|
790
|
+
|
|
791
|
+
def udf_uda_name_completer(ctxt, cass):
|
|
792
|
+
ks = ctxt.get_binding('ksname', None)
|
|
793
|
+
if ks is not None:
|
|
794
|
+
ks = dequote_name(ks)
|
|
795
|
+
try:
|
|
796
|
+
functionnames = cass.get_userfunction_names(ks) + cass.get_useraggregate_names(ks)
|
|
797
|
+
except Exception:
|
|
798
|
+
if ks is None:
|
|
799
|
+
return ()
|
|
800
|
+
raise
|
|
801
|
+
return list(map(maybe_escape_name, functionnames))
|
|
802
|
+
|
|
803
|
+
|
|
804
|
+
def ref_udf_name_completer(ctxt, cass):
|
|
805
|
+
try:
|
|
806
|
+
udanames = cass.get_userfunction_names(None)
|
|
807
|
+
except Exception:
|
|
808
|
+
return ()
|
|
809
|
+
return list(map(maybe_escape_name, udanames))
|
|
810
|
+
|
|
811
|
+
|
|
812
|
+
completer_for('functionAggregateName', 'ksname')(cf_ks_name_completer)
|
|
813
|
+
completer_for('functionAggregateName', 'dot')(cf_ks_dot_completer)
|
|
814
|
+
completer_for('functionAggregateName', 'functionname')(udf_uda_name_completer)
|
|
815
|
+
completer_for('anyFunctionName', 'ksname')(cf_ks_name_completer)
|
|
816
|
+
completer_for('anyFunctionName', 'dot')(cf_ks_dot_completer)
|
|
817
|
+
completer_for('anyFunctionName', 'udfname')(udf_name_completer)
|
|
818
|
+
completer_for('userFunctionName', 'ksname')(cf_ks_name_completer)
|
|
819
|
+
completer_for('userFunctionName', 'dot')(cf_ks_dot_completer)
|
|
820
|
+
completer_for('userFunctionName', 'udfname')(udf_name_completer)
|
|
821
|
+
completer_for('refUserFunctionName', 'udfname')(ref_udf_name_completer)
|
|
822
|
+
completer_for('userAggregateName', 'ksname')(cf_ks_name_completer)
|
|
823
|
+
completer_for('userAggregateName', 'dot')(cf_ks_dot_completer)
|
|
824
|
+
completer_for('userAggregateName', 'udaname')(uda_name_completer)
|
|
825
|
+
|
|
826
|
+
|
|
827
|
+
@completer_for('orderByClause', 'ordercol')
|
|
828
|
+
def select_order_column_completer(ctxt, cass):
|
|
829
|
+
prev_order_cols = ctxt.get_binding('ordercol', ())
|
|
830
|
+
keyname = ctxt.get_binding('keyname')
|
|
831
|
+
if keyname is None:
|
|
832
|
+
keyname = ctxt.get_binding('rel_lhs', ())
|
|
833
|
+
if not keyname:
|
|
834
|
+
return [Hint("Can't ORDER BY here: need to specify partition key in WHERE clause")]
|
|
835
|
+
layout = get_table_meta(ctxt, cass)
|
|
836
|
+
order_by_candidates = [col.name for col in layout.clustering_key]
|
|
837
|
+
if len(order_by_candidates) > len(prev_order_cols):
|
|
838
|
+
return [maybe_escape_name(order_by_candidates[len(prev_order_cols)])]
|
|
839
|
+
return [Hint('No more orderable columns here.')]
|
|
840
|
+
|
|
841
|
+
|
|
842
|
+
@completer_for('groupByClause', 'groupcol')
|
|
843
|
+
def select_group_column_completer(ctxt, cass):
|
|
844
|
+
prev_group_cols = ctxt.get_binding('groupcol', ())
|
|
845
|
+
layout = get_table_meta(ctxt, cass)
|
|
846
|
+
group_by_candidates = [col.name for col in layout.primary_key]
|
|
847
|
+
if len(group_by_candidates) > len(prev_group_cols):
|
|
848
|
+
return [maybe_escape_name(group_by_candidates[len(prev_group_cols)])]
|
|
849
|
+
return [Hint('No more columns here.')]
|
|
850
|
+
|
|
851
|
+
|
|
852
|
+
@completer_for('relation', 'token')
|
|
853
|
+
def relation_token_word_completer(ctxt, cass):
|
|
854
|
+
return ['TOKEN(']
|
|
855
|
+
|
|
856
|
+
|
|
857
|
+
@completer_for('relation', 'rel_tokname')
|
|
858
|
+
def relation_token_subject_completer(ctxt, cass):
|
|
859
|
+
layout = get_table_meta(ctxt, cass)
|
|
860
|
+
return [key.name for key in layout.partition_key]
|
|
861
|
+
|
|
862
|
+
|
|
863
|
+
@completer_for('relation', 'rel_lhs')
|
|
864
|
+
def select_relation_lhs_completer(ctxt, cass):
|
|
865
|
+
layout = get_table_meta(ctxt, cass)
|
|
866
|
+
filterable = set()
|
|
867
|
+
already_filtered_on = list(map(dequote_name, ctxt.get_binding('rel_lhs', ())))
|
|
868
|
+
for num in range(0, len(layout.partition_key)):
|
|
869
|
+
if num == 0 or layout.partition_key[num - 1].name in already_filtered_on:
|
|
870
|
+
filterable.add(layout.partition_key[num].name)
|
|
871
|
+
else:
|
|
872
|
+
break
|
|
873
|
+
for num in range(0, len(layout.clustering_key)):
|
|
874
|
+
if num == 0 or layout.clustering_key[num - 1].name in already_filtered_on:
|
|
875
|
+
filterable.add(layout.clustering_key[num].name)
|
|
876
|
+
else:
|
|
877
|
+
break
|
|
878
|
+
for idx in layout.indexes.values():
|
|
879
|
+
filterable.add(idx.index_options["target"])
|
|
880
|
+
return list(map(maybe_escape_name, filterable))
|
|
881
|
+
|
|
882
|
+
|
|
883
|
+
explain_completion('selector', 'colname')
|
|
884
|
+
|
|
885
|
+
syntax_rules += r'''
|
|
886
|
+
<insertStatement> ::= "INSERT" "INTO" cf=<columnFamilyName>
|
|
887
|
+
( ( "(" [colname]=<cident> ( "," [colname]=<cident> )* ")"
|
|
888
|
+
"VALUES" "(" [newval]=<term> ( valcomma="," [newval]=<term> )* valcomma=")")
|
|
889
|
+
| ("JSON" <stringLiteral>))
|
|
890
|
+
( "IF" "NOT" "EXISTS")?
|
|
891
|
+
( "USING" [insertopt]=<usingOption>
|
|
892
|
+
( "AND" [insertopt]=<usingOption> )* )?
|
|
893
|
+
;
|
|
894
|
+
<usingOption> ::= "TIMESTAMP" <wholenumber>
|
|
895
|
+
| "TTL" <wholenumber>
|
|
896
|
+
;
|
|
897
|
+
'''
|
|
898
|
+
|
|
899
|
+
|
|
900
|
+
def regular_column_names(table_meta):
|
|
901
|
+
if not table_meta or not table_meta.columns:
|
|
902
|
+
return []
|
|
903
|
+
regular_columns = list(set(table_meta.columns.keys())
|
|
904
|
+
- set([key.name for key in table_meta.partition_key])
|
|
905
|
+
- set([key.name for key in table_meta.clustering_key]))
|
|
906
|
+
return regular_columns
|
|
907
|
+
|
|
908
|
+
|
|
909
|
+
@completer_for('insertStatement', 'colname')
|
|
910
|
+
def insert_colname_completer(ctxt, cass):
|
|
911
|
+
layout = get_table_meta(ctxt, cass)
|
|
912
|
+
colnames = set(map(dequote_name, ctxt.get_binding('colname', ())))
|
|
913
|
+
keycols = layout.primary_key
|
|
914
|
+
for k in keycols:
|
|
915
|
+
if k.name not in colnames:
|
|
916
|
+
return [maybe_escape_name(k.name)]
|
|
917
|
+
normalcols = set(regular_column_names(layout)) - colnames
|
|
918
|
+
return list(map(maybe_escape_name, normalcols))
|
|
919
|
+
|
|
920
|
+
|
|
921
|
+
@completer_for('insertStatement', 'newval')
|
|
922
|
+
def insert_newval_completer(ctxt, cass):
|
|
923
|
+
layout = get_table_meta(ctxt, cass)
|
|
924
|
+
insertcols = list(map(dequote_name, ctxt.get_binding('colname')))
|
|
925
|
+
valuesdone = ctxt.get_binding('newval', ())
|
|
926
|
+
if len(valuesdone) >= len(insertcols):
|
|
927
|
+
return []
|
|
928
|
+
curcol = insertcols[len(valuesdone)]
|
|
929
|
+
coltype = layout.columns[curcol].cql_type
|
|
930
|
+
if coltype in ('map', 'set'):
|
|
931
|
+
return ['{']
|
|
932
|
+
if coltype == 'list':
|
|
933
|
+
return ['[']
|
|
934
|
+
if coltype == 'boolean':
|
|
935
|
+
return ['true', 'false']
|
|
936
|
+
|
|
937
|
+
return [Hint('<value for %s (%s)>' % (maybe_escape_name(curcol),
|
|
938
|
+
coltype))]
|
|
939
|
+
|
|
940
|
+
|
|
941
|
+
@completer_for('insertStatement', 'valcomma')
|
|
942
|
+
def insert_valcomma_completer(ctxt, cass):
|
|
943
|
+
numcols = len(ctxt.get_binding('colname', ()))
|
|
944
|
+
numvals = len(ctxt.get_binding('newval', ()))
|
|
945
|
+
if numcols > numvals:
|
|
946
|
+
return [',']
|
|
947
|
+
return [')']
|
|
948
|
+
|
|
949
|
+
|
|
950
|
+
@completer_for('insertStatement', 'insertopt')
|
|
951
|
+
def insert_option_completer(ctxt, cass):
|
|
952
|
+
opts = set('TIMESTAMP TTL'.split())
|
|
953
|
+
for opt in ctxt.get_binding('insertopt', ()):
|
|
954
|
+
opts.discard(opt.split()[0])
|
|
955
|
+
return opts
|
|
956
|
+
|
|
957
|
+
|
|
958
|
+
syntax_rules += r'''
|
|
959
|
+
<updateStatement> ::= "UPDATE" cf=<columnFamilyName>
|
|
960
|
+
( "USING" [updateopt]=<usingOption>
|
|
961
|
+
( "AND" [updateopt]=<usingOption> )* )?
|
|
962
|
+
"SET" <assignment> ( "," <assignment> )*
|
|
963
|
+
"WHERE" <whereClause>
|
|
964
|
+
( "IF" ( "EXISTS" | <conditions> ))?
|
|
965
|
+
;
|
|
966
|
+
<assignment> ::= updatecol=<cident>
|
|
967
|
+
(( "=" update_rhs=( <term> | <cident> )
|
|
968
|
+
( counterop=( "+" | "-" ) inc=<wholenumber>
|
|
969
|
+
| listadder="+" listcol=<cident> )? )
|
|
970
|
+
| ( indexbracket="[" <term> "]" "=" <term> )
|
|
971
|
+
| ( udt_field_dot="." udt_field=<identifier> "=" <term> ))
|
|
972
|
+
;
|
|
973
|
+
<conditions> ::= <condition> ( "AND" <condition> )*
|
|
974
|
+
;
|
|
975
|
+
<condition_op_and_rhs> ::= (("=" | "<" | ">" | "<=" | ">=" | "!=" | "CONTAINS" ( "KEY" )? ) <term>)
|
|
976
|
+
| ("IN" "(" <term> ( "," <term> )* ")" )
|
|
977
|
+
;
|
|
978
|
+
<condition> ::= conditioncol=<cident>
|
|
979
|
+
( (( indexbracket="[" <term> "]" )
|
|
980
|
+
|( udt_field_dot="." udt_field=<identifier> )) )?
|
|
981
|
+
<condition_op_and_rhs>
|
|
982
|
+
;
|
|
983
|
+
'''
|
|
984
|
+
|
|
985
|
+
|
|
986
|
+
@completer_for('updateStatement', 'updateopt')
|
|
987
|
+
def update_option_completer(ctxt, cass):
|
|
988
|
+
opts = set('TIMESTAMP TTL'.split())
|
|
989
|
+
for opt in ctxt.get_binding('updateopt', ()):
|
|
990
|
+
opts.discard(opt.split()[0])
|
|
991
|
+
return opts
|
|
992
|
+
|
|
993
|
+
|
|
994
|
+
@completer_for('assignment', 'updatecol')
|
|
995
|
+
def update_col_completer(ctxt, cass):
|
|
996
|
+
layout = get_table_meta(ctxt, cass)
|
|
997
|
+
return list(map(maybe_escape_name, regular_column_names(layout)))
|
|
998
|
+
|
|
999
|
+
|
|
1000
|
+
@completer_for('assignment', 'update_rhs')
|
|
1001
|
+
def update_countername_completer(ctxt, cass):
|
|
1002
|
+
layout = get_table_meta(ctxt, cass)
|
|
1003
|
+
curcol = dequote_name(ctxt.get_binding('updatecol', ''))
|
|
1004
|
+
coltype = layout.columns[curcol].cql_type
|
|
1005
|
+
if coltype == 'counter':
|
|
1006
|
+
return [maybe_escape_name(curcol)]
|
|
1007
|
+
if coltype in ('map', 'set'):
|
|
1008
|
+
return ["{"]
|
|
1009
|
+
if coltype == 'list':
|
|
1010
|
+
return ["["]
|
|
1011
|
+
return [Hint('<term (%s)>' % coltype)]
|
|
1012
|
+
|
|
1013
|
+
|
|
1014
|
+
@completer_for('assignment', 'counterop')
|
|
1015
|
+
def update_counterop_completer(ctxt, cass):
|
|
1016
|
+
layout = get_table_meta(ctxt, cass)
|
|
1017
|
+
curcol = dequote_name(ctxt.get_binding('updatecol', ''))
|
|
1018
|
+
return ['+', '-'] if layout.columns[curcol].cql_type == 'counter' else []
|
|
1019
|
+
|
|
1020
|
+
|
|
1021
|
+
@completer_for('assignment', 'inc')
|
|
1022
|
+
def update_counter_inc_completer(ctxt, cass):
|
|
1023
|
+
layout = get_table_meta(ctxt, cass)
|
|
1024
|
+
curcol = dequote_name(ctxt.get_binding('updatecol', ''))
|
|
1025
|
+
if layout.columns[curcol].cql_type == 'counter':
|
|
1026
|
+
return [Hint('<wholenumber>')]
|
|
1027
|
+
return []
|
|
1028
|
+
|
|
1029
|
+
|
|
1030
|
+
@completer_for('assignment', 'listadder')
|
|
1031
|
+
def update_listadder_completer(ctxt, cass):
|
|
1032
|
+
rhs = ctxt.get_binding('update_rhs')
|
|
1033
|
+
if rhs.startswith('['):
|
|
1034
|
+
return ['+']
|
|
1035
|
+
return []
|
|
1036
|
+
|
|
1037
|
+
|
|
1038
|
+
@completer_for('assignment', 'listcol')
|
|
1039
|
+
def update_listcol_completer(ctxt, cass):
|
|
1040
|
+
rhs = ctxt.get_binding('update_rhs')
|
|
1041
|
+
if rhs.startswith('['):
|
|
1042
|
+
colname = dequote_name(ctxt.get_binding('updatecol'))
|
|
1043
|
+
return [maybe_escape_name(colname)]
|
|
1044
|
+
return []
|
|
1045
|
+
|
|
1046
|
+
|
|
1047
|
+
@completer_for('assignment', 'indexbracket')
|
|
1048
|
+
def update_indexbracket_completer(ctxt, cass):
|
|
1049
|
+
layout = get_table_meta(ctxt, cass)
|
|
1050
|
+
curcol = dequote_name(ctxt.get_binding('updatecol', ''))
|
|
1051
|
+
coltype = layout.columns[curcol].cql_type
|
|
1052
|
+
if coltype in ('map', 'list'):
|
|
1053
|
+
return ['[']
|
|
1054
|
+
return []
|
|
1055
|
+
|
|
1056
|
+
|
|
1057
|
+
@completer_for('assignment', 'udt_field_dot')
|
|
1058
|
+
def update_udt_field_dot_completer(ctxt, cass):
|
|
1059
|
+
layout = get_table_meta(ctxt, cass)
|
|
1060
|
+
curcol = dequote_name(ctxt.get_binding('updatecol', ''))
|
|
1061
|
+
return ["."] if _is_usertype(layout, curcol) else []
|
|
1062
|
+
|
|
1063
|
+
|
|
1064
|
+
@completer_for('assignment', 'udt_field')
|
|
1065
|
+
def assignment_udt_field_completer(ctxt, cass):
|
|
1066
|
+
layout = get_table_meta(ctxt, cass)
|
|
1067
|
+
curcol = dequote_name(ctxt.get_binding('updatecol', ''))
|
|
1068
|
+
return _usertype_fields(ctxt, cass, layout, curcol)
|
|
1069
|
+
|
|
1070
|
+
|
|
1071
|
+
def _is_usertype(layout, curcol):
|
|
1072
|
+
coltype = layout.columns[curcol].cql_type
|
|
1073
|
+
return coltype not in simple_cql_types and coltype not in ('map', 'set', 'list')
|
|
1074
|
+
|
|
1075
|
+
|
|
1076
|
+
def _usertype_fields(ctxt, cass, layout, curcol):
|
|
1077
|
+
if not _is_usertype(layout, curcol):
|
|
1078
|
+
return []
|
|
1079
|
+
|
|
1080
|
+
coltype = layout.columns[curcol].cql_type
|
|
1081
|
+
ks = ctxt.get_binding('ksname', None)
|
|
1082
|
+
if ks is not None:
|
|
1083
|
+
ks = dequote_name(ks)
|
|
1084
|
+
user_type = cass.get_usertype_layout(ks, coltype)
|
|
1085
|
+
return [field_name for (field_name, field_type) in user_type]
|
|
1086
|
+
|
|
1087
|
+
|
|
1088
|
+
@completer_for('condition', 'indexbracket')
|
|
1089
|
+
def condition_indexbracket_completer(ctxt, cass):
|
|
1090
|
+
layout = get_table_meta(ctxt, cass)
|
|
1091
|
+
curcol = dequote_name(ctxt.get_binding('conditioncol', ''))
|
|
1092
|
+
coltype = layout.columns[curcol].cql_type
|
|
1093
|
+
if coltype in ('map', 'list'):
|
|
1094
|
+
return ['[']
|
|
1095
|
+
return []
|
|
1096
|
+
|
|
1097
|
+
|
|
1098
|
+
@completer_for('condition', 'udt_field_dot')
|
|
1099
|
+
def condition_udt_field_dot_completer(ctxt, cass):
|
|
1100
|
+
layout = get_table_meta(ctxt, cass)
|
|
1101
|
+
curcol = dequote_name(ctxt.get_binding('conditioncol', ''))
|
|
1102
|
+
return ["."] if _is_usertype(layout, curcol) else []
|
|
1103
|
+
|
|
1104
|
+
|
|
1105
|
+
@completer_for('condition', 'udt_field')
|
|
1106
|
+
def condition_udt_field_completer(ctxt, cass):
|
|
1107
|
+
layout = get_table_meta(ctxt, cass)
|
|
1108
|
+
curcol = dequote_name(ctxt.get_binding('conditioncol', ''))
|
|
1109
|
+
return _usertype_fields(ctxt, cass, layout, curcol)
|
|
1110
|
+
|
|
1111
|
+
|
|
1112
|
+
syntax_rules += r'''
|
|
1113
|
+
<deleteStatement> ::= "DELETE" ( <deleteSelector> ( "," <deleteSelector> )* )?
|
|
1114
|
+
"FROM" cf=<columnFamilyName>
|
|
1115
|
+
( "USING" [delopt]=<deleteOption> )?
|
|
1116
|
+
"WHERE" <whereClause>
|
|
1117
|
+
( "IF" ( "EXISTS" | <conditions> ) )?
|
|
1118
|
+
;
|
|
1119
|
+
<deleteSelector> ::= delcol=<cident>
|
|
1120
|
+
( ( "[" <term> "]" )
|
|
1121
|
+
| ( "." <identifier> ) )?
|
|
1122
|
+
;
|
|
1123
|
+
<deleteOption> ::= "TIMESTAMP" <wholenumber>
|
|
1124
|
+
;
|
|
1125
|
+
'''
|
|
1126
|
+
|
|
1127
|
+
|
|
1128
|
+
@completer_for('deleteStatement', 'delopt')
|
|
1129
|
+
def delete_opt_completer(ctxt, cass):
|
|
1130
|
+
opts = set('TIMESTAMP'.split())
|
|
1131
|
+
for opt in ctxt.get_binding('delopt', ()):
|
|
1132
|
+
opts.discard(opt.split()[0])
|
|
1133
|
+
return opts
|
|
1134
|
+
|
|
1135
|
+
|
|
1136
|
+
@completer_for('deleteSelector', 'delcol')
|
|
1137
|
+
def delete_delcol_completer(ctxt, cass):
|
|
1138
|
+
layout = get_table_meta(ctxt, cass)
|
|
1139
|
+
return list(map(maybe_escape_name, regular_column_names(layout)))
|
|
1140
|
+
|
|
1141
|
+
|
|
1142
|
+
syntax_rules += r'''
|
|
1143
|
+
<batchStatement> ::= "BEGIN" ( "UNLOGGED" | "COUNTER" )? "BATCH"
|
|
1144
|
+
( "USING" [batchopt]=<usingOption>
|
|
1145
|
+
( "AND" [batchopt]=<usingOption> )* )?
|
|
1146
|
+
[batchstmt]=<batchStatementMember> ";"?
|
|
1147
|
+
( [batchstmt]=<batchStatementMember> ";"? )*
|
|
1148
|
+
"APPLY" "BATCH"
|
|
1149
|
+
;
|
|
1150
|
+
<batchStatementMember> ::= <insertStatement>
|
|
1151
|
+
| <updateStatement>
|
|
1152
|
+
| <deleteStatement>
|
|
1153
|
+
;
|
|
1154
|
+
'''
|
|
1155
|
+
|
|
1156
|
+
|
|
1157
|
+
@completer_for('batchStatement', 'batchopt')
|
|
1158
|
+
def batch_opt_completer(ctxt, cass):
|
|
1159
|
+
opts = set('TIMESTAMP'.split())
|
|
1160
|
+
for opt in ctxt.get_binding('batchopt', ()):
|
|
1161
|
+
opts.discard(opt.split()[0])
|
|
1162
|
+
return opts
|
|
1163
|
+
|
|
1164
|
+
|
|
1165
|
+
syntax_rules += r'''
|
|
1166
|
+
<truncateStatement> ::= "TRUNCATE" ("COLUMNFAMILY" | "TABLE")? cf=<columnFamilyName>
|
|
1167
|
+
;
|
|
1168
|
+
'''
|
|
1169
|
+
|
|
1170
|
+
syntax_rules += r'''
|
|
1171
|
+
<createKeyspaceStatement> ::= "CREATE" wat=( "KEYSPACE" | "SCHEMA" ) ("IF" "NOT" "EXISTS")? ksname=<cfOrKsName>
|
|
1172
|
+
"WITH" <property> ( "AND" <property> )*
|
|
1173
|
+
;
|
|
1174
|
+
'''
|
|
1175
|
+
|
|
1176
|
+
|
|
1177
|
+
@completer_for('createKeyspaceStatement', 'wat')
|
|
1178
|
+
def create_ks_wat_completer(ctxt, cass):
|
|
1179
|
+
# would prefer to get rid of the "schema" nomenclature in cql3
|
|
1180
|
+
if ctxt.get_binding('partial', '') == '':
|
|
1181
|
+
return ['KEYSPACE']
|
|
1182
|
+
return ['KEYSPACE', 'SCHEMA']
|
|
1183
|
+
|
|
1184
|
+
|
|
1185
|
+
syntax_rules += r'''
|
|
1186
|
+
<createColumnFamilyStatement> ::= "CREATE" wat=( "COLUMNFAMILY" | "TABLE" ) ("IF" "NOT" "EXISTS")?
|
|
1187
|
+
( ks=<nonSystemKeyspaceName> dot="." )? cf=<cfOrKsName>
|
|
1188
|
+
"(" ( <singleKeyCfSpec> | <compositeKeyCfSpec> ) ")"
|
|
1189
|
+
( "WITH" <cfamProperty> ( "AND" <cfamProperty> )* )?
|
|
1190
|
+
;
|
|
1191
|
+
|
|
1192
|
+
<cfamProperty> ::= <property>
|
|
1193
|
+
| "COMPACT" "STORAGE" "CDC"
|
|
1194
|
+
| "CLUSTERING" "ORDER" "BY" "(" <cfamOrdering>
|
|
1195
|
+
( "," <cfamOrdering> )* ")"
|
|
1196
|
+
;
|
|
1197
|
+
|
|
1198
|
+
<cfamOrdering> ::= [ordercol]=<cident> ( "ASC" | "DESC" )
|
|
1199
|
+
;
|
|
1200
|
+
|
|
1201
|
+
<singleKeyCfSpec> ::= [newcolname]=<cident> <storageType> "PRIMARY" "KEY"
|
|
1202
|
+
( "," [newcolname]=<cident> <storageType> )*
|
|
1203
|
+
;
|
|
1204
|
+
|
|
1205
|
+
<compositeKeyCfSpec> ::= [newcolname]=<cident> <storageType>
|
|
1206
|
+
"," [newcolname]=<cident> <storageType> ( "static" )?
|
|
1207
|
+
( "," [newcolname]=<cident> <storageType> ( "static" )? )*
|
|
1208
|
+
"," "PRIMARY" k="KEY" p="(" ( partkey=<pkDef> | [pkey]=<cident> )
|
|
1209
|
+
( c="," [pkey]=<cident> )* ")"
|
|
1210
|
+
;
|
|
1211
|
+
|
|
1212
|
+
<pkDef> ::= "(" [ptkey]=<cident> "," [ptkey]=<cident>
|
|
1213
|
+
( "," [ptkey]=<cident> )* ")"
|
|
1214
|
+
;
|
|
1215
|
+
'''
|
|
1216
|
+
|
|
1217
|
+
|
|
1218
|
+
@completer_for('cfamOrdering', 'ordercol')
|
|
1219
|
+
def create_cf_clustering_order_colname_completer(ctxt, cass):
|
|
1220
|
+
colnames = list(map(dequote_name, ctxt.get_binding('newcolname', ())))
|
|
1221
|
+
# Definitely some of these aren't valid for ordering, but I'm not sure
|
|
1222
|
+
# precisely which are. This is good enough for now
|
|
1223
|
+
return colnames
|
|
1224
|
+
|
|
1225
|
+
|
|
1226
|
+
@completer_for('createColumnFamilyStatement', 'wat')
|
|
1227
|
+
def create_cf_wat_completer(ctxt, cass):
|
|
1228
|
+
# would prefer to get rid of the "columnfamily" nomenclature in cql3
|
|
1229
|
+
if ctxt.get_binding('partial', '') == '':
|
|
1230
|
+
return ['TABLE']
|
|
1231
|
+
return ['TABLE', 'COLUMNFAMILY']
|
|
1232
|
+
|
|
1233
|
+
|
|
1234
|
+
explain_completion('createColumnFamilyStatement', 'cf', '<new_table_name>')
|
|
1235
|
+
explain_completion('compositeKeyCfSpec', 'newcolname', '<new_column_name>')
|
|
1236
|
+
|
|
1237
|
+
|
|
1238
|
+
@completer_for('createColumnFamilyStatement', 'dot')
|
|
1239
|
+
def create_cf_ks_dot_completer(ctxt, cass):
|
|
1240
|
+
ks = dequote_name(ctxt.get_binding('ks'))
|
|
1241
|
+
if ks in cass.get_keyspace_names():
|
|
1242
|
+
return ['.']
|
|
1243
|
+
return []
|
|
1244
|
+
|
|
1245
|
+
|
|
1246
|
+
@completer_for('pkDef', 'ptkey')
|
|
1247
|
+
def create_cf_pkdef_declaration_completer(ctxt, cass):
|
|
1248
|
+
cols_declared = ctxt.get_binding('newcolname')
|
|
1249
|
+
pieces_already = ctxt.get_binding('ptkey', ())
|
|
1250
|
+
pieces_already = list(map(dequote_name, pieces_already))
|
|
1251
|
+
while cols_declared[0] in pieces_already:
|
|
1252
|
+
cols_declared = cols_declared[1:]
|
|
1253
|
+
if len(cols_declared) < 2:
|
|
1254
|
+
return ()
|
|
1255
|
+
return [maybe_escape_name(cols_declared[0])]
|
|
1256
|
+
|
|
1257
|
+
|
|
1258
|
+
@completer_for('compositeKeyCfSpec', 'pkey')
|
|
1259
|
+
def create_cf_composite_key_declaration_completer(ctxt, cass):
|
|
1260
|
+
cols_declared = ctxt.get_binding('newcolname')
|
|
1261
|
+
pieces_already = ctxt.get_binding('ptkey', ()) + ctxt.get_binding('pkey', ())
|
|
1262
|
+
pieces_already = list(map(dequote_name, pieces_already))
|
|
1263
|
+
while cols_declared[0] in pieces_already:
|
|
1264
|
+
cols_declared = cols_declared[1:]
|
|
1265
|
+
if len(cols_declared) < 2:
|
|
1266
|
+
return ()
|
|
1267
|
+
return [maybe_escape_name(cols_declared[0])]
|
|
1268
|
+
|
|
1269
|
+
|
|
1270
|
+
@completer_for('compositeKeyCfSpec', 'k')
|
|
1271
|
+
def create_cf_composite_primary_key_keyword_completer(ctxt, cass):
|
|
1272
|
+
return ['KEY (']
|
|
1273
|
+
|
|
1274
|
+
|
|
1275
|
+
@completer_for('compositeKeyCfSpec', 'p')
|
|
1276
|
+
def create_cf_composite_primary_key_paren_completer(ctxt, cass):
|
|
1277
|
+
return ['(']
|
|
1278
|
+
|
|
1279
|
+
|
|
1280
|
+
@completer_for('compositeKeyCfSpec', 'c')
|
|
1281
|
+
def create_cf_composite_primary_key_comma_completer(ctxt, cass):
|
|
1282
|
+
cols_declared = ctxt.get_binding('newcolname')
|
|
1283
|
+
pieces_already = ctxt.get_binding('pkey', ())
|
|
1284
|
+
if len(pieces_already) >= len(cols_declared) - 1:
|
|
1285
|
+
return ()
|
|
1286
|
+
return [',']
|
|
1287
|
+
|
|
1288
|
+
|
|
1289
|
+
syntax_rules += r'''
|
|
1290
|
+
|
|
1291
|
+
<idxName> ::= <identifier>
|
|
1292
|
+
| <quotedName>
|
|
1293
|
+
| <unreservedKeyword>;
|
|
1294
|
+
|
|
1295
|
+
<createIndexStatement> ::= "CREATE" "CUSTOM"? "INDEX" ("IF" "NOT" "EXISTS")? indexname=<idxName>? "ON"
|
|
1296
|
+
cf=<columnFamilyName> "(" (
|
|
1297
|
+
col=<cident> |
|
|
1298
|
+
"keys(" col=<cident> ")" |
|
|
1299
|
+
"full(" col=<cident> ")"
|
|
1300
|
+
) ")"
|
|
1301
|
+
( "USING" <stringLiteral> ( "WITH" "OPTIONS" "=" <mapLiteral> )? )?
|
|
1302
|
+
;
|
|
1303
|
+
|
|
1304
|
+
<createMaterializedViewStatement> ::= "CREATE" "MATERIALIZED" "VIEW" ("IF" "NOT" "EXISTS")? <materializedViewName>?
|
|
1305
|
+
"AS" <selectStatement>
|
|
1306
|
+
"PRIMARY" "KEY" <pkDef>
|
|
1307
|
+
;
|
|
1308
|
+
|
|
1309
|
+
<createUserTypeStatement> ::= "CREATE" "TYPE" ( ks=<nonSystemKeyspaceName> dot="." )? typename=<cfOrKsName> "(" newcol=<cident> <storageType>
|
|
1310
|
+
( "," [newcolname]=<cident> <storageType> )*
|
|
1311
|
+
")"
|
|
1312
|
+
;
|
|
1313
|
+
|
|
1314
|
+
<createFunctionStatement> ::= "CREATE" ("OR" "REPLACE")? "FUNCTION"
|
|
1315
|
+
("IF" "NOT" "EXISTS")?
|
|
1316
|
+
<userFunctionName>
|
|
1317
|
+
( "(" ( newcol=<cident> <storageType>
|
|
1318
|
+
( "," [newcolname]=<cident> <storageType> )* )?
|
|
1319
|
+
")" )?
|
|
1320
|
+
("RETURNS" "NULL" | "CALLED") "ON" "NULL" "INPUT"
|
|
1321
|
+
"RETURNS" <storageType>
|
|
1322
|
+
"LANGUAGE" <cident> "AS" <stringLiteral>
|
|
1323
|
+
;
|
|
1324
|
+
|
|
1325
|
+
<createAggregateStatement> ::= "CREATE" ("OR" "REPLACE")? "AGGREGATE"
|
|
1326
|
+
("IF" "NOT" "EXISTS")?
|
|
1327
|
+
<userAggregateName>
|
|
1328
|
+
( "("
|
|
1329
|
+
( <storageType> ( "," <storageType> )* )?
|
|
1330
|
+
")" )?
|
|
1331
|
+
"SFUNC" <refUserFunctionName>
|
|
1332
|
+
"STYPE" <storageType>
|
|
1333
|
+
( "FINALFUNC" <refUserFunctionName> )?
|
|
1334
|
+
( "INITCOND" <term> )?
|
|
1335
|
+
;
|
|
1336
|
+
|
|
1337
|
+
'''
|
|
1338
|
+
|
|
1339
|
+
explain_completion('createIndexStatement', 'indexname', '<new_index_name>')
|
|
1340
|
+
explain_completion('createUserTypeStatement', 'typename', '<new_type_name>')
|
|
1341
|
+
explain_completion('createUserTypeStatement', 'newcol', '<new_field_name>')
|
|
1342
|
+
|
|
1343
|
+
|
|
1344
|
+
@completer_for('createIndexStatement', 'col')
|
|
1345
|
+
def create_index_col_completer(ctxt, cass):
|
|
1346
|
+
""" Return the columns for which an index doesn't exist yet. """
|
|
1347
|
+
layout = get_table_meta(ctxt, cass)
|
|
1348
|
+
idx_targets = [idx.index_options["target"] for idx in layout.indexes.values()]
|
|
1349
|
+
colnames = [cd.name for cd in list(layout.columns.values()) if cd.name not in idx_targets]
|
|
1350
|
+
return list(map(maybe_escape_name, colnames))
|
|
1351
|
+
|
|
1352
|
+
|
|
1353
|
+
syntax_rules += r'''
|
|
1354
|
+
<dropKeyspaceStatement> ::= "DROP" "KEYSPACE" ("IF" "EXISTS")? ksname=<nonSystemKeyspaceName>
|
|
1355
|
+
;
|
|
1356
|
+
|
|
1357
|
+
<dropColumnFamilyStatement> ::= "DROP" ( "COLUMNFAMILY" | "TABLE" ) ("IF" "EXISTS")? cf=<columnFamilyName>
|
|
1358
|
+
;
|
|
1359
|
+
|
|
1360
|
+
<indexName> ::= ( ksname=<idxOrKsName> dot="." )? idxname=<idxOrKsName> ;
|
|
1361
|
+
|
|
1362
|
+
<idxOrKsName> ::= <identifier>
|
|
1363
|
+
| <quotedName>
|
|
1364
|
+
| <unreservedKeyword>;
|
|
1365
|
+
|
|
1366
|
+
<dropIndexStatement> ::= "DROP" "INDEX" ("IF" "EXISTS")? idx=<indexName>
|
|
1367
|
+
;
|
|
1368
|
+
|
|
1369
|
+
<dropMaterializedViewStatement> ::= "DROP" "MATERIALIZED" "VIEW" ("IF" "EXISTS")? mv=<materializedViewName>
|
|
1370
|
+
;
|
|
1371
|
+
|
|
1372
|
+
<dropUserTypeStatement> ::= "DROP" "TYPE" ut=<userTypeName>
|
|
1373
|
+
;
|
|
1374
|
+
|
|
1375
|
+
<dropFunctionStatement> ::= "DROP" "FUNCTION" ( "IF" "EXISTS" )? <userFunctionName>
|
|
1376
|
+
;
|
|
1377
|
+
|
|
1378
|
+
<dropAggregateStatement> ::= "DROP" "AGGREGATE" ( "IF" "EXISTS" )? <userAggregateName>
|
|
1379
|
+
;
|
|
1380
|
+
|
|
1381
|
+
'''
|
|
1382
|
+
|
|
1383
|
+
|
|
1384
|
+
@completer_for('indexName', 'ksname')
|
|
1385
|
+
def idx_ks_name_completer(ctxt, cass):
|
|
1386
|
+
return [maybe_escape_name(ks) + '.' for ks in cass.get_keyspace_names()]
|
|
1387
|
+
|
|
1388
|
+
|
|
1389
|
+
@completer_for('indexName', 'dot')
|
|
1390
|
+
def idx_ks_dot_completer(ctxt, cass):
|
|
1391
|
+
name = dequote_name(ctxt.get_binding('ksname'))
|
|
1392
|
+
if name in cass.get_keyspace_names():
|
|
1393
|
+
return ['.']
|
|
1394
|
+
return []
|
|
1395
|
+
|
|
1396
|
+
|
|
1397
|
+
@completer_for('indexName', 'idxname')
|
|
1398
|
+
def idx_ks_idx_name_completer(ctxt, cass):
|
|
1399
|
+
ks = ctxt.get_binding('ksname', None)
|
|
1400
|
+
if ks is not None:
|
|
1401
|
+
ks = dequote_name(ks)
|
|
1402
|
+
try:
|
|
1403
|
+
idxnames = cass.get_index_names(ks)
|
|
1404
|
+
except Exception:
|
|
1405
|
+
if ks is None:
|
|
1406
|
+
return ()
|
|
1407
|
+
raise
|
|
1408
|
+
return list(map(maybe_escape_name, idxnames))
|
|
1409
|
+
|
|
1410
|
+
|
|
1411
|
+
syntax_rules += r'''
|
|
1412
|
+
<alterTableStatement> ::= "ALTER" wat=( "COLUMNFAMILY" | "TABLE" ) ("IF" "EXISTS")? cf=<columnFamilyName>
|
|
1413
|
+
<alterInstructions>
|
|
1414
|
+
;
|
|
1415
|
+
<alterInstructions> ::= "ADD" ("IF" "NOT" "EXISTS")? newcol=<cident> <storageType> ("static")?
|
|
1416
|
+
| "DROP" ("IF" "EXISTS")? existcol=<cident>
|
|
1417
|
+
| "WITH" <cfamProperty> ( "AND" <cfamProperty> )*
|
|
1418
|
+
| "RENAME" ("IF" "EXISTS")? existcol=<cident> "TO" newcol=<cident>
|
|
1419
|
+
( "AND" existcol=<cident> "TO" newcol=<cident> )*
|
|
1420
|
+
;
|
|
1421
|
+
|
|
1422
|
+
<alterUserTypeStatement> ::= "ALTER" "TYPE" ("IF" "EXISTS")? ut=<userTypeName>
|
|
1423
|
+
<alterTypeInstructions>
|
|
1424
|
+
;
|
|
1425
|
+
<alterTypeInstructions> ::= "ADD" ("IF" "NOT" "EXISTS")? newcol=<cident> <storageType>
|
|
1426
|
+
| "RENAME" ("IF" "EXISTS")? existcol=<cident> "TO" newcol=<cident>
|
|
1427
|
+
( "AND" existcol=<cident> "TO" newcol=<cident> )*
|
|
1428
|
+
;
|
|
1429
|
+
'''
|
|
1430
|
+
|
|
1431
|
+
|
|
1432
|
+
@completer_for('alterInstructions', 'existcol')
|
|
1433
|
+
def alter_table_col_completer(ctxt, cass):
|
|
1434
|
+
layout = get_table_meta(ctxt, cass)
|
|
1435
|
+
cols = [str(md) for md in layout.columns]
|
|
1436
|
+
return list(map(maybe_escape_name, cols))
|
|
1437
|
+
|
|
1438
|
+
|
|
1439
|
+
@completer_for('alterTypeInstructions', 'existcol')
|
|
1440
|
+
def alter_type_field_completer(ctxt, cass):
|
|
1441
|
+
layout = get_ut_layout(ctxt, cass)
|
|
1442
|
+
fields = [atuple[0] for atuple in layout]
|
|
1443
|
+
return list(map(maybe_escape_name, fields))
|
|
1444
|
+
|
|
1445
|
+
|
|
1446
|
+
explain_completion('alterInstructions', 'newcol', '<new_column_name>')
|
|
1447
|
+
explain_completion('alterTypeInstructions', 'newcol', '<new_field_name>')
|
|
1448
|
+
|
|
1449
|
+
|
|
1450
|
+
syntax_rules += r'''
|
|
1451
|
+
<alterKeyspaceStatement> ::= "ALTER" wat=( "KEYSPACE" | "SCHEMA" ) ("IF" "EXISTS")? ks=<alterableKeyspaceName>
|
|
1452
|
+
"WITH" <property> ( "AND" <property> )*
|
|
1453
|
+
;
|
|
1454
|
+
'''
|
|
1455
|
+
|
|
1456
|
+
syntax_rules += r'''
|
|
1457
|
+
<username> ::= name=( <identifier> | <stringLiteral> )
|
|
1458
|
+
;
|
|
1459
|
+
|
|
1460
|
+
<createUserStatement> ::= "CREATE" "USER" ( "IF" "NOT" "EXISTS" )? <username>
|
|
1461
|
+
( "WITH" ("HASHED")? "PASSWORD" <stringLiteral> )?
|
|
1462
|
+
( "SUPERUSER" | "NOSUPERUSER" )?
|
|
1463
|
+
;
|
|
1464
|
+
|
|
1465
|
+
<alterUserStatement> ::= "ALTER" "USER" ("IF" "EXISTS")? <username>
|
|
1466
|
+
( "WITH" "PASSWORD" <stringLiteral> )?
|
|
1467
|
+
( "SUPERUSER" | "NOSUPERUSER" )?
|
|
1468
|
+
;
|
|
1469
|
+
|
|
1470
|
+
<dropUserStatement> ::= "DROP" "USER" ( "IF" "EXISTS" )? <username>
|
|
1471
|
+
;
|
|
1472
|
+
|
|
1473
|
+
<listUsersStatement> ::= "LIST" "USERS"
|
|
1474
|
+
;
|
|
1475
|
+
'''
|
|
1476
|
+
|
|
1477
|
+
syntax_rules += r'''
|
|
1478
|
+
<rolename> ::= <identifier>
|
|
1479
|
+
| <quotedName>
|
|
1480
|
+
| <unreservedKeyword>
|
|
1481
|
+
;
|
|
1482
|
+
|
|
1483
|
+
<createRoleStatement> ::= "CREATE" "ROLE" <rolename>
|
|
1484
|
+
( "WITH" <roleProperty> ("AND" <roleProperty>)*)?
|
|
1485
|
+
;
|
|
1486
|
+
|
|
1487
|
+
<alterRoleStatement> ::= "ALTER" "ROLE" ("IF" "EXISTS")? <rolename>
|
|
1488
|
+
( "WITH" <roleProperty> ("AND" <roleProperty>)*)?
|
|
1489
|
+
;
|
|
1490
|
+
|
|
1491
|
+
<roleProperty> ::= (("HASHED")? "PASSWORD") "=" <stringLiteral>
|
|
1492
|
+
| "OPTIONS" "=" <mapLiteral>
|
|
1493
|
+
| "SUPERUSER" "=" <boolean>
|
|
1494
|
+
| "LOGIN" "=" <boolean>
|
|
1495
|
+
| "ACCESS" "TO" "DATACENTERS" <setLiteral>
|
|
1496
|
+
| "ACCESS" "TO" "ALL" "DATACENTERS"
|
|
1497
|
+
;
|
|
1498
|
+
|
|
1499
|
+
<dropRoleStatement> ::= "DROP" "ROLE" <rolename>
|
|
1500
|
+
;
|
|
1501
|
+
|
|
1502
|
+
<grantRoleStatement> ::= "GRANT" <rolename> "TO" <rolename>
|
|
1503
|
+
;
|
|
1504
|
+
|
|
1505
|
+
<revokeRoleStatement> ::= "REVOKE" <rolename> "FROM" <rolename>
|
|
1506
|
+
;
|
|
1507
|
+
|
|
1508
|
+
<listRolesStatement> ::= "LIST" "ROLES"
|
|
1509
|
+
( "OF" <rolename> )? "NORECURSIVE"?
|
|
1510
|
+
;
|
|
1511
|
+
'''
|
|
1512
|
+
|
|
1513
|
+
syntax_rules += r'''
|
|
1514
|
+
<slaName> ::= <identifier>
|
|
1515
|
+
| <quotedName>
|
|
1516
|
+
| <unreservedKeyword>
|
|
1517
|
+
;
|
|
1518
|
+
|
|
1519
|
+
<createSlaStatement> ::= "CREATE" "SERVICE_LEVEL" ( "IF" "NOT" "EXISTS" )? <slaName>
|
|
1520
|
+
( "WITH" <slaProperty> ("AND" <slaProperty>)*)?
|
|
1521
|
+
;
|
|
1522
|
+
|
|
1523
|
+
<alterSlaStatement> ::= "ALTER" "SERVICE_LEVEL" ("IF" "EXISTS")? <slaName>
|
|
1524
|
+
( "WITH" <slaProperty> ("AND" <slaProperty>)*)?
|
|
1525
|
+
;
|
|
1526
|
+
|
|
1527
|
+
<slaProperty> ::= "WORKLOAD_TYPE" "=" <stringLiteral>
|
|
1528
|
+
| "TIMEOUT" "=" <wholenumber>
|
|
1529
|
+
| "SHARES" "=" <wholenumber>
|
|
1530
|
+
;
|
|
1531
|
+
|
|
1532
|
+
<dropSlaStatement> ::= "DROP" "SERVICE_LEVEL" ("IF" "EXISTS")? <slaName>
|
|
1533
|
+
;
|
|
1534
|
+
|
|
1535
|
+
<listSlaStatement> ::= ("LIST" "SERVICE_LEVEL" <slaName> )
|
|
1536
|
+
| ("LIST" "ATTACHED" "SERVICE_LEVEL" "OF" <rolename> )
|
|
1537
|
+
| ("LIST" "ALL" "SERVICE_LEVELS" )
|
|
1538
|
+
| ("LIST" "ALL" "ATTACHED" "SERVICE_LEVELS" )
|
|
1539
|
+
;
|
|
1540
|
+
|
|
1541
|
+
<attachSlaStatement> ::= "ATTACH" "SERVICE_LEVEL" <slaName> "TO" <rolename>
|
|
1542
|
+
;
|
|
1543
|
+
|
|
1544
|
+
<detachRSlaStatement> ::= "DETACH" "SERVICE_LEVEL" <slaName> "FROM" <rolename>
|
|
1545
|
+
;
|
|
1546
|
+
'''
|
|
1547
|
+
|
|
1548
|
+
syntax_rules += r'''
|
|
1549
|
+
<grantStatement> ::= "GRANT" <permissionExpr> "ON" <resource> "TO" <rolename>
|
|
1550
|
+
;
|
|
1551
|
+
|
|
1552
|
+
<revokeStatement> ::= "REVOKE" <permissionExpr> "ON" <resource> "FROM" <rolename>
|
|
1553
|
+
;
|
|
1554
|
+
|
|
1555
|
+
<listPermissionsStatement> ::= "LIST" <permissionExpr>
|
|
1556
|
+
( "ON" <resource> )? ( "OF" <rolename> )? "NORECURSIVE"?
|
|
1557
|
+
;
|
|
1558
|
+
|
|
1559
|
+
<permission> ::= "AUTHORIZE"
|
|
1560
|
+
| "CREATE"
|
|
1561
|
+
| "ALTER"
|
|
1562
|
+
| "DROP"
|
|
1563
|
+
| "SELECT"
|
|
1564
|
+
| "MODIFY"
|
|
1565
|
+
| "DESCRIBE"
|
|
1566
|
+
| "EXECUTE"
|
|
1567
|
+
;
|
|
1568
|
+
|
|
1569
|
+
<permissionExpr> ::= ( [newpermission]=<permission> "PERMISSION"? ( "," [newpermission]=<permission> "PERMISSION"? )* )
|
|
1570
|
+
| ( "ALL" "PERMISSIONS"? )
|
|
1571
|
+
;
|
|
1572
|
+
|
|
1573
|
+
<resource> ::= <dataResource>
|
|
1574
|
+
| <roleResource>
|
|
1575
|
+
| <functionResource>
|
|
1576
|
+
| <jmxResource>
|
|
1577
|
+
;
|
|
1578
|
+
|
|
1579
|
+
<dataResource> ::= ( "ALL" "KEYSPACES" )
|
|
1580
|
+
| ( "KEYSPACE" <keyspaceName> )
|
|
1581
|
+
| ( "ALL" "TABLES" "IN" "KEYSPACE" <keyspaceName> )
|
|
1582
|
+
| ( "TABLE"? <columnFamilyName> )
|
|
1583
|
+
;
|
|
1584
|
+
|
|
1585
|
+
<roleResource> ::= ("ALL" "ROLES")
|
|
1586
|
+
| ("ROLE" <rolename>)
|
|
1587
|
+
;
|
|
1588
|
+
|
|
1589
|
+
<functionResource> ::= ( "ALL" "FUNCTIONS" ("IN KEYSPACE" <keyspaceName>)? )
|
|
1590
|
+
| ( "FUNCTION" <functionAggregateName>
|
|
1591
|
+
( "(" ( newcol=<cident> <storageType>
|
|
1592
|
+
( "," [newcolname]=<cident> <storageType> )* )?
|
|
1593
|
+
")" )
|
|
1594
|
+
)
|
|
1595
|
+
;
|
|
1596
|
+
|
|
1597
|
+
<jmxResource> ::= ( "ALL" "MBEANS")
|
|
1598
|
+
| ( ( "MBEAN" | "MBEANS" ) <stringLiteral> )
|
|
1599
|
+
;
|
|
1600
|
+
|
|
1601
|
+
'''
|
|
1602
|
+
|
|
1603
|
+
|
|
1604
|
+
@completer_for('permissionExpr', 'newpermission')
|
|
1605
|
+
def permission_completer(ctxt, _):
|
|
1606
|
+
new_permissions = set([permission.upper() for permission in ctxt.get_binding('newpermission')])
|
|
1607
|
+
all_permissions = set([permission.arg for permission in ctxt.ruleset['permission'].arg])
|
|
1608
|
+
suggestions = all_permissions - new_permissions
|
|
1609
|
+
if len(suggestions) == 0:
|
|
1610
|
+
return [Hint('No more permissions here.')]
|
|
1611
|
+
return suggestions
|
|
1612
|
+
|
|
1613
|
+
|
|
1614
|
+
@completer_for('username', 'name')
|
|
1615
|
+
def username_name_completer(ctxt, cass):
|
|
1616
|
+
def maybe_quote(name):
|
|
1617
|
+
if CqlRuleSet.is_valid_cql3_name(name):
|
|
1618
|
+
return name
|
|
1619
|
+
return "'%s'" % name
|
|
1620
|
+
|
|
1621
|
+
# disable completion for CREATE USER.
|
|
1622
|
+
if ctxt.matched[0][1].upper() == 'CREATE':
|
|
1623
|
+
return [Hint('<username>')]
|
|
1624
|
+
|
|
1625
|
+
session = cass.session
|
|
1626
|
+
return [maybe_quote(list(row.values())[0].replace("'", "''")) for row in session.execute("LIST USERS")]
|
|
1627
|
+
|
|
1628
|
+
|
|
1629
|
+
@completer_for('rolename', 'role')
|
|
1630
|
+
def rolename_completer(ctxt, cass):
|
|
1631
|
+
def maybe_quote(name):
|
|
1632
|
+
if CqlRuleSet.is_valid_cql3_name(name):
|
|
1633
|
+
return name
|
|
1634
|
+
return "'%s'" % name
|
|
1635
|
+
|
|
1636
|
+
# disable completion for CREATE ROLE.
|
|
1637
|
+
if ctxt.matched[0][1].upper() == 'CREATE':
|
|
1638
|
+
return [Hint('<rolename>')]
|
|
1639
|
+
|
|
1640
|
+
session = cass.session
|
|
1641
|
+
return [maybe_quote(row[0].replace("'", "''")) for row in session.execute("LIST ROLES")]
|
|
1642
|
+
|
|
1643
|
+
|
|
1644
|
+
syntax_rules += r'''
|
|
1645
|
+
<createTriggerStatement> ::= "CREATE" "TRIGGER" ( "IF" "NOT" "EXISTS" )? <cident>
|
|
1646
|
+
"ON" cf=<columnFamilyName> "USING" class=<stringLiteral>
|
|
1647
|
+
;
|
|
1648
|
+
<dropTriggerStatement> ::= "DROP" "TRIGGER" ( "IF" "EXISTS" )? triggername=<cident>
|
|
1649
|
+
"ON" cf=<columnFamilyName>
|
|
1650
|
+
;
|
|
1651
|
+
'''
|
|
1652
|
+
explain_completion('createTriggerStatement', 'class', '\'fully qualified class name\'')
|
|
1653
|
+
|
|
1654
|
+
|
|
1655
|
+
def get_trigger_names(ctxt, cass):
|
|
1656
|
+
ks = ctxt.get_binding('ksname', None)
|
|
1657
|
+
if ks is not None:
|
|
1658
|
+
ks = dequote_name(ks)
|
|
1659
|
+
return cass.get_trigger_names(ks)
|
|
1660
|
+
|
|
1661
|
+
|
|
1662
|
+
@completer_for('dropTriggerStatement', 'triggername')
|
|
1663
|
+
def drop_trigger_completer(ctxt, cass):
|
|
1664
|
+
names = get_trigger_names(ctxt, cass)
|
|
1665
|
+
return list(map(maybe_escape_name, names))
|
|
1666
|
+
|
|
1667
|
+
|
|
1668
|
+
# END SYNTAX/COMPLETION RULE DEFINITIONS
|
|
1669
|
+
|
|
1670
|
+
CqlRuleSet.append_rules(syntax_rules)
|