prisma / quaint Goto Github PK
View Code? Open in Web Editor NEWSQL Query AST and Visitor for Rust
License: Apache License 2.0
SQL Query AST and Visitor for Rust
License: Apache License 2.0
Test reproduction: #186
SELECT 1; SELECT YOLO;
will fail at the second statement, but no error will be returned to the caller. We would want this feature to run a SQL script with multiple statements and know whether it succeeded or errored.
Hi,
The connector
module is not available without activating at least one backend feature. This makes it impossible to build a backend-independent crate that only uses the traits defined in this module. Is there a reason for that? Why can't I have access to the connector::Queryable
trait?
This is something I had to discover the hard way, since it is not documented.
Even while it takes a file path as parameter, Sqlite::new
does not open the file but creates an in-memory database. The method attach_database
seems to used to attach the file afterward? This is quite weird to be honest.
If Sqlite::new
takes a file name, then it should use the given file as main schema. If you want to keep new
to create in-memory database, I would advocate removing its input parameter and add a new Sqlite::open
method to open an on-disk file.
Also the method attach_database
should comply to the sqlite semantics: take a file name and a schema name, and bind them together.
Here we introduced a transaction around DDL operations in order to abort invalid enum migrations. prisma/prisma-engines#1016
When the transaction fails without an explicit rollback being submitted next, the following statement will reuse the same connection and error. See here: https://stackoverflow.com/questions/10399727/psqlexception-current-transaction-is-aborted-commands-ignored-until-end-of-tra
We should look into how Quaint could handle this case.
https://github.com/prisma/tiberius/blob/main/src/query.rs
Should skip quite a bunch of allocations and remove code from Quaint.
I wanted to create the issue so we don't forget it.
Basically due to this PR importcjj/mobc#54, if the health check fails it will retry to get a connection.
This is a good behaviour in general, but prisma decided to fail on all broken connections and defer to the client what to do.
This will break this consistent behaviour since sometimes it will retry broken connections (mobc health check) and sometimes it won't (failed perform_io).
A quick fix is to set the max_bad_conn_retries
to 0 (currently we use the default of two)
Hello all. Does Quaint allow multi tenancy with postgresql schema?
What the title says. The lib doesn't currently support the variable numeric type: https://www.postgresql.org/docs/9.1/datatype-numeric.html which says up to 131072 digits before the decimal point; up to 16383 digits after the decimal point
. It crashes if it's used with a numeric type beyond 2^128 because of the code in this function: https://github.com/prisma/quaint/blob/main/src/connector/postgres/conversion/decimal.rs#L81
Opinions on the best way to fix it? I can try submitting a PR if I get some time this week.
I realised that the PR #344 only stops the crash but the underlying issue is that large numeric types aren't supported
I'm trying to use quaint with postgres, and I'm having trouble building/using quaint.
rustup 1.24.3 (ce5817a94 2021-05-31)
rustc 1.57.0-nightly (308dffd25 2021-09-22)
cargo 1.57.0-nightly (9a28ac83c 2021-09-18)
[package]
name = "my-quaint-example"
version = "0.1.0"
edition = "2021"
[dependencies]
quaint = { version = "0.1.13", features = ["pooled"] }
tokio = { version = "1.12.0", features = ["full"] }
serde = { version = "1.0", features = ["derive"] }
async-trait = "0.1.51"
I get errors when I try to import pooled
or single
, as outlined here.
I've tried using a bunch of different combinations of the following features in Cargo.toml, but I can't get the imports to resolve:
use async_trait::async_trait;
use quaint::{pooled::Quaint, prelude::*};
// use quaint::{prelude::*, single::Quaint};
use serde::{Deserialize, Serialize};
unresolved imports `quaint::pooled`, `quaint::single`
could not find `pooled` in `quaint`
When I try to use any of the postgres features (ie full-postgresql
), I get build errors:
Compiling rust_decimal v1.16.0
error[E0432]: unresolved import `byteorder`
--> /Users/me/.cargo/registry/src/github.com-1ecc6299db9ec823/rust_decimal-1.16.0/src/db.rs:466:9
|
466 | use byteorder::{BigEndian, ReadBytesExt};
| ^^^^^^^^^ use of undeclared crate or module `byteorder`
error[E0432]: unresolved import `bytes`
--> /Users/me/.cargo/registry/src/github.com-1ecc6299db9ec823/rust_decimal-1.16.0/src/db.rs:467:9
|
467 | use bytes::{BufMut, BytesMut};
| ^^^^^ use of undeclared crate or module `bytes`
error[E0599]: no method named `read_u16` found for struct `std::io::Cursor` in the current scope
--> /Users/me/.cargo/registry/src/github.com-1ecc6299db9ec823/rust_decimal-1.16.0/src/db.rs:526:34
|
526 | let num_groups = raw.read_u16::<BigEndian>()?;
| ^^^^^^^^ method not found in `std::io::Cursor<&[u8]>`
|
::: /Users/me/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.12.0/src/io/util/async_read_ext.rs:424:16
|
424 | fn read_u16(&mut self) -> ReadU16;
| -------- the method is available for `Pin<&mut std::io::Cursor<&[u8]>>` here
|
= help: items from traits can only be used if the trait is in scope
help: consider wrapping the receiver expression with the appropriate type
|
526 | let num_groups = Pin::new(&mut raw).read_u16::<BigEndian>()?;
| +++++++++++++ +
help: the following traits are implemented but not in scope; perhaps add a `use` for one of them:
|
464 | use gimli::endianity::Endianity;
|
464 | use gimli::read::reader::Reader;
|
464 | use object::endian::Endian;
|
464 | use byteorder::io::ReadBytesExt;
|
and 1 other candidate
error[E0599]: no method named `read_i16` found for struct `std::io::Cursor` in the current scope
--> /Users/me/.cargo/registry/src/github.com-1ecc6299db9ec823/rust_decimal-1.16.0/src/db.rs:527:30
|
527 | let weight = raw.read_i16::<BigEndian>()?; // 10000^weight
| ^^^^^^^^ method not found in `std::io::Cursor<&[u8]>`
|
::: /Users/jlymecargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.12.0/src/io/util/async_read_ext.rs:462:16
|
462 | fn read_i16(&mut self) -> ReadI16;
| -------- the method is available for `Pin<&mut std::io::Cursor<&[u8]>>` here
|
= help: items from traits can only be used if the trait is in scope
help: consider wrapping the receiver expression with the appropriate type
|
527 | let weight = Pin::new(&mut raw).read_i16::<BigEndian>()?; // 10000^weight
| +++++++++++++ +
help: the following traits are implemented but not in scope; perhaps add a `use` for one of them:
|
464 | use gimli::endianity::Endianity;
|
464 | use gimli::read::reader::Reader;
|
464 | use object::endian::Endian;
|
464 | use byteorder::io::ReadBytesExt;
|
and 1 other candidate
error[E0599]: no method named `read_u16` found for struct `std::io::Cursor` in the current scope
--> /Users/me/.cargo/registry/src/github.com-1ecc6299db9ec823/rust_decimal-1.16.0/src/db.rs:529:28
|
529 | let sign = raw.read_u16::<BigEndian>()?;
| ^^^^^^^^ method not found in `std::io::Cursor<&[u8]>`
|
::: /Users/me/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.12.0/src/io/util/async_read_ext.rs:424:16
|
424 | fn read_u16(&mut self) -> ReadU16;
| -------- the method is available for `Pin<&mut std::io::Cursor<&[u8]>>` here
|
= help: items from traits can only be used if the trait is in scope
help: consider wrapping the receiver expression with the appropriate type
|
529 | let sign = Pin::new(&mut raw).read_u16::<BigEndian>()?;
| +++++++++++++ +
help: the following traits are implemented but not in scope; perhaps add a `use` for one of them:
|
464 | use gimli::endianity::Endianity;
|
464 | use gimli::read::reader::Reader;
|
464 | use object::endian::Endian;
|
464 | use byteorder::io::ReadBytesExt;
|
and 1 other candidate
error[E0599]: no method named `read_u16` found for struct `std::io::Cursor` in the current scope
--> /Users/me/.cargo/registry/src/github.com-1ecc6299db9ec823/rust_decimal-1.16.0/src/db.rs:531:29
|
531 | let scale = raw.read_u16::<BigEndian>()?;
| ^^^^^^^^ method not found in `std::io::Cursor<&[u8]>`
|
::: /Users/me/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.12.0/src/io/util/async_read_ext.rs:424:16
|
424 | fn read_u16(&mut self) -> ReadU16;
| -------- the method is available for `Pin<&mut std::io::Cursor<&[u8]>>` here
|
= help: items from traits can only be used if the trait is in scope
help: consider wrapping the receiver expression with the appropriate type
|
531 | let scale = Pin::new(&mut raw).read_u16::<BigEndian>()?;
| +++++++++++++ +
help: the following traits are implemented but not in scope; perhaps add a `use` for one of them:
|
464 | use gimli::endianity::Endianity;
|
464 | use gimli::read::reader::Reader;
|
464 | use object::endian::Endian;
|
464 | use byteorder::io::ReadBytesExt;
|
and 1 other candidate
error[E0599]: no method named `read_u16` found for struct `std::io::Cursor` in the current scope
--> /Users/me/.cargo/registry/src/github.com-1ecc6299db9ec823/rust_decimal-1.16.0/src/db.rs:536:33
|
536 | groups.push(raw.read_u16::<BigEndian>()?);
| ^^^^^^^^ method not found in `std::io::Cursor<&[u8]>`
|
::: /Users/me/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.12.0/src/io/util/async_read_ext.rs:424:16
|
424 | fn read_u16(&mut self) -> ReadU16;
| -------- the method is available for `Pin<&mut std::io::Cursor<&[u8]>>` here
|
= help: items from traits can only be used if the trait is in scope
help: consider wrapping the receiver expression with the appropriate type
|
536 | groups.push(Pin::new(&mut raw).read_u16::<BigEndian>()?);
| +++++++++++++ +
help: the following traits are implemented but not in scope; perhaps add a `use` for one of them:
|
464 | use gimli::endianity::Endianity;
|
464 | use gimli::read::reader::Reader;
|
464 | use object::endian::Endian;
|
464 | use byteorder::io::ReadBytesExt;
|
and 1 other candidate
Some errors have detailed explanations: E0432, E0599.
For more information about an error, try `rustc --explain E0432`.
error: could not compile `rust_decimal` due to 7 previous errors
Are there code examples I can use to figure out what I'm missing in my Cargo.toml & code?
Part of an epic: #138
The last item to be done after others.
library now have old dependency in rusqlite (version 0.17) but fresh version is 0.24. I need to use UPSERT sql construction, but it became available only since rusqlite v0.20.0 (https://github.com/rusqlite/rusqlite/releases)
Is there any reasons to use so old version of rusqlite and libsqlite3-sys ?
Write-up of the issue: prisma/specs#325
We discussed it with Matt and Jan, and decided that for now, we should align on what all other clients are doing, i.e. accept invalid (=not trusted) ssl certificates by default.
For all backends.
Features enabled: "sqlite", "mysql", "chrono"
Compiling quaint v0.2.0-alpha.13
error[E0599]: no variant or associated item named `DateTime` found for enum `values::Value<'_>` in the current scope
--> /Users/work/.cargo/registry/src/github.com-1ecc6299db9ec823/quaint-0.2.0-alpha.13/src/connector/sqlite/conversion.rs:40:63
|
40 | Some("DATE") | Some("DATETIME") => Value::DateTime(None),
| ^^^^^^^^ variant or associated item not found in `values::Value<'_>`
|
::: /Users/work/.cargo/registry/src/github.com-1ecc6299db9ec823/quaint-0.2.0-alpha.13/src/ast/values.rs:44:1
|
44 | pub enum Value<'a> {
| ------------------ variant or associated item `DateTime` not found here
Currently i64 is used to support MySQL UInt. Is it possible to replace it with u64 and support whole size of unsigned
big integer? serde_json
supports u64 Number type.
Our feature flags are a mess. We should clean them up and run more feature combinations on CI before merging anything.
I really like quaint so far however I would like to use it in a web but I'm not able to currently as the connection pool looks like clone isn't implemented or it is private. Here's an example with actix-web:
let pool = Quaint::new("postgres:////user:password@host/database").await?;
actix_web::HttpServer::new(move || {
actix_web::App::new()
.data(pool.clone())
.service(routes::routes())
})
.bind(format!("0.0.0.0:{}", port))?
.run()
.await?;
Hi !
Some database specific features are missing from this library. Rather than implementing everyone of them. It would be nice to be able to reuse an argument vectors, so that when concatenating queries, the arguments will be correctly numbered.
Something like (pseudo-code) :
let main_insert = Insert::single_into("my_table")
.value("foo", 10)
.build()
.returning("id");
let following_insert = Insert::single_into("my_dep_table")
.value("foo", 10)
.value("main_id", Select::from_table("main_insert").column("id"))
.build()
.returning("id");
let final_select = Select::from_table("main_insert")
.and_from("following_insert")
.column(Column::from(("main_insert", "id")).alias("main_insert_id"))
.column(Column::from(("following_insert", "id")).alias("following_insert_id"));
let params: Vec<Value<'_>> = Vec::with_capacity(128);
let (main_insert_query, params) = Postgres::build_with_params(main_insert, params);
let (following_insert_query, params) = Postgres::build_with_params(following_insert, params);
let (final_select_query, params) = Postgres::build_with_params(final_select, params);
let query = format!("WITH 'main_insert' AS ({}), 'following_insert' AS ({}) {};",
main_insert_query, following_insert_query, final_select_query);
Consider the following path:
So in between health checks, a connection is always returned to the pool even if it is broken.
There is a mechanism in place in mobc to prevent a connection from re-entering the pool:
https://github.com/importcjj/mobc/blob/master/src/lib.rs#L648
Currently the manager always return true (https://github.com/importcjj/mobc/blob/master/src/lib.rs#L187) since it doesn't override the method validate from the Manager
trait (https://github.com/prisma/quaint/blob/master/src/pooled/manager.rs#L74).
This means we needs to store information in the connection that the manager can read to deny re-entry. Unfortunately the current Queryable
interface doesn't take a mutable reference to self so we would need to change that first for all methods (https://github.com/prisma/quaint/blob/master/src/connector/queryable.rs#L19) and then we could add a method is_dead
or in_error
to that the validate
function would call.
I can do the changes, but I wanted to check with the team before since it is significant.
Support set variables for certain SQL dialects.
SET [GLOBAL | SESSION] [@]variable = value;
SET [LOCAL | SESSION] variable [=|TO] value
SQL Server cannot set a variable without declaring it first:
DECLARE @variable INT;
SET @variable = 1;
In MySQL, the prefix @
is optional while in SQL Server is required.
SQLite does not support setting variables.
Hi guys,
First, thanks for releasing this project. The flexibility it provides is exactly what I was looking for and I appreciate you opening it up to the community.
That said, I was trying to use the package and having a heck of a time (I almost gave up on it) because I kept running into an error, even when I was practically copy-pasting examples from the documentation. After further digging I've narrowed the issue down to the columns() method in the query builder which doesn't seem to play nice with MySQL 5.6 which I was testing on. I don't know if the same issue persists on all versions of MySQL, but I figured I'd inform you guys. (Or maybe I'm doing something wrong and need to be educated?).
In the code below I attempt to run the same query and get the results, first using multiple column() calls, and the second with a single columns() call. Here's the code, then I'll post the results I get after:
#[derive(Debug, PartialEq, Eq)]
pub struct User {
pub user_id: Option<i64>,
pub first_name: Option<String>,
pub last_name: Option<String>,
}
// Setup
let pool = Quaint::new("mysql://root:[email protected]:3306/some_database").await?;
let conn = pool.check_out().await?;
// ///////////////////////////////////////////////////////////
// First query with each column specified individually - WORKS
// ///////////////////////////////////////////////////////////
println!("\r\n\r\n################# FIRST QUERY #################\r\n");
// Build query
let query1 = Select::from_table("users")
.column("user_id")
.column("first_name")
.column("last_name")
.limit(5);
// Output the SQL generated
let (sql_str1, params) = Mysql::build(query1.clone());
println!("{}", sql_str1);
// Run the query and print the number of returned results
let results = conn.query(Query::from(query1)).await.unwrap();
println!("Number of results: {}", results.len());
// Try grabbing and printing the first result
if let Some(row) = results.get(0) {
println!("{:#?}", row);
let user = User {
user_id: row["user_id"].as_i64(),
first_name: row["first_name"].to_string(),
last_name: row["last_name"].to_string(),
};
println!("{:#?}", user);
};
// ///////////////////////////////////////////////////////////
// Second query with columns specified in array - BROKEN
// ///////////////////////////////////////////////////////////
println!("\r\n\r\n################# SECOND QUERY #################\r\n");
// Build query
let query2 = Select::from_table("users")
.columns(vec!["user_id", "first_name", "last_name"])
.limit(5);
// Output the SQL generated
let (sql_str2, params) = Mysql::build(query2.clone());
println!("{}", sql_str2);
// Run the query and print the number of returned results
let results = conn.query(Query::from(query2)).await.unwrap();
println!("Number of results: {}", results.len());
// Try grabbing and printing the first result
if let Some(row) = results.get(0) {
println!("{:#?}", row);
let user = User {
user_id: row["user_id"].as_i64(),
first_name: row["first_name"].to_string(),
last_name: row["last_name"].to_string(),
};
println!("{:#?}", user);
};
################# FIRST QUERY #################
SELECT `user_id`, `first_name`, `last_name` FROM `users` LIMIT ?
Number of results: 5
ResultRowRef {
name_to_index: {
"first_name": 1,
"last_name": 2,
"user_id": 0,
},
values: [
Integer(
1,
),
Text(
"John",
),
Text(
"Doe",
),
],
}
User {
user_id: Some(
1,
),
first_name: Some(
"John",
),
last_name: Some(
"Doe",
),
}
################# SECOND QUERY #################
SELECT ?, ?, ? FROM `users` LIMIT ?
Number of results: 5
ResultRowRef {
name_to_index: {
"?": 2,
},
values: [
Text(
"user_id",
),
Text(
"first_name",
),
Text(
"last_name",
),
],
}
thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', src/libcore/option.rs:378:21
Notice that in both cases the number of rows returned is correct at 5, however the results are messed up in the second scenario as they are just the column names and the program obviously panics when trying to unwrap.
SNIP (I think this was wrong, see my next comment)
The documentation on prepared queries for MySQL 5.6 seem to indicate that placeholders for column names should work (https://dev.mysql.com/doc/refman/5.6/en/sql-prepared-statements.html)
So I'm not positive where the error is coming from, but it's obviously by the difference in the generated query between column() and columns(), so for the moment I'm just going to avoid columns().
Hope I explained that well. I realize the error could be in the version of MySQL I tested on, or the Rust MySQL library, but I figured I'd submit a report and let you take a look at it. Cheers guys, thanks again and sorry about throwing a bug report your way!
This is a ticket for functionality needed before releasing version 0.1 of the crate.
ResultRow
, check if we could copy less and move insteadStream
in addition to a fully allocated Vec
failure
with something implementing std::error::Error
bonus:
The parsing logic for SqliteParams
assumes file:
.
The sqlite connector opens a new in-memory database connection, then executes a command like ATTACH /path/to/database AS quaint;
. This results in the main
schema being the in-memory one, and the quaint
schema being the actual database. This is a problem for the following reasons:
main
, and this cannot be changed. Thus, unqualified queries like SELECT * FROM my_table
are executed against the in-memory database.SELECT * FROM quaint.my_table
. However, there are a couple problems with that.
SELECT * FROM "quaint.my_table"
instead).The net result of this situation is that all queries get executed against the in-memory database, rather than the database on disk. I think the simplest way to resolve this would be to drop the db_name
functionality and avoid using schema-names other than main
entirely, since sqlite doesn't have any way to select a default schema to use, unlike e.g. Postgres's \connect
or MySQL's use
statements.
I couldn't find any way around this issue to execute commands against the database on disk, but please let me know if I missed something obvious.
Gather here what we miss from PyPika's AST
First, thank you, the library is awesome.
Second, I'm having difficulty understanding how to add an alias to an aggregate column. Specifically when using the aggregate_to_string
function (as seen below).
Select::from_table("employee")
.column(("employee", "id"))
.column(("employee", "created"))
.column(("employee", "updated"))
.column(("employee", "deleted"))
.column(("employee", "casino_id"))
.column(("employee", "uuid"))
.column(("employee", "name_first"))
.column(("employee", "name_last"))
.column(("employee", "title"))
.value(aggregate_to_string(Column::from(("role", "display"))))
.inner_join(join_credential)
.inner_join(join_credential_role)
.inner_join(join_role)
.group_by(Column::from(("employee", "id")))
Is it possible to assign an alias to the .value(aggregate_to_string(Column::from(("role", "display"))))
?
Hi !
It would be a nice addition to be able to return rows as JSON
in Postgres
.
Reproducer:
use quaint::pooled::Quaint;
use quaint::prelude::*;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
let q = Quaint::new("sqlite:test.db").await?;
let c = q.check_out().await?;
c.execute_raw("", &[]).await?;
Result::Ok(())
}
Backtrace:
* frame #0: 0x00005555557bc69c quaint-test`sqlite3_clear_bindings(pStmt=0x0000000000000000) at sqlite3.c:81610:40
frame #1: 0x000055555576df82 quaint-test`rusqlite::raw_statement::RawStatement::clear_bindings::h343c364d834a7c75(self=0x00007fffffff9d50) at raw_statement.rs:95:18
frame #2: 0x00005555557717d5 quaint-test`rusqlite::cache::StatementCache::cache_stmt::h7a92c872dee251b7(self=0x0000555555a99250, stmt=(__0 = 0x0000000000000000)) at cache.rs:139:9
frame #3: 0x000055555577137e quaint-test`_$LT$rusqlite..cache..CachedStatement$u20$as$u20$core..ops..drop..Drop$GT$::drop::h36e26cdc88cefec4(self=0x00007fffffff9f10) at cache.rs:86:13
frame #4: 0x0000555555763977 quaint-test`core::ptr::drop_in_place::h920545ed40fe7c7a((null)=0x00007fffffff9f10) at mod.rs:177:1
frame #5: 0x000055555562fd81 quaint-test`_$LT$quaint..connector..sqlite..Sqlite$u20$as$u20$quaint..connector..queryable..Queryable$GT$::execute_raw::_$u7b$$u7b$closure$u7d$$u7d$::_$u7b$$u7b$closure$u7d$$u7d$::h2fd5e94fff290f82 at sqlite.rs:205:13
frame #6: 0x000055555562fea1 quaint-test`_$LT$quaint..connector..sqlite..Sqlite$u20$as$u20$quaint..connector..queryable..Queryable$GT$::execute_raw::_$u7b$$u7b$closure$u7d$$u7d$::h88ce23e985472900 at sqlite.rs:207:19
frame #7: 0x00005555556108ae quaint-test`quaint::connector::metrics::query::_$u7b$$u7b$closure$u7d$$u7d$::h1fb49f99e7b8e4ec((null)=<unavailable>) at metrics.rs:19:19
frame #8: 0x0000555555615cdf quaint-test`_$LT$std..future..GenFuture$LT$T$GT$$u20$as$u20$core..future..future..Future$GT$::poll::h9f2b432ea5ca4614(self=Pin<&mut std::future::GenFuture<generator-0>> @ 0x00007fffffffa720, cx=0x00007fffffffb5f0) at future.rs:44:15
frame #9: 0x000055555563deb9 quaint-test`_$LT$quaint..connector..dbio..DBIO$LT$T$GT$$u20$as$u20$core..future..future..Future$GT$::poll::he066444a35b3d1db(self=Pin<&mut quaint::connector::dbio::DBIO<u64>> @ 0x00007fffffffa780, ctx=0x00007fffffffb5f0) at dbio.rs:25:9
frame #10: 0x000055555561486d quaint-test`std::future::poll_with_tls_context::h64437bc63477017d(f=Pin<&mut quaint::connector::dbio::DBIO<u64>> @ 0x00007fffffffa818) at future.rs:99:14
frame #11: 0x00005555555e59fe quaint-test`quaint_test::main::_$u7b$$u7b$closure$u7d$$u7d$::h17c3c46f3093e878((null)=<unavailable>) at main.rs:8:5
frame #12: 0x00005555555e4702 quaint-test`_$LT$std..future..GenFuture$LT$T$GT$$u20$as$u20$core..future..future..Future$GT$::poll::h71fdd89390940c42(self=Pin<&mut std::future::GenFuture<generator-0>> @ 0x00007fffffffb390, cx=0x00007fffffffb5f0) at future.rs:44:15
frame #13: 0x00005555555fc6b6 quaint-test`tokio::runtime::enter::Enter::block_on::_$u7b$$u7b$closure$u7d$$u7d$::h3e459cfe52175f05 at enter.rs:101:58
frame #14: 0x00005555555bd6da quaint-test`tokio::coop::budget::_$u7b$$u7b$closure$u7d$$u7d$::h89bc075f7eb66002(hits=0x00007ffff7c0a2d8) at coop.rs:97:9
frame #15: 0x00005555555d1d82 quaint-test`std::thread::local::LocalKey$LT$T$GT$::try_with::h3668363ab3b1f608(self=0x0000555555a27c38, f=closure-0 @ 0x00007fffffffb4f0) at local.rs:262:16
frame #16: 0x00005555555d14fd quaint-test`std::thread::local::LocalKey$LT$T$GT$::with::hc82aeb690e204b0f(self=0x0000555555a27c38, f=closure-0 @ 0x00007fffffffb568) at local.rs:239:9
frame #17: 0x00005555555fc543 quaint-test`tokio::runtime::enter::Enter::block_on::h7890a791e1399f56 [inlined] tokio::coop::budget::h28f55ca60abb5d42(f=closure-0 @ 0x00007fffffffb698) at coop.rs:79:5
frame #18: 0x00005555555fc50f quaint-test`tokio::runtime::enter::Enter::block_on::h7890a791e1399f56(self=0x00007fffffffb6f0, f=(__0 = quaint_test::main::generator-0 @ 0x00007fffffffb710)) at enter.rs:101
frame #19: 0x00005555555fec5f quaint-test`tokio::runtime::thread_pool::ThreadPool::block_on::h392433f9e3cb7450(self=0x00007fffffffd2e0, future=(__0 = quaint_test::main::generator-0 @ 0x00007fffffffc298)) at mod.rs:82:9
frame #20: 0x00005555555bf699 quaint-test`tokio::runtime::Runtime::block_on::_$u7b$$u7b$closure$u7d$$u7d$::he2e7354750fff41d at mod.rs:420:39
frame #21: 0x00005555555caa1e quaint-test`tokio::runtime::context::enter::hb24868dd9b9fc1a5(new=<unavailable>, f=closure-0 @ 0x00007fffffffcaf8) at context.rs:72:5
frame #22: 0x00005555555d575b quaint-test`tokio::runtime::handle::Handle::enter::h6817f5ac891ddcb7(self=0x00007fffffffd380, f=closure-0 @ 0x00007fffffffcef0) at handle.rs:39:9
frame #23: 0x00005555555bf5cd quaint-test`tokio::runtime::Runtime::block_on::h4a50a777093425e4(self=0x00007fffffffd2d8, future=<unavailable>) at mod.rs:415:9
frame #24: 0x00005555555fca6f quaint-test`quaint_test::main::hc13577d9a723c273 at main.rs:4:1
frame #25: 0x00005555555ce97b quaint-test`std::rt::lang_start::_$u7b$$u7b$closure$u7d$$u7d$::h1951a0cef2c0ae64 at rt.rs:67:34
frame #26: 0x00005555558f3f2f quaint-test`std::rt::lang_start_internal::h0962c0aa989e5c64 [inlined] std::rt::lang_start_internal::_$u7b$$u7b$closure$u7d$$u7d$::he55e3739ea41259e at rt.rs:52:13
frame #27: 0x00005555558f3f24 quaint-test`std::rt::lang_start_internal::h0962c0aa989e5c64 [inlined] std::panicking::try::do_call::h73e24f9817ae57df at panicking.rs:331
frame #28: 0x00005555558f3f24 quaint-test`std::rt::lang_start_internal::h0962c0aa989e5c64 [inlined] std::panicking::try::hd08eb281999526b6 at panicking.rs:274
frame #29: 0x00005555558f3f24 quaint-test`std::rt::lang_start_internal::h0962c0aa989e5c64 [inlined] std::panic::catch_unwind::hc981e5be87497715 at panic.rs:394
frame #30: 0x00005555558f3f24 quaint-test`std::rt::lang_start_internal::h0962c0aa989e5c64 at rt.rs:51
frame #31: 0x00005555555ce957 quaint-test`std::rt::lang_start::h252a346e8020a484(main=(quaint-test`quaint_test::main::hc13577d9a723c273 at main.rs:4), argc=1, argv=0x00007fffffffdf18) at rt.rs:67:5
frame #32: 0x00005555555fcb1a quaint-test`main + 42
frame #33: 0x00007ffff7d78023 libc.so.6`__libc_start_main + 243
frame #34: 0x00005555555bd30e quaint-test`_start + 46
We have stable Tokio and Bytes finally, we should uniformly use version 1 of both throughout our ecosystem; mostly the upgrades are needed in Quaint.
This requires overseeing or helping out with the following
PostgreSQL supports an options
parameter for connection strings:
Specifies command-line options to send to the server at connection start. For example, setting this to -c geqo=off sets the session's value of the geqo parameter to off. Spaces within this string are considered to separate command-line arguments, unless escaped with a backslash (); write \ to represent a literal backslash.
https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNECT-OPTIONS
Cockroach Cloud for example uses that to submit the cluster name when a connection is created: ...?options=--cluster%3D{{CLUSTER_NAME}}
Our PostgreSQL driver Tokio-Postgres also support this parameter:
options
- Command line options used to configure the server.
https://docs.rs/tokio-postgres/latest/tokio_postgres/config/struct.Config.html
Right now it seems we are filtering this value out of the connection string, or at least not forwarding it to Tokio-Postgres: https://prisma.github.io/quaint/src/quaint/connector/postgres.rs.html#267
It would be great if we could enable Prisma to use the options
parameter in PostgreSQL connection strings.
When querying certain postgres types, quaint throws Error querying the database: error deserializing column N: cannot convert between the Rust type `core::option::Option<alloc::string::String>` and the Postgres type `XXX`
, where XXX is one of:
*
: not fully supported by tokio-postgres
Some of these types are pretty obscure (though I do use them all), but some like "timestamptz" are fairly common. The type json
is an odd one, since you've already got a variant for Json in ParameterizedValue, but it doesn't seem to work
It would be fine if values of unsupported types were returned as a string, users can transform them to the proper types in client code
Hey awesome quaint maintainers :) I'm getting this error when attempting to compile quaint:
Compiling quaint v0.2.0-alpha.13 (https://github.com/prisma/quaint.git#03a6d66d)
error[E0201]: duplicate definitions with name `visit_not_equals`:
--> /Users/Max/.cargo/git/checkouts/quaint-9f01e008b9a89c14/03a6d66/src/visitor/postgres.rs:258:5
|
230 | / fn visit_not_equals(&mut self, left: Expression<'a>, right: Expression<'a>) -> visitor::Result {
231 | | // LHS must be cast to json/xml-text if the right is a json/xml-text value and vice versa.
232 | | let right_cast = match left {
233 | | #[cfg(feature = "json-1")]
... |
254 | | Ok(())
255 | | }
| |_____- previous definition of `visit_not_equals` here
...
258 | / fn visit_not_equals(&mut self, left: Expression<'a>, right: Expression<'a>) -> visitor::Result {
259 | | self.visit_expression(left)?;
260 | | self.write(" <> ")?;
261 | | self.visit_expression(right)
262 | | }
| |_____^ duplicate definition
error: aborting due to previous error
In case it helps, here are my cargo dependencies:
[dependencies]
tokio = { version = "0.2", features = ["full"]}
quaint = { git = "https://github.com/prisma/quaint.git", features = ["full-mssql"]}
and here's my silly test main.rs
:
use quaint::{prelude::*, pooled::Quaint};
// assuming a local mssql instance started via:
// docker run -e 'ACCEPT_EULA=Y' -e 'SA_PASSWORD=<YourStrong@Passw0rd>' -p 1433:1433 -d mcr.microsoft.com/mssql/server:2017-latest
#[tokio::main]
async fn main() -> Result<(), quaint::error::Error> {
let dsn = "sqlserver://127.0.0.1:1433;database=master;user=SA;password=<YourStrong@Passw0rd>;trustServerCertificate=true;encrypt=DANGER_PLAINTEXT";
let pool = Quaint::builder(dsn)?.build();
let conn = pool.check_out().await?;
let result = conn.select(Select::default().value(1)).await?;
assert_eq!(
Some(1),
result.into_iter().nth(0).and_then(|row| row[0].as_i64()),
);
Ok(())
}
The visitor always translates a ConditionTree::NoCondition
as 1=1
, which leads to the unexpected outcome that for an OR
filter, the entire expression becomes truthy.
After a cursory inspection of the visitor, I believe a fix would require the visitor to have context about the parent, which it isn't designed to have at the moment (as far as I can tell).
Part of an epic: #138
If you'd like to pull more of the connector responsibility out of quaint, SQLx's MSSQL support might be a way to do that. I know this is an odd call-out since you guys maintain tiberius :) Perhaps the SQLx devs could leverage the awesome work that's gone in to tiberius.
Looks like master is still unhappy when compiling with the full-mssql
feature turned on. Here's the failing Travis build and here's the silly test project. I'm still quite new to Rust but plan on taking a crack at these errors to see if I can help :)
To implement the errors spec in the prisma query engine, we would need to be able to discriminate these specific errors, for each supported backend. Relevant link: https://github.com/prisma/specs/tree/master/errors#p2000-input-value-too-long
Since we added MySQL8 and MariaDB to the tested databases (#315), a couple of tests are now failing. Namely:
newdecimal_conversion_is_handled_correctly
filtering_by_json_values_does_not_work_but_does_not_crash
text_columns_with_non_utf8_encodings_can_be_queried
json_array_contains_fun
(fixed by #319)json_array_begins_with_fun
(fixed by #319)json_array_not_begins_with_fun
(fixed by #319)json_array_ends_into_fun
(fixed by #319)json_array_not_ends_into_fun
(fixed by #319)These all need to be fixed.
Loving quaint so far - we are using it to build an OData service in front of a database.
In our use case we are querying the database for schema information (list schemas, list tables, get column info). This can be done in both MySQL, SQLite and PostgreSQL using queries, but the interface slightly differs in each case (i.e. in SQLite you need to query the sqlite_master
schema and use PRAGMA table_info(table_name)
, whereas in MySQL and PostgreSQL you would query the information_schema
).
Having methods in quaint that list schemas/tables would be very convenient and not at all difficult to implement. Having a way to obtain column information would be even better (but would require that quaint 'understands' the type names returned by the database and map them to some common set of types to be actually useful).
Hi !
Would'nt it be nice to be able to UNION
together more than just SELECT
? Like the returning data from INSERT
, UPDATE
and DELETE
(Postgres
only)
Would it mean that the Visitor::visit_union
should'nt be provided anymore and implemented at the visitor level ?
First of all, thanks for this great library! Really appreciate all the effort you are putting in it.
I am encountering a panic Value of type Date("\'2019-08-07 10:04:50\'") is not supported with the current configuration
when reading from a table that has a date value. I have the 'chrono' feature enabled. Cargo.toml excerpt:
quaint = {version = "^0.1.0", features = ["sqlite", "mysql", "chrono"]}
Actual version in use is 0.1.13
.
Looking at the code it appears that while the my::Value::Date(year, month, day, hour, min, sec, micro)
case is covered, there apparently also is a `my::Value::Date(String)' that should probably be added.
Table looks like this in MySQL:
CREATE TABLE `urls` (
`url_id` int(11) NOT NULL AUTO_INCREMENT,
`url_unit` varchar(64) DEFAULT NULL,
`url_url` text,
`url_value` text,
`url_found` datetime DEFAULT NULL,
PRIMARY KEY (`url_id`)
) ENGINE=InnoDB AUTO_INCREMENT=51204 DEFAULT CHARSET=utf8mb4
thread 'tokio-runtime-worker' panicked at 'Value of type Date("\'2019-08-07 10:04:50\'") is not supported with the current configuration', <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/quaint-0.1.13/src/connector/mysql/conversion.rs:59:24
stack backtrace:
0: rust_begin_unwind
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/std/src/panicking.rs:493:5
1: std::panicking::begin_panic_fmt
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/std/src/panicking.rs:435:5
2: quaint::connector::mysql::conversion::<impl quaint::connector::queryable::TakeRow for mysql_common::row::Row>::take_result_row::convert
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/quaint-0.1.13/src/connector/mysql/conversion.rs:59:24
3: quaint::connector::mysql::conversion::<impl quaint::connector::queryable::TakeRow for mysql_common::row::Row>::take_result_row
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/quaint-0.1.13/src/connector/mysql/conversion.rs:71:22
4: <quaint::connector::mysql::Mysql as quaint::connector::queryable::Queryable>::query_raw::{{closure}}::{{closure}}::{{closure}}
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/quaint-0.1.13/src/connector/mysql.rs:293:77
5: mysql_async::queryable::query_result::QueryResult<T,P>::map::{{closure}}
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/mysql_async-0.21.1/src/queryable/query_result/mod.rs:328:31
6: <core::future::from_generator::GenFuture<T> as core::future::future::Future>::poll
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/core/src/future/mod.rs:80:19
7: mysql_async::queryable::query_result::QueryResult<T,P>::map_and_drop::{{closure}}
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/mysql_async-0.21.1/src/queryable/query_result/mod.rs:342:28
8: <core::future::from_generator::GenFuture<T> as core::future::future::Future>::poll
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/core/src/future/mod.rs:80:19
9: quaint::connector::mysql::Mysql::timeout::{{closure}}
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/quaint-0.1.13/src/connector/mysql.rs:243:27
10: <core::future::from_generator::GenFuture<T> as core::future::future::Future>::poll
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/core/src/future/mod.rs:80:19
11: <quaint::connector::mysql::Mysql as quaint::connector::queryable::Queryable>::query_raw::{{closure}}::{{closure}}
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/quaint-0.1.13/src/connector/mysql.rs:293:33
12: <core::future::from_generator::GenFuture<T> as core::future::future::Future>::poll
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/core/src/future/mod.rs:80:19
13: quaint::connector::metrics::query::{{closure}}
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/quaint-0.1.13/src/connector/metrics.rs:19:19
14: <core::future::from_generator::GenFuture<T> as core::future::future::Future>::poll
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/core/src/future/mod.rs:80:19
15: <quaint::connector::dbio::DBIO<T> as core::future::future::Future>::poll
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/quaint-0.1.13/src/connector/dbio.rs:25:9
16: <quaint::connector::mysql::Mysql as quaint::connector::queryable::Queryable>::query::{{closure}}
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/quaint-0.1.13/src/connector/mysql.rs:275:13
17: <core::future::from_generator::GenFuture<T> as core::future::future::Future>::poll
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/core/src/future/mod.rs:80:19
18: <quaint::connector::dbio::DBIO<T> as core::future::future::Future>::poll
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/quaint-0.1.13/src/connector/dbio.rs:25:9
19: <quaint::single::Quaint as quaint::connector::queryable::Queryable>::query::{{closure}}
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/quaint-0.1.13/src/single.rs:146:32
20: <core::future::from_generator::GenFuture<T> as core::future::future::Future>::poll
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/core/src/future/mod.rs:80:19
21: <quaint::connector::dbio::DBIO<T> as core::future::future::Future>::poll
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/quaint-0.1.13/src/connector/dbio.rs:25:9
22: esplanade::db::database::Database::query::{{closure}}
at ./src/db/database.rs:142:13
23: <core::future::from_generator::GenFuture<T> as core::future::future::Future>::poll
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/core/src/future/mod.rs:80:19
24: esplanade::api::query_with_query::{{closure}}
at ./src/api.rs:248:19
25: <core::future::from_generator::GenFuture<T> as core::future::future::Future>::poll
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/core/src/future/mod.rs:80:19
26: <F as futures_core::future::TryFuture>::try_poll
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-core-0.3.13/src/future.rs:84:9
27: <warp::filter::and_then::AndThenFuture<T,F> as core::future::future::Future>::poll
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/warp-0.2.5/src/filter/and_then.rs:82:44
28: <F as futures_core::future::TryFuture>::try_poll
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-core-0.3.13/src/future.rs:84:9
29: <warp::filter::recover::RecoverFuture<T,F> as core::future::future::Future>::poll
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/warp-0.2.5/src/filter/recover.rs:91:65
30: <F as futures_core::future::TryFuture>::try_poll
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-core-0.3.13/src/future.rs:84:9
31: <warp::filter::or::EitherFuture<T,U> as core::future::future::Future>::poll
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/warp-0.2.5/src/filter/or.rs:87:44
32: <warp::filter::and::AndFuture<T,U> as core::future::future::Future>::poll
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/warp-0.2.5/src/filter/and.rs:71:44
33: <F as futures_core::future::TryFuture>::try_poll
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-core-0.3.13/src/future.rs:84:9
34: <warp::filter::or::EitherFuture<T,U> as core::future::future::Future>::poll
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/warp-0.2.5/src/filter/or.rs:77:65
35: <F as futures_core::future::TryFuture>::try_poll
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-core-0.3.13/src/future.rs:84:9
36: <warp::filter::recover::RecoverFuture<T,F> as core::future::future::Future>::poll
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/warp-0.2.5/src/filter/recover.rs:91:65
37: <F as futures_core::future::TryFuture>::try_poll
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-core-0.3.13/src/future.rs:84:9
38: <warp::filters::cors::internal::WrappedFuture<F> as core::future::future::Future>::poll
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/warp-0.2.5/src/filters/cors.rs:573:26
39: <futures_util::future::either::Either<A,B> as core::future::future::Future>::poll
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-util-0.3.13/src/future/either.rs:73:33
40: <F as futures_core::future::TryFuture>::try_poll
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-core-0.3.13/src/future.rs:84:9
41: <warp::filter::map::MapFuture<T,F> as core::future::future::Future>::poll
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/warp-0.2.5/src/filter/map.rs:51:22
42: <F as futures_core::future::TryFuture>::try_poll
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-core-0.3.13/src/future.rs:84:9
43: <warp::filters::log::internal::WithLogFuture<FN,F> as core::future::future::Future>::poll
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/warp-0.2.5/src/filters/log.rs:257:49
44: <F as futures_core::future::TryFuture>::try_poll
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-core-0.3.13/src/future.rs:84:9
45: <warp::filter::service::FilteredFuture<F> as core::future::future::Future>::poll::{{closure}}
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/warp-0.2.5/src/filter/service.rs:128:41
46: scoped_tls::ScopedKey<T>::set
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/scoped-tls-1.0.0/src/lib.rs:137:9
47: warp::route::set
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/warp-0.2.5/src/route.rs:17:5
48: <warp::filter::service::FilteredFuture<F> as core::future::future::Future>::poll
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/warp-0.2.5/src/filter/service.rs:128:15
49: <hyper::proto::h1::dispatch::Server<S,hyper::body::body::Body> as hyper::proto::h1::dispatch::Dispatch>::poll_msg
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/hyper-0.13.10/src/proto/h1/dispatch.rs:476:31
50: hyper::proto::h1::dispatch::Dispatcher<D,Bs,I,T>::poll_write
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/hyper-0.13.10/src/proto/h1/dispatch.rs:284:43
51: hyper::proto::h1::dispatch::Dispatcher<D,Bs,I,T>::poll_loop
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/hyper-0.13.10/src/proto/h1/dispatch.rs:151:21
52: hyper::proto::h1::dispatch::Dispatcher<D,Bs,I,T>::poll_inner
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/hyper-0.13.10/src/proto/h1/dispatch.rs:127:16
53: hyper::proto::h1::dispatch::Dispatcher<D,Bs,I,T>::poll_catch
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/hyper-0.13.10/src/proto/h1/dispatch.rs:110:28
54: <hyper::proto::h1::dispatch::Dispatcher<D,Bs,I,T> as core::future::future::Future>::poll
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/hyper-0.13.10/src/proto/h1/dispatch.rs:411:9
55: <hyper::server::conn::ProtoServer<T,B,S,E> as core::future::future::Future>::poll
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/hyper-0.13.10/src/server/conn.rs:884:39
56: <hyper::server::conn::upgrades::UpgradeableConnection<I,S,E> as core::future::future::Future>::poll
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/hyper-0.13.10/src/server/conn.rs:1063:30
57: <hyper::server::conn::spawn_all::NewSvcTask<I,N,S,E,W> as core::future::future::Future>::poll
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/hyper-0.13.10/src/server/conn.rs:1001:36
58: tokio::runtime::task::core::Core<T,S>::poll::{{closure}}
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.2.25/src/runtime/task/core.rs:173:17
59: tokio::loom::std::unsafe_cell::UnsafeCell<T>::with_mut
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.2.25/src/loom/std/unsafe_cell.rs:14:9
60: tokio::runtime::task::core::Core<T,S>::poll
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.2.25/src/runtime/task/core.rs:158:13
61: tokio::runtime::task::harness::Harness<T,S>::poll::{{closure}}
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.2.25/src/runtime/task/harness.rs:107:27
62: core::ops::function::FnOnce::call_once
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/core/src/ops/function.rs:227:5
63: <std::panic::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/std/src/panic.rs:344:9
64: std::panicking::try::do_call
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/std/src/panicking.rs:379:40
65: __rust_try
66: std::panicking::try
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/std/src/panicking.rs:343:19
67: std::panic::catch_unwind
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/std/src/panic.rs:431:14
68: tokio::runtime::task::harness::Harness<T,S>::poll
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.2.25/src/runtime/task/harness.rs:89:19
69: tokio::runtime::task::raw::poll
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.2.25/src/runtime/task/raw.rs:104:5
70: tokio::runtime::task::raw::RawTask::poll
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.2.25/src/runtime/task/raw.rs:66:18
71: tokio::runtime::task::Notified<S>::run
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.2.25/src/runtime/task/mod.rs:169:9
72: tokio::runtime::thread_pool::worker::Context::run_task::{{closure}}
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.2.25/src/runtime/thread_pool/worker.rs:349:13
73: tokio::coop::with_budget::{{closure}}
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.2.25/src/coop.rs:127:9
74: std::thread::local::LocalKey<T>::try_with
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/std/src/thread/local.rs:272:16
75: std::thread::local::LocalKey<T>::with
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/std/src/thread/local.rs:248:9
76: tokio::coop::with_budget
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.2.25/src/coop.rs:120:5
77: tokio::coop::budget
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.2.25/src/coop.rs:96:5
78: tokio::runtime::thread_pool::worker::Context::run_task
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.2.25/src/runtime/thread_pool/worker.rs:348:9
79: tokio::runtime::thread_pool::worker::Context::run
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.2.25/src/runtime/thread_pool/worker.rs:320:24
80: tokio::runtime::thread_pool::worker::run::{{closure}}
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.2.25/src/runtime/thread_pool/worker.rs:305:17
81: tokio::macros::scoped_tls::ScopedKey<T>::set
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.2.25/src/macros/scoped_tls.rs:63:9
82: tokio::runtime::thread_pool::worker::run
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.2.25/src/runtime/thread_pool/worker.rs:302:5
83: tokio::runtime::thread_pool::worker::Launch::launch::{{closure}}
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.2.25/src/runtime/thread_pool/worker.rs:281:45
84: <tokio::runtime::blocking::task::BlockingTask<T> as core::future::future::Future>::poll
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.2.25/src/runtime/blocking/task.rs:41:21
85: tokio::runtime::task::core::Core<T,S>::poll::{{closure}}
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.2.25/src/runtime/task/core.rs:173:17
86: tokio::loom::std::unsafe_cell::UnsafeCell<T>::with_mut
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.2.25/src/loom/std/unsafe_cell.rs:14:9
87: tokio::runtime::task::core::Core<T,S>::poll
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.2.25/src/runtime/task/core.rs:158:13
88: tokio::runtime::task::harness::Harness<T,S>::poll::{{closure}}
at <omitted>/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.2.25/src/runtime/task/harness.rs:107:27
89: core::ops::function::FnOnce::call_once
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/core/src/ops/function.rs:227:5
90: <std::panic::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/std/src/panic.rs:344:9
91: std::panicking::try::do_call
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/std/src/panicking.rs:379:40
92: __rust_try
93: std::panicking::try
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/std/src/panicking.rs:343:19
94: std::panic::catch_unwind
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/std/src/panic.rs:431:14
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
With the upcoming changes for mssql, we get result types in the visitors and don't need to panic anymore in cases where user wants to use types such as Array
in databases that do not support them (everything else except PostgreSQL).
Remove all places of panic!
, unimplemented!
etc. and replace them with proper error types.
Don´t know why, but the type of my smallintegers is called SMALLINTEGER, and so is not supported here
quaint/src/connector/sqlite/conversion.rs
Line 36 in fd92827
While I've been considering our shift from separate SQL crates to SQLx, our recent move to a different runtime (async-std) adds another reason to consider it as the interface to the open source databases in Quaint.
What is SQLx?
Points to consider for using it:
Prisma is anyhow stuck now with old version of Tokio due to their latest runtime performing really bad with MySQL. QE is also now ran on top of async-std so we could benefit from the Tide HTTP server and to get Unix pipe and Windows named pipe support in the near future. Due to our database crates being based on Tokio, this means we still need an extra Tokio runtime for database actions, which adds to our memory usage and which might cause trouble in the future (more moving parts).
It also helps to have one of the async-std authors in the house (yay).
What would be the work items to get this done?
With the upcoming change to support SQL Server, and the upcoming change on Tiberius to be runtime-independent, we could then make Quaint to support both: Tokio and async-std with a feature flag (#152).
Part of an epic: #138
Now we can't run tests from 3rd party pull requests. We could move our test runs to GitHub actions, which would make it easier for people to write pull requests. And, additionally, we could run the tests on platforms such as Windows and macOS.
Line 170 in 95be465
Line 22 in fa99f53
You can get this output by running:
$ cargo +nightly clippy
Thanks!
warning: large size difference between variants
--> src\ast\expression.rs:170:5
|
170 | Function(Function<'a>),
| ^^^^^^^^^^^^^^^^^^^^^^ this variant is 536 bytes
|
= note: `#[warn(clippy::large_enum_variant)]` on by default
note: and the second-largest variant is 40 bytes:
--> src\ast\expression.rs:162:5
|
162 | RawValue(Raw<'a>),
| ^^^^^^^^^^^^^^^^^
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#large_enum_variant
help: consider boxing the large fields to reduce the total size of the enum
|
170 | Function(Box<Function<'a>>),
| ^^^^^^^^^^^^^^^^^
warning: large size difference between variants
--> src\ast\table.rs:22:5
|
22 | Query(Select<'a>),
| ^^^^^^^^^^^^^^^^^ this variant is 296 bytes
|
note: and the second-largest variant is 32 bytes:
--> src\ast\table.rs:21:5
|
21 | Table(Cow<'a, str>),
| ^^^^^^^^^^^^^^^^^^^
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#large_enum_variant
help: consider boxing the large fields to reduce the total size of the enum
|
22 | Query(Box<Select<'a>>),
| ^^^^^^^^^^^^^^^
Sigh, this is kind of a tough one. But it would be great to be able to finally cut a release to crates.io. What's stopping us?
Now, we could fork tokio_postgres to our own set of crates, release them to crates.io and cut a release. But that would kind of be horrible idea for maintaining.
The other idea is to complete the SQLx transition (#138) and related tasks that triggered bugs with certain Postgres types in our quite dynamic setup. This needs some work on their side too.
Part of an epic: #138
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.