1
+ /* Copyright (c) 2016, 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
+ * 65. uninitializedLob.js
23
+ *
24
+ * DESCRIPTION
25
+ * This test is provided by GitHub user for issue #344
26
+ * It tests an uninitialized LOB returns from a PL/SQL block.
27
+ *
28
+ * NUMBERING RULE
29
+ * Test numbers follow this numbering rule:
30
+ * 1 - 20 are reserved for basic functional tests
31
+ * 21 - 50 are reserved for data type supporting tests
32
+ * 51 onwards are for other tests
33
+ *
34
+ *****************************************************************************/
35
+ 'use strict' ;
36
+
37
+ var oracledb = require ( 'oracledb' ) ;
38
+ var async = require ( 'async' ) ;
39
+ var should = require ( 'should' ) ;
40
+ var crypto = require ( 'crypto' ) ;
41
+ var stream = require ( 'stream' ) ;
42
+ var dbConfig = require ( './dbconfig.js' ) ;
43
+
44
+ describe ( '65. uninitializedLob.js' , function ( ) {
45
+
46
+ if ( dbConfig . externalAuth ) {
47
+ var credential = { externalAuth : true , connectString : dbConfig . connectString } ;
48
+ } else {
49
+ var credential = dbConfig ;
50
+ }
51
+
52
+ var connection = null ;
53
+ before ( function ( done ) {
54
+ async . series ( [
55
+ function ( callback ) {
56
+ oracledb . getConnection ( credential , function ( err , conn ) {
57
+ should . not . exist ( err ) ;
58
+ connection = conn ;
59
+ callback ( ) ;
60
+ } ) ;
61
+ } ,
62
+ function createTab ( callback ) {
63
+ var proc = "BEGIN \n" +
64
+ " DECLARE \n" +
65
+ " e_table_exists EXCEPTION; \n" +
66
+ " PRAGMA EXCEPTION_INIT(e_table_exists, -00942);\n " +
67
+ " BEGIN \n" +
68
+ " EXECUTE IMMEDIATE ('DROP TABLE testlobdpi'); \n" +
69
+ " EXCEPTION \n" +
70
+ " WHEN e_table_exists \n" +
71
+ " THEN NULL; \n" +
72
+ " END; \n" +
73
+ " EXECUTE IMMEDIATE (' \n" +
74
+ " CREATE TABLE testlobdpi ( \n" +
75
+ " id NUMBER NOT NULL PRIMARY KEY, \n" +
76
+ " spoc_cm_id NUMBER, \n" +
77
+ " created_timestamp TIMESTAMP(5) DEFAULT SYSTIMESTAMP, \n" +
78
+ " modified_timestamp TIMESTAMP(5) DEFAULT SYSTIMESTAMP \n" +
79
+ " ) \n" +
80
+ " '); \n" +
81
+ "END; " ;
82
+
83
+ connection . execute (
84
+ proc ,
85
+ function ( err ) {
86
+ should . not . exist ( err ) ;
87
+ callback ( ) ;
88
+ }
89
+ ) ;
90
+ } ,
91
+ function createSeq ( callback ) {
92
+ var proc = "BEGIN \n" +
93
+ " DECLARE \n" +
94
+ " e_sequence_exists EXCEPTION; \n" +
95
+ " PRAGMA EXCEPTION_INIT(e_sequence_exists, -02289);\n " +
96
+ " BEGIN \n" +
97
+ " EXECUTE IMMEDIATE ('DROP SEQUENCE testlobdpi_seq'); \n" +
98
+ " EXCEPTION \n" +
99
+ " WHEN e_sequence_exists \n" +
100
+ " THEN NULL; \n" +
101
+ " END; \n" +
102
+ " EXECUTE IMMEDIATE (' \n" +
103
+ " CREATE SEQUENCE testlobdpi_seq INCREMENT BY 1 START WITH 1 NOMAXVALUE CACHE 50 ORDER \n" +
104
+ " '); \n" +
105
+ "END; " ;
106
+
107
+ connection . execute (
108
+ proc ,
109
+ function ( err ) {
110
+ should . not . exist ( err ) ;
111
+ callback ( ) ;
112
+ }
113
+ ) ;
114
+ } ,
115
+ function ( callback ) {
116
+ var proc = "create or replace trigger testlobdpi_rbi \n" +
117
+ " before insert on testlobdpi referencing old as old new as new \n" +
118
+ " for each row \n" +
119
+ "begin \n" +
120
+ " :new.id := testlobdpi_seq.nextval;\n" +
121
+ "end;" ;
122
+ connection . execute (
123
+ proc ,
124
+ function ( err ) {
125
+ should . not . exist ( err ) ;
126
+ callback ( ) ;
127
+ }
128
+ ) ;
129
+ } ,
130
+ function ( callback ) {
131
+ var proc = "create or replace trigger testlobdpi_rbu \n" +
132
+ " before update on testlobdpi referencing old as old new as new \n" +
133
+ " for each row \n" +
134
+ "begin \n" +
135
+ " :new.modified_timestamp := systimestamp;\n" +
136
+ "end;" ;
137
+ connection . execute (
138
+ proc ,
139
+ function ( err ) {
140
+ should . not . exist ( err ) ;
141
+ callback ( ) ;
142
+ }
143
+ ) ;
144
+ } ,
145
+ function ( callback ) {
146
+ var sql = "ALTER TABLE testlobdpi ADD (blob_1 BLOB, unit32_1 NUMBER, date_1 TIMESTAMP(5), " +
147
+ " string_1 VARCHAR2(250), CONSTRAINT string_1_uk UNIQUE (string_1))" ;
148
+
149
+ connection . execute (
150
+ sql ,
151
+ function ( err ) {
152
+ should . not . exist ( err ) ;
153
+ callback ( ) ;
154
+ }
155
+ ) ;
156
+ }
157
+ ] , done ) ;
158
+ } ) // before
159
+
160
+ after ( function ( done ) {
161
+ async . series ( [
162
+ function ( callback ) {
163
+ connection . execute (
164
+ "DROP SEQUENCE testlobdpi_seq" ,
165
+ function ( err ) {
166
+ should . not . exist ( err ) ;
167
+ callback ( ) ;
168
+ }
169
+ ) ;
170
+ } ,
171
+ function ( callback ) {
172
+ connection . execute (
173
+ "DROP TABLE testlobdpi" ,
174
+ function ( err ) {
175
+ should . not . exist ( err ) ;
176
+ callback ( ) ;
177
+ }
178
+ ) ;
179
+ } ,
180
+ function ( callback ) {
181
+ connection . release ( function ( err ) {
182
+ should . not . exist ( err ) ;
183
+ callback ( ) ;
184
+ } ) ;
185
+ }
186
+ ] , done ) ;
187
+ } ) // after
188
+
189
+ it ( '65.1 an uninitialized Lob is returned from a PL/SQL block' , function ( done ) {
190
+ // async's times applies a function n times in series.
191
+ async . timesSeries ( 3 , function ( n , next ) {
192
+ var string_1 = n % 2 ;
193
+ var proc = "DECLARE \n" +
194
+ " row_count NUMBER := 0;" +
195
+ " negative_one NUMBER := -1;" +
196
+ "BEGIN \n" +
197
+ " SELECT COUNT(*) INTO row_count FROM testlobdpi WHERE (string_1 = :string_1);" +
198
+ " IF (row_count = 0 ) THEN\n" +
199
+ " INSERT INTO testlobdpi (blob_1, string_1, spoc_cm_id) \n" +
200
+ " VALUES (empty_blob(), :string_1, :spoc_cm_id) \n" +
201
+ " RETURNING id, blob_1 INTO :id, :blob_1; \n" +
202
+ " ELSE \n" +
203
+ " :id := negative_one;\n" +
204
+ " :blob_1 := null; \n" +
205
+ " END IF;\n" +
206
+ "END; " ;
207
+
208
+ connection . execute (
209
+ proc ,
210
+ {
211
+ id : { type : oracledb . NUMBER , dir : oracledb . BIND_OUT } ,
212
+ blob_1 : { type : oracledb . BLOB , dir : oracledb . BIND_OUT } ,
213
+ string_1 : string_1 ,
214
+ spoc_cm_id : 1
215
+ } ,
216
+ { outFormat : oracledb . OBJECT , autoCommit : false } ,
217
+ function ( err , result ) {
218
+ if ( err ) {
219
+ console . error ( err . message ) ;
220
+ return next ( err ) ;
221
+ }
222
+
223
+ //console.log(n + ':',result);
224
+
225
+ if ( result . outBinds . id == - 1 ) {
226
+ // a dup was found
227
+ return next ( null )
228
+ }
229
+
230
+ var randomBlob = new Buffer ( 0 ) ;
231
+ crypto . randomBytes ( 16 , function ( ex , buf ) {
232
+ var passthrough = new stream . PassThrough ( ) ;
233
+ passthrough . on ( 'error' , function ( err ) {
234
+ should . not . exist ( err ) ;
235
+ } ) ;
236
+
237
+ result . outBinds . blob_1 . on ( 'error' , function ( err ) {
238
+ should . not . exist ( err ) ;
239
+ } )
240
+
241
+ result . outBinds . blob_1 . on ( 'finish' , function ( err ) {
242
+ next ( err ) ;
243
+ } ) ;
244
+
245
+ passthrough . write ( buf , function ( ) {
246
+ passthrough . pipe ( result . outBinds . blob_1 ) ;
247
+ passthrough . end ( ) ;
248
+ } ) ;
249
+ } ) ;
250
+
251
+ }
252
+ ) ;
253
+ } , function ( err ) {
254
+ should . not . exist ( err ) ;
255
+ done ( ) ;
256
+ } ) ;
257
+ } ) //65.1
258
+ } )
0 commit comments