Giter VIP home page Giter VIP logo

rsfbclient's Introduction

rsfbclient's People

Contributors

dancingbug avatar fernandobatels avatar jairinhohw avatar juarezr avatar mariuz avatar silvioprog avatar weiznich avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rsfbclient's Issues

Connection strings

In the diesel pr I need create the connection using a string, because of this trait requirement.

So, I have two issues:

  • What string format are we going to use?
  • Would that be an eligible resource for the main crate?
    • We can create the string support directly in the main crate or only in the diesel support. What do you think?

Link failure

I tried to compile and run the examples on my Windows 10 machine. I bumped into a list of error messages like

  = note: librsfbclient_native-2add0a40d62a8955.rlib(rsfbclient_native-2add0a40d62a8955.rsfbclient_native.3bddf0c6-cgu.15.rcgu.o) : error LNK2019: unresolved external symbol isc_attach_database referenced in function _ZN90_$LT$rsfbclient_native..ibase..IBaseLinking$u20$as$u20$rsfbclient_native..ibase..IBase$GT$19isc_attach_database17h75cb47fbbf5608e5E

So I setup my LIBRARY_PATH and LD_LIBRARY_PATH to a folder this all the firebird DLL
Nothing worked.

I have also copied those DLLs in my System32 folder. Same failure.

rustc 1.56.0-nightly
Windows 10 (uptodate)
Firefox 4 (and tried also with Firefox 3.0.7)

What am I not doing well ?

Failed to map BIGINT using i64

Hi.

Consider the following table structure and its data:

CREATE TABLE test (
  id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL PRIMARY KEY,
  name VARCHAR(100) NOT NULL UNIQUE
);

INSERT INTO test (name) VALUES ('Fulano');
INSERT INTO test (name) VALUES ('Beltrano');
INSERT INTO test (name) VALUES ('Cicrano');

SELECT * FROM test;

-- ID	NAME
-- 1	Fulano
-- 2	Beltrano
-- 3	Cicrano

Now, consider the following example:

use rsfbclient::{Connection, FbError};

fn main() -> Result<(), FbError> {
    let conn = Connection::open("localhost", 3050, "test.fdb", "SYSDBA", "masterkey")?;
    let tr = conn.transaction()?;
    let rows = tr.prepare("SELECT * FROM test")?.query(())?.into_iter();
    println!("| ID | NAME |");
    println!("| -- | ---- |");
    for row in rows {
        let (id, name): (i64, String) = row?;
        println!("| {} | {} |", id, name);
    }
    Ok(())
}

It is returning the following result:

| ID | NAME |
| -- | ---- |
| 4294967297 | Fulano |  
| 8589934594 | Beltrano |
| 12884901891 | Cicrano |

but it should return:

| ID | NAME |
| -- | ---- |   
| 1 | Fulano |  
| 2 | Beltrano |
| 3 | Cicrano |

regards,

P.S.: Changing the column type from i64 to i32 it prints the values properly for short ones, however, it isn't managed to map a full bigint range (-2^63 .. 2^63-1).

Implement fancier test utilities and test fixtures

Create some common functionality for use by tests.

  • generation of raw sql (maybe to be replaced later by query builder as discussed in #48)
  • consider adding string formatting libraries to dev-dependencies like this or this for ease of generating nice statements
  • well-documented connection setup/teardown routines, for example setting up multiple connections/transactions or creating/dropping tables with unique names to avoid transaction deadlocks in parallel tests
  • move test database creation into separate scripts + config (docker/git action could still reference them) to make it easier for users to run tests locally with minimal dependencies, and/or create some fixed .fdb files corresponding to different fb server configurations
  • other ideas?

Make FromRow/IntoParam traits more generic

I think it may be possible to make these traits more generic, and maybe get rid of the single/plural distinction of IntoParam/IntoParams

The technique would be based on type level cons-lists (sometimes called HList or heterogeneous list).
I made an example, pasted at the bottom of this comment for demonstration

if we have
impl<A:IntoParams, B:IntoParams> IntoParams for (A,B) {...

Then no further trait impl should be needed for (A,(B,(C,(D ... (X, (Y,Z))))))))...

