@sap/async-xsjs 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (178) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/LICENSE +37 -0
  3. package/README.md +445 -0
  4. package/differences.md +162 -0
  5. package/docs/$.Application.html +262 -0
  6. package/docs/$.Session.html +674 -0
  7. package/docs/$.db.CallableStatement.html +2524 -0
  8. package/docs/$.db.Connection.html +511 -0
  9. package/docs/$.db.ParameterMetaData.html +805 -0
  10. package/docs/$.db.PreparedStatement.html +1796 -0
  11. package/docs/$.db.ResultSet.html +1308 -0
  12. package/docs/$.db.ResultSetMetaData.html +800 -0
  13. package/docs/$.db.SQLException.html +259 -0
  14. package/docs/$.db.html +773 -0
  15. package/docs/$.hdb.ColumnMetadata.html +438 -0
  16. package/docs/$.hdb.Connection.html +663 -0
  17. package/docs/$.hdb.ProcedureResult.html +280 -0
  18. package/docs/$.hdb.ResultSet.html +324 -0
  19. package/docs/$.hdb.ResultSetIterator.html +315 -0
  20. package/docs/$.hdb.ResultSetMetaData.html +259 -0
  21. package/docs/$.hdb.SQLException.html +259 -0
  22. package/docs/$.hdb.html +557 -0
  23. package/docs/$.html +471 -0
  24. package/docs/$.jobs.Job.html +783 -0
  25. package/docs/$.jobs.JobLog.html +380 -0
  26. package/docs/$.jobs.JobSchedules.html +852 -0
  27. package/docs/$.jobs.html +238 -0
  28. package/docs/$.net.Destination.html +304 -0
  29. package/docs/$.net.Mail.Part.html +510 -0
  30. package/docs/$.net.Mail.html +504 -0
  31. package/docs/$.net.SMTPConnection.html +347 -0
  32. package/docs/$.net.html +749 -0
  33. package/docs/$.net.http.Client.html +562 -0
  34. package/docs/$.net.http.Destination.html +237 -0
  35. package/docs/$.net.http.Request.html +567 -0
  36. package/docs/$.net.http.html +292 -0
  37. package/docs/$.security.AntiVirus.html +361 -0
  38. package/docs/$.security.Store.html +636 -0
  39. package/docs/$.security.crypto.html +414 -0
  40. package/docs/$.security.html +247 -0
  41. package/docs/$.security.x509.html +373 -0
  42. package/docs/$.text.analysis.Session.html +983 -0
  43. package/docs/$.text.analysis.html +242 -0
  44. package/docs/$.text.html +246 -0
  45. package/docs/$.text.mining.Session.html +2018 -0
  46. package/docs/$.text.mining.html +242 -0
  47. package/docs/$.trace.html +525 -0
  48. package/docs/$.util.SAXParser.html +955 -0
  49. package/docs/$.util.Zip.html +474 -0
  50. package/docs/$.util.codec.html +414 -0
  51. package/docs/$.util.compression.html +357 -0
  52. package/docs/$.util.html +325 -0
  53. package/docs/$.util.sql.html +290 -0
  54. package/docs/$.web.Body.html +333 -0
  55. package/docs/$.web.EntityList.html +296 -0
  56. package/docs/$.web.TupelList.html +496 -0
  57. package/docs/$.web.WebEntityRequest.html +393 -0
  58. package/docs/$.web.WebEntityResponse.html +392 -0
  59. package/docs/$.web.WebRequest.html +560 -0
  60. package/docs/$.web.WebResponse.html +609 -0
  61. package/docs/$.web.html +246 -0
  62. package/docs/Copyright-SAP.html +39 -0
  63. package/docs/Disclaimer-SAP.html +55 -0
  64. package/docs/index.html +232 -0
  65. package/docs/styles/jsdoc-default.css +382 -0
  66. package/lib/AppConfig.js +36 -0
  67. package/lib/AuditLogger.js +41 -0
  68. package/lib/cacert.js +26 -0
  69. package/lib/ctypes.js +153 -0
  70. package/lib/destinations/dest-provider.js +57 -0
  71. package/lib/index.js +235 -0
  72. package/lib/jobs/Action.js +40 -0
  73. package/lib/jobs/Job.js +100 -0
  74. package/lib/jobs/JobManager.js +150 -0
  75. package/lib/jobs/JobsRuntime.js +133 -0
  76. package/lib/jobs/SqlScriptJobRunner.js +36 -0
  77. package/lib/jobs/XsjsJobRunner.js +78 -0
  78. package/lib/jobs/index.js +11 -0
  79. package/lib/logging.js +16 -0
  80. package/lib/middleware.js +125 -0
  81. package/lib/odata/ODataService.js +125 -0
  82. package/lib/odata/index.js +7 -0
  83. package/lib/odata/service-factory.js +26 -0
  84. package/lib/passport-noauth.js +17 -0
  85. package/lib/routes.js +115 -0
  86. package/lib/runtime.js +740 -0
  87. package/lib/sandbox.js +40 -0
  88. package/lib/utils/XsJsFunctionRunner.js +57 -0
  89. package/lib/utils/XsJsLibFunctionRunner.js +57 -0
  90. package/lib/utils/buffer-utils.js +77 -0
  91. package/lib/utils/compression-utils.js +14 -0
  92. package/lib/utils/date-utils.js +104 -0
  93. package/lib/utils/errors/HttpError.js +20 -0
  94. package/lib/utils/errors/wrap-app-error.js +18 -0
  95. package/lib/utils/index.js +17 -0
  96. package/lib/utils/xs-function-runner.js +51 -0
  97. package/lib/utils/xs-types.js +21 -0
  98. package/lib/utils/xspath.js +36 -0
  99. package/lib/utils/xsstack.js +28 -0
  100. package/lib/views/error.html +28 -0
  101. package/lib/xsjs/Application.js +28 -0
  102. package/lib/xsjs/Locale.js +53 -0
  103. package/lib/xsjs/Session.js +31 -0
  104. package/lib/xsjs/constants.js +71 -0
  105. package/lib/xsjs/db/common/DbBase.js +85 -0
  106. package/lib/xsjs/db/common/DbOptions.js +163 -0
  107. package/lib/xsjs/db/common/arguments-validation.js +102 -0
  108. package/lib/xsjs/db/common/connection.js +12 -0
  109. package/lib/xsjs/db/common/enums.js +93 -0
  110. package/lib/xsjs/db/common/execute-batch.js +38 -0
  111. package/lib/xsjs/db/common/parse-time.js +139 -0
  112. package/lib/xsjs/db/dbapi/CallableStatement.js +192 -0
  113. package/lib/xsjs/db/dbapi/Connection.js +78 -0
  114. package/lib/xsjs/db/dbapi/DB.js +39 -0
  115. package/lib/xsjs/db/dbapi/ParameterMetaData.js +118 -0
  116. package/lib/xsjs/db/dbapi/PreparedStatement.js +78 -0
  117. package/lib/xsjs/db/dbapi/ResultSet.js +220 -0
  118. package/lib/xsjs/db/dbapi/ResultSetMetaData.js +116 -0
  119. package/lib/xsjs/db/dbapi/Statement.js +514 -0
  120. package/lib/xsjs/db/dbapi/conversions.js +113 -0
  121. package/lib/xsjs/db/dbapi/fetch-rows.js +32 -0
  122. package/lib/xsjs/db/hdbapi/Connection.js +525 -0
  123. package/lib/xsjs/db/hdbapi/HDB.js +32 -0
  124. package/lib/xsjs/db/hdbapi/ResultSetIterator.js +40 -0
  125. package/lib/xsjs/db/hdbapi/convert.js +77 -0
  126. package/lib/xsjs/db/hdbapi/table-string-parser.js +52 -0
  127. package/lib/xsjs/db/index.js +4 -0
  128. package/lib/xsjs/index.js +13 -0
  129. package/lib/xsjs/jobs/Job.js +228 -0
  130. package/lib/xsjs/jobs/Jobs.js +11 -0
  131. package/lib/xsjs/jobs/Logs.js +127 -0
  132. package/lib/xsjs/jobs/Schedule.js +110 -0
  133. package/lib/xsjs/jobs/Schedules.js +108 -0
  134. package/lib/xsjs/net/Destination.js +43 -0
  135. package/lib/xsjs/net/http/Client.js +220 -0
  136. package/lib/xsjs/net/http/HTTP.js +72 -0
  137. package/lib/xsjs/net/index.js +5 -0
  138. package/lib/xsjs/net/smtp/Mail.js +38 -0
  139. package/lib/xsjs/net/smtp/Part.js +30 -0
  140. package/lib/xsjs/net/smtp/SMTPConnection.js +39 -0
  141. package/lib/xsjs/net/smtp/index.js +18 -0
  142. package/lib/xsjs/net/smtp/nodemailer-util.js +77 -0
  143. package/lib/xsjs/require.js +39 -0
  144. package/lib/xsjs/security/AntiVirus.js +31 -0
  145. package/lib/xsjs/security/Store.js +119 -0
  146. package/lib/xsjs/security/crypto.js +23 -0
  147. package/lib/xsjs/security/index.js +5 -0
  148. package/lib/xsjs/security/x509.js +12 -0
  149. package/lib/xsjs/text/analysis/Session.js +128 -0
  150. package/lib/xsjs/text/index.js +30 -0
  151. package/lib/xsjs/text/mining/Session.js +82 -0
  152. package/lib/xsjs/trace/trace.js +41 -0
  153. package/lib/xsjs/util/SAXParser.js +174 -0
  154. package/lib/xsjs/util/Zip.js +220 -0
  155. package/lib/xsjs/util/codec.js +33 -0
  156. package/lib/xsjs/util/compression.js +24 -0
  157. package/lib/xsjs/util/index.js +22 -0
  158. package/lib/xsjs/web/BasicWebEntity.js +41 -0
  159. package/lib/xsjs/web/EntityList.js +11 -0
  160. package/lib/xsjs/web/TupelLists/CookiesTupelList.js +47 -0
  161. package/lib/xsjs/web/TupelLists/HeadersTupelList.js +55 -0
  162. package/lib/xsjs/web/TupelLists/ParametersTupelList.js +83 -0
  163. package/lib/xsjs/web/TupelLists/TupelListBase.js +45 -0
  164. package/lib/xsjs/web/WebBody.js +135 -0
  165. package/lib/xsjs/web/WebEntityRequest.js +40 -0
  166. package/lib/xsjs/web/WebEntityResponse.js +26 -0
  167. package/lib/xsjs/web/WebRequest.js +209 -0
  168. package/lib/xsjs/web/WebResponse.js +183 -0
  169. package/lib/xsjs/web/index.js +4 -0
  170. package/lib/xsjs/web/utils/HeadersParser.js +53 -0
  171. package/lib/xsjs/web/utils/HttpRequestParser.js +93 -0
  172. package/lib/xsjs/web/utils/MultipartParser.js +163 -0
  173. package/lib/xsjs/web/utils/MultipartResponseBuilder.js +73 -0
  174. package/lib/xsjs/web/utils/SetCookieParser.js +32 -0
  175. package/lib/xsjslib/TextBundleWrapper.js +46 -0
  176. package/lib/xsjslib/index.js +11 -0
  177. package/npm-shrinkwrap.json +11540 -0
  178. package/package.json +84 -0
