<commit_before>
openerp.web.data = function(instance) {

/**
 * Serializes the sort criterion array of a dataset into a form which can be
 * consumed by OpenERP's RPC APIs.
 *
 * @param {Array} criterion array of fields, from first to last criteria, prefixed with '-' for reverse sorting
 * @returns {String} SQL-like sorting string (``ORDER BY``) clause
 */
instance.web.serialize_sort = function (criterion) {
    return _.map(criterion,
        function (criteria) {
            if (criteria[0] === '-') {
                return criteria.slice(1) + ' DESC';
            }
            return criteria + ' ASC';
        }).join(', ');
};

instance.web.Query = instance.web.Class.extend({
    init: function (model, fields) {
        this._model = model;
        this._fields = fields;
        this._filter = [];
        this._context = {};
        this._limit = false;
        this._offset = 0;
        this._order_by = [];
    },
    clone: function (to_set) {
        to_set = to_set || {};
        var q = new instance.web.Query(this._model, this._fields);
        q._context = this._context;
        q._filter = this._filter;
        q._limit = this._limit;
        q._offset = this._offset;
        q._order_by = this._order_by;

        for(var key in to_set) {
            if (!to_set.hasOwnProperty(key)) { continue; }
            switch(key) {
            case 'filter':
                q._filter = new instance.web.CompoundDomain(
                        q._filter, to_set.filter);
                break;
            case 'context':
                q._context = new instance.web.CompoundContext(
                        q._context, to_set.context);
                break;
            case 'limit':
            case 'offset':
            case 'order_by':
                q['_' + key] = to_set[key];
            }
        }
        return q;
    },
    _execute: function () {
        var self = this;
        return instance.session.rpc('/web/dataset/search_read', {
            model: this._model.name,
            fields: this._fields || false,
            domain: this._model.domain(this._filter),
            context: this._model.context(this._context),
            offset: this._offset,
            limit: this._limit,
            sort: instance.web.serialize_sort(this._order_by)
        }).pipe(function (results) {
            self._count = results.length;
            return results.records;
        }, null);
    },
    /**
     * Fetches the first record matching the query, or null
     *
     * @returns {jQuery.Deferred<Object|null>}
     */
    first: function () {
        var self = this;
        return this.clone({limit: 1})._execute().pipe(function (records) {
            delete self._count;
            if (records.length) { return records[0]; }
            return null;
        });
    },
    /**
     * Fetches all records matching the query
     *
     * @returns {jQuery.Deferred<Array<>>}
     */
    all: function () {
        return this._execute();
    },
    /**
     * Fetches the number of records matching the query in the database
     *
     * @returns {jQuery.Deferred<Number>}
     */
    count: function () {
        if (this._count != undefined) { return $.when(this._count); }
        return this._model.call(
            'search_count', [this._filter], {
                context: this._model.context(this._context)});
    },
    /**
     * Performs a groups read according to the provided grouping criterion
     *
     * @param {String|Array<String>} grouping
     * @returns {jQuery.Deferred<Array<openerp.web.QueryGroup>> | null}
     */
    group_by: function (grouping) {
        if (grouping === undefined) {
            return null;
        }

        if (!(grouping instanceof Array)) {
            grouping = _.toArray(arguments);
        }
        if (_.isEmpty(grouping)) { return null; }

        var self = this;

        // FIXME: when pyeval is merged
        var ctx = instance.session.test_eval_contexts(
                [this._model.context(this._context)]);
        return this._model.call('read_group', {
            groupby: grouping,
            fields: _.uniq(grouping.concat(this._fields || [])),
            domain: this._model.domain(this._filter),
            context: this._model.context(this._context),
            offset: this._offset,
            limit: this._limit,
            orderby: instance.web.serialize_sort(this._order_by) || false
        }).pipe(function (results) {
            return _(results).map(function (result) {
                // FIX: querygroup initialization
                _.defaults(result.__context, ctx);
                return new instance.web.QueryGroup(
                    self._model.name, grouping[0], result);
            });
        });
    },
    /**
     * Creates a new query with the union of the current query's context and
     * the new context.
     *
     * @param context context data to add to the query
     * @returns {openerp.web.Query}
     */
    context: function (context) {
        if (!context) { return this; }
        return this.clone({context: context});
    },
    /**
     * Creates a new query with the union of the current query's filter and
     * the new domain.
     *
     * @param domain domain data to AND with the current query filter<commit_msg>[FIX] problem in read_group, caused an exception "cannot read 'lang' in undefined" in a lot of views<commit_after>
openerp.web.data = function(instance) {

/**
 * Serializes the sort criterion array of a dataset into a form which can be
 * consumed by OpenERP's RPC APIs.
 *
 * @param {Array} criterion array of fields, from first to last criteria, prefixed with '-' for reverse sorting
 * @returns {String} SQL-like sorting string (``ORDER BY``) clause
 */
instance.web.serialize_sort = function (criterion) {
    return _.map(criterion,
        function (criteria) {
            if (criteria[0] === '-') {
                return criteria.slice(1) + ' DESC';
            }
            return criteria + ' ASC';
        }).join(', ');
};

instance.web.Query = instance.web.Class.extend({
    init: function (model, fields) {
        this._model = model;
        this._fields = fields;
        this._filter = [];
        this._context = {};
        this._limit = false;
        this._offset = 0;
        this._order_by = [];
    },
    clone: function (to_set) {
        to_set = to_set || {};
        var q = new instance.web.Query(this._model, this._fields);
        q._context = this._context;
        q._filter = this._filter;
        q._limit = this._limit;
        q._offset = this._offset;
        q._order_by = this._order_by;

        for(var key in to_set) {
            if (!to_set.hasOwnProperty(key)) { continue; }
            switch(key) {
            case 'filter':
                q._filter = new instance.web.CompoundDomain(
                        q._filter, to_set.filter);
                break;
            case 'context':
                q._context = new instance.web.CompoundContext(
                        q._context, to_set.context);
                break;
            case 'limit':
            case 'offset':
            case 'order_by':
                q['_' + key] = to_set[key];
            }
        }
        return q;
    },
    _execute: function () {
        var self = this;
        return instance.session.rpc('/web/dataset/search_read', {
            model: this._model.name,
            fields: this._fields || false,
            domain: this._model.domain(this._filter),
            context: this._model.context(this._context),
            offset: this._offset,
            limit: this._limit,
            sort: instance.web.serialize_sort(this._order_by)
        }).pipe(function (results) {
            self._count = results.length;
            return results.records;
        }, null);
    },
    /**
     * Fetches the first record matching the query, or null
     *
     * @returns {jQuery.Deferred<Object|null>}
     */
    first: function () {
        var self = this;
        return this.clone({limit: 1})._execute().pipe(function (records) {
            delete self._count;
            if (records.length) { return records[0]; }
            return null;
        });
    },
    /**
     * Fetches all records matching the query
     *
     * @returns {jQuery.Deferred<Array<>>}
     */
    all: function () {
        return this._execute();
    },
    /**
     * Fetches the number of records matching the query in the database
     *
     * @returns {jQuery.Deferred<Number>}
     */
    count: function () {
        if (this._count != undefined) { return $.when(this._count); }
        return this._model.call(
            'search_count', [this._filter], {
                context: this._model.context(this._context)});
    },
    /**
     * Performs a groups read according to the provided grouping criterion
     *
     * @param {String|Array<String>} grouping
     * @returns {jQuery.Deferred<Array<openerp.web.QueryGroup>> | null}
     */
    group_by: function (grouping) {
        if (grouping === undefined) {
            return null;
        }

        if (!(grouping instanceof Array)) {
            grouping = _.toArray(arguments);
        }
        if (_.isEmpty(grouping)) { return null; }

        var self = this;

        // FIXME: when pyeval is merged
        var ctx = instance.session.test_eval_contexts(
                [this._model.context(this._context)]);
        return this._model.call('read_group', {
            groupby: grouping,
            fields: _.uniq(grouping.concat(this._fields || [])),
            domain: this._model.domain(this._filter),
            context: this._model.context(this._context),
            offset: this._offset,
            limit: this._limit,
            orderby: instance.web.serialize_sort(this._order_by) || false
        }).pipe(function (results) {
            return _(results).map(function (result) {
                // FIX: querygroup initialization
                result.__context = result.__context || {};
                result.__context.group_by = result.__context.group_by || [];
                _.defaults(result.__context, ctx);
                return new instance.web.QueryGroup(
                    self._model.name, grouping[0], result);
            });
        });
    },
    /**
     * Creates a new query with the union of the current query's context and
     * the new context.
     *
     * @param context context data to add to the query
     * @returns {openerp.web.Query}
     */
    context: function (context) {
        if (!context) { return this; }
        return this.clone({context: context});
    },
    /**
     * Creates a new query with the union of the current query's filter and
     * the new domain.
     *
     * @param domain domain data to AND with the current query filter
{'fraction_non_alphanumeric': 0.122054883119283, 'fraction_numerical': 0.0011087498845052204, 'mean_word_length': 1.8019673828630598, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 17, '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': '4800966', 'n_tokens_mistral': 3011, 'n_tokens_neox': 2936, 'n_words': 764}