PageRenderTime 74ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/node_modules/azure-mobile-services/runtime/script/sqladapter.js

https://gitlab.com/TomBruyneelTrisco/krumbappservice
JavaScript | 167 lines | 127 code | 22 blank | 18 comment | 15 complexity | a31ac16fce67d48f1836ce7b46503e74 MD5 | raw file
  1. // ----------------------------------------------------------------------------
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. // ----------------------------------------------------------------------------
  4. //
  5. // Adapts the sqlserver module for direct use from ZUMO scripts
  6. var core = require('../core'),
  7. sqlserver = require('sqlserver'),
  8. scriptErrors = require('./scripterror'),
  9. util = require('util');
  10. module.exports.create = function(connectionString, logger, metrics, source, responseCallback) {
  11. var adapter = new SqlAdapter(connectionString, logger, metrics, source, responseCallback);
  12. return adapter.createMSSQLModule();
  13. };
  14. var logSource = 'SqlAdapter';
  15. function SqlAdapter(connectionString, logger, metrics, source, responseCallback) {
  16. this.connectionString = connectionString;
  17. this.logger = logger;
  18. this.source = source;
  19. this.responseCallback = responseCallback;
  20. this.metrics = metrics;
  21. }
  22. SqlAdapter.prototype.createMSSQLModule = function () {
  23. var self = this;
  24. self.logger.trace(logSource, 'Creating MSSQL Module', self.getTraceDetails());
  25. return {
  26. open: function (callbackOptions) {
  27. var traceDetails = self.getTraceDetails("open");
  28. var args = self.prepareArgs('open', null, callbackOptions, traceDetails, "Unable to open connection: ");
  29. self.executeSqlServerFunction(traceDetails, function () {
  30. return sqlserver.open(self.connectionString, args.callback);
  31. });
  32. },
  33. query: function (query, paramsOrCallback, callbackOptions) {
  34. var traceDetails = self.getTraceDetails("query", query);
  35. var args = self.prepareArgs('query', paramsOrCallback, callbackOptions, traceDetails, "Error occurred executing query: ");
  36. self.executeSqlServerFunction(traceDetails, function () {
  37. return sqlserver.query(self.connectionString, query, args.params, args.callback);
  38. });
  39. },
  40. queryRaw: function (query, paramsOrCallback, callbackOptions) {
  41. var traceDetails = self.getTraceDetails("queryRaw", query);
  42. var args = self.prepareArgs('queryRaw', paramsOrCallback, callbackOptions, traceDetails, "Error occurred executing query: ");
  43. self.executeSqlServerFunction(traceDetails, function () {
  44. return sqlserver.queryRaw(self.connectionString, query, args.params, args.callback);
  45. });
  46. }
  47. };
  48. };
  49. SqlAdapter.prototype.prepareArgs = function (method, paramsOrCallbackOptions, callbackOptions, traceDetails, errormsg) {
  50. var params;
  51. if (!callbackOptions) {
  52. if (core.isObject(paramsOrCallbackOptions)) {
  53. // We have only one argument but it is an object indicating callback parameters
  54. callbackOptions = paramsOrCallbackOptions;
  55. params = [];
  56. } else if (core.isFunction(paramsOrCallbackOptions)) {
  57. // We have only one argument but it is a function. The user probably misread the documentation
  58. // and is trying to pass a callback as a single function. We will set it as the callback so that it gets
  59. // validated as a callback and a better error message is given than a SQL error saying "bad parameters"
  60. callbackOptions = paramsOrCallbackOptions;
  61. params = [];
  62. }
  63. }
  64. // If nothing above is hit, it means that we either have:
  65. // - Both params and callbackOptions
  66. // - A single argument that is most likely a parameter
  67. if (!params) {
  68. params = paramsOrCallbackOptions;
  69. }
  70. // Validate callback
  71. try {
  72. core.validateCallbackOptions(callbackOptions, method);
  73. }
  74. catch (exception) {
  75. this.logger.trace(logSource, 'Call into MSSQL Module failed - Invalid callbackOptions', traceDetails);
  76. throw exception;
  77. }
  78. // normalize the parameters by arrayifying single values
  79. if (params && !core.isArray(params)) {
  80. params = [params];
  81. }
  82. return { params: params, callback: this.constructCallback(callbackOptions, traceDetails, errormsg) };
  83. };
  84. SqlAdapter.prototype.executeSqlServerFunction = function (traceDetails, sqlServerFunction) {
  85. this.metrics.event('api.mssql.' + traceDetails.sqlFunction);
  86. this.logger.trace(logSource, 'Calling into MSSQL Module', traceDetails);
  87. try {
  88. return sqlServerFunction();
  89. }
  90. catch (exception) {
  91. this.logger.trace(logSource, 'Call into MSSQL Module failed - Exception thrown', traceDetails);
  92. throw exception;
  93. }
  94. };
  95. SqlAdapter.prototype.constructCallback = function (callbackOptions, traceDetails, errormsg) {
  96. var self = this;
  97. return function (err) {
  98. if (err) {
  99. // wrap the sql error in our own type
  100. err = new core.MobileServiceError(err, core.ErrorCodes.ScriptError);
  101. traceDetails.error = err.toString();
  102. if (callbackOptions && callbackOptions.error) {
  103. self.logger.trace(logSource, 'Call into MSSQL Module failed - Calling user error callback', traceDetails);
  104. self.executeUserCallback(traceDetails, function () {
  105. callbackOptions.error(scriptErrors.prepareUserError(err));
  106. });
  107. } else {
  108. self.logger.trace(logSource, 'Call into MSSQL Module failed - Calling default error callback', traceDetails);
  109. scriptErrors.handleScriptError(err, self.source, self.logger, self.responseCallback, errormsg);
  110. }
  111. } else {
  112. self.logger.trace(logSource, 'Call into MSSQL Module was successful', traceDetails);
  113. if (callbackOptions && callbackOptions.success) {
  114. // Skip the error argument, pass the rest.
  115. var args = Array.prototype.slice.call(arguments).slice(1);
  116. self.executeUserCallback(traceDetails, function () {
  117. callbackOptions.success.apply(null, args);
  118. });
  119. }
  120. }
  121. };
  122. };
  123. SqlAdapter.prototype.executeUserCallback = function (traceDetails, callback) {
  124. try {
  125. this.logger.trace(logSource, 'Executing user callback', traceDetails);
  126. callback();
  127. this.logger.trace(logSource, 'Execution of user callback was successful', traceDetails);
  128. }
  129. catch (exception) {
  130. this.logger.trace(logSource, 'Execution of user callback threw an exception', traceDetails);
  131. scriptErrors.handleScriptError(new core.MobileServiceError(exception, core.ErrorCodes.ScriptError), this.source, this.logger, this.responseCallback);
  132. }
  133. };
  134. SqlAdapter.prototype.getTraceDetails = function (sqlFunction, query) {
  135. // need to be sure not to log any sensitive information here,
  136. // for example connection string, etc.
  137. var traceDetails = {
  138. source: this.source,
  139. sqlFunction: sqlFunction
  140. };
  141. if (query) {
  142. traceDetails.query = query;
  143. }
  144. return traceDetails;
  145. };