count.js 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. // ██████╗ ██████╗ ██╗ ██╗███╗ ██╗████████╗ █████╗ ██████╗████████╗██╗ ██████╗ ███╗ ██╗
  2. // ██╔════╝██╔═══██╗██║ ██║████╗ ██║╚══██╔══╝ ██╔══██╗██╔════╝╚══██╔══╝██║██╔═══██╗████╗ ██║
  3. // ██║ ██║ ██║██║ ██║██╔██╗ ██║ ██║ ███████║██║ ██║ ██║██║ ██║██╔██╗ ██║
  4. // ██║ ██║ ██║██║ ██║██║╚██╗██║ ██║ ██╔══██║██║ ██║ ██║██║ ██║██║╚██╗██║
  5. // ╚██████╗╚██████╔╝╚██████╔╝██║ ╚████║ ██║ ██║ ██║╚██████╗ ██║ ██║╚██████╔╝██║ ╚████║
  6. // ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═══╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═══╝
  7. //
  8. module.exports = require('machine').build({
  9. friendlyName: 'Count',
  10. description: 'Return the count 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 count query.',
  33. outputExample: '==='
  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 count(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: 'count',
  71. criteria: query.criteria
  72. });
  73. } catch (e) {
  74. return exits.error(e);
  75. }
  76. // Compile the original Waterline Query
  77. var compiledQuery;
  78. try {
  79. compiledQuery = Helpers.query.compileStatement(statement);
  80. } catch (e) {
  81. return exits.error(e);
  82. }
  83. // ╔═╗╔═╗╔═╗╦ ╦╔╗╔ ┌─┐┌─┐┌┐┌┌┐┌┌─┐┌─┐┌┬┐┬┌─┐┌┐┌
  84. // ╚═╗╠═╝╠═╣║║║║║║ │ │ │││││││├┤ │ │ ││ ││││
  85. // ╚═╝╩ ╩ ╩╚╩╝╝╚╝ └─┘└─┘┘└┘┘└┘└─┘└─┘ ┴ ┴└─┘┘└┘
  86. // ┌─┐┬─┐ ┬ ┬┌─┐┌─┐ ┬ ┌─┐┌─┐┌─┐┌─┐┌┬┐ ┌─┐┌─┐┌┐┌┌┐┌┌─┐┌─┐┌┬┐┬┌─┐┌┐┌
  87. // │ │├┬┘ │ │└─┐├┤ │ ├┤ ├─┤└─┐├┤ ││ │ │ │││││││├┤ │ │ ││ ││││
  88. // └─┘┴└─ └─┘└─┘└─┘ ┴─┘└─┘┴ ┴└─┘└─┘─┴┘ └─┘└─┘┘└┘┘└┘└─┘└─┘ ┴ ┴└─┘┘└┘
  89. // Spawn a new connection for running queries on.
  90. Helpers.connection.spawnOrLeaseConnection(inputs.datastore, query.meta, function spawnConnectionCb(err, connection) {
  91. if (err) {
  92. return exits.badConnection(err);
  93. }
  94. // ╦═╗╦ ╦╔╗╔ ┌─┐ ┬ ┬┌─┐┬─┐┬ ┬
  95. // ╠╦╝║ ║║║║ │─┼┐│ │├┤ ├┬┘└┬┘
  96. // ╩╚═╚═╝╝╚╝ └─┘└└─┘└─┘┴└─ ┴
  97. var queryType = 'count';
  98. Helpers.query.runQuery({
  99. connection: connection,
  100. nativeQuery: compiledQuery.nativeQuery,
  101. valuesToEscape: compiledQuery.valuesToEscape,
  102. meta: compiledQuery.meta,
  103. queryType: queryType,
  104. disconnectOnError: leased ? false : true
  105. },
  106. function runQueryCb(err, report) {
  107. // The runQuery helper will automatically release the connection on error
  108. // if needed.
  109. if (err) {
  110. return exits.error(err);
  111. }
  112. // Always release the connection unless a leased connection from outside
  113. // the adapter was used.
  114. Helpers.connection.releaseConnection(connection, leased, function releaseConnectionCb() {
  115. return exits.success(report.result);
  116. }); // </ releaseConnection >
  117. }); // </ runQuery >
  118. }); // </ spawnConnection >
  119. }
  120. });