Skip to content

Commit 4d05ad3

Browse files
committed
Code optimizations with DB objects and error name standardization
1 parent 889ca3c commit 4d05ad3

File tree

11 files changed

+333
-265
lines changed

11 files changed

+333
-265
lines changed

lib/connection.js

Lines changed: 15 additions & 195 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ const impl = require('./impl');
3939
const util = require('util');
4040
const constants = require('./constants.js');
4141
const settings = require('./settings.js');
42+
const transformer = require('./transformer.js');
4243
const types = require('./types.js');
4344

4445
// global mapping of subscriptions; these cannot be tied to a particular
@@ -128,38 +129,6 @@ class Connection extends EventEmitter {
128129
return (DbObject);
129130
}
130131

131-
//---------------------------------------------------------------------------
132-
// _checkBindType()
133-
//
134-
// Check that the bind type matches one of the given bind types. If the bind
135-
// type has not been specified yet, the first bind type is assumed to be the
136-
// correct one.
137-
//---------------------------------------------------------------------------
138-
_checkBindType(bindInfo, pos) {
139-
if (bindInfo.type === undefined && arguments.length > 2) {
140-
bindInfo.type = arguments[2];
141-
} else {
142-
let matches = false;
143-
for (let i = 2; i < arguments.length; i++) {
144-
if (bindInfo.type === arguments[i]) {
145-
matches = true;
146-
break;
147-
}
148-
}
149-
if (!matches) {
150-
if (bindInfo.isArray && bindInfo.name) {
151-
errors.throwErr(errors.ERR_INCOMPATIBLE_TYPE_ARRAY_BIND, pos,
152-
bindInfo.name);
153-
} else if (bindInfo.isArray) {
154-
errors.throwErr(errors.ERR_INCOMPATIBLE_TYPE_ARRAY_INDEX_BIND, pos,
155-
bindInfo.pos);
156-
} else {
157-
errors.throwErr(errors.ERR_BIND_VALUE_AND_TYPE_MISMATCH);
158-
}
159-
}
160-
}
161-
}
162-
163132
//---------------------------------------------------------------------------
164133
// _getDbObjectClass()
165134
//
@@ -327,127 +296,18 @@ class Connection extends EventEmitter {
327296
// on the value and normalizes it for use by the implementation class. If no
328297
// bind info has been defined yet, the value defines that.
329298
//---------------------------------------------------------------------------
330-
async _processBindValue(bindInfo, value, iterNum, allowArray) {
331-
332-
// null and undefined can always be bound so nothing needs to be done
333-
if (value === undefined || value === null) {
334-
bindInfo.values[iterNum] = undefined;
335-
return;
336-
}
337-
338-
// handle binding plain JS values to database objects
339-
if (bindInfo.type === types.DB_TYPE_OBJECT) {
340-
let obj = value;
341-
if (!(value instanceof BaseDbObject)) {
342-
obj = new bindInfo.typeClass(value);
343-
}
344-
bindInfo.values[iterNum] = obj._impl;
345-
346-
// handle binding plain JS values to JSON
347-
} else if (bindInfo.type === types.DB_TYPE_JSON) {
348-
bindInfo.values[iterNum] = this._processJsonValue(value);
349-
350-
// handle binding strings
351-
} else if (typeof value === 'string') {
352-
this._checkBindType(bindInfo, iterNum,
353-
types.DB_TYPE_VARCHAR,
354-
types.DB_TYPE_NVARCHAR,
355-
types.DB_TYPE_CHAR,
356-
types.DB_TYPE_NCHAR,
357-
types.DB_TYPE_CLOB,
358-
types.DB_TYPE_NCLOB);
359-
if (bindInfo.type !== constants.DB_TYPE_CLOB &&
360-
bindInfo.type !== constants.DB_TYPE_NCLOB &&
361-
(bindInfo.maxSize === undefined || value.length > bindInfo.maxSize)) {
362-
if (bindInfo.checkSize) {
363-
errors.throwErr(errors.ERR_MAX_SIZE_TOO_SMALL, bindInfo.maxSize,
364-
value.length, iterNum);
365-
}
366-
bindInfo.maxSize = value.length;
367-
}
368-
bindInfo.values[iterNum] = value;
369-
370-
// handle binding numbers
371-
} else if (typeof value === 'number') {
372-
this._checkBindType(bindInfo, iterNum,
373-
types.DB_TYPE_NUMBER,
374-
types.DB_TYPE_BINARY_INTEGER,
375-
types.DB_TYPE_BINARY_FLOAT,
376-
types.DB_TYPE_BINARY_DOUBLE);
377-
bindInfo.values[iterNum] = value;
378-
if (Number.isNaN(value) && bindInfo.type === types.DB_TYPE_NUMBER) {
379-
errors.throwErr(errors.ERR_NAN_VALUE);
380-
}
381-
382-
// handle binding booleans
383-
} else if (typeof value === 'boolean') {
384-
this._checkBindType(bindInfo, iterNum, types.DB_TYPE_BOOLEAN);
385-
bindInfo.values[iterNum] = value;
386-
387-
// handle binding dates
388-
} else if (util.isDate(value)) {
389-
this._checkBindType(bindInfo, iterNum,
390-
types.DB_TYPE_TIMESTAMP,
391-
types.DB_TYPE_TIMESTAMP_TZ,
392-
types.DB_TYPE_TIMESTAMP_LTZ,
393-
types.DB_TYPE_DATE);
394-
bindInfo.values[iterNum] = value;
395-
396-
// handle binding buffers
397-
} else if (Buffer.isBuffer(value)) {
398-
this._checkBindType(bindInfo, iterNum,
399-
types.DB_TYPE_RAW,
400-
types.DB_TYPE_BLOB);
401-
bindInfo.values[iterNum] = value;
402-
if (bindInfo.type === types.DB_TYPE_RAW &&
403-
(bindInfo.maxSize === undefined || value.length > bindInfo.maxSize)) {
404-
if (bindInfo.checkSize) {
405-
errors.throwErr(errors.ERR_MAX_SIZE_TOO_SMALL, bindInfo.maxSize,
406-
value.length, iterNum);
407-
}
408-
bindInfo.maxSize = value.length;
409-
}
410-
411-
// handle binding result sets
412-
} else if (value instanceof ResultSet) {
413-
this._checkBindType(bindInfo, iterNum, types.DB_TYPE_CURSOR);
414-
bindInfo.values[iterNum] = value._impl;
415-
416-
// handle binding LOBs
417-
} else if (value instanceof Lob) {
418-
this._checkBindType(bindInfo, iterNum, value.type);
419-
bindInfo.values[iterNum] = value._impl;
420-
421-
// handle binding database objects
422-
} else if (value instanceof BaseDbObject) {
423-
this._checkBindType(bindInfo, iterNum, types.DB_TYPE_OBJECT);
424-
if (!bindInfo.typeClass) {
425-
bindInfo.typeClass = await this._getDbObjectClass(value._objType);
426-
bindInfo.objType = bindInfo.typeClass._objType;
427-
}
428-
bindInfo.values[iterNum] = value._impl;
429-
430-
// handle binding arrays
431-
} else if (allowArray && Array.isArray(value)) {
432-
bindInfo.isArray = true;
433-
if (bindInfo.dir === constants.BIND_IN) {
434-
bindInfo.maxArraySize = value.length || 1;
435-
} else if (bindInfo.maxArraySize === undefined) {
436-
errors.throwErr(errors.ERR_REQUIRED_MAX_ARRAY_SIZE);
437-
} else if (value.length > bindInfo.maxArraySize) {
438-
errors.throwErr(errors.ERR_INVALID_ARRAY_SIZE);
439-
}
440-
for (let i = 0; i < value.length; i++) {
441-
await this._processBindValue(bindInfo, value[i], i, false);
442-
}
443-
444-
// no suitable bind value found
299+
async _processBindValue(bindInfo, value, options) {
300+
const transformed = transformer.transformValueIn(bindInfo, value, options);
301+
if (bindInfo.isArray) {
302+
bindInfo.values = transformed.concat(bindInfo.values.slice(transformed.length));
445303
} else {
446-
if (bindInfo.type === undefined)
447-
errors.throwErr(errors.ERR_INVALID_BIND_DATA_TYPE, 2);
448-
this._checkBindType(bindInfo, iterNum);
304+
bindInfo.values[options.pos] = transformed;
305+
}
306+
if (bindInfo.type === types.DB_TYPE_OBJECT &&
307+
bindInfo.typeClass === undefined) {
308+
bindInfo.typeClass = await this._getDbObjectClass(value._objType);
309+
bindInfo.objType = bindInfo.typeClass._objType;
449310
}
450-
451311
}
452312

453313
//---------------------------------------------------------------------------
@@ -473,7 +333,8 @@ class Connection extends EventEmitter {
473333

474334
// for IN and IN/OUT binds, process the value
475335
if (bindInfo.dir !== constants.BIND_OUT) {
476-
await this._processBindValue(bindInfo, bindValue, 0, true);
336+
const options = {pos: 0, allowArray: true};
337+
await this._processBindValue(bindInfo, bindValue, options);
477338
}
478339

479340
// if only null values were found (or an OUT bind was specified), type
@@ -581,12 +442,13 @@ class Connection extends EventEmitter {
581442
// process each of the rows
582443
for (let i = 0; i < binds.length; i++) {
583444
const row = binds[i];
445+
const options = {pos: i, allowArray: false};
584446
errors.assert((byPosition && Array.isArray(row)) ||
585447
(!byPosition && nodbUtil.isObject(row)), errors.ERR_MIXED_BIND);
586448
for (let j = 0; j < normBinds.length; j++) {
587449
const bindInfo = normBinds[j];
588450
const value = (byPosition) ? row[j] : row[bindInfo.name];
589-
await this._processBindValue(bindInfo, value, i, false);
451+
await this._processBindValue(bindInfo, value, options);
590452
}
591453
}
592454

@@ -603,48 +465,6 @@ class Connection extends EventEmitter {
603465
return normBinds;
604466
}
605467

606-
//---------------------------------------------------------------------------
607-
// _processJsonValue()
608-
//
609-
// Returns a normalized JSON value. Scalar values are returned unchanged.
610-
// Arrays are returned as a new array with processed JSON values. Objects are
611-
// returned as new objects with keys "fields" and "values", both of which
612-
// are arrays with processes JSON values.
613-
//---------------------------------------------------------------------------
614-
_processJsonValue(value) {
615-
616-
// handle simple scalars
617-
if (value === undefined || value === null ||
618-
typeof value === 'number' || typeof value === 'string' ||
619-
typeof value === 'boolean' || Buffer.isBuffer(value) ||
620-
util.isDate(value))
621-
return value;
622-
623-
// arrays are transformed to a new array with processed values
624-
if (Array.isArray(value)) {
625-
const outValue = new Array(value.length);
626-
for (let i = 0; i < value.length; i++) {
627-
outValue[i] = this._processJsonValue(value[i]);
628-
}
629-
return outValue;
630-
}
631-
632-
// database objects are treated as empty objects
633-
if (value instanceof BaseDbObject)
634-
return {fields: [], values: []};
635-
636-
// all other objects are transformed to an object with two arrays (fields
637-
// and values)
638-
const outValue = {};
639-
outValue.fields = Object.getOwnPropertyNames(value);
640-
outValue.values = new Array(outValue.fields.length);
641-
for (let i = 0; i < outValue.fields.length; i++) {
642-
outValue.values[i] = this._processJsonValue(value[outValue.fields[i]]);
643-
}
644-
return outValue;
645-
646-
}
647-
648468
//---------------------------------------------------------------------------
649469
// _transformOutBind()
650470
//

lib/dbObject.js

Lines changed: 25 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,14 @@ class BaseDbObject {
5353
// Sets the value of the attribute on the object to the given value.
5454
//---------------------------------------------------------------------------
5555
_setAttrValue(attr, value) {
56-
value = this._transformValueIn(value, attr.typeClass);
56+
const info = {
57+
fqn: this._objType.fqn,
58+
attrName: attr.name,
59+
type: attr.type,
60+
typeClass: attr.typeClass
61+
};
62+
const options = {allowArray: false};
63+
value = transformer.transformValueIn(info, value, options);
5764
this._impl.setAttrValue(attr, value);
5865
}
5966

@@ -83,25 +90,6 @@ class BaseDbObject {
8390
return (result);
8491
}
8592

86-
//---------------------------------------------------------------------------
87-
// _transformValueIn()
88-
//
89-
// Transforms a value coming from the caller to the implementation.
90-
//---------------------------------------------------------------------------
91-
_transformValueIn(value, cls) {
92-
let outValue = value;
93-
if (cls && value !== null && value !== undefined) {
94-
if (value instanceof cls) {
95-
outValue = value._impl;
96-
} else {
97-
outValue = new cls(value)._impl;
98-
}
99-
} else if (value instanceof Lob) {
100-
outValue = value._impl;
101-
}
102-
return outValue;
103-
}
104-
10593
//---------------------------------------------------------------------------
10694
// _transformValueOut()
10795
//
@@ -129,7 +117,13 @@ class BaseDbObject {
129117
//---------------------------------------------------------------------------
130118
append(value) {
131119
errors.assertArgCount(arguments, 1, 1);
132-
value = this._transformValueIn(value, this.elementTypeClass);
120+
const info = {
121+
fqn: this._objType.fqn,
122+
type: this._objType.elementType,
123+
typeClass: this._objType.elementTypeClass
124+
};
125+
const options = {allowArray: false};
126+
value = transformer.transformValueIn(info, value, options);
133127
this._impl.append(value);
134128
}
135129

@@ -334,7 +328,13 @@ class BaseDbObject {
334328
setElement(index, value) {
335329
errors.assertArgCount(arguments, 2, 2);
336330
errors.assertParamValue(Number.isInteger(index), 1);
337-
value = this._transformValueIn(value, this.elementTypeClass);
331+
const info = {
332+
fqn: this._objType.fqn,
333+
type: this._objType.elementType,
334+
typeClass: this._objType.elementTypeClass
335+
};
336+
const options = {allowArray: false};
337+
value = transformer.transformValueIn(info, value, options);
338338
this._impl.setElement(index, value);
339339
}
340340

@@ -458,5 +458,7 @@ BaseDbObject._collectionProxyHandler = {
458458

459459
};
460460

461-
462461
module.exports = BaseDbObject;
462+
463+
// load this after the module exports are set so that it is available
464+
const transformer = require('./transformer.js');

0 commit comments

Comments
 (0)