dbcli / mycli

A Terminal Client for MySQL with AutoCompletion and Syntax Highlighting.
http://mycli.net
Other
11.49k stars 663 forks source link

Fix autocomplete exception on quoted string. #1006

Closed emorozov closed 2 years ago

emorozov commented 3 years ago

Description

Open mycli and type (including quotes): 'where i=';

Press Enter. mycli will abort with exception:

Traceback (most recent call last):
  File "/home/jmv/work/mycli/mycli/main.py", line 1420, in <module>
    cli()
  File "/home/jmv/.cache/pypoetry/virtualenvs/mycli-859CWqQ5-py3.9/lib/python3.9/site-packages/click/core.py", line 1137, in __call__
    return self.main(*args, **kwargs)
  File "/home/jmv/.cache/pypoetry/virtualenvs/mycli-859CWqQ5-py3.9/lib/python3.9/site-packages/click/core.py", line 1062, in main
    rv = self.invoke(ctx)
  File "/home/jmv/.cache/pypoetry/virtualenvs/mycli-859CWqQ5-py3.9/lib/python3.9/site-packages/click/core.py", line 1404, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/home/jmv/.cache/pypoetry/virtualenvs/mycli-859CWqQ5-py3.9/lib/python3.9/site-packages/click/core.py", line 763, in invoke
    return __callback(*args, **kwargs)
  File "/home/jmv/work/mycli/mycli/main.py", line 1296, in cli
    mycli.run_cli()
  File "/home/jmv/work/mycli/mycli/main.py", line 836, in run_cli
    one_iteration()
  File "/home/jmv/work/mycli/mycli/main.py", line 635, in one_iteration
    text = self.prompt_app.prompt()
  File "/home/jmv/.cache/pypoetry/virtualenvs/mycli-859CWqQ5-py3.9/lib/python3.9/site-packages/prompt_toolkit/shortcuts/prompt.py", line 1020, in prompt
    return self.app.run(
  File "/home/jmv/.cache/pypoetry/virtualenvs/mycli-859CWqQ5-py3.9/lib/python3.9/site-packages/prompt_toolkit/application/application.py", line 891, in run
    return loop.run_until_complete(
  File "/usr/lib/python3.9/asyncio/base_events.py", line 642, in run_until_complete
    return future.result()
  File "/home/jmv/.cache/pypoetry/virtualenvs/mycli-859CWqQ5-py3.9/lib/python3.9/site-packages/prompt_toolkit/application/application.py", line 816, in run_async
    return await _run_async2()
  File "/home/jmv/.cache/pypoetry/virtualenvs/mycli-859CWqQ5-py3.9/lib/python3.9/site-packages/prompt_toolkit/application/application.py", line 798, in _run_async2
    await self.cancel_and_wait_for_background_tasks()
  File "/home/jmv/.cache/pypoetry/virtualenvs/mycli-859CWqQ5-py3.9/lib/python3.9/site-packages/prompt_toolkit/application/application.py", line 1001, in cancel_and_wait_for_background_tasks
    await task
  File "/home/jmv/.cache/pypoetry/virtualenvs/mycli-859CWqQ5-py3.9/lib/python3.9/site-packages/prompt_toolkit/buffer.py", line 1909, in new_coroutine
    await coroutine(*a, **kw)
  File "/home/jmv/.cache/pypoetry/virtualenvs/mycli-859CWqQ5-py3.9/lib/python3.9/site-packages/prompt_toolkit/buffer.py", line 1738, in async_completer
    async for completion in self.completer.get_completions_async(
  File "/home/jmv/.cache/pypoetry/virtualenvs/mycli-859CWqQ5-py3.9/lib/python3.9/site-packages/prompt_toolkit/completion/base.py", line 271, in get_completions_async
    async for completion in completer.get_completions_async(
  File "/home/jmv/.cache/pypoetry/virtualenvs/mycli-859CWqQ5-py3.9/lib/python3.9/site-packages/prompt_toolkit/completion/base.py", line 271, in get_completions_async
    async for completion in completer.get_completions_async(
  File "/home/jmv/.cache/pypoetry/virtualenvs/mycli-859CWqQ5-py3.9/lib/python3.9/site-packages/prompt_toolkit/completion/base.py", line 198, in get_completions_async
    for item in self.get_completions(document, complete_event):
  File "/home/jmv/work/mycli/mycli/sqlcompleter.py", line 261, in get_completions
    suggestions = suggest_type(document.text, document.text_before_cursor)
  File "/home/jmv/work/mycli/mycli/packages/completion_engine.py", line 80, in suggest_type
    return suggest_based_on_last_token(last_token, text_before_cursor,
  File "/home/jmv/work/mycli/mycli/packages/completion_engine.py", line 130, in suggest_based_on_last_token
    return suggest_based_on_last_token(prev_keyword, text_before_cursor,
  File "/home/jmv/work/mycli/mycli/packages/completion_engine.py", line 133, in suggest_based_on_last_token
    token_v = token.value.lower()
AttributeError: 'NoneType' object has no attribute 'value'

This pull request attempts to fix the error because it is very annoying. mycli shouldn't abort, instead it should display syntax error or pass the statement to MySQL.

My fix is very naive. I didn't have time to fully understand how autocompletion works, played with it a bit in the debugger and this is the best fix I could come up with.

Checklist

amjith commented 2 years ago

@emorozov Thank you for the reproducible case and the PR. I'm so sorry it took me this long to merge. Thank you!