def __init__( self, datasource: Dict, queries: List[Dict], ): self.datasource = ConnectorRegistry.get_datasource(datasource.get('type'), int(datasource.get('id')), db.session) self.queries = list(map(lambda query_obj: QueryObject(**query_obj), queries))
def __init__( self, datasource: Dict, queries: List[Dict], force: bool = False, custom_cache_timeout: int = None, ): self.datasource = ConnectorRegistry.get_datasource(datasource.get('type'), int(datasource.get('id')), db.session) self.queries = list(map(lambda query_obj: QueryObject(**query_obj), queries)) self.force = force self.custom_cache_timeout = custom_cache_timeout self.enforce_numerical_metrics = True
def save(self): datasource = json.loads(request.form.get('data')) datasource_id = datasource.get('id') datasource_type = datasource.get('type') orm_datasource = ConnectorRegistry.get_datasource( datasource_type, datasource_id, db.session) if not check_ownership(orm_datasource, raise_if_false=False): return json_error_response( __( 'You are not authorized to modify ' 'this data source configuration'), status='401', ) orm_datasource.update_from_object(datasource) data = orm_datasource.data db.session.commit() return self.json_response(data)
def get_viz( slice_id=None, form_data=None, datasource_type=None, datasource_id=None, force=False, ): if slice_id: slc = (db.session.query(models.Slice).filter_by(id=slice_id).one()) return slc.get_viz() else: viz_type = form_data.get('viz_type', 'table') datasource = ConnectorRegistry.get_datasource(datasource_type, datasource_id, db.session) viz_obj = viz.viz_types[viz_type]( datasource, form_data=form_data, force=force, ) return viz_obj
def __init__( # pylint: disable=too-many-arguments self, datasource: DatasourceDict, queries: List[Dict[str, Any]], force: bool = False, custom_cache_timeout: Optional[int] = None, result_type: Optional[ChartDataResultType] = None, result_format: Optional[ChartDataResultFormat] = None, ) -> None: self.datasource = ConnectorRegistry.get_datasource( str(datasource["type"]), int(datasource["id"]), db.session) self.queries = [QueryObject(**query_obj) for query_obj in queries] self.force = force self.custom_cache_timeout = custom_cache_timeout self.result_type = result_type or ChartDataResultType.FULL self.result_format = result_format or ChartDataResultFormat.JSON self.cache_values = { "datasource": datasource, "queries": queries, "result_type": self.result_type, "result_format": self.result_format, }
def save(self): datasource = json.loads(request.form.get('data')) datasource_id = datasource.get('id') datasource_type = datasource.get('type') orm_datasource = ConnectorRegistry.get_datasource( datasource_type, datasource_id, db.session) if not check_ownership(orm_datasource, raise_if_false=False): return json_error_response( __( 'You are not authorized to modify ' 'this data source configuration'), status='401', ) if 'owners' in datasource: datasource['owners'] = db.session.query(orm_datasource.owner_class).filter( orm_datasource.owner_class.id.in_(datasource['owners'])).all() orm_datasource.update_from_object(datasource) data = orm_datasource.data db.session.commit() return self.json_response(data)
def external_metadata( self, datasource_type: str, datasource_id: int ) -> FlaskResponse: """Gets column info from the source system""" if datasource_type == "druid": datasource = ConnectorRegistry.get_datasource( datasource_type, datasource_id, db.session ) elif datasource_type == "table": database = ( db.session.query(Database).filter_by(id=request.args.get("db_id")).one() ) table_class = ConnectorRegistry.sources["table"] datasource = table_class( database=database, table_name=request.args.get("table_name"), schema=request.args.get("schema") or None, ) else: raise Exception(f"Unsupported datasource_type: {datasource_type}") external_metadata = datasource.external_metadata() return self.json_response(external_metadata)
def save(self) -> FlaskResponse: data = request.form.get("data") if not isinstance(data, str): return json_error_response("Request missing data field.", status=500) datasource_dict = json.loads(data) datasource_id = datasource_dict.get("id") datasource_type = datasource_dict.get("type") database_id = datasource_dict["database"].get("id") orm_datasource = ConnectorRegistry.get_datasource( datasource_type, datasource_id, db.session ) orm_datasource.database_id = database_id if "owners" in datasource_dict and orm_datasource.owner_class is not None: datasource_dict["owners"] = ( db.session.query(orm_datasource.owner_class) .filter(orm_datasource.owner_class.id.in_(datasource_dict["owners"])) .all() ) duplicates = [ name for name, count in Counter( [col["column_name"] for col in datasource_dict["columns"]] ).items() if count > 1 ] if duplicates: return json_error_response( f"Duplicate column name(s): {','.join(duplicates)}", status=409 ) orm_datasource.update_from_object(datasource_dict) data = orm_datasource.data db.session.commit() return self.json_response(data)
def test_query_cache_key_changes_when_metric_is_updated(self): self.login(username="******") payload = get_query_context("birth_names") # make temporary change and revert it to refresh the changed_on property datasource = ConnectorRegistry.get_datasource( datasource_type=payload["datasource"]["type"], datasource_id=payload["datasource"]["id"], session=db.session, ) datasource.metrics.append( SqlMetric(metric_name="foo", expression="select 1;")) db.session.commit() # construct baseline query_cache_key query_context = ChartDataQueryContextSchema().load(payload) query_object = query_context.queries[0] cache_key_original = query_context.query_cache_key(query_object) # wait a second since mysql records timestamps in second granularity time.sleep(1) datasource.metrics[0].expression = "select 2;" db.session.commit() # create new QueryContext with unchanged attributes, extract new query_cache_key query_context = ChartDataQueryContextSchema().load(payload) query_object = query_context.queries[0] cache_key_new = query_context.query_cache_key(query_object) datasource.metrics = [] db.session.commit() # the new cache_key should be different due to updated datasource self.assertNotEqual(cache_key_original, cache_key_new)
def get_viz( slice_id=None, form_data=None, datasource_type=None, datasource_id=None, force=False, ): if slice_id: slc = ( db.session.query(models.Slice) .filter_by(id=slice_id) .one() ) return slc.get_viz() else: viz_type = form_data.get('viz_type', 'table') datasource = ConnectorRegistry.get_datasource( datasource_type, datasource_id, db.session) viz_obj = viz.viz_types[viz_type]( datasource, form_data=form_data, force=force, ) return viz_obj
def _convert_to_model(self, datasource: DatasourceDict) -> BaseDatasource: return ConnectorRegistry.get_datasource(str(datasource["type"]), int(datasource["id"]), db.session)
def get(self, datasource_type: str, datasource_id: int) -> FlaskResponse: datasource = ConnectorRegistry.get_datasource(datasource_type, datasource_id, db.session) return self.json_response(datasource.data)
def __init__( self, datasource: Optional[DatasourceDict] = None, result_type: Optional[ChartDataResultType] = None, annotation_layers: Optional[List[Dict[str, Any]]] = None, applied_time_extras: Optional[Dict[str, str]] = None, apply_fetch_values_predicate: bool = False, granularity: Optional[str] = None, metrics: Optional[List[Union[Dict[str, Any], str]]] = None, groupby: Optional[List[str]] = None, filters: Optional[List[Dict[str, Any]]] = None, time_range: Optional[str] = None, time_shift: Optional[str] = None, is_timeseries: Optional[bool] = None, timeseries_limit: int = 0, row_limit: Optional[int] = None, row_offset: Optional[int] = None, timeseries_limit_metric: Optional[Metric] = None, order_desc: bool = True, extras: Optional[Dict[str, Any]] = None, columns: Optional[List[str]] = None, orderby: Optional[List[OrderBy]] = None, post_processing: Optional[List[Optional[Dict[str, Any]]]] = None, is_rowcount: bool = False, **kwargs: Any, ): columns = columns or [] groupby = groupby or [] extras = extras or {} annotation_layers = annotation_layers or [] self.is_rowcount = is_rowcount self.datasource = None if datasource: self.datasource = ConnectorRegistry.get_datasource( str(datasource["type"]), int(datasource["id"]), db.session) self.result_type = result_type self.apply_fetch_values_predicate = apply_fetch_values_predicate or False self.annotation_layers = [ layer for layer in annotation_layers # formula annotations don't affect the payload, hence can be dropped if layer["annotationType"] != "FORMULA" ] self.applied_time_extras = applied_time_extras or {} self.granularity = granularity self.from_dttm, self.to_dttm = get_since_until( relative_start=extras.get("relative_start", config["DEFAULT_RELATIVE_START_TIME"]), relative_end=extras.get("relative_end", config["DEFAULT_RELATIVE_END_TIME"]), time_range=time_range, time_shift=time_shift, ) # is_timeseries is True if time column is in either columns or groupby # (both are dimensions) self.is_timeseries = (is_timeseries if is_timeseries is not None else DTTM_ALIAS in columns + groupby) self.time_range = time_range self.time_shift = parse_human_timedelta(time_shift) self.post_processing = [ post_proc for post_proc in post_processing or [] if post_proc ] # Support metric reference/definition in the format of # 1. 'metric_name' - name of predefined metric # 2. { label: 'label_name' } - legacy format for a predefined metric # 3. { expressionType: 'SIMPLE' | 'SQL', ... } - adhoc metric self.metrics = metrics and [ x if isinstance(x, str) or is_adhoc_metric(x) else x["label"] # type: ignore for x in metrics ] self.row_limit = config["ROW_LIMIT"] if row_limit is None else row_limit self.row_offset = row_offset or 0 self.filter = filters or [] self.timeseries_limit = timeseries_limit self.timeseries_limit_metric = timeseries_limit_metric self.order_desc = order_desc self.extras = extras if config["SIP_15_ENABLED"]: self.extras["time_range_endpoints"] = get_time_range_endpoints( form_data=self.extras) self.columns = columns self.groupby = groupby or [] self.orderby = orderby or [] # rename deprecated fields for field in DEPRECATED_FIELDS: if field.old_name in kwargs: logger.warning( "The field `%s` is deprecated, please use `%s` instead.", field.old_name, field.new_name, ) value = kwargs[field.old_name] if value: if hasattr(self, field.new_name): logger.warning( "The field `%s` is already populated, " "replacing value with contents from `%s`.", field.new_name, field.old_name, ) setattr(self, field.new_name, value) # move deprecated extras fields to extras for field in DEPRECATED_EXTRAS_FIELDS: if field.old_name in kwargs: logger.warning( "The field `%s` is deprecated and should " "be passed to `extras` via the `%s` property.", field.old_name, field.new_name, ) value = kwargs[field.old_name] if value: if hasattr(self.extras, field.new_name): logger.warning( "The field `%s` is already populated in " "`extras`, replacing value with contents " "from `%s`.", field.new_name, field.old_name, ) self.extras[field.new_name] = value
from superset.connectors.connector_registry import ConnectorRegistry from flask_appbuilder.security.sqla.models import User from superset.viz import TableViz from superset import db from flask import g import json f = open('d:\\home\\pivot_viz\\form_data.json') form_data_json = f.read() f.close() g.user = db.session.query(User).filter(User.id == 2).one() form_data = json.loads(form_data_json) datasource_type = form_data.get('viz_type', 'table') datasource_id = form_data['datasource'].split('__')[0] datasource = ConnectorRegistry.get_datasource(datasource_type, datasource_id, db.session) viz = TableViz(datasource, form_data) res = viz.get_payload(force=True) # print(res) with open('d:\\home\\pivot_viz\\response.json', 'w', encoding='utf8') as f: f.write(viz.json_dumps(res))
def __init__( # pylint: disable=too-many-arguments,too-many-locals self, query_context: "QueryContext", annotation_layers: Optional[List[Dict[str, Any]]] = None, applied_time_extras: Optional[Dict[str, str]] = None, apply_fetch_values_predicate: bool = False, columns: Optional[List[str]] = None, datasource: Optional[DatasourceDict] = None, extras: Optional[Dict[str, Any]] = None, filters: Optional[List[QueryObjectFilterClause]] = None, granularity: Optional[str] = None, is_rowcount: bool = False, is_timeseries: Optional[bool] = None, metrics: Optional[List[Metric]] = None, order_desc: bool = True, orderby: Optional[List[OrderBy]] = None, post_processing: Optional[List[Optional[Dict[str, Any]]]] = None, result_type: Optional[ChartDataResultType] = None, row_limit: Optional[int] = None, row_offset: Optional[int] = None, series_columns: Optional[List[str]] = None, series_limit: int = 0, series_limit_metric: Optional[Metric] = None, time_range: Optional[str] = None, time_shift: Optional[str] = None, **kwargs: Any, ): columns = columns or [] extras = extras or {} annotation_layers = annotation_layers or [] self.time_offsets = kwargs.get("time_offsets", []) self.inner_from_dttm = kwargs.get("inner_from_dttm") self.inner_to_dttm = kwargs.get("inner_to_dttm") if series_columns: self.series_columns = series_columns elif is_timeseries and metrics: self.series_columns = columns else: self.series_columns = [] self.is_rowcount = is_rowcount self.datasource = None if datasource: self.datasource = ConnectorRegistry.get_datasource( str(datasource["type"]), int(datasource["id"]), db.session) self.result_type = result_type or query_context.result_type self.apply_fetch_values_predicate = apply_fetch_values_predicate or False self.annotation_layers = [ layer for layer in annotation_layers # formula annotations don't affect the payload, hence can be dropped if layer["annotationType"] != "FORMULA" ] self.applied_time_extras = applied_time_extras or {} self.granularity = granularity self.from_dttm, self.to_dttm = get_since_until( relative_start=extras.get("relative_start", config["DEFAULT_RELATIVE_START_TIME"]), relative_end=extras.get("relative_end", config["DEFAULT_RELATIVE_END_TIME"]), time_range=time_range, time_shift=time_shift, ) # is_timeseries is True if time column is in either columns or groupby # (both are dimensions) self.is_timeseries = (is_timeseries if is_timeseries is not None else DTTM_ALIAS in columns) self.time_range = time_range self.time_shift = parse_human_timedelta(time_shift) self.post_processing = [ post_proc for post_proc in post_processing or [] if post_proc ] # Support metric reference/definition in the format of # 1. 'metric_name' - name of predefined metric # 2. { label: 'label_name' } - legacy format for a predefined metric # 3. { expressionType: 'SIMPLE' | 'SQL', ... } - adhoc metric self.metrics = metrics and [ x if isinstance(x, str) or is_adhoc_metric(x) else x["label"] # type: ignore for x in metrics ] default_row_limit = (config["SAMPLES_ROW_LIMIT"] if self.result_type == ChartDataResultType.SAMPLES else config["ROW_LIMIT"]) self.row_limit = apply_max_row_limit(row_limit or default_row_limit) self.row_offset = row_offset or 0 self.filter = filters or [] self.series_limit = series_limit self.series_limit_metric = series_limit_metric self.order_desc = order_desc self.extras = extras if config["SIP_15_ENABLED"]: self.extras["time_range_endpoints"] = get_time_range_endpoints( form_data=self.extras) self.columns = columns self.orderby = orderby or [] self._rename_deprecated_fields(kwargs) self._move_deprecated_extra_fields(kwargs)
def external_metadata(self, datasource_type=None, datasource_id=None): """Gets column info from the source system""" orm_datasource = ConnectorRegistry.get_datasource( datasource_type, datasource_id, db.session) return self.json_response(orm_datasource.external_metadata())
def get_datasource_by_id(datasource_id: int, datasource_type: str) -> BaseDatasource: try: return ConnectorRegistry.get_datasource(datasource_type, datasource_id) except (NoResultFound, KeyError): raise DatasourceNotFoundValidationError()