So if we expose a macro to the user for right-associating arbitrary tuples (we could have params!(a,b,c..) become (a, (b, (c, ...)) or do something with a list-builder like param_list.push(x).push(y).push(z) then we can have statically-typed, arbitrary-length parameter lists whenever it's actually possible, without vectors, and without generating a bunch of trait impls for different tuple types.

here is an existing crate with helper macros for this kind of thing: https://docs.rs/tuple_list/0.1.2/tuple_list/

code snippet to demonstrate feasibility

below is a bit of example code to demonstrate this approach and show that it's probably feasible in some way
(rust playground link)

trait IntoParams {}
struct A0;
struct A1;
struct A2;
struct A3;
struct A4;
impl IntoParams for A0{}
impl IntoParams for A1{}
impl IntoParams for A2{}
impl IntoParams for A3{}
impl IntoParams for A4{}
impl<A:IntoParams, B:IntoParams> IntoParams for (A,B) {}
fn use_flub<T: IntoParams>(flub: T){}

fn main() {
   let a_flub: (A0, (A1, (A2, (A3, (A4, A0))))) = (A0,(A1,(A2,(A3,(A4,A0)))));
    //proof that a_flub is an IntoParams. otherwise we wouldn't be able to pass it to use_flub
    use_flub(a_flub);
}

This might also simplify an implementation of "compile-time named parameters", if we ever do that.

The vector approach, or something similar, will probably still be needed for some situations

Implementation of XSQLDA_LENGTH macro is wrong

The implementation of the XSQLDA_LENGTH here is returning the wrong length.

The code could be written as the following to return the correct value (and not panic on size < 1):

    /// Implementation of XSQLDA_LENGTH macro
    fn xsqlda_length(size: i16) -> usize {
        let n = (size - 1).max(0) as usize;

        std::mem::size_of::<XSQLDA>() + (std::mem::size_of::<XSQLVAR>() * n)
    }

Document initial questions and answers about Firebird client implementations

This issue can be a temporary place for questions and answers about Internals of Firebird clients (including our own rsfbclient-rust) that are not covered clearly by existing links in README.md or CONTRIBUTING.md

For starters:

  • What is a high level overview of the flow of wire protocol and BLR on client and server sides of the FB remote code?
  • In rsfbclient-rust are there any choices being made about communicating with the remote side? or is the wire protocol so tightly specified that there's really only ever one valid sequence of interaction? Does rsfbclient-rust try to match the choices of some other client?
  • In Firebird source, what parts of their code turn into fbclient.so/dll (in new and in older versions)? what is the exact relationship between standard ibase.h and the Firebird Remote / YValve source?

Permit recovery of failed transaction commit or rollback

At present, Transaction::commit and Transaction::rollback have signatures
pub fn commit (mut self) -> Result<(), FbError> and
pub fn rollback(mut self) -> Result<(), FbError>

Can these ever fail without actually releasing resources? I found this and this which indicate that it's been a problem in the past.

If this does happen, the caller can't even attempt to recover straightforwardly because these methods consume the transaction.

API Ergonomics: Consider reorganizing lifetimes in rsfbclient main crate traits/structs

The lifetime in Queryable<'a, R> (and Transaction<'a,C>, StmtIter<'a, R,C> etc) will tend to infect whatever uses it.
Unfortunately, due to some warts of the rust language, this leads to unexpected compilation errors in some cases.
For example:

  const GTT_QRY: &str =
  "select rdb$relation_name
     from rdb$relations
    where     rdb$relation_name = 'GTT_TABLE'
          and rdb$relation_type > 3;";

  const GTT_CREATE: &str =
    "create global temporary table GTT_TABLE
     (table_id INT not null primary key)
     on commit preserve rows;";

  pub fn with_temporary_table<'a, E>( conn: &'a mut E ) -> ()
    where 
      E: Execute + Queryable<'a, (String,)>
  {
    let result : Vec<(String,)> = conn.query(GTT_QRY, ()).unwrap();
    let result2 =  conn.execute(GTT_CREATE, ());
  }

error[E0499]: cannot borrow `*conn` as mutable more than once at a time
   --> src/main.rs:100:20
    |
95  |   pub fn with_temporary_table<'a, E>( conn: &'a mut E ) -> ()
    |                               -- lifetime `'a` defined here
