<commit_before>exports = module.exports = Sql;
var slice = Array.prototype.slice;

function Sql(opts, parts) {
	if(!(this instanceof Sql)) return new Sql(opts, parts);
	this._opts = opts || { variablePrefix: '$' };
	this._parts = parts || [];
}

Sql.escape = function (v, quote) {
	if(!quote) quote = "'";
	return ((v||'').toString().replace(RegExp('[' + quote + ']', 'g'), function(m) { return m + m }));
}

Sql.prototype.append = function append(sql, args) {
	if((sql instanceof Sql)) {
		var built = sql.toQuery();
		sql = built.text;
		args = built.parameters;
	}

	if(args && (args instanceof Array) && (args[0] instanceof Array) && args[0].length === 0) {
		throw new Error("Nested arrays cannot be used as sql parameter.");
	}

	return new Sql(this._opts, this._parts.concat([[sql, args || []]]));
};

Sql.prototype.wrap = function wrap(prefix, txt, suffix, args) {
	return this.append(prefix || '').append(txt, args).append(suffix || '');
};

Sql.prototype.select = function select(args) { return this.append('SELECT ' + slice.call(arguments).join(',')); };
Sql.prototype.from = function from(args) { return this.append('FROM ' + slice.call(arguments).join(',')); };
Sql.prototype.where = function where(txt, args) { return this.wrap('WHERE (', txt, ')', args); };
Sql.prototype.or = function or(txt, args) { return this.wrap('OR (', txt, ')', args); };
Sql.prototype.and = function and(txt, args) { return this.wrap('AND (', txt, ')', args); };
Sql.prototype.orderBy = function orderBy(args) { return this.append('ORDER BY ' + slice.call(arguments).join(',')); };
Sql.prototype.groupBy = function groupBy(args) { return this.append('GROUP BY ' + slice.call(arguments).join(',')); };

Sql.prototype.toQuery = function toQuery() {
	var variable = this._opts.variablePrefix || '$';
	if (this._built !== undefined) return this._built;
	var sqlList = [], argList = [], argCount = 0;
	var outputArguments = new Map();
	for(var i=0; i<this._parts.length; ++i) {
		var txt = this._parts[i][0];
		var args = this._parts[i][1];
		txt = txt.replace(new RegExp('(?!\\\\)\\' + (variable) + '(\\d+)', 'g'), function (m, idx) {
			var argumentValue = args[Number(idx) - 1];
			var savedIndex = outputArguments.get(argumentValue);
			if (savedIndex === undefined) {
				argCount += 1;
				savedIndex = argCount;
				argList.push(argumentValue);
				outputArguments.set(argumentValue, savedIndex);
			}
			return variable + savedIndex;
		});
		sqlList.push(txt);
	}
	this._built = { text: sqlList.join(' '), parameters: argList };
	return this._built;
};
<commit_msg>rename _opts to opts<commit_after>exports = module.exports = Sql;
var slice = Array.prototype.slice;

function Sql(opts, parts) {
	if(!(this instanceof Sql)) return new Sql(opts, parts);
	this.opts = opts || { variablePrefix: '$' };
	this._parts = parts || [];
}

Sql.escape = function (v, quote) {
	if(!quote) quote = "'";
	return ((v||'').toString().replace(RegExp('[' + quote + ']', 'g'), function(m) { return m + m }));
}

Sql.prototype.append = function append(sql, args) {
	if((sql instanceof Sql)) {
		var built = sql.toQuery();
		sql = built.text;
		args = built.parameters;
	}

	if(args && (args instanceof Array) && (args[0] instanceof Array) && args[0].length === 0) {
		throw new Error("Nested arrays cannot be used as sql parameter.");
	}

	return new Sql(this.opts, this._parts.concat([[sql, args || []]]));
};

Sql.prototype.wrap = function wrap(prefix, txt, suffix, args) {
	return this.append(prefix || '').append(txt, args).append(suffix || '');
};

Sql.prototype.select = function select(args) { return this.append('SELECT ' + slice.call(arguments).join(',')); };
Sql.prototype.from = function from(args) { return this.append('FROM ' + slice.call(arguments).join(',')); };
Sql.prototype.where = function where(txt, args) { return this.wrap('WHERE (', txt, ')', args); };
Sql.prototype.or = function or(txt, args) { return this.wrap('OR (', txt, ')', args); };
Sql.prototype.and = function and(txt, args) { return this.wrap('AND (', txt, ')', args); };
Sql.prototype.orderBy = function orderBy(args) { return this.append('ORDER BY ' + slice.call(arguments).join(',')); };
Sql.prototype.groupBy = function groupBy(args) { return this.append('GROUP BY ' + slice.call(arguments).join(',')); };

Sql.prototype.toQuery = function toQuery() {
	var variable = this.opts.variablePrefix || '$';
	if (this._built !== undefined) return this._built;
	var sqlList = [], argList = [], argCount = 0;
	var outputArguments = new Map();
	for(var i=0; i<this._parts.length; ++i) {
		var txt = this._parts[i][0];
		var args = this._parts[i][1];
		txt = txt.replace(new RegExp('(?!\\\\)\\' + (variable) + '(\\d+)', 'g'), function (m, idx) {
			var argumentValue = args[Number(idx) - 1];
			var savedIndex = outputArguments.get(argumentValue);
			if (savedIndex === undefined) {
				argCount += 1;
				savedIndex = argCount;
				argList.push(argumentValue);
				outputArguments.set(argumentValue, savedIndex);
			}
			return variable + savedIndex;
		});
		sqlList.push(txt);
	}
	this._built = { text: sqlList.join(' '), parameters: argList };
	return this._built;
};

{'fraction_non_alphanumeric': 0.20070285044904335, 'fraction_numerical': 0.003514252245216712, 'mean_word_length': 4.415433403805497, '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': '5570851', 'n_tokens_mistral': 1735, 'n_tokens_neox': 1657, 'n_words': 405}