333
schangxiang@126.com
2025-09-19 18966e02fb573c7e2bb0c6426ed792b38b910940
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
// Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved
 
//-----------------------------------------------------------------------------
//
// You may not use the identified files except in compliance with the Apache
// License, Version 2.0 (the "License.")
//
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0.
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// See the License for the specific language governing permissions and
// limitations under the License.
//
//-----------------------------------------------------------------------------
 
'use strict';
 
const { Duplex } = require('stream');
const nodbUtil = require('./util.js');
 
//-----------------------------------------------------------------------------
// close()
//   Close the LOB and make it unusable for further operations. If the LOB is
// already closed, nothing is done in order to support multiple close() calls.
//
//   This method is deprecated and will be removed in a future version of the
// node-oracledb driver. Use lob.destroy() instead. NOTE: this method will
// emit a duplicate "close" event in order to be compatible with previous
// versions of node-oracledb.
//-----------------------------------------------------------------------------
async function close() {
  nodbUtil.checkArgCount(arguments, 0, 0);
  if (this.valid) {
    try {
      await this._close();
      this.emit('close');
    } catch (err) {
      this.destroy(err);
    }
  }
}
 
 
//-----------------------------------------------------------------------------
// getData()
//   Returns all of the data in the LOB as a single string or buffer.
//-----------------------------------------------------------------------------
async function getData() {
  nodbUtil.checkArgCount(arguments, 0, 0);
  return await this._getData();
}
 
 
class Lob extends Duplex {
 
  constructor() {
    super({ decodeStrings: false });
    this.offset = 1;
    this.once('finish', function() {
      if (this._autoCloseLob) {
        this.destroy();
      }
    });
  }
 
  _extend(oracledb) {
    this._oracledb = oracledb;
    this.close = nodbUtil.callbackify(close);
    this.getData = nodbUtil.callbackify(getData);
  }
 
  // called by stream.destroy() and ensures that the LOB is closed if it has
  // not already been closed (never called directly)
  async _destroy(err, cb) {
    if (this.valid) {
      try {
        await this._close();
      } catch (closeErr) {
        cb(closeErr);
        return;
      }
    }
    cb(err);
  }
 
  // implementation of streaming read; if lob is set to auto-close, the lob is
  // automatically closed within the C code when an error occurs or when there
  // are no more bytes to transfer; all that needs to be done in the JS layer
  // is to destroy the streaming LOB
  async _read() {
    try {
      const data = await this.__read(this.offset);
      if (data) {
        this.offset += data.length;
        this.push(data);
      } else {
        this.push(null);
        if (this._autoCloseLob) {
          this.destroy();
        }
      }
    } catch (err) {
      this.destroy(err);
    }
  }
 
  // implementation of streaming write; if lob is set to auto-close, the lob is
  // automatically closed in the "finish" event; all that needs to be done here
  // is to destroy the streaming LOB
  async _write(data, encoding, cb) {
 
    // convert data if needed
    if (this.type == this._oracledb.DB_TYPE_BLOB && !Buffer.isBuffer(data)) {
      data = Buffer.from(data);
    } else if (this.type == this._oracledb.DB_TYPE_CLOB &&
        Buffer.isBuffer(data)) {
      data = data.toString();
    }
 
    try {
      await this.__write(this.offset, data);
    } catch (err) {
      cb(err);
      this.destroy(err);
      return;
    }
    this.offset += data.length;
    cb(null);
 
  }
 
}
 
module.exports = Lob;