<commit_before>var InsertCommand = require('./commands/insert_command').InsertCommand,
  QueryCommand = require('./commands/query_command').QueryCommand,
  DeleteCommand = require('./commands/delete_command').DeleteCommand,
  UpdateCommand = require('./commands/update_command').UpdateCommand,
  DbCommand = require('./commands/db_command').DbCommand,
  BinaryParser = require('./bson/binary_parser').BinaryParser,
  OrderedHash = require('./bson/collections').OrderedHash,
  BSON = require('./bson/bson'),
  ObjectID = BSON.ObjectID,
  Code = BSON.Code,
  Cursor = require('./cursor').Cursor;

/**
  Handles all the operations on objects in collections
**/
var Collection = exports.Collection = function(db, collectionName, pkFactory) {
    this.db = db;
  this.collectionName = collectionName;
  this.internalHint;
  this.pkFactory = pkFactory == null ? ObjectID : pkFactory;
  // Add getter and setters
  this.__defineGetter__("hint", function() { return this.internalHint; });
  this.__defineSetter__("hint", function(value) { this.internalHint = this.normalizeHintField(value); });
  // Ensure the collection name is not illegal
  this.checkCollectionName(collectionName);
};

Collection.prototype.insert = function(docs, checkKeys, callback) {
  var args = Array.prototype.slice.call(arguments, 1);
  callback = args.pop();
  checkKeys = args.length ? args.shift() : true;

  this.insertAll(Array.isArray(docs) ? docs : [docs], checkKeys, callback);
  return this;
};

Collection.prototype.checkCollectionName = function(collectionName) {
  if (typeof collectionName != 'string')
    throw Error("collection name must be a String");

  if (!collectionName || collectionName.indexOf('..') != -1)
    throw Error("collection names cannot be empty");

  if (collectionName.indexOf('$') != -1 && collectionName.match(/((^\$cmd)|(oplog\.\$main))/) == null)
    throw Error("collection names must not contain '$'");

  if (collectionName.match(/^\.|\.$/) != null)
    throw Error("collection names must not start or end with '.'");
};

Collection.prototype.remove = function(selector, callback) {
  if(callback == null) { callback = selector; selector = null; }

  // Generate selector for remove all if not available
  var removeSelector = selector == null ? {} : selector;
  var deleteCommand = new DeleteCommand(this.db.databaseName + "." + this.collectionName, removeSelector);
  // Execute the command
  this.db.executeCommand(deleteCommand, callback);
  // Callback with no commands
  if(callback != null) callback(null, this);
};

Collection.prototype.rename = function(collectionName, callback) {
  var self = this;

  try {
    this.checkCollectionName(collectionName);
    this.db.renameCollection(this.collectionName, collectionName, function(err, result) {
      if(err != null || result.documents[0].ok == 0) {
        err != null ? callback(err, null) : callback(new Error(result.documents[0].errmsg), null);
      } else {
        // Set collectionname to new one and return the collection
        self.db.collection(collectionName, callback);
      }
    });
  } catch(err) {
    callback(err, null);
  }
};

Collection.prototype.insertAll = function(docs, checkKeys, callback) {
  var args = Array.prototype.slice.call(arguments, 1);
  callback = args.pop();
  checkKeys = args.length ? args.shift() : true;
  var error= null;
  
  try {
    // List of all id's inserted
    var objects = [];
    // Create an insert command
    var insertCommand = new InsertCommand(this.db.databaseName + "." + this.collectionName, checkKeys);
    // Add id to each document if it's not already defined
    for(var index = 0; index < docs.length; index++) {
      var doc = docs[index];

      if(!(doc instanceof OrderedHash)) {
        doc._id = doc._id == null ? this.pkFactory.createPk() : doc._id;
      } else {
        // Add the id to the document
        var id = doc.get("_id") == null ? this.pkFactory.createPk() : doc.get("_id");
        doc.add('_id', id);
      }

      // Insert the document
      insertCommand.add(doc);
      objects.push(doc);
    }
    // Execute the command
    this.db.executeCommand(insertCommand);
  } catch(err) {
    error= err;
  }
  // Return the id's inserted calling the callback (mongo does not callback on inserts)
  if(callback )  {
    if( error ) callback(error, null);
    else callback(null, objects);
  }
};

Collection.prototype.save = function(doc, options, callback) {
  var args = Array.prototype.slice.call(arguments, 1);
  callback = args.pop();
  options = args.length ? args.shift() : null;

  var id = (doc instanceof OrderedHash) ? doc.get('_id') : doc['_id'];
  var checkKeys = options != null && options.check_keys != null ? options.check_keys : true;

  if(id != null) {
    this.update({'_id':id}, doc, {upsert: true, safe: options != null ? options.safe : false}, callback);
  } else {
    this.insert(doc, checkKeys, function(err, docs) { Array.isArray(docs) ? callback(err, docs[0]) : callback(err, docs); });
  }
};

