- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试使用actix-web和sqlx设置Web应用程序,在那里我可以进行具有自己的Web服务器和数据库事务的测试。我尝试设置服务器创建方式,使其接受数据库(Postgres)池或使用Executor特性的事务。尽管我在获取应用程序代码和测试编译时遇到了一些问题:
// main.rs
use std::net::TcpListener;
use actix_web::dev::Server;
use actix_web::{web, App, HttpServer, Responder};
use sqlx::PgPool;
async fn create_pool() -> PgPool {
PgPool::connect("postgres://postgres:postgres@localhost:5432/postgres")
.await
.expect("Failed to create pool")
}
async fn index() -> impl Responder {
"Hello World!"
}
pub fn create_server<'a, E: 'static>(
listener: TcpListener,
pool: E,
) -> Result<Server, std::io::Error>
where
E: sqlx::Executor<'a, Database = sqlx::Postgres> + Copy,
{
let server = HttpServer::new(move || App::new().data(pool).route("/", web::get().to(index)))
.listen(listener)?
.run();
Ok(server)
}
pub async fn server(pool: PgPool) -> std::io::Result<()> {
const PORT: usize = 8088;
let listener =
TcpListener::bind(format!("0.0.0.0:{}", PORT)).expect("Failed to create listener");
println!("Running on port {}", PORT);
create_server(listener, pool).unwrap().await
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
let pool = create_pool().await;
server(pool).await;
Ok(())
}
#[cfg(test)]
pub mod tests {
use super::*;
use std::net::TcpListener;
#[actix_rt::test]
async fn test_foo() {
let pool = create_pool().await;
let mut transaction = pool.begin().await.expect("Failed to create transaction");
let listener = TcpListener::bind("0.0.0.0:0").expect("Failed to create listener");
let server = create_server(listener, &mut transaction).expect("Failed to create server");
tokio::spawn(server);
}
}
# Cargo.toml
[package]
name = "sqlx-testing"
version = "0.1.0"
authors = ["Oskar"]
edition = "2018"
[dependencies]
actix-rt = "1.1.1"
actix-web = "3.3.2"
sqlx = { version = "0.4.2", default-features = false, features = ["postgres", "runtime-async-std-native-tls"] }
tokio = "0.2.22"
编译输出
error[E0277]: the trait bound `Pool<Postgres>: Executor<'_>` is not satisfied
--> src\main.rs:37:29
|
17 | pub fn create_server<'a, E: 'static>(
| ------------- required by a bound in this
...
22 | E: sqlx::Executor<'a, Database = sqlx::Postgres> + Copy,
| --------------------------------------------- required by this bound in `create_server`
...
37 | create_server(listener, pool).unwrap().await
| ^^^^ the trait `Executor<'_>` is not implemented for `Pool<Postgres>`
|
= help: the following implementations were found:
<&Pool<DB> as Executor<'p>>
error[E0277]: the trait bound `Pool<Postgres>: Copy` is not satisfied
--> src\main.rs:37:29
|
17 | pub fn create_server<'a, E: 'static>(
| ------------- required by a bound in this
...
22 | E: sqlx::Executor<'a, Database = sqlx::Postgres> + Copy,
| ---- required by this bound in `create_server`
...
37 | create_server(listener, pool).unwrap().await
| ^^^^ the trait `Copy` is not implemented for `Pool<Postgres>`
最佳答案
试图对Executor特质进行通用化是有点矫kill过正。
您可能应该只在测试中使用大小为1的池,然后手动调用Begin
和ROLLBACK
。
#[actix_rt::test]
async fn test_endpoint() {
// build with only one connection
let pool = PgPoolOptions::new()
.max_connections(1)
.connect("postgres://postgres:postgres@localhost:5432/postgres")
.await
.expect("pool failed");
sqlx::query("BEGIN")
.execute(&pool)
.await
.expect("BEGIN failed");
let saved_pool = pool.clone();
let listener = TcpListener::bind("0.0.0.0:0").expect("Failed to create listener");
let server = HttpServer::new(move ||
App::new().data(pool.clone()).service(one))
.listen(listener)
.expect("fail to bind")
.run();
tokio::spawn(server);
// your test
sqlx::query("ROLLBACK")
.execute(&saved_pool)
.await
.expect("ROLLBACK failed");
}
这样,您无需更改代码即可处理测试
// main.rs
use actix_web::{get, web, App, HttpServer, Responder};
use sqlx::{postgres::PgPool, Row};
use std::net::TcpListener;
#[get("/one")]
async fn one(pool: web::Data<PgPool>) -> impl Responder {
let row = sqlx::query("select 1 as id")
.fetch_one(pool.get_ref())
.await
.unwrap();
let one: i32 = row.try_get("id").unwrap();
format!("{:?}", one)
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
let pool = PgPool::connect("postgres://postgres:postgres@localhost:5432/postgres")
.await
.expect("Failed to create pool");
const PORT: usize = 8088;
let listener =
TcpListener::bind(format!("0.0.0.0:{}", PORT)).expect("Failed to create listener");
println!("Running on port {}", PORT);
HttpServer::new(move || App::new().data(pool.clone()).service(one))
.listen(listener)?
.run()
.await
}
#[cfg(test)]
pub mod tests {
use super::*;
use sqlx::postgres::PgPoolOptions;
#[actix_rt::test]
async fn test_endpoint() {
// build with only one connection
let pool = PgPoolOptions::new()
.max_connections(1)
.connect("postgres://postgres:postgres@localhost:5432/postgres")
.await
.expect("pool failed");
sqlx::query("BEGIN")
.execute(&pool)
.await
.expect("BEGIN failed");
let saved_pool = pool.clone();
let listener = TcpListener::bind("0.0.0.0:0").expect("Failed to create listener");
let server = HttpServer::new(move || App::new().data(pool.clone()).service(one))
.listen(listener)
.expect("fail to bind")
.run();
tokio::spawn(server);
// your test
sqlx::query("ROLLBACK")
.execute(&saved_pool)
.await
.expect("ROLLBACK failed");
}
#[actix_rt::test]
async fn test_rollback() {
let pool = PgPoolOptions::new()
.max_connections(1)
.connect("postgres://postgres:postgres@localhost:5432/postgres")
.await
.expect("pool failed");
sqlx::query("BEGIN")
.execute(&pool)
.await
.expect("BEGIN failed");
sqlx::query("CREATE TABLE IF NOT EXISTS test (id SERIAL, name TEXT)")
.execute(&pool)
.await
.expect("CREATE TABLE test failed");
sqlx::query("INSERT INTO test (name) VALUES ('bob')")
.execute(&pool)
.await
.expect("INSERT test failed");
let count: i64 = sqlx::query("SELECT COUNT(id) as count from test")
.fetch_one(&pool)
.await
.expect("SELECT COUNT test failed")
.try_get("count")
.unwrap();
sqlx::query("ROLLBACK")
.execute(&pool)
.await
.expect("ROLLBACK failed");
assert_eq!(count, 1);
}
#[actix_rt::test]
async fn test_no_rollback() {
let pool = PgPoolOptions::new()
.max_connections(1)
.connect("postgres://postgres:postgres@localhost:5432/postgres")
.await
.expect("pool failed");
sqlx::query("CREATE TABLE IF NOT EXISTS test2 (id SERIAL, name TEXT)")
.execute(&pool)
.await
.expect("CREATE TABLE test failed");
sqlx::query("INSERT INTO test2 (name) VALUES ('bob')")
.execute(&pool)
.await
.expect("INSERT test failed");
let count: i64 = sqlx::query("SELECT COUNT(id) as count from test2")
.fetch_one(&pool)
.await
.expect("SELECT COUNT failed")
.try_get("count")
.unwrap();
// this will failed the second time you run your test
assert_eq!(count, 1);
}
}
关于types - 如何创建同时接受sqlx数据库池和事务的actix-web服务器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65370752/
我正在使用 jmoiron sqlx我的 golang 项目的库。我试图创建一个数据库连接mysql。所以,我找到了这两个函数:sqlx.Connect() 和 sqlx.Open(),但没有发现区别
我正在尝试实现一个 sql 查询,它以 jQuery Datatables 期望的方式返回数据,同时允许用户自定义查询(我正在做很多输入验证以确保没有任何 sql 注入(inject))。查询是应该按
前言 上次咱们学习了如何使用Go操作Mysql,并且实现了简单的增删改查。 但是相对来说,还有有点复杂的,可能那些大佬也都觉得繁琐叭。 就又开发出了增强版查询Mysql操作库Sqlx。
我有不同类型的 REST API,它们有一些共同点: 所有类型都有Id 所有类型都有类型 所有类型都有属性,但属性不同 因为我不想有大量不必要的类型,所以我提出了一种类型格式,但它似乎不能被 sqlx
如果我尝试如下使用SQLx Rust的postgres功能, [dependencies] sqlx = { version = "0.3.3", default-features=false , f
我正在尝试使用准备好的语句从 postgress 表中获取一些数据 如果我尝试使用 database.Get() 返回所有内容。 表格: create table accounts ( id
假设我有两个模型, type Customer struct { Id int `json:"id" db:"id"` Name strin
main.rs: #[async_std::main] async fn main() -> Result { use sqlx::Connect; let mut conn = sq
在 sqlx有一个 Transaction type 允许您在一个事务中运行多个查询。 我试图弄清楚如何做到这一点,遗憾的是没有记录,尽管有自动生成的 API 文档。 我的第一次尝试: async f
我在MySQL数据库中有一张大表,我正试图尽可能高效地读取该表。我当时在考虑通过添加多个工作程序来加速代码,但是当我这样做时,在运行它的开始(并且仅在开始时)出现编码(marshal)处理错误,它看起
我在 Go 中使用 sqlx,这非常有帮助,但是当我使用 struct scan 并且 struct 的类型与 sql 类型不匹配时,它似乎没有抛出错误。例如,我在这里设置了一个数据库,使其具有名称(
我正在使用 sqlx 在我的 Go 代码中执行查询。该查询有一长串值(~10,000),我需要在 WHERE IN (?) 子句中对其进行过滤。这会导致性能大幅下降。我该如何优化这样的查询?此外,此查
此问题特定于 github.com/jmoiron/sqlx .我想用命名查询插入一个已知的时间戳或日期。我怎么做?我使用 time.Now() 作为给定时间戳的示例。 这是我在 MySQL 中的表:
我正在尝试使用一个简单的查询将两个表 person 和 profile 内部连接起来,这似乎适用于 mysql 但不适用于 sqlx。这是我的代码: package main import (
我正在使用 go 1.10.3,我正在尝试使用 sqlx 包获取一行并将其输入到带有 Get() 的结构中,或者获取多行并输入它们使用 Select() slice 。 让我们从将一行放入结构开始。
我想在单个查询中更新多行: //threadIDs is a variable length slice of integers like [3 5 6] query := "UPDATE messa
考虑以下示例: package main import ( "fmt" "github.com/jmoiron/sqlx" _ "github.com/go-sql-drive
但是下面粘贴的代码永远不起作用,而不是一个一个地迭代和扫描结果,是否有可能让下面的代码起作用?? 非常感谢您的投入。谢谢 type CustomData struct { ID
我正在尝试执行包含自定义 geoPoint 类型的 postgres 查询,但收到意外的 EOF 错误。对我做错了什么有什么想法吗? type Account struct { Id
我正在学习 Go 并尝试创建一个具有“字段”参数的 API 端点。当我尝试将 sqlx 结果行扫描到结构中时,但是用户省略的字段将作为空字符串返回。有没有办法可以更改结构以仅反射(reflect)用户
我是一名优秀的程序员,十分优秀!