node-oracledb/lib/dbObject.js

421 lines
13 KiB
JavaScript
Raw Normal View History

2022-05-17 11:09:34 +08:00
// Copyright (c) 2019, 2022, Oracle and/or its affiliates.
//
//----------------------------------------------------------------------------
//
// 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';
2023-02-21 07:44:26 +08:00
const constants = require('./constants.js');
2023-02-21 09:33:06 +08:00
const Lob = require('./lob.js');
const impl = require('./impl');
const errors = require('errors');
const util = require('util');
// define base database object class; instances of this class are never
// instantiated; instead, classes subclassed from this one will be
// instantiated; a cache of these classes are maintained on each connection
class BaseDbObject {
2023-02-21 09:33:06 +08:00
//---------------------------------------------------------------------------
// _getAttrValue()
//
// Returns the value of the given attribute on the object.
//---------------------------------------------------------------------------
_getAttrValue(attr) {
const value = this._impl.getAttrValue(attr);
return this._transformValueOut(value, attr.typeClass);
}
//---------------------------------------------------------------------------
// _setAttrValue()
//
// Sets the value of the attribute on the object to the given value.
//---------------------------------------------------------------------------
_setAttrValue(attr, value) {
value = this._transformValueIn(value, attr.typeClass);
this._impl.setAttrValue(attr, value);
}
2023-02-21 09:33:06 +08:00
//---------------------------------------------------------------------------
// _toPojo()
//
// Returns the database object as a plain Javascript object.
//---------------------------------------------------------------------------
_toPojo() {
if (this.isCollection) {
2020-11-19 10:06:47 +08:00
const result = this.getValues();
2023-02-21 07:44:26 +08:00
if (this.elementType == constants.DB_TYPE_OBJECT) {
2020-11-19 10:06:47 +08:00
for (let i = 0; i < result.length; i++) {
result[i] = result[i]._toPojo();
}
}
2021-04-01 12:48:37 +08:00
return (result);
}
const result = {};
2023-02-21 09:33:06 +08:00
for (const name in this.attributes) {
let value = this[name];
if (value instanceof BaseDbObject) {
value = value._toPojo();
}
result[name] = value;
}
2021-04-01 12:48:37 +08:00
return (result);
}
2023-02-21 09:33:06 +08:00
//---------------------------------------------------------------------------
// _transformValueIn()
//
// Transforms a value coming from the caller to the implementation.
//---------------------------------------------------------------------------
_transformValueIn(value, cls) {
let outValue = value;
if (cls && value !== null && value !== undefined) {
if (value instanceof cls) {
outValue = value._impl;
} else {
outValue = new cls(value)._impl;
}
} else if (value instanceof Lob) {
outValue = value._impl;
}
return outValue;
}
//---------------------------------------------------------------------------
// _transformValueOut()
//
// Transforms a value going out to the caller from the implementation.
//---------------------------------------------------------------------------
_transformValueOut(value, cls) {
let outValue = value;
if (value instanceof impl.LobImpl) {
outValue = new Lob();
outValue._setup(value, true);
} else if (value instanceof impl.DbObjectImpl) {
outValue = Object.create(cls.prototype);
outValue._impl = value;
if (outValue.isCollection) {
outValue = new Proxy(outValue, BaseDbObject._collectionProxyHandler);
}
}
return outValue;
}
//---------------------------------------------------------------------------
// append()
//
// Appends an element to the collection.
//---------------------------------------------------------------------------
append(value) {
errors.assertArgCount(arguments, 1, 1);
value = this._transformValueIn(value, this.elementTypeClass);
this._impl.append(value);
}
//---------------------------------------------------------------------------
// attributes
//
// Property for the attributes stored on the object type.
//---------------------------------------------------------------------------
get attributes() {
if (!this._attributes) {
const implAttrs = this._objType.attributes;
const attrs = {};
for (let i = 0; i < implAttrs.length; i++) {
const implAttr = implAttrs[i];
const attr = {
type: implAttr.type,
typeName: implAttr.typeName
};
if (implAttr.typeClass) {
attr.typeClass = implAttr.typeClass;
}
attrs[implAttr.name] = attr;
}
this._attributes = attrs;
}
return this._attributes;
}
//---------------------------------------------------------------------------
// deleteElement()
//
// Deletes the element in a collection at the specified index.
//---------------------------------------------------------------------------
deleteElement(index) {
errors.assertArgCount(arguments, 1, 1);
errors.assertParamValue(Number.isInteger(index), 1);
return this._impl.deleteElement(index);
}
//---------------------------------------------------------------------------
// elementType
//
// Property for the element type, if the database object type is a
// collection. It will be one of the DB_TYPE_ constants.
//---------------------------------------------------------------------------
get elementType() {
return this._objType.elementType;
}
//---------------------------------------------------------------------------
// elementTypeClass
//
// Property for the element type class, if the database object type is a
// collection and the elements in the collection refer to database objects.
//---------------------------------------------------------------------------
get elementTypeClass() {
return this._objType.elementTypeClass;
}
//---------------------------------------------------------------------------
// elementTypeName
//
// Property for the element type name, if the database object type is a
// collection.
//---------------------------------------------------------------------------
get elementTypeName() {
return this._objType.elementTypeName;
}
//---------------------------------------------------------------------------
// fqn
//
// Property for the fully qualified name of the database object type in the
// form: <schema>.<name>.
//---------------------------------------------------------------------------
get fqn() {
return this._objType.fqn;
}
//---------------------------------------------------------------------------
// getElement()
//
// Returns the element in a collection at the specified index.
//---------------------------------------------------------------------------
getElement(index) {
errors.assertArgCount(arguments, 1, 1);
errors.assertParamValue(Number.isInteger(index), 1);
const value = this._impl.getElement(index);
return this._transformValueOut(value, this.elementTypeClass);
}
//---------------------------------------------------------------------------
// getKeys()
//
// Returns an array of the keys of the collection.
//---------------------------------------------------------------------------
getKeys() {
errors.assertArgCount(arguments, 0, 0);
return this._impl.getKeys();
}
//---------------------------------------------------------------------------
// getFirstIndex()
//
// Returns the first index in the collection.
//---------------------------------------------------------------------------
getFirstIndex() {
errors.assertArgCount(arguments, 0, 0);
return this._impl.getFirstIndex();
}
//---------------------------------------------------------------------------
// getLastIndex()
//
// Returns the last index in the collection.
//---------------------------------------------------------------------------
getLastIndex() {
errors.assertArgCount(arguments, 0, 0);
return this._impl.getLastIndex();
}
//---------------------------------------------------------------------------
// getNextIndex()
//
// Returns the next index in the collection.
//---------------------------------------------------------------------------
getNextIndex(index) {
errors.assertArgCount(arguments, 1, 1);
errors.assertParamValue(Number.isInteger(index), 1);
return this._impl.getNextIndex(index);
}
//---------------------------------------------------------------------------
// getPrevIndex()
//
// Returns the previous index in the collection.
//---------------------------------------------------------------------------
getPrevIndex(index) {
errors.assertArgCount(arguments, 1, 1);
errors.assertParamValue(Number.isInteger(index), 1);
return this._impl.getPrevIndex(index);
}
//---------------------------------------------------------------------------
// getValues()
//
// Returns the elements in a collection.
//---------------------------------------------------------------------------
getValues() {
errors.assertArgCount(arguments, 0, 0);
const values = this._impl.getValues();
for (let i = 0; i < values.length; i++) {
values[i] = this._transformValueOut(values[i], this.elementTypeClass);
}
return values;
}
//---------------------------------------------------------------------------
// hasElement()
//
// Returns a boolean indicating if an element exists at the specified index.
//---------------------------------------------------------------------------
hasElement(index) {
errors.assertArgCount(arguments, 1, 1);
errors.assertParamValue(Number.isInteger(index), 1);
return this._impl.hasElement(index);
}
//---------------------------------------------------------------------------
// isCollection
//
// Property indicating if the object is a collection or not.
//---------------------------------------------------------------------------
get isCollection() {
return this._objType.isCollection;
}
//---------------------------------------------------------------------------
// name
//
// Property for the name of the database object type.
//---------------------------------------------------------------------------
get name() {
return this._objType.name;
}
//---------------------------------------------------------------------------
// schema
//
// Property for the schema of the database object type.
//---------------------------------------------------------------------------
get schema() {
return this._objType.schema;
}
//---------------------------------------------------------------------------
// setElement()
//
// Sets the element in the collection at the specified index to the given
// value.
//---------------------------------------------------------------------------
setElement(index, value) {
errors.assertArgCount(arguments, 2, 2);
errors.assertParamValue(Number.isInteger(index), 1);
value = this._transformValueIn(value, this.elementTypeClass);
this._impl.setElement(index, value);
}
//---------------------------------------------------------------------------
// trim()
//
// Trims the specified number of elements from the end of the collection.
//---------------------------------------------------------------------------
trim(numToTrim) {
errors.assertArgCount(arguments, 1, 1);
errors.assertParamValue(Number.isInteger(numToTrim), 1);
this._impl.trim(numToTrim);
}
// custom inspection routine
[util.inspect.custom](depth, options) {
2021-04-01 12:48:37 +08:00
return ('[' + this.fqn + '] ' + util.inspect(this._toPojo(), options));
}
[Symbol.iterator]() {
if (this.isCollection) {
const values = this.getValues();
2021-04-01 12:48:37 +08:00
return (values[Symbol.iterator]());
}
throw TypeError("obj is not iterable");
}
2019-06-28 08:29:16 +08:00
[Symbol.toPrimitive](hint) {
switch (hint) {
case 'number':
2021-04-01 12:48:37 +08:00
return (NaN);
2019-06-28 08:29:16 +08:00
default:
2021-04-01 12:48:37 +08:00
return ('[' + this.fqn + '] ' + util.inspect(this._toPojo(), {}));
2019-06-28 08:29:16 +08:00
}
}
2019-11-05 07:54:10 +08:00
get [Symbol.toStringTag]() {
2021-04-01 12:48:37 +08:00
return (this.fqn);
2019-11-05 07:54:10 +08:00
}
toJSON() {
2021-04-01 12:48:37 +08:00
return (this._toPojo());
}
}
2019-11-05 07:54:10 +08:00
// define proxy handler used for collections
BaseDbObject._collectionProxyHandler = {
deleteProperty(target, prop) {
if (typeof prop === 'string') {
const index = +prop;
if (!isNaN(index)) {
2021-04-01 12:48:37 +08:00
return (target.deleteElement(index));
2019-11-05 07:54:10 +08:00
}
}
2021-04-01 12:48:37 +08:00
return (delete target[prop]);
2019-11-05 07:54:10 +08:00
},
get(target, prop) {
if (typeof prop === 'string') {
const index = +prop;
if (!isNaN(index)) {
2021-04-01 12:48:37 +08:00
return (target.getElement(index));
2019-11-05 07:54:10 +08:00
}
}
const value = target[prop];
if (typeof value === 'function') {
2021-04-01 12:48:37 +08:00
return (value.bind(target));
2019-11-05 07:54:10 +08:00
}
2021-04-01 12:48:37 +08:00
return (value);
2019-11-05 07:54:10 +08:00
},
set(target, prop, value) {
if (typeof prop === 'string') {
const index = +prop;
if (!isNaN(index)) {
target.setElement(index, value);
2021-04-01 12:48:37 +08:00
return (true);
2019-11-05 07:54:10 +08:00
}
}
target[prop] = value;
2021-04-01 12:48:37 +08:00
return (true);
2019-11-05 07:54:10 +08:00
}
};
module.exports = BaseDbObject;