Giter VIP home page Giter VIP logo

rdbc's People

Contributors

95th avatar andygrove avatar golddranks avatar gwenn avatar manuel-woelker 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  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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rdbc's Issues

prepared Statement Convert Date Type fail in Mysql error.but create Statement is success.

  • rust error
Connection.prepare(sql);
create_statement.execute_query(&arg_array);

Err(General("Couldn\'t convert the value `Date(\"\\\'2019-12-12\\\'\")` to a desired type"))
  • mysql data row
date   `2019-12-12 00:00:00`

so i check the code. maybe you need add a mothed support the date. and i use this code ,query date success.

//just like 

/// Result set from executing a query against a statement
pub trait ResultSet {
    /// get meta data about this result set
    fn meta_data(&self) -> Result<Box<dyn ResultSetMetaData>>;

    /// Move the cursor to the next available row if one exists and return true if it does
    fn next(&mut self) -> bool;

    fn get_i8(&self, i: u64) -> Result<Option<i8>>;
    fn get_i16(&self, i: u64) -> Result<Option<i16>>;
    fn get_i32(&self, i: u64) -> Result<Option<i32>>;
    fn get_i64(&self, i: u64) -> Result<Option<i64>>;
    fn get_f32(&self, i: u64) -> Result<Option<f32>>;
    fn get_f64(&self, i: u64) -> Result<Option<f64>>;
    fn get_string(&self, i: u64) -> Result<Option<String>>;
    fn get_bytes(&self, i: u64) -> Result<Option<Vec<u8>>>;

    fn get_date(&self, i: u64) -> Result<Option<String>>; // this code impl to support date
}
impl <'a>MySQLResultSet<'a>{
    fn get_my_date(&self, i: u64) -> Result<Option<my::Value>, Error> {
        match &self.row {
            Some(Ok(row)) => row
                .get_opt(i as usize)
                .expect("we will never `take` the value so the outer `Option` is always `Some`")
                .map(|v| Some(v))
                .map_err(value_to_rdbc_err),
            _ => Ok(None),
        }
    }
}


//get_date impl
impl<'a> rdbc::ResultSet for MySQLResultSet<'a> {
fn get_date(&self, i: u64) -> Result<Option<String>, Error> {
         let date=self.get_my_date(i)?;
         if date.is_some(){
             let v=date.unwrap();
            return Ok(Option::from(v.as_sql(true)));
         }else{
             return Ok(None);
         }
    }
}

Design async version of traits

The initial PoC of RDBC was pretty naive and copied from ODBC/JDBC and is not idiomatic Rust code. This issue has been created to discuss how to create an idiomatic Rust set of traits using async for the project.

Specific issues with the current traits:

  • Not async
  • Data access does not use generics and instead has one accessor method per datatype e.g. get_i32()
  • There are ownership issues when trying to create more than one prepared statement per connection
  • There is no support for batch or columnar, but that can potentially be addressed later

Add ability to dynamically load an RDBC driver

Currently, it is necessary to statically link to all possible RDBC driver implementations that need to be used at runtime but one of the main benefits of ODBC/JDBC is that new drivers can be loaded at runtime, so we need a similar mechanism here.

Add support for vectors and complex data types

Hi,

Would be cool have support for other DBMS not strictly purely SQL based DBMS, the API defined so far are generic enough that could be used also with some NoSql DBMS, the missing part at this stage I think is the support for more advanced types, in the specific I think would be enough to add a collection type so adding to ResultSet:

    fn get_vec_i8(&self, i: u64) -> Result<Option<Vec<i8>>>;
    fn get_vec_i16(&self, i: u64) -> Result<Option<Vec<i16>>>;
    fn get_vec_i32(&self, i: u64) -> Result<Option<Vec<i32>>>;
    fn get_vec_i64(&self, i: u64) -> Result<Option<Vec<i64>>>;
    fn get_vec_f32(&self, i: u64) -> Result<Option<Vec<f32>>>;
    fn get_vec_f64(&self, i: u64) -> Result<Option<Vec<f64>>>;
    fn get_vec_string(&self, i: u64) -> Result<Option<Vec<String>>>;
    fn get_vec_bytes(&self, i: u64) -> Result<Option<Vec<Vec<u8>>>>;

As well adding a sort of nested type

   // ResultSet
   fn get_vec_value(&self, i: u64) -> Result<Option<Vec<Value>>>;
   fn get_vec_value(&self, i: u64) -> Result<Option<Value>>;
  // Nested Type
  trait Value {
     //Same signatures of ResultSet for access values
  }

Another important part i think is the named access to values, often there is also a name associate to a value and may not be there at all a position.
So maybe would be cool to have also the relative methods:

    fn get_named_i8(&self, name: &str) -> Result<Option<i8>>;
    // And all the other types combinations.

If you are interested to this I can also write a PR for this cases.
Regards

Decide on 0-based versus 1-based indexes

So far I've been mimicking ODBC/JDBC in using 1-based indexes in ResultSet and ResultSetMetaData.

