sum.js 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. // ███████╗██╗ ██╗███╗ ███╗ █████╗ ██████╗████████╗██╗ ██████╗ ███╗ ██╗
  2. // ██╔════╝██║ ██║████╗ ████║ ██╔══██╗██╔════╝╚══██╔══╝██║██╔═══██╗████╗ ██║
  3. // ███████╗██║ ██║██╔████╔██║ ███████║██║ ██║ ██║██║ ██║██╔██╗ ██║
  4. // ╚════██║██║ ██║██║╚██╔╝██║ ██╔══██║██║ ██║ ██║██║ ██║██║╚██╗██║
  5. // ███████║╚██████╔╝██║ ╚═╝ ██║ ██║ ██║╚██████╗ ██║ ██║╚██████╔╝██║ ╚████║
  6. // ╚══════╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═══╝
  7. //
  8. module.exports = require('machine').build({
  9. friendlyName: 'SUM',
  10. description: 'Return the SUM of the records matched by the query.',
  11. inputs: {
  12. datastore: {
  13. description: 'The datastore to use for connections.',
  14. extendedDescription: 'Datastores represent the config and manager required to obtain an active database connection.',
  15. required: true,
  16. readOnly: true,
  17. example: '==='
  18. },
  19. models: {
  20. description: 'An object containing all of the model definitions that have been registered.',
  21. required: true,
  22. example: '==='
  23. },
  24. query: {
  25. description: 'A valid stage three Waterline query.',
  26. required: true,
  27. example: '==='
  28. }
  29. },
  30. exits: {
  31. success: {
  32. description: 'The results of the sum query.',
  33. outputType: 'ref'
  34. },
  35. invalidDatastore: {
  36. description: 'The datastore used is invalid. It is missing key pieces.'
  37. },
  38. badConnection: {
  39. friendlyName: 'Bad connection',
  40. description: 'A connection either could not be obtained or there was an error using the connection.'
  41. }
  42. },
  43. fn: function sum(inputs, exits) {
  44. // Dependencies
  45. var _ = require('@sailshq/lodash');
  46. var Converter = require('waterline-utils').query.converter;
  47. var Helpers = require('./private');
  48. // Store the Query input for easier access
  49. var query = inputs.query;
  50. query.meta = query.meta || {};
  51. // Find the model definition
  52. var model = inputs.models[query.using];
  53. if (!model) {
  54. return exits.invalidDatastore();
  55. }
  56. // Set a flag if a leased connection from outside the adapter was used or not.
  57. var leased = _.has(query.meta, 'leasedConnection');
  58. // ╔═╗╔═╗╔╗╔╦ ╦╔═╗╦═╗╔╦╗ ┌┬┐┌─┐ ┌─┐┌┬┐┌─┐┌┬┐┌─┐┌┬┐┌─┐┌┐┌┌┬┐
  59. // ║ ║ ║║║║╚╗╔╝║╣ ╠╦╝ ║ │ │ │ └─┐ │ ├─┤ │ ├┤ │││├┤ │││ │
  60. // ╚═╝╚═╝╝╚╝ ╚╝ ╚═╝╩╚═ ╩ ┴ └─┘ └─┘ ┴ ┴ ┴ ┴ └─┘┴ ┴└─┘┘└┘ ┴
  61. // Convert the Waterline criteria into a Waterline Query Statement. This
  62. // turns it into something that is declarative and can be easily used to
  63. // build a SQL query.
  64. // See: https://github.com/treelinehq/waterline-query-docs for more info
  65. // on Waterline Query Statements.
  66. var statement;
  67. try {
  68. statement = Converter({
  69. model: query.using,
  70. method: 'sum',
  71. criteria: query.criteria,
  72. values: query.numericAttrName
  73. });
  74. } catch (e) {
  75. return exits.error(e);
  76. }
  77. // Compile the original Waterline Query
  78. var compiledQuery;
  79. try {
  80. compiledQuery = Helpers.query.compileStatement(statement);
  81. } catch (e) {
  82. return exits.error(e);
  83. }
  84. // ╔═╗╔═╗╔═╗╦ ╦╔╗╔ ┌─┐┌─┐┌┐┌┌┐┌┌─┐┌─┐┌┬┐┬┌─┐┌┐┌
  85. // ╚═╗╠═╝╠═╣║║║║║║ │ │ │││││││├┤ │ │ ││ ││││
  86. // ╚═╝╩ ╩ ╩╚╩╝╝╚╝ └─┘└─┘┘└┘┘└┘└─┘└─┘ ┴ ┴└─┘┘└┘
  87. // ┌─┐┬─┐ ┬ ┬┌─┐┌─┐ ┬ ┌─┐┌─┐┌─┐┌─┐┌┬┐ ┌─┐┌─┐┌┐┌┌┐┌┌─┐┌─┐┌┬┐┬┌─┐┌┐┌
  88. // │ │├┬┘ │ │└─┐├┤ │ ├┤ ├─┤└─┐├┤ ││ │ │ │││││││├┤ │ │ ││ ││││
  89. // └─┘┴└─ └─┘└─┘└─┘ ┴─┘└─┘┴ ┴└─┘└─┘─┴┘ └─┘└─┘┘└┘┘└┘└─┘└─┘ ┴ ┴└─┘┘└┘
  90. // Spawn a new connection for running queries on.
  91. Helpers.connection.spawnOrLeaseConnection(inputs.datastore, query.meta, function spawnConnectionCb(err, connection) {
  92. if (err) {
  93. return exits.badConnection(err);
  94. }
  95. // ╦═╗╦ ╦╔╗╔ ┌─┐ ┬ ┬┌─┐┬─┐┬ ┬
  96. // ╠╦╝║ ║║║║ │─┼┐│ │├┤ ├┬┘└┬┘
  97. // ╩╚═╚═╝╝╚╝ └─┘└└─┘└─┘┴└─ ┴
  98. var queryType = 'sum';
  99. Helpers.query.runQuery({
  100. connection: connection,
  101. nativeQuery: compiledQuery.nativeQuery,
  102. valuesToEscape: compiledQuery.valuesToEscape,
  103. meta: compiledQuery.meta,
  104. queryType: queryType,
  105. disconnectOnError: leased ? false : true
  106. },
  107. function runQueryCb(err, report) {
  108. // The runQuery helper will automatically release the connection on error
  109. // if needed.
  110. if (err) {
  111. return exits.error(err);
  112. }
  113. // Always release the connection unless a leased connection from outside
  114. // the adapter was used.
  115. Helpers.connection.releaseConnection(connection, leased, function releaseConnectionCb() {
  116. return exits.success(report.result);
  117. }); // </ releaseConnection >
  118. }); // </ runQuery >
  119. }); // </ spawnConnection >
  120. }
  121. });