...
99  |     let result : Vec<(String,)> = conn.query(GTT_QRY, ()).unwrap();
    |                                   -----------------------
    |                                   |
    |                                   first mutable borrow occurs here
    |                                   argument requires that `*conn` is borrowed for `'a`
100 |     let result2 =  conn.execute(GTT_CREATE, ());
    |                    ^^^^ second mutable borrow occurs here

pardon if i'm misunderstanding something, but I also also don't see why R of Queryable<'a, R> should be bounded by 'a at the trait level like it is in its where clause either: where R : FromRow + 'a
It seems like the lifetime of R should be unrelated to the connection/transaction/iterator at the trait level: Once we have an R on hand, we should be able to do whatever we want with it, or the Connection, in either order, if our impl allows it.

cannot find tuple struct or tuple variant `Timestamp` in this scope

After adding rsfbclient-rust = "0.15.0" to Cargo.toml and building I get the following error during the build:

Compiling rsfbclient-core v0.15.0
error[E0531]: cannot find tuple struct or tuple variant Timestamp in this scope
--> /usr/local/cargo/registry/src/github.com-1ecc6299db9ec823/rsfbclient-core-0.15.0/src/params.rs:25:13
|
25 | Timestamp(_) => (ibase::SQL_TIMESTAMP + 1, 0),
| ^^^^^^^^^ not found in this scope

error: aborting due to previous error

environment :
inside docker container from image: rust:1.50.0-buster

What am I doing wrong?

serde interoperability

It would be nice to be able to use existing serde-derives with FromRow or IntoParams

an example use case is converting between JSON/YAML/protobuf/etc and Firebird

Diesel support

I'm thinking in implement a Firebird backend for diesel ORM. Honestly, I've never used the diesel before, but I have good feelings about this tool.

So, some questions come to me:

  • This backend can be implemented here in a rsfbcleint-diesel crate?
  • Do you know any guide for this implementation? I couldn't find anything, so I'm using the pg backend as example.

Connection builder

I'm thinking in make a "ConnectionBuilder" for start a new connection instead of the 'connection' and 'connection_local'. Like in the sled.

In our case we will use this for set the db dialect and more. Something like:

let mut conn = ConnectionBuilder::default()
     .host("localhost")
     .user("sysdba")
     .dialect(Dialect::D3)
     .connect()?;

What you think @jairinhohw ?

Rust parser/deserializer for Firebird DSQL

With a parser, we could do compile-time checks on DSQL and statement parameters, and more.

Some resources (for commit permalinks, make sure to check the latest versions)

Do any major database-agnostic DB libraries (ie something like Diesel) expect parsers/deserializers or their output to implement specific traits? I suspect so, but I don't know.

Continuing the GitHub Actions setup

  • Next steps
    • Run test with Firebird 2.5-ss, 3.0 and 4.0
    • Run on Windows
    • Run on Linux/ARM
    • Run on Linux/ARM/LittleEndian
    • Release workflow to crates.io and rust docs.
  • Status
    • Coverage failing on cc linking (needs help...)
    • Next steps on further PRs

Continuation of #24

Error Testing the firebird combine with rust using MacOS catalina

use rsfbclient::{prelude::*, ConnectionBuilder, FbError};

