SAP / node-hdb

SAP HANA Database Client for Node
Apache License 2.0
317 stars 98 forks source link

Insert of blob field from stream.Readable hangs #215

Open rweinzierl opened 1 year ago

rweinzierl commented 1 year ago

If I try to write to a blob field from a simple readable stream, e.g.

stream.Readable.from([Buffer.from('0'), Buffer.from('1'), Buffer.from('2')])

the statement execution hangs indefinitely.

Interestingly, inserting a shorter stream with 2 elements works, whereas a longer stream with 1mio elements causes an error Chunk length larger than remaining bytes.

To reproduce execute the JavaScript file below (replace host, port, user, password, schema):

test.js:

const stream = require('stream')
const fs = require('fs')
const os = require('os')
const path = require('path')
const hdb = require('hdb')
const crypto = require('crypto')
const { exec, execSync } = require('child_process')

const passReadableThroughNamedPipe = r => {
    const fifoPath = path.join(os.tmpdir(), 'fifo-' + crypto.randomBytes(16).toString('hex'))
    execSync(`mkfifo ${fifoPath}`)
    const r2 = fs.createReadStream(fifoPath)
    r.pipe(fs.createWriteStream(fifoPath))
    return r2
}

{
    (async () => {
        const nChunks = parseInt(process.argv[2])

        let logo = stream.Readable.from([...Array(nChunks).keys()].map(i => Buffer.from(`${i}`)))
        if (process.argv[3] === 'fifo')
            logo = passReadableThroughNamedPipe(logo)

        const defaultEnv = JSON.parse(fs.readFileSync('default-env.json'))
        const { host, port, user, password, schema } = defaultEnv.VCAP_SERVICES.hana[0].credentials

        const client = hdb.createClient({ host, port, user, password })

        client.connect((err) => {
            if (err) throw Error(err)
            client.exec(`SET SCHEMA ${schema}`, (err) => {
                if (err) throw Error(err)
                client.exec('drop table TEST_BLOBS', () => {
                    client.exec([
                        'create column table TEST_BLOBS (',
                        '"ID"     INT NOT NULL,',
                        '"NAME"   NVARCHAR(256) NOT NULL,',
                        '"IMG"  BLOB,',
                        '"LOGO"  BLOB,',
                        '"DESCR"  NCLOB,',
                        'PRIMARY KEY ("ID"))'
                    ].join('\n'), () => {
                        client.prepare('insert into TEST_BLOBS values (?, ?, ?, ?, ?)', (err, statement) => {
                            if (err) throw Error(err)
                            console.log('Inserting')
                            statement.exec([
                                1,
                                'SAP AG',
                                fs.createReadStream('test.js'),
                                logo,
                                Buffer.from('SAP headquarters located in Walldorf, Germany', 'ascii')
                            ], (err) => {
                                if (err) throw Error(err)
                                client.exec('select * from TEST_BLOBS', (err, rows) => {
                                    console.log(rows[0].LOGO.length)
                                    process.exit()
                                })
                            })
                        })
                    })
                })
            })
        })

    })()
}