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 | 'use strict';
|
28 |
|
29 | const BaseDbObject = require('./dbObject.js');
|
30 | const { Buffer } = require('buffer');
|
31 | const Lob = require('./lob.js');
|
32 | const ResultSet = require('./resultset.js');
|
33 | const constants = require('./constants.js');
|
34 | const errors = require('./errors.js');
|
35 | const util = require('util');
|
36 | const types = require('./types.js');
|
37 | const nodbUtil = require('./util.js');
|
38 |
|
39 |
|
40 |
|
41 |
|
42 |
|
43 |
|
44 |
|
45 |
|
46 |
|
47 |
|
48 | function checkType(info, options) {
|
49 | if (info.type === undefined && arguments.length > 2) {
|
50 | info.type = arguments[2];
|
51 | } else {
|
52 | let matches = false;
|
53 | for (let i = 2; i < arguments.length; i++) {
|
54 | if (info.type === arguments[i]) {
|
55 | matches = true;
|
56 | break;
|
57 | }
|
58 | }
|
59 | if (!matches) {
|
60 | if (info.attrName) {
|
61 | errors.throwErr(errors.ERR_WRONG_VALUE_FOR_DBOBJECT_ATTR,
|
62 | info.attrName, info.fqn);
|
63 | } else if (info.fqn) {
|
64 | errors.throwErr(errors.ERR_WRONG_VALUE_FOR_DBOBJECT_ELEM, info.fqn);
|
65 | } else if (info.isArray && info.name) {
|
66 | errors.throwErr(errors.ERR_INCOMPATIBLE_TYPE_ARRAY_BIND, options.pos,
|
67 | info.name);
|
68 | } else if (info.isArray) {
|
69 | errors.throwErr(errors.ERR_INCOMPATIBLE_TYPE_ARRAY_INDEX_BIND,
|
70 | options.pos, info.pos);
|
71 | } else {
|
72 | errors.throwErr(errors.ERR_BIND_VALUE_AND_TYPE_MISMATCH);
|
73 | }
|
74 | }
|
75 | }
|
76 | }
|
77 |
|
78 |
|
79 |
|
80 |
|
81 |
|
82 |
|
83 |
|
84 |
|
85 |
|
86 | function transformJsonValue(value) {
|
87 |
|
88 |
|
89 | if (value === undefined || value === null ||
|
90 | typeof value === 'number' || typeof value === 'string' ||
|
91 | typeof value === 'boolean' || Buffer.isBuffer(value) ||
|
92 | util.isDate(value) || nodbUtil.isVectorValue(value))
|
93 | return value;
|
94 |
|
95 |
|
96 | if (Array.isArray(value)) {
|
97 | const outValue = new Array(value.length);
|
98 | for (let i = 0; i < value.length; i++) {
|
99 | outValue[i] = transformJsonValue(value[i]);
|
100 | }
|
101 | return outValue;
|
102 | }
|
103 |
|
104 |
|
105 | if (value instanceof BaseDbObject)
|
106 | return {fields: [], values: []};
|
107 |
|
108 |
|
109 |
|
110 | const outValue = {};
|
111 | outValue.fields = Object.getOwnPropertyNames(value);
|
112 | outValue.values = new Array(outValue.fields.length);
|
113 | for (let i = 0; i < outValue.fields.length; i++) {
|
114 | outValue.values[i] = transformJsonValue(value[outValue.fields[i]]);
|
115 | }
|
116 | return outValue;
|
117 |
|
118 | }
|
119 |
|
120 |
|
121 |
|
122 |
|
123 |
|
124 |
|
125 |
|
126 |
|
127 |
|
128 | function transformValueIn(info, value, options) {
|
129 |
|
130 |
|
131 | if (value === undefined || value === null)
|
132 | return undefined;
|
133 |
|
134 |
|
135 | if (info.type === types.DB_TYPE_OBJECT) {
|
136 | let obj = value;
|
137 | if (!(value instanceof BaseDbObject)) {
|
138 | obj = new info.typeClass(value);
|
139 | }
|
140 | return obj._impl;
|
141 |
|
142 |
|
143 | } else if (info.type === types.DB_TYPE_JSON) {
|
144 | return transformJsonValue(value);
|
145 |
|
146 |
|
147 | } else if (typeof value === 'string') {
|
148 | checkType(info, options,
|
149 | types.DB_TYPE_VARCHAR,
|
150 | types.DB_TYPE_NVARCHAR,
|
151 | types.DB_TYPE_CHAR,
|
152 | types.DB_TYPE_NCHAR,
|
153 | types.DB_TYPE_CLOB,
|
154 | types.DB_TYPE_NCLOB);
|
155 | if (info.type !== types.DB_TYPE_CLOB &&
|
156 | info.type !== types.DB_TYPE_NCLOB) {
|
157 | const valueLen = Buffer.byteLength(value);
|
158 | if (info.maxSize === undefined || valueLen > info.maxSize) {
|
159 | if (info.checkSize) {
|
160 | errors.throwErr(errors.ERR_MAX_SIZE_TOO_SMALL, info.maxSize,
|
161 | valueLen, options.pos);
|
162 | }
|
163 | info.maxSize = valueLen;
|
164 | }
|
165 | }
|
166 | return value;
|
167 |
|
168 |
|
169 | } else if (typeof value === 'number') {
|
170 | checkType(info, options,
|
171 | types.DB_TYPE_NUMBER,
|
172 | types.DB_TYPE_BINARY_INTEGER,
|
173 | types.DB_TYPE_BINARY_FLOAT,
|
174 | types.DB_TYPE_BINARY_DOUBLE);
|
175 | if (Number.isNaN(value) && info.type === types.DB_TYPE_NUMBER) {
|
176 | errors.throwErr(errors.ERR_NAN_VALUE);
|
177 | }
|
178 | return value;
|
179 |
|
180 |
|
181 | } else if (typeof value === 'boolean') {
|
182 | checkType(info, options, types.DB_TYPE_BOOLEAN);
|
183 | return value;
|
184 |
|
185 |
|
186 | } else if (util.isDate(value)) {
|
187 | checkType(info, options,
|
188 | types.DB_TYPE_TIMESTAMP,
|
189 | types.DB_TYPE_TIMESTAMP_TZ,
|
190 | types.DB_TYPE_TIMESTAMP_LTZ,
|
191 | types.DB_TYPE_DATE);
|
192 | return value;
|
193 |
|
194 |
|
195 | } else if (Buffer.isBuffer(value)) {
|
196 | checkType(info, options,
|
197 | types.DB_TYPE_RAW,
|
198 | types.DB_TYPE_BLOB);
|
199 | if (info.type === types.DB_TYPE_RAW &&
|
200 | (info.maxSize === undefined || value.length > info.maxSize)) {
|
201 | if (info.checkSize) {
|
202 | errors.throwErr(errors.ERR_MAX_SIZE_TOO_SMALL, info.maxSize,
|
203 | value.length, options.pos);
|
204 | }
|
205 | info.maxSize = value.length;
|
206 | }
|
207 | return value;
|
208 |
|
209 |
|
210 | } else if (value instanceof ResultSet) {
|
211 | checkType(info, options, types.DB_TYPE_CURSOR);
|
212 | return value._impl;
|
213 |
|
214 |
|
215 | } else if (value instanceof Lob) {
|
216 | checkType(info, options, value.type);
|
217 | return value._impl;
|
218 |
|
219 |
|
220 | } else if (value instanceof BaseDbObject) {
|
221 | checkType(info, options, types.DB_TYPE_OBJECT);
|
222 | return value._impl;
|
223 |
|
224 |
|
225 | } else if (value instanceof Float32Array || value instanceof Float64Array ||
|
226 | value instanceof Int8Array) {
|
227 | checkType(info, options, types.DB_TYPE_VECTOR);
|
228 | return value;
|
229 | } else if (info.type === types.DB_TYPE_VECTOR && Array.isArray(value)) {
|
230 | return new Float64Array(value);
|
231 |
|
232 |
|
233 | } else if (options.allowArray && Array.isArray(value)) {
|
234 | info.isArray = true;
|
235 | if (info.dir === constants.BIND_IN) {
|
236 | info.maxArraySize = value.length || 1;
|
237 | } else if (info.maxArraySize === undefined) {
|
238 | errors.throwErr(errors.ERR_REQUIRED_MAX_ARRAY_SIZE);
|
239 | } else if (value.length > info.maxArraySize) {
|
240 | errors.throwErr(errors.ERR_INVALID_ARRAY_SIZE);
|
241 | }
|
242 | options.allowArray = false;
|
243 | const transformed = new Array(value.length);
|
244 | for (let i = 0; i < value.length; i++) {
|
245 | options.pos = i;
|
246 | transformed[i] = transformValueIn(info, value[i], options);
|
247 | }
|
248 | return transformed;
|
249 | }
|
250 |
|
251 |
|
252 | if (info.type === undefined)
|
253 | errors.throwErr(errors.ERR_INVALID_BIND_DATA_TYPE, 2);
|
254 | checkType(info, options);
|
255 |
|
256 | }
|
257 |
|
258 |
|
259 | module.exports = {
|
260 | transformJsonValue,
|
261 | transformValueIn
|
262 |
|
263 | };
|