You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

211 lines
5.5 KiB

  1. /*!
  2. * Module dependencies.
  3. */
  4. var MongooseCollection = require('../../collection')
  5. , Collection = require('mongodb').Collection
  6. , STATES = require('../../connectionstate')
  7. , utils = require('../../utils')
  8. /**
  9. * A [node-mongodb-native](https://github.com/mongodb/node-mongodb-native) collection implementation.
  10. *
  11. * All methods methods from the [node-mongodb-native](https://github.com/mongodb/node-mongodb-native) driver are copied and wrapped in queue management.
  12. *
  13. * @inherits Collection
  14. * @api private
  15. */
  16. function NativeCollection () {
  17. this.collection = null;
  18. MongooseCollection.apply(this, arguments);
  19. }
  20. /*!
  21. * Inherit from abstract Collection.
  22. */
  23. NativeCollection.prototype.__proto__ = MongooseCollection.prototype;
  24. /**
  25. * Called when the connection opens.
  26. *
  27. * @api private
  28. */
  29. NativeCollection.prototype.onOpen = function () {
  30. var self = this;
  31. // always get a new collection in case the user changed host:port
  32. // of parent db instance when re-opening the connection.
  33. if (!self.opts.capped.size) {
  34. // non-capped
  35. return self.conn.db.collection(self.name, callback);
  36. }
  37. // capped
  38. return self.conn.db.collection(self.name, function (err, c) {
  39. if (err) return callback(err);
  40. // discover if this collection exists and if it is capped
  41. c.options(function (err, exists) {
  42. if (err) return callback(err);
  43. if (exists) {
  44. if (exists.capped) {
  45. callback(null, c);
  46. } else {
  47. var msg = 'A non-capped collection exists with the name: '+ self.name +'\n\n'
  48. + ' To use this collection as a capped collection, please '
  49. + 'first convert it.\n'
  50. + ' http://www.mongodb.org/display/DOCS/Capped+Collections#CappedCollections-Convertingacollectiontocapped'
  51. err = new Error(msg);
  52. callback(err);
  53. }
  54. } else {
  55. // create
  56. var opts = utils.clone(self.opts.capped);
  57. opts.capped = true;
  58. self.conn.db.createCollection(self.name, opts, callback);
  59. }
  60. });
  61. });
  62. function callback (err, collection) {
  63. if (err) {
  64. // likely a strict mode error
  65. self.conn.emit('error', err);
  66. } else {
  67. self.collection = collection;
  68. MongooseCollection.prototype.onOpen.call(self);
  69. }
  70. };
  71. };
  72. /**
  73. * Called when the connection closes
  74. *
  75. * @api private
  76. */
  77. NativeCollection.prototype.onClose = function () {
  78. MongooseCollection.prototype.onClose.call(this);
  79. };
  80. /*!
  81. * Copy the collection methods and make them subject to queues
  82. */
  83. for (var i in Collection.prototype) {
  84. (function(i){
  85. NativeCollection.prototype[i] = function () {
  86. if (this.buffer) {
  87. this.addQueue(i, arguments);
  88. return;
  89. }
  90. var collection = this.collection
  91. , args = arguments
  92. , self = this
  93. , debug = self.conn.base.options.debug;
  94. if (debug) {
  95. if ('function' === typeof debug) {
  96. debug.apply(debug
  97. , [self.name, i].concat(utils.args(args, 0, args.length-1)));
  98. } else {
  99. console.error('\x1B[0;36mMongoose:\x1B[0m %s.%s(%s) %s %s %s'
  100. , self.name
  101. , i
  102. , print(args[0])
  103. , print(args[1])
  104. , print(args[2])
  105. , print(args[3]))
  106. }
  107. }
  108. collection[i].apply(collection, args);
  109. };
  110. })(i);
  111. }
  112. /*!
  113. * Debug print helper
  114. */
  115. function print (arg) {
  116. var type = typeof arg;
  117. if ('function' === type || 'undefined' === type) return '';
  118. return format(arg);
  119. }
  120. /*!
  121. * Debug print helper
  122. */
  123. function format (obj, sub) {
  124. var x = utils.clone(obj);
  125. if (x) {
  126. if ('Binary' === x.constructor.name) {
  127. x = '[object Buffer]';
  128. } else if ('ObjectID' === x.constructor.name) {
  129. var representation = 'ObjectId("' + x.toHexString() + '")';
  130. x = { inspect: function() { return representation; } };
  131. } else if ('Date' === x.constructor.name) {
  132. var representation = 'new Date("' + x.toUTCString() + '")';
  133. x = { inspect: function() { return representation; } };
  134. } else if ('Object' === x.constructor.name) {
  135. var keys = Object.keys(x)
  136. , i = keys.length
  137. , key
  138. while (i--) {
  139. key = keys[i];
  140. if (x[key]) {
  141. if ('Binary' === x[key].constructor.name) {
  142. x[key] = '[object Buffer]';
  143. } else if ('Object' === x[key].constructor.name) {
  144. x[key] = format(x[key], true);
  145. } else if ('ObjectID' === x[key].constructor.name) {
  146. ;(function(x){
  147. var representation = 'ObjectId("' + x[key].toHexString() + '")';
  148. x[key] = { inspect: function() { return representation; } };
  149. })(x)
  150. } else if ('Date' === x[key].constructor.name) {
  151. ;(function(x){
  152. var representation = 'new Date("' + x[key].toUTCString() + '")';
  153. x[key] = { inspect: function() { return representation; } };
  154. })(x)
  155. } else if (Array.isArray(x[key])) {
  156. x[key] = x[key].map(function (o) {
  157. return format(o, true)
  158. });
  159. }
  160. }
  161. }
  162. }
  163. if (sub) return x;
  164. }
  165. return require('util')
  166. .inspect(x, false, 10, true)
  167. .replace(/\n/g, '')
  168. .replace(/\s{2,}/g, ' ')
  169. }
  170. /**
  171. * Retreives information about this collections indexes.
  172. *
  173. * @param {Function} callback
  174. * @method getIndexes
  175. * @api public
  176. */
  177. NativeCollection.prototype.getIndexes = NativeCollection.prototype.indexInformation;
  178. /*!
  179. * Module exports.
  180. */
  181. module.exports = NativeCollection;