class NewColumn(AuxiliaryColumnsMixin, Base): __tablename__ = "sl_columns" id = sa.Column(sa.Integer, primary_key=True) # A temporary column to link physical columns with tables so we don't # have to insert a record in the relationship table while creating new columns. table_id = sa.Column(sa.Integer, nullable=True) is_aggregation = sa.Column(sa.Boolean, nullable=False, default=False) is_additive = sa.Column(sa.Boolean, nullable=False, default=False) is_dimensional = sa.Column(sa.Boolean, nullable=False, default=False) is_filterable = sa.Column(sa.Boolean, nullable=False, default=True) is_increase_desired = sa.Column(sa.Boolean, nullable=False, default=True) is_managed_externally = sa.Column(sa.Boolean, nullable=False, default=False) is_partition = sa.Column(sa.Boolean, nullable=False, default=False) is_physical = sa.Column(sa.Boolean, nullable=False, default=False) is_temporal = sa.Column(sa.Boolean, nullable=False, default=False) is_spatial = sa.Column(sa.Boolean, nullable=False, default=False) name = sa.Column(sa.Text) type = sa.Column(sa.Text) unit = sa.Column(sa.Text) expression = sa.Column(MediumText()) description = sa.Column(MediumText()) warning_text = sa.Column(MediumText()) external_url = sa.Column(sa.Text, nullable=True) extra_json = sa.Column(MediumText(), default="{}")
class NewDataset(Base, AuxiliaryColumnsMixin): __tablename__ = "sl_datasets" id = sa.Column(sa.Integer, primary_key=True) database_id = sa.Column(sa.Integer, sa.ForeignKey("dbs.id"), nullable=False) is_physical = sa.Column(sa.Boolean, default=False) is_managed_externally = sa.Column(sa.Boolean, nullable=False, default=False) name = sa.Column(sa.Text) expression = sa.Column(MediumText()) external_url = sa.Column(sa.Text, nullable=True) extra_json = sa.Column(MediumText(), default="{}")
class SqlMetric(AuxiliaryColumnsMixin, Base): __tablename__ = "sql_metrics" __table_args__ = (UniqueConstraint("table_id", "metric_name"),) id = sa.Column(sa.Integer, primary_key=True) table_id = sa.Column(sa.Integer, sa.ForeignKey("tables.id")) extra = sa.Column(sa.Text) metric_type = sa.Column(sa.String(32)) metric_name = sa.Column(sa.String(255), nullable=False) expression = sa.Column(MediumText(), nullable=False) warning_text = sa.Column(MediumText()) description = sa.Column(MediumText()) d3format = sa.Column(sa.String(128)) verbose_name = sa.Column(sa.String(1024))
class NewTable(AuxiliaryColumnsMixin, Base): __tablename__ = "sl_tables" id = sa.Column(sa.Integer, primary_key=True) # A temporary column to keep the link between NewTable to SqlaTable sqlatable_id = sa.Column(sa.Integer, primary_key=False, nullable=True, unique=True) database_id = sa.Column(sa.Integer, sa.ForeignKey("dbs.id"), nullable=False) is_managed_externally = sa.Column(sa.Boolean, nullable=False, default=False) catalog = sa.Column(sa.Text) schema = sa.Column(sa.Text) name = sa.Column(sa.Text) external_url = sa.Column(sa.Text, nullable=True) extra_json = sa.Column(MediumText(), default="{}") database: Database = relationship( "Database", backref=backref("new_tables", cascade="all, delete-orphan"), foreign_keys=[database_id], )
def downgrade(): with op.batch_alter_table("dashboards") as batch_op: batch_op.alter_column( "position_json", existing_type=MediumText(), type_=sa.Text(), existing_nullable=True, )
def upgrade(): with op.batch_alter_table('dashboards') as batch_op: batch_op.alter_column( 'position_json', existing_type=sa.Text(), type_=MediumText(), existing_nullable=True, )
class TableColumn(AuxiliaryColumnsMixin, Base): __tablename__ = "table_columns" __table_args__ = (UniqueConstraint("table_id", "column_name"),) id = sa.Column(sa.Integer, primary_key=True) table_id = sa.Column(sa.Integer, sa.ForeignKey("tables.id")) is_active = sa.Column(sa.Boolean, default=True) extra = sa.Column(sa.Text) column_name = sa.Column(sa.String(255), nullable=False) type = sa.Column(sa.String(32)) expression = sa.Column(MediumText()) description = sa.Column(MediumText()) is_dttm = sa.Column(sa.Boolean, default=False) filterable = sa.Column(sa.Boolean, default=True) groupby = sa.Column(sa.Boolean, default=True) verbose_name = sa.Column(sa.String(1024)) python_date_format = sa.Column(sa.String(255))
class Dashboard(Base): __tablename__ = "dashboards" id = Column(Integer, primary_key=True) css = Column(Text) dashboard_title = Column(String(500)) description = Column(Text) json_metadata = Column(Text) position_json = Column(MediumText()) slug = Column(String(255))
class SqlaTable(BaseDatasourceMixin, Base): __tablename__ = "tables" default_endpoint = Column(MediumText()) fetch_values_predicate = Column(String(1000)) main_dttm_col = Column(String(250)) schema = Column(String(255)) sql = Column(Text) table_name = Column(String(250)) template_params = Column(Text)
class BaseMetric(AuditMixinNullable, ImportExportMixin): """Interface for Metrics""" __tablename__: Optional[str] = None # {connector_name}_metric id = Column(Integer, primary_key=True) metric_name = Column(String(255), nullable=False) verbose_name = Column(String(1024)) metric_type = Column(String(32)) description = Column(MediumText()) d3format = Column(String(128)) warning_text = Column(Text) """ 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) -> Optional[str]: raise NotImplementedError() @property def expression(self) -> Column: raise NotImplementedError() @property def data(self) -> Dict[str, Any]: attrs = ( "id", "metric_name", "verbose_name", "description", "expression", "warning_text", "d3format", ) return {s: getattr(self, s) for s in attrs}
class SqlaTable(AuxiliaryColumnsMixin, Base): __tablename__ = "tables" __table_args__ = (UniqueConstraint("database_id", "schema", "table_name"),) id = sa.Column(sa.Integer, primary_key=True) extra = sa.Column(sa.Text) database_id = sa.Column(sa.Integer, sa.ForeignKey("dbs.id"), nullable=False) database: Database = relationship( "Database", backref=backref("tables", cascade="all, delete-orphan"), foreign_keys=[database_id], ) schema = sa.Column(sa.String(255)) table_name = sa.Column(sa.String(250), nullable=False) sql = sa.Column(MediumText()) is_managed_externally = sa.Column(sa.Boolean, nullable=False, default=False) external_url = sa.Column(sa.Text, nullable=True)
class BaseColumn(AuditMixinNullable, ImportExportMixin): """Interface for column""" __tablename__: Optional[str] = None # {connector_name}_column id = Column(Integer, primary_key=True) column_name = Column(String(255), nullable=False) verbose_name = Column(String(1024)) is_active = Column(Boolean, default=True) type = Column(Text) groupby = Column(Boolean, default=True) filterable = Column(Boolean, default=True) description = Column(MediumText()) is_dttm = None # [optional] Set this to support import/export functionality export_fields: List[Any] = [] def __repr__(self) -> str: return str(self.column_name) bool_types = ("BOOL", ) num_types = ( "DOUBLE", "FLOAT", "INT", "BIGINT", "NUMBER", "LONG", "REAL", "NUMERIC", "DECIMAL", "MONEY", ) date_types = ("DATE", "TIME") str_types = ("VARCHAR", "STRING", "CHAR") @property def is_numeric(self) -> bool: return self.type and any( map(lambda t: t in self.type.upper(), self.num_types)) @property def is_temporal(self) -> bool: return self.type and any( map(lambda t: t in self.type.upper(), self.date_types)) @property def is_string(self) -> bool: return self.type and any( map(lambda t: t in self.type.upper(), self.str_types)) @property def is_boolean(self) -> bool: return self.type and any( map(lambda t: t in self.type.upper(), self.bool_types)) @property def type_generic(self) -> Optional[utils.GenericDataType]: if self.is_string: return utils.GenericDataType.STRING if self.is_boolean: return utils.GenericDataType.BOOLEAN if self.is_numeric: return utils.GenericDataType.NUMERIC if self.is_temporal: return utils.GenericDataType.TEMPORAL return None @property def expression(self) -> Column: raise NotImplementedError() @property def python_date_format(self) -> Column: raise NotImplementedError() @property def data(self) -> Dict[str, Any]: attrs = ( "id", "column_name", "verbose_name", "description", "expression", "filterable", "groupby", "is_dttm", "type", ) return {s: getattr(self, s) for s in attrs if hasattr(self, s)}