Skip to content

Transform a resultSet into a readable stream #219

Closed
@jgoux

Description

@jgoux

Hello,
I want to turn a resultSet into a readableStream (like node-mssql and node-mysql provide through their pipe methods), so I can pipe it to whatever I want to do with the results (millions of lines).
Here is my function to execute a query and then returns a readable stream :

async function executeQuery(connectionParameters, query, queryParameters) {
    const getConnection = promisify(oracle.getConnection.bind(oracle))
    const connection = await getConnection(connectionParameters)

    const executeQuery = promisify(connection.execute.bind(connection))
    const result = await executeQuery(query, queryParameters, { resultSet: true })

    const getRow = promisify(result.resultSet.getRow.bind(result.resultSet))

    const rs = Readable({ objectMode: true })
    rs._read = async function() {
        const row = await getRow()
        if (!row) {
            result.resultSet.close((e) => { if (e) throw e })
            connection.release((e) => { if (e) throw e })
            return rs.push(null)
        }
        rs.push(row)
    }
    return rs
}

Here is how I use it :

const query$ = await executeQuery(connectionParameters, query, queryParameters)

    return new Promise((resolve, reject) => {
        query$.on("error", reject)

        const csvStringifier$ = csvStringify({ delimiter: argv.delimiter })
        csvStringifier$.on("error", reject)

        const file$ = fs.createWriteStream("./extraction.csv")
        file$.on("finish", resolve).on("error", reject)

        query$.pipe(csvStringifier$).pipe(file$)
    })

My issue is as a certain point, the fetching stops without errors.
For the same query, sometimes they're 10K rows written to the file, then only 2K, then 14K...
I'm pretty sure it's due to my _read implementation, but I can't figure out what's wrong with it.
In node.js doc (https://nodejs.org/api/stream.html#stream_readable_read_size_1) this part is unclear to me :

When _read is called, if data is available from the resource, _read should start pushing that data into the read queue by calling this.push(dataChunk). _read should continue reading from the resource and pushing data until push returns false, at which point it should stop reading from the resource. Only when _read is called again after it has stopped should it start reading more data from the resource and pushing that data onto the queue.

Thanks in advance.

EDIT : Here is an example of an implementation : https://github.com/felixge/node-mysql/blob/de5913227dbbaacbbdf22ee38689d090e1451be9/lib/protocol/sequences/Query.js#L188

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions