prisma / tiberius

TDS 7.2+ (Microsoft SQL Server) driver for Rust
Apache License 2.0
327 stars 119 forks source link

Query API -> Dynamic parameters #279

Open Cloud33 opened 1 year ago

Cloud33 commented 1 year ago

I recommend adding a new API to 'Query' to add dynamic SQL scripts.

Motivation: Some data in my foreground needs to be updated, and it will tell me which fields need to be modified, but I currently have no way to implement them well.

That's all I can do now

var user= xxx
var commands = vec![Update::Name,Update::Pwd]  //Fields to be modified
let mut update_sql = "UPDATE [dbo].[user] SET ";
for command in commands.iter() {
   match xxxx
         Update::Name => update_sql + = " Name=@P1"
         Update::Pwd=> update_sql + = " Pwd=@P2";
   xxx
};
let mut query = tiberius::Query::new(update_sql);
for command in commands.iter() {
   match xxxx
         Update::Name => query.bind(user.Name);
         Update::Pwd=> query.bind(user.Pwd);
   xxx
};

let results = query.execute(&mut client).await?;

"I hope it only takes' for 'once, or there's a better way, like C# (Linq):

var user = xxx
var data = Db.Update<User>xxxx;
for command in commands {
   switch(command )
         case Update::Id:  data.SetColumns(t => t.Id== user.Id);
   xxx
};
bittrance commented 1 year ago

I'm not sure I understand exactly what you are trying to achieve, but if what you are trying to achieve is dynamically construct SQL statements, I recommend using a proper SQL grammar lib. sqlparser seems to be the leader of this pack. In your case, I think you want to look at Statement::Update which will allow you to construct Update statements. Once you have constructed one, you can statement.to_string() to get the SQL. Apart from solving the immediate problem, you are also protected against injection attacks (assuming the lib is sufficiently diligent).

If you want a full ORM, tiberius is not the right lib. You may want e.g. SeaORM.

UPDATE: That was impolite. For grammar libs there is also Prisma's own quaint. As far as I can tell, Prisma has no ORM geared toward Rust.

Cloud33 commented 1 year ago

Thank you for your reply. My idea is that I only need for once

like this:

var user= xxx
var commands = vec![Update::Name,Update::Pwd]  //Fields to be modified
let mut query = tiberius::Query::new();
for command in commands.iter() {
   match xxxx
         Update::Name => {
           query.sql + = " Name=@P1";
           query.bind(user.Name);
         },
         Update::Pwd=> {
           query.sql + = " Pwd=@P2";
           query.bind(user.Pwd)
         }
   xxx
};
let results = query.execute(&mut client).await?;

query.sql Can be dynamically assembled