betodealmeida / shillelagh

Making it easy to query APIs via SQL

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Getting trouble when creating VT table

rainnnnny opened this issue · comments

Describe the bug
Works fine when the table name is simply select * from table_a, but fail with schema as prefix like select * from schema.table_a;

I'm writing my custom adapter of graphql based on cancan101/graphql-db-api, the problem doesn't exist in his version; And I wrote an almost totally different adapter then this becomes a problem

To Reproduce
Steps to reproduce the behavior:

  1. Query with select bla,bla from 'tunnel_account_cash' where blabla, works fine.
  2. Query with select bla,bla from 'main.tunnel_account_cash' where blabla
  3. in apsw/db.py, debug like:

image

  1. got output except create main.tunnel_account_cash twice,
    and end up with apsw.SQLError: SQLError: table "tunnel_account_cash" already exists
except create main.tunnel_account_cash
except create main.tunnel_account_cash
Traceback (most recent call last):
  File "/home/rss/new40g/python/venv/lib/python3.8/site-packages/shillelagh/backends/apsw/db.py", line 223, in execute
    self._cursor.execute(operation, parameters)
  File "src/cursor.c", line 1081, in APSWCursor_execute.sqlite3_prepare
apsw.SQLError: SQLError: no such table: main.tunnel_account_cash

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/rss/python38/lib/python3.8/runpy.py", line 200, in _run_module_as_main
    return _run_code(code, main_globals, None, "__main__", mod_spec)
  File "/home/rss/python38/lib/python3.8/runpy.py", line 92, in _run_code
    exec(code, run_globals)
  File "/home/rss/.vscode-server/extensions/ms-python.python-2023.7.11081008/pythonFiles/lib/python/debugpy/adapter/../../debugpy/launcher/../../debugpy/__main__.py", line 39, in <module>
    cli.main()
  File "/home/rss/.vscode-server/extensions/ms-python.python-2023.7.11081008/pythonFiles/lib/python/debugpy/adapter/../../debugpy/launcher/../../debugpy/../debugpy/server/cli.py", line 430, in main
    run()
  File "/home/rss/.vscode-server/extensions/ms-python.python-2023.7.11081008/pythonFiles/lib/python/debugpy/adapter/../../debugpy/launcher/../../debugpy/../debugpy/server/cli.py", line 284, in run_file
    runpy.run_path(target, run_name="__main__")
  File "/home/rss/.vscode-server/extensions/ms-python.python-2023.7.11081008/pythonFiles/lib/python/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_runpy.py", line 321, in run_path
    return _run_module_code(code, init_globals, run_name,
  File "/home/rss/.vscode-server/extensions/ms-python.python-2023.7.11081008/pythonFiles/lib/python/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_runpy.py", line 135, in _run_module_code
    _run_code(code, mod_globals, init_globals,
  File "/home/rss/.vscode-server/extensions/ms-python.python-2023.7.11081008/pythonFiles/lib/python/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_runpy.py", line 124, in _run_code
    exec(code, run_globals)
  File "/home/rss/new40g/scripts/graphqltest/graphql_cli.py", line 31, in <module>
    for row in connection.execute(
  File "/home/rss/new40g/python/venv/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 1011, in execute
    return meth(self, multiparams, params)
  File "/home/rss/new40g/python/venv/lib/python3.8/site-packages/sqlalchemy/sql/elements.py", line 298, in _execute_on_connection
    return connection._execute_clauseelement(self, multiparams, params)
  File "/home/rss/new40g/python/venv/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 1124, in _execute_clauseelement
    ret = self._execute_context(
  File "/home/rss/new40g/python/venv/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 1316, in _execute_context
    self._handle_dbapi_exception(
  File "/home/rss/new40g/python/venv/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 1514, in _handle_dbapi_exception
    util.raise_(exc_info[1], with_traceback=exc_info[2])
  File "/home/rss/new40g/python/venv/lib/python3.8/site-packages/sqlalchemy/util/compat.py", line 182, in raise_
    raise exception
  File "/home/rss/new40g/python/venv/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 1276, in _execute_context
    self.dialect.do_execute(
  File "/home/rss/new40g/python/venv/lib/python3.8/site-packages/sqlalchemy/engine/default.py", line 593, in do_execute
    cursor.execute(statement, parameters)
  File "/home/rss/new40g/python/venv/lib/python3.8/site-packages/shillelagh/backends/apsw/db.py", line 81, in wrapper
    return method(self, *args, **kwargs)
  File "/home/rss/new40g/python/venv/lib/python3.8/site-packages/shillelagh/backends/apsw/db.py", line 234, in execute
    self._create_table(uri)
  File "/home/rss/new40g/python/venv/lib/python3.8/site-packages/shillelagh/backends/apsw/db.py", line 294, in _create_table
    self._cursor.execute(
  File "src/cursor.c", line 240, in resetcursor
apsw.SQLError: SQLError: table "tunnel_account_cash" already exists

Expected behavior
VT table be created properly.

My extra questions
Correct me if I'm wrong: it seems the adapter matters only for the create table sql generating, I checked the sql of VTTable.get_create_table and it's totally same when with or without schema prefix main., so I can only consider the problem is not in my adapter but in apsw cursor's execute, which failed to find table.

While I'm not familiar with C and getting hard to read apsw C code , I couldn't stop thinking about why do I need the VT table, what I want is converting sql to graphql query, get the result and return back, so, what's the tradeoff of shillelagh basing on sqlite and apsw? Could I write something like gsheets-db-api which seems getting rid of all sqlite things?

Screenshots
If applicable, add screenshots to help explain your problem.

Desktop (please complete the following information):

  • OS: [centos]
  • Browser [e.g. chrome, safari]
  • Version [1.2.0]

Smartphone (please complete the following information):

  • Device: [e.g. iPhone6]
  • OS: [e.g. iOS8.1]
  • Browser [e.g. stock browser, safari]
  • Version [e.g. 22]

Additional context
Add any other context about the problem here.

I think the problem is that your syntax is incorrect. This:

SELECT * FROM "main.t";  -- or 'main.t'

Means select everything from the table called "main.t". What you want to do is:

SELECT * FROM "main"."t";  -- or 'main'.'t'

Sorry I made a stupid mistake, the problem's gone, thanks a lot

But I still wish to know why shillelagh based on sqlite, would you please take a look at my questions: (copied from 'My extra questions' above)

While I'm not familiar with C and getting hard to read apsw C code , I couldn't stop thinking about why do I need the VT table, what I want is converting sql to graphql query, get the result and return back, so, what's the tradeoff of shillelagh basing on sqlite and apsw? Could I write something like gsheets-db-api which seems getting rid of all sqlite things?

Sorry I made a stupid mistake, the problem's gone, thanks a lot

No worries, I'm glad it was something simple!

But I still wish to know why shillelagh based on sqlite, would you please take a look at my questions: (copied from 'My extra questions' above)

While I'm not familiar with C and getting hard to read apsw C code , I couldn't stop thinking about why do I need the VT table, what I want is converting sql to graphql query, get the result and return back, so, what's the tradeoff of shillelagh basing on sqlite and apsw? Could I write something like gsheets-db-api which seems getting rid of all sqlite things?

There are pros and cons to both approaches.

gsheets-db-api tries to solve the problem by parsing the SQL and translating it to REST calls. Parsing the SQL, doing the calls, and building the result set is not trivial. For simple queries like

SELECT * FROM "https://docs.gooogle.com/..."
WHERE col > 1

it's relatively easy, but handling any valid SQL query is a lot of work. Because of this, gsheets-db-api supports only a small subset of SQL, mostly the queries produced by Apache Superset.

The pros of this approach is that it can be more efficient. For example, in gsheets-db-api we can push the aggregations to the server, potentially greatly reducing the amount of data that has to be downloaded by the client. This is not true for shillelagh.

For shillelagh I used the virtual table approach. This means that all the SQL parsing and result set generation is done by SQLite. Any query that is a valid SQLite query, not matter how complex, will work. All it needs to worry about is fetching data, filtering it, and sorting it, which are easy to do.

The disadvantage is that now the aggregations are done outside of the virtual table by SQLite. A simple query like SELECT COUNT(*) FROM some_table requires all the data to be downloaded and passed to SQLite so it can be counted.

Got it and thank you so much for your detailed explanation. I'm exactly doing my work for Superset query, as there seems no available open-source Graphql-based BI tools so far. I've done my work basing on shillelagh for demo and will take more consideration for production use. And shillelagh is really a great idea and convenience for situation like me!