fn main() {
    #[cfg(feature = "dynamic_loading")]
        let mut conn = ConnectionBuilder::with_client("/Library/Frameworks/Firebird.framework/Versions/A/Libraries/libfbclient.dylib")
        .embedded()
        .db_name("/tmp/examples.fdb")
        .user("SYSDBA")
        .connect()?;

    println!("Hello, world!");
}
Message:
error: linking with `cc` failed: exit code: 1
  |
  = note: "cc" "-m64" "-arch" "x86_64" "-L"  /Users/.../..........
  = note: ld: library not found for -llibfbclient
          clang: error: linker command failed with exit code 1 (use -v to see invocation)

Make the main crate easier to source-patch

Until we've fully settled on on design choices of the main api and its implementation, it would be useful to make it easier to substitute other source (say using cargo's [patch] facility) without having to worry too much about the content of specific files in src/.

Currently src/lib.rs mixes together re-exports, cfg flags, and exports of crate-internal paths.
Generally if i'm patching, I want to keep the re-exports of other crates, but replace internal modules.

@fernandobatels originally suggested to me that we could move the main source into a different crate, but after I thought about it more I think a simpler way is just to organize modules, visibility specifiers and re-exports more carefully.

in particular, we should move all crate-internal source into sub-modules. I propose just a single sub-module for now. Let's say for now it's called default_impl.
then lib.rs and default_impl.rs become the only files in src/ (as opposed to using mod.rs in a subdirectory) and everything else is in src/default_impl/. This is easy to patch over.

all crate-internal visibility should be controlled by default_impl.rs, this includes both inter-module visibility as well as pub use declarations for exporting and aliasing internals of the crate

lib.rs would consist only of re-exports of external crate paths, as well as

mod default_impl;
pub use default_impl::*;

on a related note we should be careful about how we use crate:: -prefixed imports in internal modules since these can break easily when things get moved around.
super:: is advantageous because it allows different kinds of visibility to be controlled almost entirely from module roots (by which i mean the equivalent of mod.rs or default_impl.rs here), and when you're feeling lazy you can just do super::* in all of the modules to use a common set of items which are used in the module root.

what do you think?
if you are ok with this proposal, do you have any suggestions for the module name? i don't really care in the end but I did not try very hard with the name "default_impl"

Builders as a features

Some libs use the 'cargo features' for force user to chose between async/sync. We can do the same for chose the 'connection builders'.

  • Move the dynamic link to a feature
  • Move the dynamic fbclient lib loading to a feature
  • Create an option, on builders, for make the embedded database connection

Should date_time still exist as a separate feature?

Feature date_time seems to have become mandatory at some point.
Trying to build without it (--no-default-features --feature linking for example) fails for me.

I think I am not the only one: #102

I do not know why it was made optional in the first place

Should we add appropriate cfg guards so that date_time is optional again?
or should it just not be a separate feature (that is, get rid of the cfg guards and remove it from Cargo.tomls)

Abstract SQL statement type

It could be helpful to introduce an abstract SQL statement type in the main crate.

By this i mean that instead of

query_iter<...>(... sql: &str ...)

we have instead something like

query_iter<..., T: SqlStatement>(..., sql: T, ...)

with a default impl for &str

SqlStatement here could be things like NamedParamsStatement<'a>(&'a str) or some future StatementBuilder

that way it becomes easier to extend functionality around SQL statements.

There might be other approaches besides using a trait in the above way.
Note that implementing this might be more complex than it appears.. it might have to touch a lot of methods in Connection, Transaction, and Statement to be fully flexible

[Security] Potential Secret Leak

It has been noticed that while using juarezr/[email protected] your firebird_password test_password is present in plaintext. Please ensure that secrets are encrypted or not passed as plain text in github workflows.

Consider switching to some form of outparams in FirebirdClient fetch results

Instead of doing this in our clients

