<commit_before>var transformComps = require('./transform-composed-nodes'),
    async = require('async'),
    _ = require('underscore'),
    compositionRelationCypherList = require('./composition-relation-cypher-list'),
    sortComps = require('./sort-compositions');

function stripComposedObjects(object) {
  var compStripped = _.clone(object);
  Object.keys(this.compositions).forEach(function(comp) {
    delete compStripped[comp]
  });
  return compStripped;
}

function makeName(names) {
  var count = -1, name;
  do {
    name = this.type + ++count;
  } while (~names.indexOf(name))
  names.push(name);
  return name;
}

function createNodeGraph(node, names, allNodes) {
  names = names || [];
  var root = stripComposedObjects.call(this, node);
  var graph = { 
    name: makeName.call(this, names),
    props: root,
    model: this,
    children: []
  };

  if (!allNodes) allNodes = graph.allNodes = [graph];

  for (var compName in this.compositions) {
    var comp = this.compositions[compName];
    if (!node[comp.name]) continue;
    var subnodes = node[comp.name];
    if (!Array.isArray(subnodes)) subnodes = [subnodes];
    for (var i in subnodes) {
      var subgraph = createNodeGraph.call(comp.model, subnodes[i], names, allNodes);
      subgraph.comp = comp;
      graph.children.push(subgraph);
      allNodes.push(subgraph);
    }
  }

  return graph;
}

function reassembleFromGraph(graph, data) {
  function _reassembleFromGraph(node, object) {
    node.children.forEach(function(child) {
      var node =  _reassembleFromGraph(child, data[child.name]);
      if (!object[child.comp.name]) 
        object[child.comp.name] = child.comp.many ? [node] : node;
      else if (!Array.isArray(object[child.comp.name]))
        object[child.comp.name] = [object[child.comp.name], node];
      else
        object[child.comp.name].push(node);
    });
    return object;
  }
  return _reassembleFromGraph(graph, data[graph.name] || data);
}

function getSetCreatedTimestampStatement(node) {
  var prop = node.name + '.' + node.model.createdField;
  return prop + '= CASE WHEN has(' + prop + ') THEN ' + prop + ' ELSE timestamp() END';
};

var compose = {
  // get the START statement of a write query
  // this will start with all the pre-existing nodes
  start: function (graph, opts, params) {
    var self = this;
    var savedNodes = graph.allNodes.filter(function(node) {
      return node.props[self.db.options.id] != null 
          && !node.model.uniqueness
    });

    if (!savedNodes.length) return '';

    var statements = savedNodes.map(function(node) {
      params[node.name + 'id'] = self.db._getId(node.props);
      return node.name + '=node({' + node.name + 'id})';
    });

    return 'START ' + statements.join(',');
  },
  match: function (graph, opts, params) {
    var self = this;
    var savedUniqueNodes = graph.allNodes.filter(function(node) {
      return node.props[self.db.options.id] != null 
          && node.model.uniqueness
          && !node.model.uniqueness.returnOld;
    });

    if (!savedUniqueNodes.length) return '';

    var statements = savedUniqueNodes.map(function(node) {
      var uniqueKey = node.model.uniqueness.key;
      params[node.name + 'key'] = node.props[uniqueKey];
      return '(' + node.name + ':' + node.model.type + ' {' + uniqueKey + ': {' + node.name + 'key}})';<commit_msg>don't use match as a start clause in writes to avoid false negatives<commit_after>var transformComps = require('./transform-composed-nodes'),
    async = require('async'),
    _ = require('underscore'),
    compositionRelationCypherList = require('./composition-relation-cypher-list'),
    sortComps = require('./sort-compositions');

function stripComposedObjects(object) {
  var compStripped = _.clone(object);
  Object.keys(this.compositions).forEach(function(comp) {
    delete compStripped[comp]
  });
  return compStripped;
}

function makeName(names) {
  var count = -1, name;
  do {
    name = this.type + ++count;
  } while (~names.indexOf(name))
  names.push(name);
  return name;
}

function createNodeGraph(node, names, allNodes) {
  names = names || [];
  var root = stripComposedObjects.call(this, node);
  var graph = { 
    name: makeName.call(this, names),
    props: root,
    model: this,
    children: []
  };

  if (!allNodes) allNodes = graph.allNodes = [graph];

  for (var compName in this.compositions) {
    var comp = this.compositions[compName];
    if (!node[comp.name]) continue;
    var subnodes = node[comp.name];
    if (!Array.isArray(subnodes)) subnodes = [subnodes];
    for (var i in subnodes) {
      var subgraph = createNodeGraph.call(comp.model, subnodes[i], names, allNodes);
      subgraph.comp = comp;
      graph.children.push(subgraph);
      allNodes.push(subgraph);
    }
  }

  return graph;
}

function reassembleFromGraph(graph, data) {
  function _reassembleFromGraph(node, object) {
    node.children.forEach(function(child) {
      var node =  _reassembleFromGraph(child, data[child.name]);
      if (!object[child.comp.name]) 
        object[child.comp.name] = child.comp.many ? [node] : node;
      else if (!Array.isArray(object[child.comp.name]))
        object[child.comp.name] = [object[child.comp.name], node];
      else
        object[child.comp.name].push(node);
    });
    return object;
  }
  return _reassembleFromGraph(graph, data[graph.name] || data);
}

function getSetCreatedTimestampStatement(node) {
  var prop = node.name + '.' + node.model.createdField;
  return prop + '= CASE WHEN has(' + prop + ') THEN ' + prop + ' ELSE timestamp() END';
};

var compose = {
  // get the START statement of a write query
  // this will start with all the pre-existing nodes
  start: function (graph, opts, params) {
    var self = this;
    var savedNodes = graph.allNodes.filter(function(node) {
      return node.props[self.db.options.id] != null 
          && !(node.model.uniqueness && node.model.uniqueness.returnOld);
    });

    if (!savedNodes.length) return '';

    var statements = savedNodes.map(function(node) {
      params[node.name + 'id'] = self.db._getId(node.props);
      return node.name + '=node({' + node.name + 'id})';
    });

    return 'START ' + statements.join(',');
  },
  match: function (graph, opts, params) {
    // starting with  match is currently unsafe because if you want to change
    // the key of an object, the object you're saving will already have a different
    // key, and seraph-model has no reference to the old one. hopefully this code
    // can come back into use at some time, but as it is now it is not possible.
    return '';
    var self = this;
    var savedUniqueNodes = graph.allNodes.filter(function(node) {
      return node.props[self.db.options.id] != null 
          && node.model.uniqueness
          && !node.model.uniqueness.returnOld;
    });

    if (!savedUniqueNodes.length) return '';

    var statements = savedUniqueNodes.map(function(node) {
      var uniqueKey = node.model.uniqueness.key;
      params[node.name + 'key'] = node.props[uniqueKey];
      return '(' + node.name + ':' + node.model.type + ' {' + uniqueKey + ': {' + node.name + 'key}})';
{'fraction_non_alphanumeric': 0.14641308907845058, 'fraction_numerical': 0.00027968116347364006, 'mean_word_length': 3.2470308788598574, 'pattern_counts': {'":': 0, '<': 3, '<?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': '7166826', 'n_tokens_mistral': 2283, 'n_tokens_neox': 2235, 'n_words': 523}