I'm trying to add a special data source to Superset (a data exploration platform). This database only supports HTTP API, and returns data in json format. ex:
> http://localhost/api/sql/query?q="select * from table"
< [{"id": 1, "value":10}, {"id": 2, "value": 30} ...]
Therefore, I have to write my own adapter in python SQLAlchemy for Superset. I have read the document and part of source code, but still need good example to follow.
Could you give me some clue? Anything help is welcome.
====
UPDATE:
I have solved this problem. Here is what I do.
- Go to
./site-packages/sqlalchemy/dialects
Copy any concrete dialects to the new one (eg: named
zeta
) as the start point. A better way is to usefrom sqlalchemy.engine.default import DefaultDialect class ZetaDialect(DefaultDialect): ...
Add
zeta
into__all__
section of./site-packages/sqlalchemy/dialects/__init__.py
Create a test program:
from sqlalchemy import create_engine engine = create_engine('zeta://XXX') result = engine.execute("select * from table_name") for row in result: print(row)
Run it and get error. Use
pdb
to find the reason. In most cases, the reason is NotImplement some interfaces. Solve it one by one.When test program gives correct answer, it has almost been done 90%. For completeness, we should also implement several interface used by inspectors:
class ZetaDialect(DefaultDialect): # default_paramstyle = 'qmark' name = 'zeta' def __init__(self, **kwargs): DefaultDialect.__init__(self, **kwargs) @classmethod def dbapi(cls): return zeta_dbapi @reflection.cache def get_table_names(self, connection, schema=None, **kw): return [u'table_1', u'table_2', ...] @reflection.cache def get_pk_constraint(self, connection, table_name, schema=None, **kw): return [] @reflection.cache def get_foreign_keys(self, connection, table_name, schema=None, **kw): return [] @reflection.cache def get_unique_constraints(self, connection, table_name, schema=None, **kw): return [] @reflection.cache def get_indexes(self, connection, table_name, schema=None, **kw): return [] @reflection.cache def get_schema_names(self, connection, **kw): return [] @reflection.cache def get_columns(self, connection, table_name, schema=None, **kw): # just an example of the column structure result = connection.execute('select * from %s limit 1' % table_name) return [{'default': None, 'autoincrement': False, 'type': TEXT, 'name': colname, 'nullable': False} for colname, coltype in result.curs
or.description]
来源:https://stackoverflow.com/questions/43929132/how-to-write-my-own-dialect-in-sqlalchemy-to-adapt-http-api