(token, stmt)
| 292 | |
| 293 | |
| 294 | def suggest_based_on_last_token(token, stmt): |
| 295 | |
| 296 | if isinstance(token, string_types): |
| 297 | token_v = token.lower() |
| 298 | elif isinstance(token, Comparison): |
| 299 | # If 'token' is a Comparison type such as |
| 300 | # 'select * FROM abc a JOIN def d ON a.id = d.'. Then calling |
| 301 | # token.value on the comparison type will only return the lhs of the |
| 302 | # comparison. In this case a.id. So we need to do token.tokens to get |
| 303 | # both sides of the comparison and pick the last token out of that |
| 304 | # list. |
| 305 | token_v = token.tokens[-1].value.lower() |
| 306 | elif isinstance(token, Where): |
| 307 | # sqlparse groups all tokens from the where clause into a single token |
| 308 | # list. This means that token.value may be something like |
| 309 | # 'where foo > 5 and '. We need to look "inside" token.tokens to handle |
| 310 | # suggestions in complicated where clauses correctly |
| 311 | prev_keyword = stmt.reduce_to_prev_keyword() |
| 312 | return suggest_based_on_last_token(prev_keyword, stmt) |
| 313 | elif isinstance(token, Identifier): |
| 314 | # If the previous token is an identifier, we can suggest datatypes if |
| 315 | # we're in a parenthesized column/field list, e.g.: |
| 316 | # CREATE TABLE foo (Identifier <CURSOR> |
| 317 | # CREATE FUNCTION foo (Identifier <CURSOR> |
| 318 | # If we're not in a parenthesized list, the most likely scenario is the |
| 319 | # user is about to specify an alias, e.g.: |
| 320 | # SELECT Identifier <CURSOR> |
| 321 | # SELECT foo FROM Identifier <CURSOR> |
| 322 | prev_keyword, _ = find_prev_keyword(stmt.text_before_cursor) |
| 323 | if prev_keyword and prev_keyword.value == '(': |
| 324 | # Suggest datatypes |
| 325 | return suggest_based_on_last_token('type', stmt) |
| 326 | return (Keyword(),) |
| 327 | else: |
| 328 | token_v = token.value.lower() |
| 329 | |
| 330 | if not token: |
| 331 | return (Keyword(), Special()) |
| 332 | if token_v.endswith('('): |
| 333 | p = sqlparse.parse(stmt.text_before_cursor)[0] |
| 334 | |
| 335 | if p.tokens and isinstance(p.tokens[-1], Where): |
| 336 | # Four possibilities: |
| 337 | # 1 - Parenthesized clause like "WHERE foo AND (" |
| 338 | # Suggest columns/functions |
| 339 | # 2 - Function call like "WHERE foo(" |
| 340 | # Suggest columns/functions |
| 341 | # 3 - Subquery expression like "WHERE EXISTS (" |
| 342 | # Suggest keywords, in order to do a subquery |
| 343 | # 4 - Subquery OR array comparison like "WHERE foo = ANY(" |
| 344 | # Suggest columns/functions AND keywords. (If we wanted to be |
| 345 | # really fancy, we could suggest only array-typed columns) |
| 346 | |
| 347 | column_suggestions = suggest_based_on_last_token('where', stmt) |
| 348 | |
| 349 | # Check for a subquery expression (cases 3 & 4) |
| 350 | where = p.tokens[-1] |
| 351 | prev_tok = where.token_prev(len(where.tokens) - 1)[1] |
no test coverage detected