From 796ae5ce811918c8648a754ad2741b3788bf3208 Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Mon, 11 May 2026 15:10:49 +0200 Subject: [PATCH] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20(seaorm):=20Revisa=20y=20m?= =?UTF-8?q?ejora=20la=20API=20p=C3=BAblica?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- extensions/pagetop-seaorm/README.md | 21 +++--- extensions/pagetop-seaorm/src/config.rs | 6 +- extensions/pagetop-seaorm/src/db.rs | 72 +++++++++++++++++-- extensions/pagetop-seaorm/src/db/dbconn.rs | 17 ++--- extensions/pagetop-seaorm/src/db/migration.rs | 4 +- extensions/pagetop-seaorm/src/lib.rs | 3 +- 6 files changed, 92 insertions(+), 31 deletions(-) diff --git a/extensions/pagetop-seaorm/README.md b/extensions/pagetop-seaorm/README.md index 0a1de4f5..fff02d6d 100644 --- a/extensions/pagetop-seaorm/README.md +++ b/extensions/pagetop-seaorm/README.md @@ -38,7 +38,8 @@ db_name = "my_app.db" max_pool_size = 5 ``` -Para MySQL o PostgreSQL añade también `db_user`, `db_pass`, `db_host` y `db_port`. +Para MySQL o PostgreSQL añade también `db_user`, `db_pass` y `db_host`. El campo `db_port` es +opcional; si se omite se usa el puerto predeterminado del motor. **Declara la extensión** en tu aplicación o en la extensión que la requiera: @@ -117,15 +118,15 @@ usarlo como dependencia ya que su paradigma de CLI no es compatible con el ciclo extensiones de PageTop, donde las migraciones deben ejecutarse durante la inicialización de cada extensión. Los ficheros adaptados del original son: -| Archivos | Observaciones | -|----------------------------|--------------------------------------------------------------| -| `lib.rs` en `migration.rs` | Excluye módulos y exportaciones del CLI | -| `connection.rs` | Integración completa | -| `manager.rs` | Adapta *features* propias | -| `migrator.rs` | Adapta *features* propias y omite gestión de errores del CLI | -| `prelude.rs` | Excluye exportaciones del CLI | -| `schema.rs` | Integración ajustada con cambios menores | -| `seaql_migrations.rs` | Integración completa | +| Archivos | Observaciones | +|-----------------------|--------------------------------------------------------------------------| +| `lib.rs` | Incluido en `migration.rs`, descarta módulos y exportaciones del CLI | +| `connection.rs` | Integración completa | +| `manager.rs` | Adapta *features* propias | +| `migrator.rs` | Adapta *features* propias y omite gestión de errores del CLI | +| `prelude.rs` | Excluye exportaciones del CLI | +| `schema.rs` | Integra con ajustes, original de [loco](https://github.com/loco-rs/loco) | +| `seaql_migrations.rs` | Integración completa | ## 🚧 Advertencia diff --git a/extensions/pagetop-seaorm/src/config.rs b/extensions/pagetop-seaorm/src/config.rs index bec565b3..b1276c50 100644 --- a/extensions/pagetop-seaorm/src/config.rs +++ b/extensions/pagetop-seaorm/src/config.rs @@ -34,7 +34,6 @@ include_config!(SETTINGS: Settings => [ "database.db_user" => "", "database.db_pass" => "", "database.db_host" => "localhost", - "database.db_port" => 0, "database.max_pool_size" => 5, ]); @@ -57,8 +56,9 @@ pub struct Database { pub db_pass: String, /// Servidor de conexión a la base de datos (para mysql/postgres). pub db_host: String, - /// Puerto de conexión a la base de datos, normalmente 3306 (para mysql) ó 5432 (para postgres). - pub db_port: u16, + /// Puerto de conexión a la base de datos (para mysql/postgres). Si es `None` se usa el puerto + /// predeterminado para el motor: 3306 para MySQL y 5432 para PostgreSQL. + pub db_port: Option, /// Número máximo de conexiones habilitadas. pub max_pool_size: u32, } diff --git a/extensions/pagetop-seaorm/src/db.rs b/extensions/pagetop-seaorm/src/db.rs index d1188a35..f954d9ce 100644 --- a/extensions/pagetop-seaorm/src/db.rs +++ b/extensions/pagetop-seaorm/src/db.rs @@ -1,7 +1,7 @@ use pagetop::core::TypeInfo; use pagetop::trace; -pub use url::Url as DbUri; +pub(crate) use url::Url as DbUri; pub use sea_orm::error::{DbErr, RuntimeErr}; pub use sea_orm::{DatabaseConnection as DbConn, ExecResult, QueryResult}; @@ -16,7 +16,30 @@ mod migration; pub use migration::prelude::*; pub use migration::schema::*; -pub async fn query(stmt: &mut Q) -> Result, DbErr> { +/// Ejecuta una consulta para devolver todas las filas resultantes. +/// +/// Acepta cualquier tipo que implemente [`QueryStatementWriter`] (p. ej. [`SelectStatement`]) y +/// serializa la sentencia al dialecto de la base de datos configurada antes de ejecutarla. Cada +/// fila se devuelve como un [`QueryResult`] sin tipar; extrae los valores con +/// [`QueryResult::try_get`]. +/// +/// ```rust,no_run +/// use pagetop_seaorm::db::*; +/// +/// async fn example() -> Result<(), DbErr> { +/// let mut stmt = Query::select() +/// .column(Asterisk) +/// .from(Alias::new("users")) +/// .to_owned(); +/// let rows = fetch_all(&mut stmt).await?; +/// for row in rows { +/// let name: String = row.try_get("", "name")?; +/// println!("{name}"); +/// } +/// Ok(()) +/// } +/// ``` +pub async fn fetch_all(stmt: &mut Q) -> Result, DbErr> { let dbconn = &*DBCONN; let dbbackend = dbconn.get_database_backend(); dbconn @@ -31,7 +54,30 @@ pub async fn query(stmt: &mut Q) -> Result(stmt: &mut Q) -> Result, DbErr> { +/// Ejecuta una consulta y devuelve sólo la primera fila, si existe. +/// +/// Funciona igual que [`fetch_all`] pero detiene la ejecución tras la primera fila y devuelve +/// `None` si la consulta no produce resultados. +/// +/// ```rust,no_run +/// use pagetop_seaorm::db::*; +/// +/// async fn example() -> Result<(), DbErr> { +/// let mut stmt = Query::select() +/// .column(Asterisk) +/// .from(Alias::new("users")) +/// .and_where(Expr::col(Alias::new("id")).eq(1)) +/// .to_owned(); +/// if let Some(row) = fetch_one(&mut stmt).await? { +/// let name: String = row.try_get("", "name")?; +/// println!("{name}"); +/// } +/// Ok(()) +/// } +/// ``` +pub async fn fetch_one( + stmt: &mut Q, +) -> Result, DbErr> { let dbconn = &*DBCONN; let dbbackend = dbconn.get_database_backend(); dbconn @@ -46,11 +92,27 @@ pub async fn exec(stmt: &mut Q) -> Result Result { +/// Ejecuta una sentencia SQL en crudo (INSERT, UPDATE, DELETE…) y devuelve el resultado de +/// la operación. +/// +/// A diferencia de [`fetch_all`] y [`fetch_one`], no construye la consulta, sino que la recibe como +/// cadena ya formada. Útil para sentencias avanzadas o para migraciones puntuales. El +/// [`ExecResult`] devuelto permite consultar las filas afectadas o el último ID insertado. +/// +/// ```rust,no_run +/// use pagetop_seaorm::db::*; +/// +/// async fn example() -> Result<(), DbErr> { +/// let result = execute("DELETE FROM sessions WHERE expired = 1").await?; +/// println!("Filas eliminadas: {}", result.rows_affected()); +/// Ok(()) +/// } +/// ``` +pub async fn execute(stmt: impl Into) -> Result { let dbconn = &*DBCONN; let dbbackend = dbconn.get_database_backend(); dbconn - .execute(Statement::from_string(dbbackend, stmt)) + .execute(Statement::from_string(dbbackend, stmt.into())) .await } diff --git a/extensions/pagetop-seaorm/src/db/dbconn.rs b/extensions/pagetop-seaorm/src/db/dbconn.rs index bd227956..e4881c08 100644 --- a/extensions/pagetop-seaorm/src/db/dbconn.rs +++ b/extensions/pagetop-seaorm/src/db/dbconn.rs @@ -35,10 +35,8 @@ pub static DBCONN: LazyLock = LazyLock::new(|| { tmp_uri .set_password(Some(config::SETTINGS.database.db_pass.as_str())) .unwrap(); - if config::SETTINGS.database.db_port != 0 { - tmp_uri - .set_port(Some(config::SETTINGS.database.db_port)) - .unwrap(); + if let Some(port) = config::SETTINGS.database.db_port { + tmp_uri.set_port(Some(port)).unwrap(); } tmp_uri } @@ -51,13 +49,10 @@ pub static DBCONN: LazyLock = LazyLock::new(|| { .as_str(), ) .unwrap(), - _ => { - trace::error!( - "Unrecognized database type \"{}\"", - &config::SETTINGS.database.db_type - ); - DbUri::parse("").unwrap() - } + _ => panic!( + "Unrecognized database type \"{}\"", + config::SETTINGS.database.db_type + ), }; run_now(Database::connect::({ diff --git a/extensions/pagetop-seaorm/src/db/migration.rs b/extensions/pagetop-seaorm/src/db/migration.rs index 29314bf6..0c32c10a 100644 --- a/extensions/pagetop-seaorm/src/db/migration.rs +++ b/extensions/pagetop-seaorm/src/db/migration.rs @@ -28,6 +28,8 @@ pub trait MigrationTrait: MigrationName + Send + Sync { /// Define actions to perform when rolling back the migration async fn down(&self, _manager: &SchemaManager) -> Result<(), DbErr> { - Err(DbErr::Migration("We Don't Do That Here".to_owned())) + Err(DbErr::Migration( + "Rollback not implemented for this migration".to_owned(), + )) } } diff --git a/extensions/pagetop-seaorm/src/lib.rs b/extensions/pagetop-seaorm/src/lib.rs index 103d95eb..0b686cb2 100644 --- a/extensions/pagetop-seaorm/src/lib.rs +++ b/extensions/pagetop-seaorm/src/lib.rs @@ -39,7 +39,8 @@ db_name = "my_app.db" max_pool_size = 5 ``` -Para MySQL o PostgreSQL añade también `db_user`, `db_pass`, `db_host` y `db_port`. +Para MySQL o PostgreSQL añade también `db_user`, `db_pass` y `db_host`. El campo `db_port` es +opcional; si se omite se usa el puerto predeterminado del motor. **Declara la extensión** en tu aplicación o en la extensión que la requiera: