1+ /* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. */
2+
3+ /******************************************************************************
4+ *
5+ * You may not use the identified files except in compliance with the Apache
6+ * License, Version 2.0 (the "License.")
7+ *
8+ * You may obtain a copy of the License at
9+ * http://www.apache.org/licenses/LICENSE-2.0.
10+ *
11+ * Unless required by applicable law or agreed to in writing, software
12+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+ *
15+ * See the License for the specific language governing permissions and
16+ * limitations under the License.
17+ *
18+ * The node-oracledb test suite uses 'mocha', 'should' and 'async'.
19+ * See LICENSE.md for relevant licenses.
20+ *
21+ * NAME
22+ * 245. fetchLobAsStrBuf.js
23+ *
24+ * DESCRIPTION
25+ * Testing CLOB binding as String with DML and Blob binding as Buffer with DML
26+ *
27+ *****************************************************************************/
28+ 'use strict' ;
29+
30+ var oracledb = require ( 'oracledb' ) ;
31+ var should = require ( 'should' ) ;
32+ var async = require ( 'async' ) ;
33+ var dbConfig = require ( './dbconfig.js' ) ;
34+ var random = require ( './random.js' ) ;
35+ var assist = require ( './dataTypeAssist.js' ) ;
36+
37+ describe ( '245. fetchLobAsStrBuf.js' , function ( ) {
38+ var connection = null ;
39+ var insertID = 1 ;
40+ var tableName = "fetchLobAsStrBuf_table" ;
41+ var fun_create_table = "BEGIN \n" +
42+ " DECLARE \n" +
43+ " e_table_missing EXCEPTION; \n" +
44+ " PRAGMA EXCEPTION_INIT(e_table_missing, -00942);\n" +
45+ " BEGIN \n" +
46+ " EXECUTE IMMEDIATE ('DROP TABLE " + tableName + " PURGE' ); \n" +
47+ " EXCEPTION \n" +
48+ " WHEN e_table_missing \n" +
49+ " THEN NULL; \n" +
50+ " END; \n" +
51+ " EXECUTE IMMEDIATE ( ' \n" +
52+ " CREATE TABLE " + tableName + " ( \n" +
53+ " id NUMBER, \n" +
54+ " clob_col clob, \n" +
55+ " blob_col blob \n" +
56+ " ) \n" +
57+ " '); \n" +
58+ "END; " ;
59+ var drop_table = "DROP TABLE " + tableName + " PURGE" ;
60+
61+ before ( function ( done ) {
62+ oracledb . getConnection ( dbConfig , function ( err , conn ) {
63+ should . not . exist ( err ) ;
64+ connection = conn ;
65+ done ( ) ;
66+ } ) ;
67+ } ) ;
68+
69+ after ( function ( done ) {
70+ connection . release ( function ( err ) {
71+ should . not . exist ( err ) ;
72+ done ( ) ;
73+ } ) ;
74+ } ) ;
75+
76+ var executeSQL = function ( sql , callback ) {
77+ connection . execute (
78+ sql ,
79+ function ( err ) {
80+ should . not . exist ( err ) ;
81+ return callback ( ) ;
82+ }
83+ ) ;
84+ } ;
85+
86+ var insertIntoTable = function ( id , contentClob , contentBlob , callback ) {
87+ if ( contentClob == "EMPTY_CLOB" && contentBlob == "EMPTY_BLOB" ) {
88+ connection . execute ( "insert INTO fetchLobAsStrBuf_table values(:id, EMPTY_CLOB(), EMPTY_BLOB())" ,
89+ [ id ] ,
90+ function ( err , result ) {
91+ should . not . exist ( err ) ;
92+ should . strictEqual ( result . rowsAffected , 1 ) ;
93+ callback ( ) ;
94+ } ) ;
95+ }
96+ else {
97+ var sql = "insert into fetchLobAsStrBuf_table (id, clob_col, blob_col) values(:id, :str, :buf)" ;
98+ var bindings = {
99+ id : { val : id } ,
100+ str : { val :contentClob , type :oracledb . STRING , dir :oracledb . BIND_IN } ,
101+ buf : { val :contentBlob , type :oracledb . BUFFER , dir :oracledb . BIND_IN }
102+ } ;
103+ connection . execute ( sql , bindings ,
104+ function ( err , result ) {
105+ should . not . exist ( err ) ;
106+ should . strictEqual ( result . rowsAffected , 1 ) ;
107+ callback ( ) ;
108+ } ) ;
109+ }
110+ } ;
111+
112+ var checkInsertResult = function ( id , contentClob , specialStr , contentBlob , callback ) {
113+ async . series ( [
114+ function ( cb ) {
115+ var sql = "select clob_col from fetchLobAsStrBuf_table where id = " + id ;
116+ verifyClobValueWithString ( sql , contentClob , specialStr , cb ) ;
117+ } ,
118+ function ( cb ) {
119+ var sql = "select blob_col from fetchLobAsStrBuf_table where id = " + id ;
120+ verifyBlobValueWithBuffer ( sql , contentBlob , specialStr , cb ) ;
121+ }
122+ ] , callback ) ;
123+ } ;
124+
125+ var verifyClobValueWithString = function ( selectSql , originalString , specialStr , callback ) {
126+ connection . execute (
127+ selectSql ,
128+ function ( err , result ) {
129+ should . not . exist ( err ) ;
130+ var lob = result . rows [ 0 ] [ 0 ] ;
131+ if ( originalString == '' || originalString == undefined || originalString == null ) {
132+ should . not . exist ( lob ) ;
133+ return callback ( ) ;
134+ } else {
135+ should . exist ( lob ) ;
136+ // set the encoding so we get a 'string' not a 'buffer'
137+ lob . setEncoding ( 'utf8' ) ;
138+ var clobData = '' ;
139+
140+ lob . on ( 'data' , function ( chunk ) {
141+ clobData += chunk ;
142+ } ) ;
143+
144+ lob . on ( 'error' , function ( err ) {
145+ should . not . exist ( err , "lob.on 'error' event." ) ;
146+ } ) ;
147+
148+ lob . on ( 'end' , function ( err ) {
149+ should . not . exist ( err ) ;
150+ if ( originalString == "EMPTY_CLOB" ) {
151+ should . strictEqual ( clobData , "" ) ;
152+ } else {
153+ var resultLength = clobData . length ;
154+ var specStrLength = specialStr . length ;
155+ should . strictEqual ( resultLength , originalString . length ) ;
156+ should . strictEqual ( clobData . substring ( 0 , specStrLength ) , specialStr ) ;
157+ should . strictEqual ( clobData . substring ( resultLength - specStrLength , resultLength ) , specialStr ) ;
158+ }
159+ return callback ( ) ;
160+ } ) ;
161+ }
162+ }
163+ ) ;
164+ } ;
165+
166+ var verifyBlobValueWithBuffer = function ( selectSql , originalBuffer , specialStr , callback ) {
167+ connection . execute (
168+ selectSql ,
169+ function ( err , result ) {
170+ should . not . exist ( err ) ;
171+ var lob = result . rows [ 0 ] [ 0 ] ;
172+ if ( originalBuffer == '' || originalBuffer == undefined ) {
173+ should . not . exist ( lob ) ;
174+ return callback ( ) ;
175+ } else {
176+ should . exist ( lob ) ;
177+ var blobData = Buffer . alloc ( 0 ) ;
178+ var totalLength = 0 ;
179+
180+ lob . on ( 'data' , function ( chunk ) {
181+ totalLength = totalLength + chunk . length ;
182+ blobData = Buffer . concat ( [ blobData , chunk ] , totalLength ) ;
183+ } ) ;
184+
185+ lob . on ( 'error' , function ( err ) {
186+ should . not . exist ( err , "lob.on 'error' event." ) ;
187+ } ) ;
188+
189+ lob . on ( 'end' , function ( ) {
190+ if ( originalBuffer == "EMPTY_BLOB" ) {
191+ var nullBuffer = Buffer . from ( '' , "utf-8" ) ;
192+ should . strictEqual ( assist . compare2Buffers ( blobData , nullBuffer ) , true ) ;
193+ } else {
194+ should . strictEqual ( totalLength , originalBuffer . length ) ;
195+ var specStrLength = specialStr . length ;
196+ should . strictEqual ( blobData . toString ( 'utf8' , 0 , specStrLength ) , specialStr ) ;
197+ should . strictEqual ( blobData . toString ( 'utf8' , ( totalLength - specStrLength ) , totalLength ) , specialStr ) ;
198+ should . strictEqual ( assist . compare2Buffers ( blobData , originalBuffer ) , true ) ;
199+ }
200+ return callback ( ) ;
201+ } ) ;
202+ }
203+ }
204+ ) ;
205+ } ;
206+
207+ describe ( '245.1 CLOB,BLOB Insert' , function ( ) {
208+
209+ before ( function ( done ) {
210+ executeSQL ( fun_create_table , done ) ;
211+ } ) ;
212+
213+ after ( function ( done ) {
214+ executeSQL ( drop_table , done ) ;
215+ } ) ;
216+
217+ it ( '245.1.1 Insert and fetch CLOB,BLOB with EMPTY_CLOB and EMPTY_BLOB' , function ( done ) {
218+ var id = insertID ++ ;
219+ var contentClob = "EMPTY_CLOB" ;
220+ var contentBlob = "EMPTY_BLOB" ;
221+ async . series ( [
222+ function ( cb ) {
223+ insertIntoTable ( id , contentClob , contentBlob , cb ) ;
224+ } ,
225+ function ( cb ) {
226+ checkInsertResult ( id , contentClob , null , contentBlob , cb ) ;
227+ }
228+ ] , done ) ;
229+ } ) ;
230+
231+ it ( '245.1.2 Insert and fetch CLOB,BLOB with String and Buffer of length 32K' , function ( done ) {
232+ var id = insertID ++ ;
233+ var contentLength = 32768 ;
234+ var specialStr = "245.1.2" ;
235+ var contentClob = random . getRandomString ( contentLength , specialStr ) ;
236+ var contentBlob = Buffer . from ( contentClob , "utf-8" ) ;
237+
238+ async . series ( [
239+ function ( cb ) {
240+ insertIntoTable ( id , contentClob , contentBlob , cb ) ;
241+ } ,
242+ function ( cb ) {
243+ checkInsertResult ( id , contentClob , specialStr , contentBlob , cb ) ;
244+ }
245+ ] , done ) ;
246+
247+ } ) ;
248+
249+ it ( '245.1.3 Insert and fetch CLOB,BLOB with String and Buffer of length (1MB + 1)' , function ( done ) {
250+ var id = insertID ++ ;
251+ var contentLength = 1048577 ;
252+ var specialStr = "245.1.2" ;
253+ var contentClob = random . getRandomString ( contentLength , specialStr ) ;
254+ var contentBlob = Buffer . from ( contentClob , "utf-8" ) ;
255+
256+ async . series ( [
257+ function ( cb ) {
258+ insertIntoTable ( id , contentClob , contentBlob , cb ) ;
259+ } ,
260+ function ( cb ) {
261+ checkInsertResult ( id , contentClob , specialStr , contentBlob , cb ) ;
262+ }
263+ ] , done ) ;
264+
265+ } ) ;
266+ } ) ;
267+
268+ } ) ;
0 commit comments