astronomer / astro-sdk

Astro SDK allows rapid and clean development of {Extract, Load, Transform} workflows using Python and SQL, powered by Apache Airflow.
https://astro-sdk-python.rtfd.io/
Apache License 2.0
329 stars 40 forks source link

Table from SQLAlchemy/Pydantic model #2150

Open 1cadumagalhaes opened 1 month ago

1cadumagalhaes commented 1 month ago

Please describe the feature you'd like to see I want to be able to create a Table from a SQLAlchemy model, import it's columns with types and constraints. Context: I'm running astro on a database from which the tables and migrations are defined by SQLALchemy models, that are also used by the application.

What happens here is:

  1. I declare my tables as models and write the database migrations based on it.
  2. The data for some of these tables come from aql.transform (with replace or append) and aql.merge.
  3. If I just declare the tables with the name, conn_id and metadata, when replacing the table it will lose all constraints, and might get some types wrong. One common issue with this behaviour is that tables lose their primary key, but also all foreign keys, sequences and etc.
  4. On the other hand, if I already have my tables defined as classes, it should not be hard to get every definition about it

Describe the solution you'd like

I'm not sure about the syntax, but we could do something like:

Table(model=MySQLAlchemyClass, conn_id=connection_id)

# Or even

Table(conn_id=connection_id).from_model(MySQLAlchemyClass)

With this, we could import the table name, the schema, all columns with types and constraints

Are there any alternatives to this feature? I don't think so

Additional context There is also sqlmodel which adds annotations to models so they're compatible with both pydantic and SQLAlchemy.

But adding support to python dataclasses would be nice for someone who isn't using SQLAlchemy or a similar ORM, but still wants an easier way of defining their table specifics.

Acceptance Criteria

1cadumagalhaes commented 1 month ago

For now I'll try to create a function/decorator to do this conversion and if it works I'll add it here.