| 152 | |
| 153 | |
| 154 | def _emit_lparen(ctx: SuggestContext) -> list[Suggestion]: |
| 155 | if ctx.parsed_cb().tokens and isinstance(ctx.parsed_cb().tokens[-1], Where): |
| 156 | # Four possibilities: |
| 157 | # 1 - Parenthesized clause like "WHERE foo AND (" |
| 158 | # Suggest columns/functions |
| 159 | # 2 - Function call like "WHERE foo(" |
| 160 | # Suggest columns/functions |
| 161 | # 3 - Subquery expression like "WHERE EXISTS (" |
| 162 | # Suggest keywords, in order to do a subquery |
| 163 | # 4 - Subquery OR array comparison like "WHERE foo = ANY(" |
| 164 | # Suggest columns/functions AND keywords. (If we wanted to be |
| 165 | # really fancy, we could suggest only array-typed columns) |
| 166 | |
| 167 | # override a few properties in the SuggestContext |
| 168 | column_suggestions = _emit_select_like( |
| 169 | SuggestContext( |
| 170 | token='where', |
| 171 | token_value='where', |
| 172 | text_before_cursor=ctx.text_before_cursor, |
| 173 | word_before_cursor=None, |
| 174 | full_text=ctx.full_text, |
| 175 | identifier=ctx.identifier, |
| 176 | parsed_cb=ctx.parsed_cb, |
| 177 | tokens_wo_space_cb=ctx.tokens_wo_space_cb, |
| 178 | ) |
| 179 | ) |
| 180 | |
| 181 | # Check for a subquery expression (cases 3 & 4) |
| 182 | where = ctx.parsed_cb().tokens[-1] |
| 183 | _idx, prev_tok = where.token_prev(len(where.tokens) - 1) |
| 184 | |
| 185 | if isinstance(prev_tok, Comparison): |
| 186 | # e.g. "SELECT foo FROM bar WHERE foo = ANY(" |
| 187 | prev_tok = prev_tok.tokens[-1] |
| 188 | |
| 189 | prev_tok = prev_tok.value.lower() |
| 190 | if prev_tok == 'exists': |
| 191 | return _keyword_suggestions() |
| 192 | return column_suggestions |
| 193 | |
| 194 | # Get the token before the parens |
| 195 | _idx, prev_tok = ctx.parsed_cb().token_prev(len(ctx.parsed_cb().tokens) - 1) |
| 196 | if prev_tok and prev_tok.value and prev_tok.value.lower() == 'using': |
| 197 | # tbl1 INNER JOIN tbl2 USING (col1, col2) |
| 198 | # suggest columns that are present in more than one table |
| 199 | return [{'type': 'column', 'tables': _tables(ctx), 'drop_unique': True}] |
| 200 | if ctx.parsed_cb().tokens and ctx.parsed_cb().token_first() and ctx.parsed_cb().token_first().value.lower() == 'select': |
| 201 | # If the lparen is preceeded by a space chances are we're about to |
| 202 | # do a sub-select. |
| 203 | if last_word(ctx.text_before_cursor, 'all_punctuations').startswith('('): |
| 204 | return _keyword_suggestions() |
| 205 | elif ctx.parsed_cb().tokens and ctx.parsed_cb().token_first() and ctx.parsed_cb().token_first().value.lower() == 'show': |
| 206 | return [{'type': 'show'}] |
| 207 | |
| 208 | # We're probably in a function argument list |
| 209 | return [{'type': 'column', 'tables': _tables(ctx)}] |
| 210 | |
| 211 | |