asfernandes / node-firebird-drivers

Node.js Firebird Drivers
MIT License
53 stars 17 forks source link

Incorrect writing/reading of large BLOBs #19

Closed gsbelarus closed 5 years ago

gsbelarus commented 5 years ago

We have a strange problem. Below is a test. It works fine with BLOB string of 65 000 bytes but when size of BLOB is increased up to 650 000 bytes it fails. It is written without any problem but subsequent SELECT statement could read only 60 176 bytes of it.

We test it with FB3 embedded and Nodejs 11.12.

test('#fetch() with large blob', async () => {
    const attachment = await client.createDatabase(getTempFile('ResultSet-fetch-with-large-blob.fdb'), options);
    let transaction = await attachment.startTransaction();
    await attachment.execute(transaction, `create table t1 (x_blob blob)`);

    await transaction.commit();
    transaction = await attachment.startTransaction();
    const buffer = Buffer.from('#'.repeat(650000));

    await attachment.execute(transaction, insert into t1 (x_blob) VALUES (?), [buffer]);

    await transaction.commit();
    transaction = await attachment.startTransaction();

    const resultSet = await attachment.executeQuery(transaction, `select x_blob from t1`);
    const result = await resultSet.fetch();
    const readStream = await attachment.openBlob(transaction, result[0][0]);

    const resultBuffer = Buffer.alloc(await readStream.length);
    await readStream.read(resultBuffer);
    await readStream.close();
    expect(resultBuffer.toString().length).toEqual(buffer.toString().length);

    await resultSet.close();
    await transaction.commit();
    await attachment.dropDatabase();
   });
asfernandes commented 5 years ago

Both blob read and write has problems with data > 64KB. I don't known why you say write succeded.

However, I think read not necessarily returns in one go the total bytes you're requesting. You should read in a loop until it returns -1 representing the stream end. That could also be parameterized with a option to fully read the requested size in one call.

gsbelarus commented 5 years ago

I thought that write succeded because there were no error thrown during method call.

Is it limitation of node/driver, fbclient library or fb server itself?

asfernandes commented 5 years ago

In my test the method throwed. Firebird has the limitation, each segment can have a maximum of 64KB, so we should call it spliting the buffer.