/// Data associated with a prepared statement
pub struct StmtHandleData {
    /// Statement handle
    raw_stmt_handle: ibase::isc_stmt_handle,
    /// Output xsqlda
    xsqlda: XSqlDa,
    /// Buffers for the output xsqlda
    col_buffers: Vec<ColumnBuffer>,
}

and this in core API

fn fetch(
    &mut self,
    db_handle: &mut Self::DbHandle,
    tr_handle: &mut Self::TrHandle,
    stmt_handle: &mut Self::StmtHandle,
) -> Result<Option<Vec<Column>>, FbError>;

what if we had this in our clients (as the stmt handle used to be)

/// Data associated with a prepared statement
type StmtHandle = ibase::isc_stmt_handle;

pub struct XYZClientRowBuffer {
    //Handle passed along with corresponding buffer
    stmt_handle: StmtHandle,
    /// Output xsqlda
    xsqlda: XSqlDa,
    /// Buffers for the output xsqlda
    col_buffers: Vec<ColumnBuffer>
}

and this in our core api:

fn get_buffer(
    &mut self,
    stmt_handle: &mut Self::StmtHandle,
    row_count: usize,
) -> Result<Self::RowBuffer, FbError>;

fn fetch(
    &mut self,
    db_handle: &mut Self::DbHandle,
    tr_handle: &mut Self::TrHandle,
    result_buffer: &mut Self::RowBuffer,
) -> Result<FetchStatus, FbError>;

in this example Self::RowBuffer is XYZClientRowBuffer, which has a trait bound to help move/copy the contents of the buffer out, which would be used in FromRow::try_from().

Actually this could be quite useful for testing: A mock buffer that succeeds for any FromRow, returning fake data

Some possible variations:

  • prepare_statement returns a a transparent enum with only some variants containing a buffer or just the xsqlda in addition to the statement handle. StmtType could be placed in there too, either transparently or opaquely.
  • The client itself manages the buffers automatically for open cursors, and get_buffer (or maybe just fetch) return a handle to it that can be used to copy/move the data out.

your thoughts on this?

Find better abstraction for associating Connection-StmtIter-Transaction

Compare the code of Connection's Queryable impl and that of Transaction
(impl for Connection) | (impl for Transaction)

