fernandobatels / rsfbclient

Rust Firebird Client
MIT License
74 stars 10 forks source link

Subtype support for Blob -1 #146

Closed hellitonsm closed 11 months ago

hellitonsm commented 11 months ago

Issue Description:

I made a modification to the rsfbclient-native/row.rs file at line 80, adding the following lines:

ibase::SQL_BLOB if (sqlsubtype == 0 || sqlsubtype == 1 || sqlsubtype == -1) => {
    let blob_id = Box::new(ibase::GDS_QUAD_t {
        gds_quad_high: 0,
        gds_quad_low: 0,
    });

    var.sqltype = ibase::SQL_BLOB as i16 + 1;

    if sqlsubtype == 0 {
        BlobBinary(blob_id)
    } else if sqlsubtype == -1 {
        BlobBinary(blob_id)
    } else {
        BlobText(blob_id)
    }
}

The reason for this modification is that my Firebird Database uses a value of -1 to represent Blob columns.

In my Delphi client, there's an option for -1 Blob:

DriverName=DevartInterBase
RoleName=
SQLDialect=3
BlobSize=-1
ErrorResourceFile=
LocaleCode=0000
DevartInterBase TransIsolation=ReadCommited
WaitOnLocks=True
Charset=WIN1252
CharLength=1
EnableBCD=True
OptimizedNumerics=True
LongStrings=True
UseQuoteChar=False
FetchAll=False

With this change, I no longer encounter the error related to the wrong column type.

Error: [DatabaseError(Unknown, error: Unsupported column type (520 -1))]

Additional Information:

Firebird Server Version: Firebird_2_5 Operating System: Linux Mint 20.3 (Una) Rust Version: 1.73.0

Please review and consider including this modification in the codebase. Thank you!

fernandobatels commented 11 months ago

Can you provide an reproducible example? Like a query forcing this blob variation on a column.

hellitonsm commented 11 months ago

I'am using Diesel 2.0.4, i made:

main.rs:

for i in interno {
        let images = image::interno::table
            .filter(image::interno::ID_INTERNO.eq(i.id_interno))
            .first::<image::Image>(&mut conn)
            .expect("Falha ao recuperar dados");

        let base64_text = match images.foto {
            Some(b) => base64::encode(b),
            _ => String::from("Null"),
        };

        let data = Data {
            id: i.id_interno,
            nome_interno: i.nome_interno.clone(),
            base64_foto: base64_text.clone(),
        };

        all_data.push(data);

and schema.rs:

use diesel::*;

#[derive(Queryable)]
#[diesel(table_name = INTERNO)]
pub struct Image {
    #[diesel(column_name = "ID_INTERNO")]
    pub id_interno: i32,
    #[diesel(column_name = "FOTO")]
    pub foto: Option<Vec<u8>>,
}

table! {
    interno (ID_INTERNO) {
        ID_INTERNO -> Integer,
        FOTO ->  Nullable<Binary>,
    }
}

using let schema:::table Load() does not work cause binary is not supported, then i'm using First

Without this change, my code show:

Error: [DatabaseError(Unknown, error: Unsupported column type (520 -1))]

With this change, the code work perfectly.

hellitonsm commented 11 months ago

DDL for Domain:

CREATE DOMAIN DM_FOTO AS blob sub_type -1 ;

fernandobatels commented 11 months ago

Please, try this fix 4c728cc.

hellitonsm commented 11 months ago

Perfect.

fernandobatels commented 11 months ago

Please, check the new released version: v0.23.1

https://github.com/fernandobatels/rsfbclient/releases/tag/v0.23.1