I did this to ease the translation of existing ODBC/JDBC code but it feels dirty.

Realistically we will want idiomatic Rust ways of accessing this API using iterators so maybe this low-level API can remain ugly ... I am interested to hear what others think.

Purpose of Rc<Refcell<T>>

I see most of the type returned from traits functions are Rc<Refcell>. What is the reason behind this? Shouldn't the user wrap it himself if he needs it?

Datatype for 64-bit integers (long long)?

Hi, there is DataType::Integer. I was wondering if it's meant to signify 32-bit integers, (int in MySQL and integer in Postgres). Is there a plan for having a data type for 64-bit integers?

It would also be very helpful if there were a correspondence table between the data types of this library, standard SQL and commonly used DB's such as Postgres, MySQL and Sqlite.

Clarify maintenance status

It looks like the last commit was 15 months ago. Might be worth being explicit about the maintenance status for this project if the intention is that not much more work on it will be done?

Replace trait objects with generics

I really get sore eyes when I see Box<dyn Something> in rust code. It's not an idiomatic rust to use them, they bypass type safety and they hurt performance.

I understand that the API is oriented around trait objects so as to be able to link your compiled program against any driver at runtime. There certainly are cases where people would want to build apps that are compiled-once and which work with any database at runtime, but there are also cases where people would want to use RDBC API for accessing just one particular database. It's obvious that in the second case performance is harmed, and more importantly, type safety is lost. Also, API in the current state doesn't allow for downcasting or any other method of accessing concrete types which I found to be of use, although rarely, for some driver specific behavior when using JDBC. I think backdoors are always a nice to have feature in any API.

I would like to propose an alternative which would include best of both worlds. This means that API would use generics instead of trait objects like this:

pub trait Driver: Sync + Send {
    type C: Connection
    fn connect(&self, url: &str) -> Result<Self::C>;
}
pub trait Connection {
    type S: Statement;
    fn create(&mut self, sql: &str) -> Result<Self::S>;
    fn prepare(&mut self, sql: &str) -> Result<Self::S>;
}
pub trait Statement {
    type RS: ResultSet;
    fn execute_query(&mut self, params: &[Value]) -> Result<RS>;
    fn execute_update(&mut self, params: &[Value]) -> Result<u64>;
}

This API would support native compilation for any driver used, but the limitation is that the driver would have to be known in compile time. To handle that limitation, the trick is to make a driver-agnostic concrete implementation of the API which would wrap trait objects, it would hide the boxed API and expose it as generic. This way the user would only have to choose whether he wants his code compiled against native implementation or driver-agnostic implementation of the API.

PS: Compiling this project is broken. It complains that it cannot compile sqlparser

Add support for transactions

I suggest we have explicit being/commit/rollback functions as well as the ability to set autocommit mode when creating connections.

Impossible to create multiple prepared statements at once

I would expect that it's possible to create multiple prepared statements for a single connection at once like following:

fn check<'a>(
    conn: &'a mut (dyn Connection + 'static),
) -> (
    Rc<RefCell<dyn Statement + 'a>>,
    Rc<RefCell<dyn Statement + 'a>>,
) {
    let a = conn.prepare("SELECT name, id FROM users").unwrap();
    let b = conn.prepare("SELECT name, id FROM posts").unwrap();

    (a, b)
}

This fails because to create a prepared statement it is required to borrow the connection mutably, which implies that you can only create one prepared statement per connection at one point in time.
This disallows common patterns like a prepared statement cache.

Error message:

error[E0499]: cannot borrow `*conn` as mutable more than once at a time
  --> src/main.rs:16:13
   |
9  | fn check<'a>(
   |          -- lifetime `'a` defined here
...
15 |     let a = conn.prepare("SELECT name, id FROM users").unwrap();
   |             ---- first mutable borrow occurs here
16 |     let b = conn.prepare("SELECT name, id FROM posts").unwrap();
   |             ^^^^ second mutable borrow occurs here
17 | 
18 |     (a, b)
   |     ------ returning this value requires that `*conn` is borrowed for `'a`

MariaDB?

Any reason for not mentioning MariaDB as one of the supported databases?

Add support for named parameters

RDBC currently supports positional parameters with ? syntax but it would be good to have the option of using named parameters as well using :name syntax.

Proposal: avoid borrow_mut()

IMHO borrow_mut() does not looks good in terms of rust.

let conn = connect_postgres()?;
let mut conn = conn.borrow_mut();
let stmt = conn.prepare("SELECT a FROM b WHERE c = ?")?;
let mut stmt = stmt.borrow_mut();

What if there will be another approach like:

  • Having generic trait for implementing single connection or connection pool
  • Connection (or pool) is immutable.
  • It can produce sessions
  • Session is used to execute one ore more queries (you can think of session as a transaction)
  • When session goes out of scope it is closed or reused for next calls
let cnx = connect_postgres()?;
let mut session = cnx.start_session()?;
let stmt = conn.prepare("SELECT a FROM b WHERE c = ?")?;
// ...

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.