I have a feeling we can find a way to either to get rid of one the implementations, have one be a thin wrapper for the other, or make both Connection and Transaction generic over the type of iterator they use, possibly using some kind of wrapper struct and still be able to keep lifetimes out of the trait-level Queryable signature , even without dyn Trait in query_iter (see #51, #54) and possibly also simplify the lifetimes between the three structs.

I don't yet have an understanding about what's going on with stmt_cache but I plan to read the implementation and then do some experimenting

Support for named parameters

Please consider to include support for namend SQL parameters:

SELECT * FROM test WHERE customerId = :customer_id

Firebird supports this and it is much safer than using unnamed question marks.

rsfbclient and rsfbclient-native are always recompiled

when i do a cargo run, even if i changed nothing, rsfbclient and rsfbclient-native are always recompiled. i am using windows10.

this is caused by the build.rs file in rsfbclient-native line 17:

17:  println!("cargo:rerun-if-changed=src/tests/mod.rs");

There is no directory tests and no file tests/mod.rs so this always fires and causes the recompilation. when i comment this lie out everything works

Cross Language Object Oriented Programming (cloop) tool

https://github.com/asfernandes/cloop/

It is used to process this Interface Description Language file into different programming languages. It appears to be used in official Firebird build scripts

Should we consider making a rust output generator?
We could also potentially translate the c++ code of this tool? (the c++ is not so complicated) I don't know if this is helpful or not.

Maybe someone wants to discuss it with the maintainer (who is also one of the primary contributors to the official FirebirdSQL github project )

Blob support

Implement the support for firebird blobs(binary and text subtypes)

  • Params
  • Row column
  • Tests(like the #8):
    • Params
    • Row column

Parameters and querys

Now, the lib only can execute a simple queries without parameters, and this is not ok. So:

  • add support for parameters in querys like the https://github.com/rusqlite/rusqlite
  • the "query_simple" and "execute_simple" approaches will be removed
  • Use the no_params! macro, or similar, instead

CI: allow method to disable workflows for draft PRs/other situations

Sometimes on drafts we know tests won't pass, or we're just making little changes. Check annotations can be noisy and we're just spinning up a bunch of docker containers for nothing and using the free minutes (2000/month)

I can think of different ways to do this:

  • using if: github.event.pull_request.draft == false on all jobs (this might be a bit broken but there's workarounds)
  • using special branches as the merge target (complication: keep them synchronized with master only)
  • using labels

Some ways make it so it is still hard or impossible to accidentally get merged later without testing. these tend to be more complicated.

Other ways are just manual overrides that can be used in any situation including drafts but also regular PRs. these tend to be simpler.

@fernandobatels I think it's just a question of whether you as repository owner are ok with this or not since you are doing the merging. It's always possible to make an issue referencing changes in a fork instead of making a draft pr here.

if you're interested I can provide more details on different approaches

Cannot get connectionpool working with embedded db

Hi!

I cannot compile the r2d2 sample with embedded db:

    let builder =
        rsfbclient::builder_native()
            .with_dyn_load("C:\\develop\\libs\\fb4\\fbclient.dll")
            .with_embedded()
            .db_name("c:\\temp\\test.fdb")
            .user("SYSDBA");

    let manager = FirebirdConnectionManager::new(builder);
    let pool = Arc::new(r2d2::Pool::builder().max_size(4).build(manager).unwrap());

The Error is:

error[E0277]: the trait bound `&mut NativeConnectionBuilder<DynLoad, ConnEmbedded>: FirebirdClientFactory` is not satisfied
  --> src\main.rs:51:50
   |
51 |     let manager = FirebirdConnectionManager::new(builder);
   |                                                  ^^^^^^^ the trait `FirebirdClientFactory` is not implemented for `&mut NativeConnectionBuilder<DynLoad, ConnEmbedded>`
   |
   = help: the following implementations were found:
             <NativeConnectionBuilder<DynLoad, A> as FirebirdClientFactory>
   = note: required by `FirebirdConnectionManager::<F>::new`

i am new to rust so i cannot figure out how to fix this.

[Feature Request] Pure rust implementation

[Feature Request] Pure rust implementation

  1. Actually rsfbclient requires fbclient library available for low level protocol handling.
  2. It's a lot of work, but it's possible to develop this library in pure Rust .
  3. For example, Jaybird rewrote the protocol in pure java.
  4. The main pros are:
    1. Assure that library is safe from memory leakis and race conditions, granted by Rust borrow checker.
    2. No need for unsafe code.
    3. No need for deploying or static linking fbclient library.

Of course it's better get it working and stable using fbclient library first and after explore this possibility.

Add Contributing.md or notes in the readme about contributing

As I've written a couple PRs and issues now I've been wondering what the main contributors' preferences are with regard to contributions, since there's no specified place to ask.

Some questions:

  • Should I submit PRs first?
  • Should I open an issue for discussions related to certain things (like API or architecture changes), before spending time on a PR?
  • Do the main contributors have a certain set of features/upcoming changes in mind? Like a detailed roadmap, but it could be short-term
  • What usage scenarios should be supported?
  • What reference documentation is the crate based on, if any?

We could mention something about the Github workflow (ie run cargo fmt and cargo test before submitting a PR) even if it seems like common sense. Users of Firebird are likely to be users of other programming languages (Java, C#, Pascal variants, Python, C++) so it could be good to give a little bit of guidance for people who are still getting familiar with Rust ecosystem specifics.

I also notice many contributors are from Brasil. I assume their native language is Portuguese. If it's preferred not to discuss anything about that, I understand. But if some contributors want to say 'find me on #rust-br!' or if there's specific kinds of contributions related to language that they would find helpful, I think that's also useful to say.

RUSTSEC-2020-0071: Potential segfault in the time crate

Potential segfault in the time crate

Details
Package time
Version 0.1.44
URL time-rs/time#293
Date 2020-11-18
Patched versions >=0.2.23
Unaffected versions =0.2.0,=0.2.1,=0.2.2,=0.2.3,=0.2.4,=0.2.5,=0.2.6

Impact

Unix-like operating systems may segfault due to dereferencing a dangling pointer in specific circumstances. This requires an environment variable to be set in a different thread than the affected functions. This may occur without the user's knowledge, notably in a third-party library.

The affected functions from time 0.2.7 through 0.2.22 are:

  • time::UtcOffset::local_offset_at
  • time::UtcOffset::try_local_offset_at
  • time::UtcOffset::current_local_offset
  • time::UtcOffset::try_current_local_offset
  • time::OffsetDateTime::now_local
  • time::OffsetDateTime::try_now_local

The affected functions in time 0.1 (all versions) are:

  • at
  • at_utc

Non-Unix targets (including Windows and wasm) are unaffected.

Patches

Pending a proper fix, the internal method that determines the local offset has been modified to always return None on the affected operating systems. This has the effect of returning an Err on the try_* methods and UTC on the non-try_* methods.

Users and library authors with time in their dependency tree should perform cargo update, which will pull in the updated, unaffected code.

Users of time 0.1 do not have a patch and should upgrade to an unaffected version: time 0.2.23 or greater or the 0.3. series.

Workarounds

No workarounds are known.

References

time-rs/time#293

See advisory page for additional details.

Thread safety support and deadlock supression

While building the CI in PR #31 a deadlock error occurred randomly.

It happened either while running cargo test or with cargo tarpaulin that triggers cargo test for creating coverage.

The backtrace is:

---- tests::params::linking::ints stdout ----
Error: FbError { msg: "deadlock\nupdate conflicts with concurrent update\nconcurrent transaction number is 123", code: -913 }
thread 'tests::params::linking::ints' panicked at 'assertion failed: `(left == right)`
  left: `1`,
 right: `0`: the test returned a termination value with a non-zero status code (1) which indicates a failure', /rustc/d3fb005a39e62501b8b0b356166e515ae24e2e54/src/libstd/macros.rs:16:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

failures:
    tests::params::linking::ints

I can easily reproduce the problem in my local computer by running:

cargo tarpaulin --ignore-config --out Lcov Xml Html --run-types AllTargets -v --line --count --branch --features 'linking date_time pool'

However, the error goes away when restricting parallel test execution to 1 thread by adding --test-threads 1 to cargo test throught cargo tarpaulin:

cargo tarpaulin --ignore-config --out Lcov Xml Html --run-types AllTargets -v --line --count --branch --features 'linking date_time pool' -- --test-threads 1

Also I saw in the Github Action log that simply using cargo test can trigger the bug:

cargo test --features dynamic_loading date_time pool

I have concluded that is a deadlock bug because:

  1. The error message says deadlock\nupdate conflicts with concurrent update
  2. The fbclient wasn't thread safe sometime ago. I don't know the current status.
  3. The error happened radomnly in anyone of test cases and changed every time command was run.

I don't know what is the resolution that should be taken in this context. Maybe:

  1. this should be fixed because just is a test case bug.
  2. this should be fixed because just is a driver bug.
  3. this should be addressed with some extra checking for handling thread safety.
  4. this should not be handled by the driver, because is a normal database concurrency issue.
  5. the test cases should run with concurrency = 1

More tests

Implement tests for the params and columns access. Using the firebird datatypes:

  • BIGINT(see the #11)
  • CHAR(n), CHARACTER(n)
  • DATE
  • DECIMAL. With different precision
  • DOUBLE PRECISION
  • FLOAT
  • INTEGER, INT
  • NUMERIC. With different precision
  • SMALLINT
  • TIME
  • TIMESTAMP
  • VARCHAR(n), CHAR VARYING, CHARACTER VARYING

Add CreateDatabase for embedded client

Please add the feature to create a database with the embedded client. now i have to use isql to do this. otherwise i get an error

let mut conn =
        rsfbclient::builder_native()
            .with_dyn_load("C:\\develop\\libs\\fb\\fbclient.dll")
            .with_embedded()
            .db_name("test123.fdb")
            .user("SYSDBA")
            .connect()?;


Gives this Error.

Error: Sql { msg: "I/O error during \"CreateFile (open)\" operation for file \"test123.fdb\"\nError while trying to open file\nDas System kann die angegebene Datei nicht finden. ", code: -902 }
error: process didn't exit successfully: `target\debug\rust01.exe` (exit code: 1)

Can't cross compile from linux to win32

I'm trying to create a win32 dll, I'm running:
cargo build --target=x86_64-pc-windows-gnu --release

and getting this error:
note: /usr/bin/x86_64-w64-mingw32-ld: cannot find -lfbclient

cargo.toml:
image

lib.rs:
image

the trait `FromRow` is not implemented for ....

What this error means?
image

I have a custom type holding a tuple with the type of each column from the table:

type ClienteFields = (String, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<i32>, Option<i32>, Option<i32>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<f64>, Option<f64>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>, Option<i32>, Option<i32>, Option<String>, Option<f64>, Option<f64>, Option<String>, Option<String>, Option<String>, Option<String>, Option<String>);

And I'm using it like this:

` let rows = conn.query_iter("SELECT * FROM C000007", ())?;

for row in rows {
    let row_data: ClienteFields = row.unwrap();

    println!("{:?}", row_data.0);
}

`

Static link support

Learn and implement the static link support for the lib on 'native' variation

Encoding

How can I specify a encoding to connect to a database?

Example in python:

conn  = fdb.connect(
    user='SYSDBA',
    password='masterkey',
    database='/firebird/data/BASE.FDB',
    charset='win1252'
)

Drop impl for Transaction has silent side effects

In number #58 we eliminated all but one path toward executing the Drop::drop impl of Transaction

While working on that PR i was thinking about whether there really should be side effects in a Drop impl at all (for example rolling back)

Was a conscious decision made when Drop was implemented at first?

I actually don't know what the idiomatic way is in Rust here, but it seems like it could be a silent source of bugs or unintended behavior, for example if the transaction handle was already invalidated by some other means (maybe even not implemented yet- every new mut self method will have to be on guard for such behavior)

Alternative ideas-

  • Panic to loudly let the user know they forgot to deal with it?
  • Let it die and be the user's problem?
  • set_drop_behavior like rusqlite, but where the user is forced to make an initial choice in Transaction::new() ? that way they can't manually construct a Transaction without being made aware of the behavior.
  • Maybe TransactionData should actually be managed by Connection and not Transaction? I wonder if there could be a trick here using lifetimes (say if TransactionData is borrowed by Transaction I think it would be the other way around. If TransactionData<'a> held a &mut 'a Transaction then it would mean we had to drop TransactionData before the Transaction)
  • Maybe Transaction as it is, isn't the right abstraction to leverage Rust safety. Maybe it should really be TransactionBuilder<InconsistentState> (needs commit/rollback) and TransactionBuilder<ConsistentState> (no pending writes) and you can only pass the ConsistentState one to a Connection to execute. These could potentially be implemented as Futures` (but we just run them in a single thread because of Firebird limitations). I'm not sure if that would mean having to use a bunch of complicated async/await machinery or not.

relates to #56

Thoughts?

ARM support

Test the project into a ARM processor, like the raspberry PI, and fix what are missing for work.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.