oracle / node-oracledb

Oracle Database driver for Node.js maintained by Oracle Corp.
http://oracle.github.io/node-oracledb/
Other
2.24k stars 1.07k forks source link

Question about closing lobs #1535

Closed sosoba closed 1 year ago

sosoba commented 1 year ago
  1. What versions are you using? 5.2
  2. Describe the problem

I would like to confirm this point in the documentation: https://oracle.github.io/node-oracledb/doc/api.html#-197-closing-lobs

  1. Include a runnable Node.js script that shows the problem.
const {rows} = await conn.exeecute('SELECT date, blob FROM my_files where id=1');
const [[date, blob]]  = rows;
if (local_file_is_outdated(date)) {
  await pipeline( blob, createWriteStream( filename ) );
} else {
  // Does any selected lob must be destroyed manually even if it was untouched?
  blob.destroy();
}

Does the rest of the garbage apply to JS only or the C stack as well?

anthony-tuininga commented 1 year ago

The code above looks correct. LOBs that are streamed to completion will be automatically closed. The other LOBs should be destroyed. Failing to do so will simply result in a delay before the memory is reclaimed as the garbage collector will have to notice that the value is no longer in use (which will internally call the equivalent of the close).

sosoba commented 1 year ago

Thank you. We have noticed problems when SQL has a wide list of columns that are not fully used. What do you think about the system solution:

const {rows, destroy} = await conn.exeecute('SELECT * FROM table_with_blobs');
try {
   // Consuming blobs in rows or not
} finally {
  destroy(); // Clean up
}
anthony-tuininga commented 1 year ago

I guess the problem with the solution you suggest is that it is only truly helpful if you don't wany any of the LOBs to remain after the fetch is complete. The other question: why do you fetch data that you don't require?

It should be possible to write this independent of the driver in any case. Something like this:

const result = await connection.execute("select * from table_with_blobs");
const rows = result.rows;
for (let i = 0; i < rows.length; i++) {
  const row = rows[i];
  for (let j = 0; j < row.length; j++) {
    const val = row[j];
    if (val instanceof oracledb.Lob) {
      await val.close();  // or simply val.destroy();
    }
  }
}
stale[bot] commented 1 year ago

This issue has been automatically marked as inactive because it has not been updated recently. It will be closed if no further activity occurs. Thank you for your contributions.

anthony-tuininga commented 1 year ago

An additional note: with version 6.0 you can use a fetch type handler to perform any adjustments that are needed.