Skip to content

SELECT FOR UPDATE #96

@gammelalf

Description

@gammelalf

Support SELECT ... FOR UPDATE (should be simple)

Workaround for applications until fixed:

/// Use `rorm::query(SelectForUpdate(&mut tx), ...)` to lock the queried rows.
///
/// This type wraps a `&mut Transaction` and its `Executor`
/// to tweak the raw "SELECT" statement before passing it to the database:
/// It appends a "FOR UPDATE" to the "SELECT" statement.
///
/// It is a workaround and should be replaced with proper rorm support.
pub struct SelectForUpdate<'a>(pub &'a mut Transaction);
impl<'executor> Executor<'executor> for SelectForUpdate<'executor> {
    fn execute<'data, 'result, Q>(
        self,
        mut query: String,
        values: Vec<Value<'data>>,
    ) -> Q::Result<'result>
    where
        'executor: 'result,
        'data: 'result,
        Q: QueryStrategy,
    {
        assert!(
            matches!(self.0.dialect(), DBImpl::Postgres),
            "SelectForUpdate executor only supports postgres"
        );
        assert!(
            query.starts_with("SELECT "),
            "SelectForUpdate executor only supports select queries"
        );
        assert!(query.ends_with(';'), "SQL statements end on a semicolon");

        query.pop();
        query.push_str(" FOR UPDATE;");

        self.0.execute::<Q>(query, values)
    }

    fn dialect(&self) -> DBImpl {
        DBImpl::Postgres
    }

    fn into_dyn(self) -> DynamicExecutor<'executor> {
        unimplemented!()
    }

    type EnsureTransactionFuture = Pending<Result<TransactionGuard<'executor>, Error>>;

    fn ensure_transaction(
        self,
    ) -> Pin<Box<dyn Future<Output = Result<TransactionGuard<'executor>, Error>> + Send + 'executor>>
    {
        unimplemented!()
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions