A Firebird client library to Rust programing language
- Rust Api
- Dynamic link with fbclient
- Dynamic loading the fbclient(.dll or .so)
- ARM support
- Firebird embedded support
Rust Firebird Client
License: MIT License
A Firebird client library to Rust programing language
In the diesel pr I need create the connection using a string, because of this trait requirement.
So, I have two issues:
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 ?
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).
Create some common functionality for use by tests.
dev-dependencies
like this or this for ease of generating nice statementsI 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/
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
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)
}
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:
BLR
on client and server sides of the FB remote code?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?fbclient.so/dll
(in new and in older versions)? what is the exact relationship between standard ibase.h
and the Firebird Remote / YValve source?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.
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.
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
environment :
inside docker container from image: rust:1.50.0-buster
What am I doing wrong?
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
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:
rsfbcleint-diesel
crate?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 ?
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.
Continuation of #24
Hi, i try made this example, but don't work in the new version 0.16.0.
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)
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 use
d 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"
How we can improve our readme.md for show the features and documentation? Any ideas? @jairinhohw @juarezr @mariuz
I think we don't need more the firebird references.
Some libs use the 'cargo features' for force user to chose between async/sync. We can do the same for chose the 'connection builders'.
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.toml
s)
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
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.
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:
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?
crate has been renamed to
cipher
Details | |
---|---|
Status | unmaintained |
Package | block-cipher |
Version | 0.7.1 |
URL | RustCrypto/traits#337 |
Date | 2020-10-15 |
This crate has been renamed from block-cipher
to cipher
.
The new repository location is at:
<https://github.com/RustCrypto/traits/tree/master/cipher>
See advisory page for additional details.
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
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.
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
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 )
See #68 where I provide an example approach and commentary
Implement the support for firebird blobs(binary and text subtypes)
Now, the lib only can execute a simple queries without parameters, and this is not ok. So:
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:
if: github.event.pull_request.draft == false
on all jobs (this might be a bit broken but there's workarounds)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
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.
rsfbclient
requires fbclient
library available for low level protocol handling.Rust
.fbclient
library.Of course it's better get it working and stable using fbclient
library first and after explore this possibility.
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:
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.
Transaction::commit
consumes the Transaction but is actually calling isc_commit_retaining
, where the intention is to re-use the handle.
It probably doesn't cause too many problems right now since it gets immediately dropped when it goes out of scope (which calls isc_rollback_transaction
), but the Drop
implementation could change so it should be explicit.
Links to source:
main crate 1
main crate 2
fb-native
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 |
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.
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.
No workarounds are known.
See advisory page for additional details.
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:
deadlock\nupdate conflicts with concurrent update
fbclient
wasn't thread safe sometime ago. I don't know the current status.I don't know what is the resolution that should be taken in this context. Maybe:
Implement tests for the params and columns access. Using the firebird datatypes:
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)
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);
}
`
Learn and implement the static link support for the lib on 'native' variation
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'
)
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-
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.TransactionData
should actually be managed by Connection
and not Transaction
? I wonder if there could be a trick here using lifetimes (TransactionData
is borrowed by Transaction
TransactionData<'a>
held a &mut 'a Transaction
then it would mean we had to drop TransactionData
before the Transaction
)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 Future
s` (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?
Hi friends.
What do you think about to isolate the pool implementation as a new crate? It would be useful to publish the FirebirdConnectionManager
as a new r2d2 adapter at their adapters list: r2d2#adapters. ๐
cheers
Refs:
Hi.
It would be nice to provide some build feature allowing to load the client library (fbclient.dll
/libfirebird.so
) dynamically at run time.
cheers
Hi.
It would be nice some documentation for how to build the library (and examples) on Windows.
cheers
Test the project into a ARM processor, like the raspberry PI, and fix what are missing for work.
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.