/**
  Update a single document in this collection.
    spec - a associcated array containing the fields that need to be present in
      the document for the update to succeed

    document - an associated array with the fields to be updated or in the case of
      a upsert operation the fields to be inserted.

  Options:
    upsert - true/false (perform upsert operation)
    safe - true/false (perform check if the operation failed, required extra call to db)
**/<commit_msg>Revert "Allowed for turning of check keys on insert"<commit_after>var InsertCommand = require('./commands/insert_command').InsertCommand,
  QueryCommand = require('./commands/query_command').QueryCommand,
  DeleteCommand = require('./commands/delete_command').DeleteCommand,
  UpdateCommand = require('./commands/update_command').UpdateCommand,
  DbCommand = require('./commands/db_command').DbCommand,
  BinaryParser = require('./bson/binary_parser').BinaryParser,
  OrderedHash = require('./bson/collections').OrderedHash,
  BSON = require('./bson/bson'),
  ObjectID = BSON.ObjectID,
  Code = BSON.Code,
  Cursor = require('./cursor').Cursor;

/**
  Handles all the operations on objects in collections
**/
var Collection = exports.Collection = function(db, collectionName, pkFactory) {
    this.db = db;
  this.collectionName = collectionName;
  this.internalHint;
  this.pkFactory = pkFactory == null ? ObjectID : pkFactory;
  // Add getter and setters
  this.__defineGetter__("hint", function() { return this.internalHint; });
  this.__defineSetter__("hint", function(value) { this.internalHint = this.normalizeHintField(value); });
  // Ensure the collection name is not illegal
  this.checkCollectionName(collectionName);
};

Collection.prototype.insert = function(docs, callback) {
  this.insertAll(Array.isArray(docs) ? docs : [docs], callback);
  return this;
};

Collection.prototype.checkCollectionName = function(collectionName) {
  if (typeof collectionName != 'string')
    throw Error("collection name must be a String");

  if (!collectionName || collectionName.indexOf('..') != -1)
    throw Error("collection names cannot be empty");

  if (collectionName.indexOf('$') != -1 && collectionName.match(/((^\$cmd)|(oplog\.\$main))/) == null)
    throw Error("collection names must not contain '$'");

  if (collectionName.match(/^\.|\.$/) != null)
    throw Error("collection names must not start or end with '.'");
};

Collection.prototype.remove = function(selector, callback) {
  if(callback == null) { callback = selector; selector = null; }

  // Generate selector for remove all if not available
  var removeSelector = selector == null ? {} : selector;
  var deleteCommand = new DeleteCommand(this.db.databaseName + "." + this.collectionName, removeSelector);
  // Execute the command
  this.db.executeCommand(deleteCommand, callback);
  // Callback with no commands
  if(callback != null) callback(null, this);
};

Collection.prototype.rename = function(collectionName, callback) {
  var self = this;

  try {
    this.checkCollectionName(collectionName);
    this.db.renameCollection(this.collectionName, collectionName, function(err, result) {
      if(err != null || result.documents[0].ok == 0) {
        err != null ? callback(err, null) : callback(new Error(result.documents[0].errmsg), null);
      } else {
        // Set collectionname to new one and return the collection
        self.db.collection(collectionName, callback);
      }
    });
  } catch(err) {
    callback(err, null);
  }
};

Collection.prototype.insertAll = function(docs, callback) {
  var error= null;
  
  try {
    // List of all id's inserted
    var objects = [];
    // Create an insert command
    var insertCommand = new InsertCommand(this.db.databaseName + "." + this.collectionName);
    // Add id to each document if it's not already defined
    for(var index = 0; index < docs.length; index++) {
      var doc = docs[index];

      if(!(doc instanceof OrderedHash)) {
        doc._id = doc._id == null ? this.pkFactory.createPk() : doc._id;
      } else {
        // Add the id to the document
        var id = doc.get("_id") == null ? this.pkFactory.createPk() : doc.get("_id");
        doc.add('_id', id);
      }

      // Insert the document
      insertCommand.add(doc);
      objects.push(doc);
    }
    // Execute the command
    this.db.executeCommand(insertCommand);
  } catch(err) {
    error= err;
  }
  // Return the id's inserted calling the callback (mongo does not callback on inserts)
  if(callback )  {
    if( error ) callback(error, null);
    else callback(null, objects);
  }
};

Collection.prototype.save = function(doc, options, callback) {
  var args = Array.prototype.slice.call(arguments, 1);
  callback = args.pop();
  options = args.length ? args.shift() : null;

  var id = (doc instanceof OrderedHash) ? doc.get('_id') : doc['_id'];

  if(id != null) {
    this.update({'_id':id}, doc, {upsert: true, safe: options != null ? options.safe : false}, callback);
  } else {
    this.insert(doc, function(err, docs) { Array.isArray(docs) ? callback(err, docs[0]) : callback(err, docs); });
  }
};

/**
  Update a single document in this collection.
    spec - a associcated array containing the fields that need to be present in
      the document for the update to succeed

    document - an associated array with the fields to be updated or in the case of
      a upsert operation the fields to be inserted.

  Options:
    upsert - true/false (perform upsert operation)
    safe - true/false (perform check if the operation failed, required extra call to db)
**/
{'fraction_non_alphanumeric': 0.13760166445999622, 'fraction_numerical': 0.0017022886324947987, 'mean_word_length': 3.6280087527352296, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4088824', 'n_tokens_mistral': 3077, 'n_tokens_neox': 3026, 'n_words': 863}