-
Notifications
You must be signed in to change notification settings - Fork 14k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refactoring Druid & SQLa into a proper "Connector" interface #2362
Merged
Merged
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
7cc71e3
Formalizing the Connector interface
mistercrunch 661e0fc
Checkpoint
mistercrunch 1035821
Fixing views
mistercrunch 7f8800c
Fixing tests
mistercrunch a82c069
Adding migrtion
mistercrunch 4da1e88
Tests
mistercrunch f5aeccb
Final
mistercrunch 8a23073
Addressing comments
mistercrunch File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
import json | ||
|
||
from sqlalchemy import Column, Integer, String, Text, Boolean | ||
|
||
from superset import utils | ||
from superset.models.helpers import AuditMixinNullable, ImportMixin | ||
|
||
|
||
class BaseDatasource(AuditMixinNullable, ImportMixin): | ||
|
||
"""A common interface to objects that are queryable (tables and datasources)""" | ||
|
||
__tablename__ = None # {connector_name}_datasource | ||
|
||
# Used to do code highlighting when displaying the query in the UI | ||
query_language = None | ||
|
||
@property | ||
def column_names(self): | ||
return sorted([c.column_name for c in self.columns]) | ||
|
||
@property | ||
def main_dttm_col(self): | ||
return "timestamp" | ||
|
||
@property | ||
def groupby_column_names(self): | ||
return sorted([c.column_name for c in self.columns if c.groupby]) | ||
|
||
@property | ||
def filterable_column_names(self): | ||
return sorted([c.column_name for c in self.columns if c.filterable]) | ||
|
||
@property | ||
def dttm_cols(self): | ||
return [] | ||
|
||
@property | ||
def url(self): | ||
return '/{}/edit/{}'.format(self.baselink, self.id) | ||
|
||
@property | ||
def explore_url(self): | ||
if self.default_endpoint: | ||
return self.default_endpoint | ||
else: | ||
return "/superset/explore/{obj.type}/{obj.id}/".format(obj=self) | ||
|
||
@property | ||
def column_formats(self): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. have u meant metric_formats ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yeah I agree that this is weird but here I just moved the class without changing it... |
||
return { | ||
m.metric_name: m.d3format | ||
for m in self.metrics | ||
if m.d3format | ||
} | ||
|
||
@property | ||
def data(self): | ||
"""Data representation of the datasource sent to the frontend""" | ||
order_by_choices = [] | ||
for s in sorted(self.column_names): | ||
order_by_choices.append((json.dumps([s, True]), s + ' [asc]')) | ||
order_by_choices.append((json.dumps([s, False]), s + ' [desc]')) | ||
|
||
d = { | ||
'all_cols': utils.choicify(self.column_names), | ||
'column_formats': self.column_formats, | ||
'edit_url': self.url, | ||
'filter_select': self.filter_select_enabled, | ||
'filterable_cols': utils.choicify(self.filterable_column_names), | ||
'gb_cols': utils.choicify(self.groupby_column_names), | ||
'id': self.id, | ||
'metrics_combo': self.metrics_combo, | ||
'name': self.name, | ||
'order_by_choices': order_by_choices, | ||
'type': self.type, | ||
} | ||
|
||
# TODO move this block to SqlaTable.data | ||
if self.type == 'table': | ||
grains = self.database.grains() or [] | ||
if grains: | ||
grains = [(g.name, g.name) for g in grains] | ||
d['granularity_sqla'] = utils.choicify(self.dttm_cols) | ||
d['time_grain_sqla'] = grains | ||
return d | ||
|
||
|
||
class BaseColumn(AuditMixinNullable, ImportMixin): | ||
"""Interface for column""" | ||
|
||
__tablename__ = None # {connector_name}_column | ||
|
||
id = Column(Integer, primary_key=True) | ||
column_name = Column(String(255)) | ||
verbose_name = Column(String(1024)) | ||
is_active = Column(Boolean, default=True) | ||
type = Column(String(32)) | ||
groupby = Column(Boolean, default=False) | ||
count_distinct = Column(Boolean, default=False) | ||
sum = Column(Boolean, default=False) | ||
avg = Column(Boolean, default=False) | ||
max = Column(Boolean, default=False) | ||
min = Column(Boolean, default=False) | ||
filterable = Column(Boolean, default=False) | ||
description = Column(Text) | ||
|
||
# [optional] Set this to support import/export functionality | ||
export_fields = [] | ||
|
||
def __repr__(self): | ||
return self.column_name | ||
|
||
num_types = ('DOUBLE', 'FLOAT', 'INT', 'BIGINT', 'LONG', 'REAL', 'NUMERIC') | ||
date_types = ('DATE', 'TIME', 'DATETIME') | ||
str_types = ('VARCHAR', 'STRING', 'CHAR') | ||
|
||
@property | ||
def is_num(self): | ||
return any([t in self.type.upper() for t in self.num_types]) | ||
|
||
@property | ||
def is_time(self): | ||
return any([t in self.type.upper() for t in self.date_types]) | ||
|
||
@property | ||
def is_string(self): | ||
return any([t in self.type.upper() for t in self.str_types]) | ||
|
||
|
||
class BaseMetric(AuditMixinNullable, ImportMixin): | ||
|
||
"""Interface for Metrics""" | ||
|
||
__tablename__ = None # {connector_name}_metric | ||
|
||
id = Column(Integer, primary_key=True) | ||
metric_name = Column(String(512)) | ||
verbose_name = Column(String(1024)) | ||
metric_type = Column(String(32)) | ||
description = Column(Text) | ||
is_restricted = Column(Boolean, default=False, nullable=True) | ||
d3format = Column(String(128)) | ||
|
||
""" | ||
The interface should also declare a datasource relationship pointing | ||
to a derivative of BaseDatasource, along with a FK | ||
|
||
datasource_name = Column( | ||
String(255), | ||
ForeignKey('datasources.datasource_name')) | ||
datasource = relationship( | ||
# needs to be altered to point to {Connector}Datasource | ||
'BaseDatasource', | ||
backref=backref('metrics', cascade='all, delete-orphan'), | ||
enable_typechecks=False) | ||
""" | ||
@property | ||
def perm(self): | ||
raise NotImplementedError() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
from . import models # noqa | ||
from . import views # noqa |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Line too long (83 > 79 characters)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Personally I'm ok with up to 85-90 and that's the way I set up pylint / landscape but I can't do it on codeclimate...