@@ -0,0 +1,525 @@
1
+ 'use strict';
2
+
3
+ var _ = require('lodash');
4
+ var assert = require('assert');
5
+ var FunctionCode = require('@sap/hana-client/extension/FunctionCode');
6
+ var enums = require('../common/enums');
7
+ var executeBatchPromise = require('../common/execute-batch').executeBatchPromise;
8
+ var ResultSetIterator = require('./ResultSetIterator.js');
9
+ var ctypes = require('../../../ctypes');
10
+ var convert = require('./convert');
11
+ var hdbext = require('@sap/hdbext');
12
+ var DB_TYPE = require('@sap/hana-client/extension/TypeCode');
13
+ var bufferUtils = require('../../../utils/buffer-utils');
14
+ var dateUtils = require('../../../utils/date-utils');
15
+ var moment = require('moment');
16
+
17
+ module.exports = Connection;
18
+
19
+ /**
20
+ * @class $.hdb.Connection
21
+ * @classdesc HANA database connection.
22
+ * @constructor
23
+ */
24
+ function Connection(tracer, client, treatDateAsUTC, enableColumnIndices) {
25
+ assert(typeof client === 'object', 'A valid client object should be provided to create $.hdb.Connection');
26
+ this._tracer = tracer;
27
+ this._client = client;
28
+ this._treatDateAsUTC = treatDateAsUTC;
29
+ this._enableColumnIndices = enableColumnIndices;
30
+ }
31
+
32
+ /**
33
+ * Returns underlying client object
34
+ */
35
+ Connection.prototype.getClient = function () {
36
+ return this._client;
37
+ };
38
+
39
+ /**
40
+ * Closes the connection
41
+ * @throws Throws an error if the operation fails.
42
+ */
43
+ Connection.prototype.close = async function () {
44
+ await this._client.close();
45
+ };
46
+
47
+ /**
48
+ * Commits the changes and ends the current transaction. <b>By default autocommit mode is disabled, which means all database changes must be explicitly commited.</b>
49
+ * @throws Throws an error if the operation fails.
50
+ * @example
51
+ *
52
+ * var connection = $.hdb.getConnection();
53
+ * connection.executeUpdate('UPDATE "DB_EXAMPLE"."ICECREAM" SET QUANTITY=? WHERE FLAVOR=?', 9, 'CHOCOLATE');
54
+ * connection.commit();
55
+ */
56
+ Connection.prototype.commit = async function () {
57
+ await this._client.commit();
58
+ };
59
+
60
+ /**
61
+ * Reverts the changes and ends the current transaction.
62
+ * @throws Throws an error if the operation fails.
63
+ * @example
64
+ *
65
+ * var connection = $.hdb.getConnection();
66
+ * connection.executeUpdate('UPDATE "DB_EXAMPLE"."ICECREAM" SET QUANTITY=? WHERE FLAVOR=?', 9, 'CHOCOLATE');
67
+ * connection.rollback();
68
+ */
69
+ Connection.prototype.rollback = async function () {
70
+ await this._client.rollback();
71
+ };
72
+
73
+ /**
74
+ * Changes the auto-commit flag of the connection.
75
+ * @param {bool} autoCommit A bool value, which can be true or false
76
+ */
77
+ Connection.prototype.setAutoCommit = function (autoCommit) {
78
+ this._client.setAutoCommit(autoCommit);
79
+ };
80
+
81
+ /**
82
+ * Executes a database query.
83
+ * @param {string} query The query string to be executed.
84
+ * @param {...varArgs} [arguments] Variable number of arguments to be bound to the query parameters.
85
+ * @returns {$.hdb.ResultSet}
86
+ * @throws Throws an error if the statement cannot be executed.
87
+ * @example
88
+ * var connection = $.hdb.getConnection();
89
+ * connection.executeQuery('SELECT * FROM "DB_EXAMPLE"."ICECREAM"');
90
+ * connection.executeQuery('SELECT * FROM "DB_EXAMPLE"."ICECREAM" WHERE FLAVOR = ?', 'CHOCOLATE');
91
+ * connection.executeQuery('SELECT * FROM "DB_EXAMPLE"."ICECREAM" WHERE FLAVOR = ? AND PRICE < ?', 'STRAWBERRY', 2.50);
92
+ */
93
+ Connection.prototype.executeQuery = async function () {
94
+ var args = Array.prototype.slice.call(arguments);
95
+ args = normalizeInput(args, this._treatDateAsUTC);
96
+ var rs = await executePromise(this._tracer, this._client, args.shift(), args);
97
+ return processResultSet(rs, this._treatDateAsUTC, this._enableColumnIndices);
98
+ };
99
+
100
+ /**
101
+ * Executes a SQL statement, which changes the database state. SELECT and CALL statements are not allowed here.
102
+ * @param {string} statement The statement to be executed.
103
+ * @param {...varArgs} [arguments] Variable number of arguments to be bound to the query parameters.
104
+ * @returns {number|array} Number of affected rows | Array of numbers in case of batch update.
105
+ * @throws Throws an error if the statement cannot be executed.
106
+ * @example
107
+ *
108
+ * var connection = $.hdb.getConnection();
109
+ * connection.executeUpdate('INSERT INTO "DB_EXAMPLE"."ICECREAM" VALUES (?,?,?)','STRAWBERRY', 2.50, 64.18);
110
+ * connection.executeUpdate('UPDATE "DB_EXAMPLE"."CASH" SET INCOME=?', 64.18);
111
+ * connection.executeUpdate('DELETE FROM "DB_EXAMPLE"."ICECREAM" WHERE FLAVOR = ?', 'STRAWBERRY');
112
+ *
113
+ * // Batch Insert
114
+ * var argsArray = [["MINT", 3.50, 34.5], ["VANILLA", 2.50, 23.6], ["CHERRY", 4.50, 67.9]];
115
+ * connection.executeUpdate('INSERT INTO "DB_EXAMPLE"."ICECREAM" VALUES (?,?,?)', argsArray)
116
+ * connection.commit();
117
+ */
118
+ Connection.prototype.executeUpdate = async function () {
119
+ var args = Array.prototype.slice.call(arguments);
120
+ args = normalizeInput(args, this._treatDateAsUTC);
121
+ var result = await executePromise(this._tracer, this._client, args.shift(), args);
122
+ return result;
123
+ };
124
+
125
+ /**
126
+ * Returns a JavaScript function representing the stored procedure being loaded.
127
+ * @param {string} [schema] The schema to which the procedure belongs.
128
+ * @param {string} procedure The name of the procedure.
129
+ * @returns {function}
130
+ * @example
131
+ *
132
+ * var connection = $.hdb.getConnection();
133
+ * // looks for the stored procedure in the current schema
134
+ * var fnSell = connection.loadProcedure('icecream.shop::sell');
135
+ * // the procedure has signature 'DB_EXAMPLE'.'icecream.shop::sell'(IN flavor VARCHAR, IN quantity INTEGER, IN payment DECIMAL, OUT change DECIMAL)
136
+ * var fnSell = connection.loadProcedure('DB_EXAMPLE', 'icecream.shop::sell');
137
+ * // call the procedure just like calling a javascript function
138
+ * // sell three ice cream cups with chocolate flavor for 20 bucks each
139
+ * var result = fnSell('CHOCOLATE', 3, 20.00);
140
+ * // alternatively use named parameters
141
+ * var result = fnSell({FLAVOR: 'CHOCOLATE', QUANTITY: 3, PAYMENT: 20.00});
142
+ * // result is a $.hdb.ProcedureResult object
143
+ *
144
+ * @example
145
+ * <b><font size="4">Table Parameter Support For Stored Procedures</font></b>
146
+ *
147
+ * // the procedure has signature 'DB_EXAMPLE'.'icecream.shop::lower_price_by'(IN ice_cream_prices prices_table_type, IN lower_price_by DOUBLE, OUT new_ice_cream_prices prices_table_type)
148
+ * var fnlowerPrice = connection.loadProcedure('DB_EXAMPLE', 'icecream.shop::lower_price_by');
149
+ *
150
+ * // passing a $.hdb.ResultSet object
151
+ * var price_list = connection.executeQuery('SELECT * FROM "DB_EXAMPLE"."SOLD_FLAVORS_PRICES"');
152
+ * var result = fnlowerPrice(price_list, 1.50);
153
+ *
154
+ * // passing a string containing the name of existing table in the database
155
+ * var result = fnlowerPrice('"DB_EXAMPLE"."SOLD_FLAVORS_PRICES"', 1.50);
156
+ *
157
+ * // passing an array of JSON objects representing the rows in the table
158
+ * var price_list = [{FLAVOR: 'STRAWBERRY', PRICE: 4.50}, {FLAVOR : 'VANILLA', PRICE: 3.50}, {FLAVOR: 'CHOCOLATE', PRICE: 5.50}];
159
+ * var result = fnlowerPrice(price_list, 1.50);
160
+ *
161
+ * // We can get the table output parameter "new_ice_cream_prices" like any other output parameter:
162
+ * var new_price_list = result.NEW_ICE_CREAM_PRICES;
163
+ * // new_price_list is a $.hdb.ResultSet object
164
+ */
165
+ Connection.prototype.loadProcedure = async function (schema, name) {
166
+ var treatDateAsUTC = this._treatDateAsUTC;
167
+ var enableColumnIndices = this._enableColumnIndices;
168
+ if (arguments.length === 1) {
169
+ name = arguments[0];
170
+ schema = undefined;
171
+ }
172
+
173
+ var storedProc = await hdbext.loadProcedurePromise(this._client, schema, name);
174
+
175
+ return callsp.bind(this);
176
+
177
+ function callsp() {
178
+ var inargs = Array.prototype.slice.call(arguments);
179
+ return new Promise ((resolve, reject) => {
180
+ inargs = normalizeInput(inargs, treatDateAsUTC);
181
+ inargs = convertInput(this._tracer, inargs, storedProc.paramsMetadata);
182
+
183
+ // Workaround for named paramaters - @sap/hana-client uses 'instanceof Object' (to validate its input)
184
+ // which returns false for an object created in a different context.
185
+ // This is why we need to create the object in the same context.
186
+ if (usingNamedParameters(inargs)) {
187
+ inargs[0] = _.extend({}, inargs[0]);
188
+ }
189
+
190
+ var ondone = function () {
191
+ var args = arguments;
192
+ var at = 0;
193
+
194
+ var err = args[at++];
195
+ if (err) {
196
+ return reject(err);
197
+ }
198
+
199
+ var parameters = args[at++] || {};
200
+
201
+ storedProc.paramsMetadata.forEach(function (i) {
202
+ if (i.DATA_TYPE_NAME === 'TABLE_TYPE' && i.PARAMETER_TYPE === 'OUT') {
203
+ parameters[i.PARAMETER_NAME] = processResultSet(args[at++], treatDateAsUTC, enableColumnIndices);
204
+ }
205
+ if (!isOutgoing(i) || parameters[i.PARAMETER_NAME] === null) {
206
+ return;
207
+ }
208
+
209
+ if (i.DATA_TYPE_NAME === 'BIGINT') {
210
+ parameters[i.PARAMETER_NAME] = new ctypes.Int64(parameters[i.PARAMETER_NAME]);
211
+ }
212
+ if (i.DATA_TYPE_NAME === 'BLOB' || i.DATA_TYPE_NAME === 'BINARY' || i.DATA_TYPE_NAME === 'VARBINARY') {
213
+ parameters[i.PARAMETER_NAME] = bufferUtils.toArrayBuffer(parameters[i.PARAMETER_NAME]);
214
+ }
215
+ if (i.DATA_TYPE_NAME === 'CLOB' || i.DATA_TYPE_NAME === 'NCLOB') {
216
+ if (Buffer.isBuffer(parameters[i.PARAMETER_NAME])) {
217
+ parameters[i.PARAMETER_NAME] = parameters[i.PARAMETER_NAME].toString();
218
+ }
219
+ }
220
+ if (i.DATA_TYPE_NAME === 'DATE') {
221
+ parameters[i.PARAMETER_NAME] = dateUtils.dateToJsDate(parameters[i.PARAMETER_NAME], treatDateAsUTC);
222
+ }
223
+ if (i.DATA_TYPE_NAME === 'TIME') {
224
+ parameters[i.PARAMETER_NAME] = dateUtils.timeToJsDate(parameters[i.PARAMETER_NAME], treatDateAsUTC);
225
+ }
226
+ if (i.DATA_TYPE_NAME === 'SECONDDATE' || i.DATA_TYPE_NAME === 'TIMESTAMP') {
227
+ parameters[i.PARAMETER_NAME] = dateUtils.dateTimeToJsDate(parameters[i.PARAMETER_NAME], treatDateAsUTC);
228
+ }
229
+ });
230
+
231
+ var spResultSets = [];
232
+ while (at < args.length) {
233
+ spResultSets.push(processResultSet(args[at++], treatDateAsUTC, enableColumnIndices));
234
+ }
235
+
236
+ Object.defineProperty(parameters, '$resultSets', { enumerable: false, value: spResultSets });
237
+ resolve(parameters);
238
+ };
239
+ inargs.push(ondone);
240
+ storedProc.apply(null, inargs);
241
+ });
242
+ }
243
+ };
244
+
245
+ function usingNamedParameters(input) {
246
+ return input.length === 1 && _.isObject(input[0]) &&
247
+ !_.isArray(input[0]) && !Buffer.isBuffer(input[0]);
248
+ }
249
+
250
+ function convertInput(tracer, input, paramsMetadata) {
251
+ if (!paramsMetadata) {
252
+ return input;
253
+ }
254
+
255
+ if (usingNamedParameters(input)) {
256
+ paramsMetadata.forEach(function(metadata) {
257
+ var value = input[0][metadata.PARAMETER_NAME];
258
+ if (value) {
259
+ input[0][metadata.PARAMETER_NAME] = convert(tracer, value, metadata.DATA_TYPE_NAME);
260
+ }
261
+ });
262
+ } else {
263
+ var inParamsMetadata = paramsMetadata.filter(function (meta) {
264
+ return meta.PARAMETER_TYPE !== 'OUT';
265
+ });
266
+ input.forEach(function (arg, index) {
267
+ input[index] = convert(tracer, arg, inParamsMetadata[index].DATA_TYPE_NAME);
268
+ });
269
+ }
270
+
271
+ return input;
272
+ }
273
+
274
+ function normalizeInput(input, treatDateAsUTC) {
275
+ // process objects with special semantics
276
+ if (input instanceof ctypes.Int64) {
277
+ return input.valueOf();
278
+ }
279
+
280
+ if (_.isBuffer(input)) {
281
+ return input;
282
+ }
283
+
284
+ if (_.isArrayBuffer(input)) {
285
+ return bufferUtils.toBuffer(input);
286
+ }
287
+
288
+ if (_.isDate(input)) {
289
+ return (treatDateAsUTC ? moment(input).utc() : moment(input)).format('YYYY-MM-DD HH:mm:ss.SSSSSSS');
290
+ }
291
+
292
+ // traverse container objects (including arrays)
293
+ if (_.isObjectLike(input)) {
294
+ for (var key in input) {
295
+ input[key] = normalizeInput(input[key], treatDateAsUTC);
296
+ }
297
+ return input;
298
+ }
299
+
300
+ return input;
301
+ }
302
+
303
+ function isOutgoing(procParam) {
304
+ return procParam.PARAMETER_TYPE === 'INOUT' || procParam.PARAMETER_TYPE === 'OUT';
305
+ }
306
+
307
+ function processResultSet(rs, treatDateAsUTC, enableColumnIndices) {
308
+ Object.defineProperty(rs, 'getIterator', {
309
+ enumerable: false,
310
+ value: function () {
311
+ return new ResultSetIterator(rs);
312
+ }
313
+ });
314
+
315
+ var names = getNamesOfColumnsForProcessing(rs.columnInfo);
316
+ var row;
317
+ for (var bigIntColumn of names.bigIntColumns) {
318
+ for (row of rs) {
319
+ if (row[bigIntColumn] !== null) {
320
+ row[bigIntColumn] = new ctypes.Int64(row[bigIntColumn]);
321
+ }
322
+ }
323
+ }
324
+ for (var binaryColumn of names.binaryColumns) {
325
+ for (row of rs) {
326
+ if (row[binaryColumn] !== null) {
327
+ row[binaryColumn] = bufferUtils.toArrayBuffer(row[binaryColumn]);
328
+ }
329
+ }
330
+ }
331
+ for (var dateColumn of names.dateColumns) {
332
+ for (row of rs) {
333
+ if (row[dateColumn] !== null) {
334
+ row[dateColumn] = dateUtils.dateToJsDate(row[dateColumn], treatDateAsUTC);
335
+ }
336
+ }
337
+ }
338
+ for (var timeColumn of names.timeColumns) {
339
+ for (row of rs) {
340
+ if (row[timeColumn] !== null) {
341
+ row[timeColumn] = dateUtils.timeToJsDate(row[timeColumn], treatDateAsUTC);
342
+ }
343
+ }
344
+ }
345
+ for (var dateTimeColumn of names.dateTimeColumns) {
346
+ for (row of rs) {
347
+ if (row[dateTimeColumn] !== null) {
348
+ row[dateTimeColumn] = dateUtils.dateTimeToJsDate(row[dateTimeColumn], treatDateAsUTC);
349
+ }
350
+ }
351
+ }
352
+
353
+ var result = rs;
354
+ if (enableColumnIndices) {
355
+ result = attachColumnIndices(rs);
356
+ }
357
+
358
+ attachResultSetMetadata(rs);
359
+ return result;
360
+ }
361
+
362
+ function getNamesOfColumnsForProcessing(columnInfo) {
363
+ var names = {
364
+ bigIntColumns: [],
365
+ binaryColumns: [],
366
+ dateColumns: [],
367
+ timeColumns: [],
368
+ dateTimeColumns: []
369
+ };
370
+
371
+ for (var info of columnInfo) {
372
+ switch (info.nativeType) {
373
+ case DB_TYPE.BIGINT:
374
+ names.bigIntColumns.push(info.columnName);
375
+ break;
376
+ case DB_TYPE.BLOB:
377
+ case DB_TYPE.BINARY:
378
+ case DB_TYPE.VARBINARY:
379
+ names.binaryColumns.push(info.columnName);
380
+ break;
381
+ case DB_TYPE.DAYDATE:
382
+ names.dateColumns.push(info.columnName);
383
+ break;
384
+ case DB_TYPE.SECONDTIME:
385
+ names.timeColumns.push(info.columnName);
386
+ break;
387
+ case DB_TYPE.SECONDDATE:
388
+ case DB_TYPE.LONGDATE:
389
+ names.dateTimeColumns.push(info.columnName);
390
+ break;
391
+ default:
392
+ break;
393
+ }
394
+ }
395
+
396
+ return names;
397
+ }
398
+
399
+ function attachColumnIndices(rs) {
400
+ const columnIndexObject = createColumnIndexObject(rs.columnInfo);
401
+
402
+ rs.forEach((row, index, rs) => {
403
+ rs[index] = Object.assign(Object.create(columnIndexObject), row);
404
+ });
405
+
406
+ updateColumnIndexObject(columnIndexObject, rs.columnInfo);
407
+ return rs;
408
+ }
409
+
410
+ function createColumnIndexObject(columnInfo) {
411
+ const properties = {};
412
+
413
+ for (let index in columnInfo) {
414
+ properties[index] = {
415
+ enumerable: false,
416
+ configurable: true,
417
+ set: function (value) {
418
+ this[Symbol.for(index)] = value;
419
+ }
420
+ };
421
+ }
422
+
423
+ return Object.defineProperties({}, properties);
424
+ }
425
+
426
+ function updateColumnIndexObject(columnIndexObject, columnInfo) {
427
+ const properties = {};
428
+
429
+ for (let index in columnInfo) {
430
+ properties[index] = {
431
+ enumerable: false,
432
+ configurable: false,
433
+ set: function () {
434
+ throw new Error(`"${index}" is read-only`);
435
+ },
436
+ get: function () {
437
+ const columnName = columnInfo[index].columnName;
438
+ const valueByIndex = this[Symbol.for(columnName)];
439
+ return valueByIndex !== undefined ? valueByIndex : this[columnName];
440
+ }
441
+ };
442
+ }
443
+
444
+ return Object.defineProperties(columnIndexObject, properties);
445
+ }
446
+
447
+ function attachResultSetMetadata(rs) {
448
+ var columnsMetadata = [];
449
+ for (var i = 0; i < rs.columnInfo.length; ++i) {
450
+ var info = rs.columnInfo[i];
451
+ var metadata = {
452
+ label: info.columnName,
453
+ name: info.originalColumnName,
454
+ type: enums.convert.toXscType(info.nativeType),
455
+ typeName: enums.convert.toXscTypeName(info.nativeTypeName),
456
+ precision: info.precision,
457
+ scale: info.scale,
458
+ tableName: info.tableName,
459
+ isNullable: !!info.nullable
460
+ };
461
+ columnsMetadata.push(metadata);
462
+ }
463
+ Object.defineProperty(rs, 'metadata', {
464
+ value: { columns: columnsMetadata }
465
+ });
466
+ }
467
+
468
+ async function executePromise(tracer, client, sql, sqlArgs) {
469
+ if (!_.isString(sql)) {
470
+ throw ('Invalid sql');
471
+ }
472
+
473
+ var args = sqlArgs || [];
474
+ var isBatch = args.length === 1 && Array.isArray(args[0]);
475
+ if (isBatch) {
476
+ args = args[0];
477
+ }
478
+
479
+ var statement = await client.prepare(sql);
480
+ try {
481
+ args = applyDefaultConversions(tracer, args, statement.getParameterInfo());
482
+ } catch (err) {
483
+ await afterStatementDropPromise(tracer, statement);
484
+ }
485
+ var fnCode = statement.functionCode();
486
+ if (fnCode === FunctionCode.NIL || fnCode === FunctionCode.DDL ||
487
+ fnCode === FunctionCode.INSERT || fnCode === FunctionCode.UPDATE || fnCode === FunctionCode.DELETE)
488
+ {
489
+ var result;
490
+ if (isBatch) {
491
+ result = await executeBatchPromise(statement, args);
492
+ } else {
493
+ result = await statement.execute(args);
494
+ }
495
+ return result;
496
+ } else {
497
+
498
+ var rows = await statement.execute(args) || [];
499
+ Object.defineProperty(rows, 'columnInfo', { value: statement.getColumnInfo() });
500
+ await afterStatementDropPromise(tracer, statement);
501
+ return rows;
502
+ }
503
+ }
504
+
505
+ async function afterStatementDropPromise(tracer, stmt){
506
+ try {
507
+ await stmt.drop();
508
+ } catch (err) {
509
+ tracer.debug(err, 'Could not drop statement');
510
+ }
511
+ }
512
+
513
+ function applyDefaultConversions(tracer, sqlArgs, parameterInfo) {
514
+ return sqlArgs.map(function(current, i) {
515
+ if (_.isArray(current)) {
516
+ return current.map(function(arg, j) {
517
+ if (j < parameterInfo.length) {
518
+ return convert(tracer, arg, parameterInfo[j].nativeType);
519
+ }
520
+ });
521
+ }
522
+
523
+ return convert(tracer, current, parameterInfo[i].nativeType);
524
+ });
525
+ }
@@ -0,0 +1,32 @@
1
+ 'use strict';
2
+
3
+ var Connection = require('./Connection.js');
4
+ var DbBase = require('../common/DbBase');
5
+ var util = require('util');
6
+
7
+ module.exports = HDB;
8
+
9
+ function HDB(dbReqOptions, tracer) {
10
+ DbBase.call(this, dbReqOptions);
11
+ this._tracer = tracer;
12
+ }
13
+ util.inherits(HDB, DbBase);
14
+
15
+ /**
16
+ * Returns a database connection.
17
+ * @param {JSON} [options] JSON object specifying the options:
18
+ * <ul>
19
+ * <li>isolationLevel - transaction isolation level. Default is $.hdb.isolation.READ_COMMITTED</li>
20
+ * <li>schema - schema to use</li>
21
+ * </ul>
22
+ * @returns {$.hdb.Connection} Connection - The internal connection to the database with the user of the current session.
23
+ * @example
24
+ *
25
+ * var connection = $.hdb.getConnection({"isolationLevel": $.hdb.isolation.REPEATABLE_READ, "schema": "myschema"});
26
+ */
27
+ HDB.prototype.getConnection = async function (userOptions) {
28
+ userOptions = userOptions || {};
29
+ var treatDateAsUTC = !!userOptions.treatDateAsUTC;
30
+ var enableColumnIndices = (userOptions.enableColumnIndices === false) ? false : true;
31
+ return new Connection(this._tracer, await this._getClient(userOptions), treatDateAsUTC, enableColumnIndices);
32
+ };
@@ -0,0 +1,40 @@
1
+ 'use strict';
2
+
3
+ module.exports = ResultSetIterator;
4
+
5
+ /**
6
+ * @class $.hdb.ResultSetIterator
7
+ * @classdesc Represents an iterator over a $.hdb.ResultSet object.
8
+ * @constructor
9
+ * @example
10
+ * var result = connection.executeQuery('SELECT FLAVOR, PRICE, QUANTITY FROM "DB_EXAMPLE"."ICECREAM"');
11
+ * var iterator = result.getIterator();
12
+ * var totalPrice = 0;
13
+ * while(iterator.next()) {
14
+ * var currentRow = iterator.value();
15
+ * totalPrice += currentRow['PRICE'];
16
+ * }
17
+ */
18
+ function ResultSetIterator(data) {
19
+ this._data = data;
20
+ this._at = -1;
21
+ }
22
+
23
+ /** Checks if the underlying $.hdb.ResultSet has more rows and sets the value of the iterator to the next row if it exists.
24
+ * @returns {boolean} True if the result set has more rows otherwise returns false.
25
+ */
26
+ ResultSetIterator.prototype.next = function() {
27
+ ++this._at;
28
+ return this._at < this._data.length;
29
+ };
30
+
31
+ /** Returns the current row that the iterator's value is set to. Should always be called after a call to next();
32
+ * @returns {object} An object representing the row of a $.hdb.ResultSet.
33
+ * @throws Throws an error if next() was not previously called or if there are no rows in the result set.
34
+ */
35
+ ResultSetIterator.prototype.value = function() {
36
+ if (this._at === -1 || this._at >= this._data.length) {
37
+ throw new Error('Cannot read past the end of the result set.');
38
+ }
39
+ return this._data[this._at];
40
+ };
@@ -0,0 +1,77 @@
1
+ 'use strict';
2
+
3
+ var _ = require('lodash');
4
+ var types = require('@sap/hana-client/extension/TypeCode');
5
+ var bufferUtils = require('../../../utils/buffer-utils');
6
+ var parseTableString = require('./table-string-parser').parse;
7
+ var adaptForHdbext = require('./table-string-parser').adaptForHdbext;
8
+
9
+
10
+ module.exports = function (tracer, sqlArg, dataType) {
11
+ if (_.isNil(sqlArg) || (_.isNumber(sqlArg) && !_.isFinite(sqlArg))) {
12
+ return sqlArg;
13
+ }
14
+
15
+ if (Array.isArray(sqlArg) && dataType === 'TABLE_TYPE') {
16
+ return sqlArg;
17
+ }
18
+ if (_.isString(sqlArg) && dataType === 'TABLE_TYPE') {
19
+ return convertTableString(tracer, sqlArg);
20
+ }
21
+
22
+ var realType = _.isString(dataType) ? types[dataType] : dataType;
23
+ switch (realType) {
24
+ case types.BINARY:
25
+ case types.VARBINARY:
26
+ return (_.isString(sqlArg) ? bufferUtils.hexStringToBuffer(sqlArg) : bufferUtils.toBuffer(sqlArg));
27
+
28
+ case types.ALPHANUM:
29
+ case types.CHAR:
30
+ case types.DECIMAL:
31
+ case types.NCHAR:
32
+ case types.NSTRING:
33
+ case types.NVARCHAR:
34
+ case types.SHORTTEXT:
35
+ case types.STRING:
36
+ case types.VARCHAR1:
37
+ return toString(sqlArg);
38
+
39
+ case types.DAYDATE:
40
+ if (_.isString(sqlArg)) {
41
+ return sqlArg.split(' ')[0]; // take only the year-month-day part
42
+ }
43
+ return sqlArg;
44
+ case types.SECONDTIME:
45
+ if (_.isString(sqlArg)) {
46
+ return sqlArg.split(' ')[1]; // take only the hour:minute:second.fraction part
47
+ }
48
+ return sqlArg;
49
+
50
+ default:
51
+ return sqlArg;
52
+ }
53
+ };
54
+
55
+ function toString(arg) {
56
+ if (_.isString(arg)) {
57
+ return arg;
58
+ }
59
+ if (bufferUtils.isBuffer(arg)) {
60
+ return arg.toString('utf8');
61
+ }
62
+ return '' + arg;
63
+ }
64
+
65
+ function convertTableString(tracer, str) {
66
+ tracer.debug('Parsing `%s` as <schema>.<table>', str);
67
+ var parsed = parseTableString(str);
68
+ if (parsed === null) {
69
+ tracer.debug('Parsing `%s` as <schema>.<table> failed', str);
70
+ throw new Error('Could not parse string `' + str + '` into <schema>.<table>');
71
+ }
72
+ tracer.debug('Parsing `%s` as <schema>.<table> resulted in %j', str, parsed);
73
+
74
+ var adapted = adaptForHdbext(parsed);
75
+ tracer.debug('Adapted <schema>.<table> for hdbext: %j', adapted);
76
+ return adapted;
77
+ }