This commit abstracts the database operations to use the generic
`sqlx::Executor` trait instead of a concrete `&sqlx::PgPool`.
This change allows all generated methods (find, create, update,
delete, and relationships) to be executed within a
`sqlx::Transaction`, in addition to a connection pool. This is a
crucial feature for ensuring atomic operations and data consistency.
The public-facing traits `Georm` and `Defaultable` have been updated
to require `sqlx::Executor`, and the documentation has been updated to
reflect this new capability.
This commit introduces support for PostgreSQL generated columns by
adding two new field attributes to the `Georm` derive macro:
`#[georm(generated)]` and `#[georm(generated_always)]`.
The `#[georm(generated_always)]` attribute is for fields that are
always generated by the database, such as `GENERATED ALWAYS AS
IDENTITY` columns or columns with a `GENERATED ALWAYS AS (expression)
STORED` clause. These fields are now excluded from `INSERT` and
`UPDATE` statements, preventing accidental writes and ensuring data
integrity at compile time.
The `#[georm(generated)]` attribute is for fields that have a default
value generated by the database but can also be manually overridden,
such as `GENERATED BY DEFAULT AS IDENTITY` columns. These fields
behave similarly to `#[georm(defaultable)]` fields, allowing them to
be omitted from `INSERT` statements to use the database-generated
value.
For now, the behaviour is the same between `#[georm(generated)]` and
`#[georm(defaultable)]`, but the addition of the former now will be
useful for future features.
Key changes:
- Added `generated` and `generated_always` attributes to
`GeormFieldAttributes`.
- Introduced `GeneratedType` enum in the IR to represent the different
generation strategies.
- Modified the `create` and `update` query generation to exclude
fields marked with `#[georm(generated_always)]`.
- Integrated `#[georm(generated)]` fields with the existing
defaultable struct logic.
- Added validation to prevent conflicting attribute usage, namely
`#[georm(generated)]` and `#[georm(generated_always)]` on the same
field.
Implements #3
Completely rewrite and expand documentation for Georm’s core
functionality with detailed explanations, examples, and implementation
details.
Changes:
- Rewrite lib.rs with comprehensive library documentation covering all
features
- Add extensive Georm trait documentation with method-specific details
- Add detailed Defaultable trait documentation with usage patterns
The documentation now provides complete coverage of:
- All CRUD operations with database behavior details
- Composite key support and generated ID structs
- Defaultable field patterns and companion struct generation
- Relationship modeling (field-level and struct-level)
- Error handling and performance characteristics
- PostgreSQL-specific features and optimizations
Add support for entities with composite primary keys using multiple
#[georm(id)] fields. Automatically generates {EntityName}Id structs for
type-safe composite key handling.
Features:
- Multi-field primary key detection and ID struct generation
- Full CRUD operations (find, create, update, delete, create_or_update)
- Proper SQL generation with AND clauses for composite keys
- Updated documNtation in README and lib.rs
Note: Relationships not yet supported for composite key entities
Introduces support for `#[georm(defaultable)]` attribute on entity
fields. When fields are marked as defaultable, generates companion
`<Entity>Default` structs where defaultable fields become `Option<T>`,
enabling easier entity creation when some fields have database defaults
or are auto-generated.
Key features:
- Generates `<Entity>Default` structs with optional defaultable fields
- Implements `Defaultable<Id, Entity>` trait with async `create` method
- Validates that `Option<T>` fields cannot be marked as defaultable
- Preserves field visibility in generated companion structs
- Only generates companion struct when defaultable fields are present
Currently, all methods declared in the Georm trait are available.
If a struct has an ID pointing towards another entity, the user can
create a get method to get the entity pointed at from the database
too (local one-to-one relationship).
I still need to implement remote one-to-one relationships (one-to-one
relationships when the ID of the remote object is not available
locally).
I still need to also test and debug one-to-many relationships (ID of
the remote entiies not available locally) and many-to-many
relationships (declared in a dedicated table).
For now, IDs in all cases are simple types recognized by SQLx that are
not arrays. Options are only supported when explicitely specified for
one-to-one relationships.