|
@@ -1,3 +1,4 @@
|
|
|
+use std::collections::HashMap;
|
|
|
use std::fmt::Write;
|
|
|
use std::io;
|
|
|
|
|
@@ -7,6 +8,7 @@ use futures::stream::futures_unordered::FuturesUnordered;
|
|
|
use futures::{Future, FutureExt, StreamExt, TryStreamExt};
|
|
|
use rand::rngs::SmallRng;
|
|
|
use rand::{Rng, SeedableRng};
|
|
|
+use tokio_postgres::types::ToSql;
|
|
|
use tokio_postgres::{connect, Client, NoTls, Statement};
|
|
|
|
|
|
use crate::models::World;
|
|
@@ -18,6 +20,7 @@ pub struct PgConnection {
|
|
|
fortune: Statement,
|
|
|
world: Statement,
|
|
|
rng: SmallRng,
|
|
|
+ updates: HashMap<u16, Statement>,
|
|
|
}
|
|
|
|
|
|
impl PgConnection {
|
|
@@ -28,12 +31,31 @@ impl PgConnection {
|
|
|
actix_rt::spawn(conn.map(|_| ()));
|
|
|
|
|
|
let fortune = cl.prepare("SELECT * FROM fortune").await.unwrap();
|
|
|
+ let mut updates = HashMap::new();
|
|
|
+ for num in 1..=500u16 {
|
|
|
+ let mut pl = 1;
|
|
|
+ let mut q = String::new();
|
|
|
+ q.push_str("UPDATE world SET randomnumber = CASE id ");
|
|
|
+ for _ in 1..=num {
|
|
|
+ let _ = write!(&mut q, "when ${} then ${} ", pl, pl + 1);
|
|
|
+ pl += 2;
|
|
|
+ }
|
|
|
+ q.push_str("ELSE randomnumber END WHERE id IN (");
|
|
|
+ for _ in 1..=num {
|
|
|
+ let _ = write!(&mut q, "${},", pl);
|
|
|
+ pl += 1;
|
|
|
+ }
|
|
|
+ q.pop();
|
|
|
+ q.push(')');
|
|
|
+ updates.insert(num, cl.prepare(&q).await.unwrap());
|
|
|
+ }
|
|
|
let world = cl.prepare("SELECT * FROM world WHERE id=$1").await.unwrap();
|
|
|
|
|
|
PgConnection {
|
|
|
cl,
|
|
|
fortune,
|
|
|
world,
|
|
|
+ updates,
|
|
|
rng: SmallRng::from_entropy(),
|
|
|
}
|
|
|
}
|
|
@@ -49,7 +71,7 @@ impl PgConnection {
|
|
|
Error::from(io::Error::new(io::ErrorKind::Other, format!("{:?}", e)))
|
|
|
})?;
|
|
|
|
|
|
- let mut body = BytesMut::with_capacity(33);
|
|
|
+ let mut body = BytesMut::with_capacity(40);
|
|
|
serde_json::to_writer(
|
|
|
Writer(&mut body),
|
|
|
&World {
|
|
@@ -90,7 +112,7 @@ impl PgConnection {
|
|
|
|
|
|
pub fn update(
|
|
|
&mut self,
|
|
|
- num: usize,
|
|
|
+ num: u16,
|
|
|
) -> impl Future<Output = Result<Vec<World>, io::Error>> {
|
|
|
let worlds = FuturesUnordered::new();
|
|
|
for _ in 0..num {
|
|
@@ -114,23 +136,20 @@ impl PgConnection {
|
|
|
}
|
|
|
|
|
|
let cl = self.cl.clone();
|
|
|
+ let st = self.updates.get(&num).unwrap().clone();
|
|
|
async move {
|
|
|
let worlds: Vec<World> = worlds.try_collect().await?;
|
|
|
|
|
|
- let mut update = String::with_capacity(120 + 6 * num as usize);
|
|
|
- update.push_str(
|
|
|
- "UPDATE world SET randomnumber = temp.randomnumber FROM (VALUES ",
|
|
|
- );
|
|
|
-
|
|
|
+ let mut params: Vec<&dyn ToSql> = Vec::with_capacity(num as usize * 3);
|
|
|
for w in &worlds {
|
|
|
- let _ = write!(&mut update, "({}, {}),", w.id, w.randomnumber);
|
|
|
+ params.push(&w.id);
|
|
|
+ params.push(&w.randomnumber);
|
|
|
+ }
|
|
|
+ for w in &worlds {
|
|
|
+ params.push(&w.id);
|
|
|
}
|
|
|
- update.pop();
|
|
|
- update.push_str(
|
|
|
- " ORDER BY 1) AS temp(id, randomnumber) WHERE temp.id = world.id",
|
|
|
- );
|
|
|
|
|
|
- cl.simple_query(&update)
|
|
|
+ cl.query(&st, ¶ms)
|
|
|
.await
|
|
|
.map_err(|e| io::Error::new(io::ErrorKind::Other, format!("{:?}", e)))?;
|
|
|
|