<commit_before>﻿DataExplorer.QueryEditor = (function () {
    var editor, field, activeError, params = {}, query,
        options = {
            'mode': 'text/x-t-sql'
        };

    function exists() {
        return !!editor || !!query;
    }

    function create(target, callback) {
        if (typeof target === 'string') {
            target = $(target);
        }

        if (!target.length) {
            return;
        }

        field = target;
        target = target[0];

        if (target.nodeName === 'TEXTAREA') {
            editor = CodeMirror.fromTextArea(target, $.extend({}, options, {
                'lineNumbers': true,
                'onChange': onChange
            }));
        } else {
            query = target[_textContent];
            editor = CodeMirror.runMode(query, options.mode, target);
        }

        if (callback && typeof callback === 'function') {
            callback(editor);
        }
    }

    function dispatch(event, value) {
        if (events[event]) {
            event = events[event];

            for (var i = 0; i < event.length; ++i) {
                event[i](value);
            }
        }
    }

    function getValue() {
        if (!exists()) {
            return null;
        }

        if (query) {
            return query;
        }   

        var value = editor.getValue();

        // Strip zero-width that randomly appears when copying text from the current
        // Data Explorer query editor into this one, at least until I can figure out
        // where it's coming from.
        if (value.charCodeAt(value.length - 1) === 8203) {
            value = value.substring(0, value.length - 1);

            // Explicitly update the field when this happens
            field.val(value);
        }

        return value;
    }

    function registerHandler(event, callback) {
        if (events[event] && typeof callback === 'function') {
            events[event].push(callback);
        }
    }

    function onChange() {
        if (activeError !== null) {
            editor.setLineClass(activeError, null);

            activeError = null;
        }
    }

    function onError(line) {
        if (!DataExplorer.options.enableAdvancedSqlErrors || !editor) {
            return;
        }

        activeError = +line;

        editor.setLineClass(activeError, 'error-line');
    }

    function parseParameters(sql) {
        // Until we fix this to handle the non-editor view too...
        var value = sql || getValue(),
            pattern = /##([a-zA-Z][A-Za-z0-9]*)(?::([^A-Za-z]+))?(?:\?([^#]+))?##/,
            commented = 0, stringified = false,
            params = { 'items': {}, 'count': 0 };

        if (!value || !value.length) {
            return;
        }

        value = value.split("\n");

        try {
            for (var i = 0; i < value.length; ++i) {
                parseLine(value[i]);
            }
        } catch (ex) {}

        return params;

        function parseLine(line, depth) {
            var line = line.trim(), param,
                endComment, endString,
                startComment, startString,
                substitutes = [];

            if (!line) {
                return;
            }

            if (typeof depth === 'undefined') {
                depth = 0;
            } else if (depth === 10) {
                throw new Error("The query body is too incomprehensible to continue "
                    + "parsing, or logic has failed us");
            } else {
                ++depth;
            }

            if (commented) {
                if ((endComment = line.indexOf('*/')) !== -1) {
                    commented += line.substring(0, endComment).split('/*').length - 1;
                    line = line.substring(endComment + '*/'.length);

                    if (--commented) {
                        return parseLine(line, depth);
                    }
                }
            } else if (stringified) {
                if ((endString = line.indexOf("'")) === -1) {
                    return scan(line);
                }

                scan(line.substring(0, endString));
                line = line.substring(endString + 1);

                if (line[0] === "'") {
                    return parseLine(line.substring(1), depth);
                }

                stringified = false;
            }

            line = line.replace("''", '');
            line = line.replace(/'[^']+'/, function (match) {
                substitutes.push(match);

                return '~S' + (substitutes.length - 1);
            });
            line = line.split('--');
            startString = line[0].indexOf("'");
            startComment = line[0].indexOf('/*');

            if (startString !== -1 || startComment !== -1) {
                line = line.join('--');

                if ((startString < startComment && startString !== -1) ||
                        startComment === -1) {
                    stringified = true;
                } else {
                    ++commented;
                    parseLine(line.substring(startComment + '/*'.length), depth);
                    line = line.substring(0, startComment);
                }
            } else if (commented) {
                return;
            } else {
                line = line[0];
            }

            for (var i = 0; i < substitutes.length; ++i) {
                line = line.replace('~S' + i, substitutes[i]);
            }

            scan(line);
        }

        function scan(segment) {
            while (param = segment.match(pattern)) {
                params.items[param[1]] = params.items[param[1]] || {};

                if (typeof params.items[param[1]].index === 'undefined') {
                    params.items[param[1]].index = params.count;
                    ++params.count;
                }

                params.items[param[1]].type = param[2] || params.items[param[1]].type;
                params.items[param[1]].auto = param[3] || params.items[param[1]].auto;

                segment = segment.substring(param.index + param[0].length);
            }
        }
    }

    return {
        'create': create,
        'value': getValue,
        'change': registerHandler,
        'error': onError,
        'exists': exists,
        'parse': parseParameters
    };
})();

DataExplorer.ready(function () {
    var schema = $('#schema'),
        history = $('#history'),
        panel = $('#editor-panel'),
        metadata = $('#query-metadata .info'),
        gridOptions = {
            'enableCellNavigation': false,
            'enableColumnReorder': false,
            'enableCellRangeSelection': false
        },
        error = $('#error-message'),
        form = $('#runQueryForm');

    DataExplorer.QueryEditor.create('#queryBodyText');
    DataExplorer.QueryEditor.create('#sql', function (editor) {
        var wrapper, resizer, border = 2,
            toggle = $('#schema-toggle'),
            schemaPreference = null;

        if (DataExplorer.options.User.isAuthenticated) {
            schemaPreference = new DataExplorer.DeferredRequest({
                'url': '/users/save-preference/:id/HideSchema'.format({
                    'id': DataExplorer.options.User.id
                })
            });
        }

        if (editor) {
            wrapper = $(editor.getScrollerElement());
        }

        function resize (available) {
            var remaining = available - history.outerHeight(true);

            schema.height(remaining);

            if (wrapper) {
                wrapper.height(available);
                editor.refresh();
            }
        }

        resizer = $('#editor').TextAreaResizer(resize, { 
            'useParentWidth': true,
            'resizeWrapper': true,
            'minHeight': 300,
            'initCallback': true
        });
        resize();
        
        schema.addClass('cm-s-' + editor.getOption('theme') + '');
        schema.delegate('.schema-table', 'click', function () {
            var self = $(this);

            self.toggleClass('closed');
            self.next('dl').toggle();
        });

        function showSchema() {
            panel.animate({ 'width': '70%' }, 'fast', function () {
                schema.show();
                history.show();
            });
            toggle.text("hide sidebar").removeClass('hidden');

            if (schemaPreference) {
                schemaPreference.request({ 'value': false });
            }
        }

        function hideSchema(immediately) {
            schema.hide();
            history.hide();
            
            if (immediately !== true) {
                panel.animate({ 'width': '100%' }, 'fast');
            } else {
                panel.css('width', '100%');
            }

            toggle.text("show sidebar").addClass('hidden');

            if (schemaPreference) {
                schemaPreference.request({ 'value': true });
            }
        }

        if (DataExplorer.options.User.hideSchema) {
            hideSchema(true);
        }

        toggle.click(function () {
            var self = $(this);

            if (self.hasClass('hidden')) {
                showSchema();
            } else {<commit_msg>Fixed schema toggle link behaviour<commit_after>﻿DataExplorer.QueryEditor = (function () {
    var editor, field, activeError, params = {}, query,
        options = {
            'mode': 'text/x-t-sql'
        };

    function exists() {
        return !!editor || !!query;
    }

    function create(target, callback) {
        if (typeof target === 'string') {
            target = $(target);
        }

        if (!target.length) {
            return;
        }

        field = target;
        target = target[0];

        if (target.nodeName === 'TEXTAREA') {
            editor = CodeMirror.fromTextArea(target, $.extend({}, options, {
                'lineNumbers': true,
                'onChange': onChange
            }));
        } else {
            query = target[_textContent];
            editor = CodeMirror.runMode(query, options.mode, target);
        }

        if (callback && typeof callback === 'function') {
            callback(editor);
        }
    }

    function dispatch(event, value) {
        if (events[event]) {
            event = events[event];

            for (var i = 0; i < event.length; ++i) {
                event[i](value);
            }
        }
    }

    function getValue() {
        if (!exists()) {
            return null;
        }

        if (query) {
            return query;
        }   

        var value = editor.getValue();

        // Strip zero-width that randomly appears when copying text from the current
        // Data Explorer query editor into this one, at least until I can figure out
        // where it's coming from.
        if (value.charCodeAt(value.length - 1) === 8203) {
            value = value.substring(0, value.length - 1);

            // Explicitly update the field when this happens
            field.val(value);
        }

        return value;
    }

    function registerHandler(event, callback) {
        if (events[event] && typeof callback === 'function') {
            events[event].push(callback);
        }
    }

    function onChange() {
        if (activeError !== null) {
            editor.setLineClass(activeError, null);

            activeError = null;
        }
    }

    function onError(line) {
        if (!DataExplorer.options.enableAdvancedSqlErrors || !editor) {
            return;
        }

        activeError = +line;

        editor.setLineClass(activeError, 'error-line');
    }

    function parseParameters(sql) {
        // Until we fix this to handle the non-editor view too...
        var value = sql || getValue(),
            pattern = /##([a-zA-Z][A-Za-z0-9]*)(?::([^A-Za-z]+))?(?:\?([^#]+))?##/,
            commented = 0, stringified = false,
            params = { 'items': {}, 'count': 0 };

        if (!value || !value.length) {
            return;
        }

        value = value.split("\n");

        try {
            for (var i = 0; i < value.length; ++i) {
                parseLine(value[i]);
            }
        } catch (ex) {}

        return params;

        function parseLine(line, depth) {
            var line = line.trim(), param,
                endComment, endString,
                startComment, startString,
                substitutes = [];

            if (!line) {
                return;
            }

            if (typeof depth === 'undefined') {
                depth = 0;
            } else if (depth === 10) {
                throw new Error("The query body is too incomprehensible to continue "
                    + "parsing, or logic has failed us");
            } else {
                ++depth;
            }

            if (commented) {
                if ((endComment = line.indexOf('*/')) !== -1) {
                    commented += line.substring(0, endComment).split('/*').length - 1;
                    line = line.substring(endComment + '*/'.length);

                    if (--commented) {
                        return parseLine(line, depth);
                    }
                }
            } else if (stringified) {
                if ((endString = line.indexOf("'")) === -1) {
                    return scan(line);
                }

                scan(line.substring(0, endString));
                line = line.substring(endString + 1);

                if (line[0] === "'") {
                    return parseLine(line.substring(1), depth);
                }

                stringified = false;
            }

            line = line.replace("''", '');
            line = line.replace(/'[^']+'/, function (match) {
                substitutes.push(match);

                return '~S' + (substitutes.length - 1);
            });
            line = line.split('--');
            startString = line[0].indexOf("'");
            startComment = line[0].indexOf('/*');

            if (startString !== -1 || startComment !== -1) {
                line = line.join('--');

                if ((startString < startComment && startString !== -1) ||
                        startComment === -1) {
                    stringified = true;
                } else {
                    ++commented;
                    parseLine(line.substring(startComment + '/*'.length), depth);
                    line = line.substring(0, startComment);
                }
            } else if (commented) {
                return;
            } else {
                line = line[0];
            }

            for (var i = 0; i < substitutes.length; ++i) {
                line = line.replace('~S' + i, substitutes[i]);
            }

            scan(line);
        }

        function scan(segment) {
            while (param = segment.match(pattern)) {
                params.items[param[1]] = params.items[param[1]] || {};

                if (typeof params.items[param[1]].index === 'undefined') {
                    params.items[param[1]].index = params.count;
                    ++params.count;
                }

                params.items[param[1]].type = param[2] || params.items[param[1]].type;
                params.items[param[1]].auto = param[3] || params.items[param[1]].auto;

                segment = segment.substring(param.index + param[0].length);
            }
        }
    }

    return {
        'create': create,
        'value': getValue,
        'change': registerHandler,
        'error': onError,
        'exists': exists,
        'parse': parseParameters
    };
})();

DataExplorer.ready(function () {
    var schema = $('#schema'),
        history = $('#history'),
        panel = $('#editor-panel'),
        metadata = $('#query-metadata .info'),
        gridOptions = {
            'enableCellNavigation': false,
            'enableColumnReorder': false,
            'enableCellRangeSelection': false
        },
        error = $('#error-message'),
        form = $('#runQueryForm');

    DataExplorer.QueryEditor.create('#queryBodyText');
    DataExplorer.QueryEditor.create('#sql', function (editor) {
        var wrapper, resizer, border = 2,
            toggle = $('#schema-toggle'),
            toolbar = $('#editor-toolbar'),
            schemaPreference = null;

        if (DataExplorer.options.User.isAuthenticated) {
            schemaPreference = new DataExplorer.DeferredRequest({
                'url': '/users/save-preference/:id/HideSchema'.format({
                    'id': DataExplorer.options.User.id
                })
            });
        }

        if (editor) {
            wrapper = $(editor.getScrollerElement());
        }

        function resize (available) {
            var remaining = available - history.outerHeight(true);

            schema.height(remaining);

            if (wrapper) {
                wrapper.height(available);
                editor.refresh();
            }
        }

        resizer = $('#editor').TextAreaResizer(resize, { 
            'useParentWidth': true,
            'resizeWrapper': true,
            'minHeight': 300,
            'initCallback': true
        });
        resize();
        
        schema.addClass('cm-s-' + editor.getOption('theme') + '');
        schema.delegate('.schema-table', 'click', function () {
            var self = $(this);

            self.toggleClass('closed');
            self.next('dl').toggle();
        });

        function showSchema() {
            panel.add(toolbar).animate({ 'width': '70%' }, 'fast', function () {
                schema.show();
                history.show();
            });
            toggle.text("hide sidebar").removeClass('hidden');

            if (schemaPreference) {
                schemaPreference.request({ 'value': false });
            }
        }

        function hideSchema(immediately) {
            schema.hide();
            history.hide();
            
            if (immediately !== true) {
                panel.add(toolbar).animate({ 'width': '100%' }, 'fast');
            } else {
                panel.add(toolbar).css('width', '100%');
            }

            toggle.text("show sidebar").addClass('hidden');

            if (schemaPreference) {
                schemaPreference.request({ 'value': true });
            }
        }

        if (DataExplorer.options.User.hideSchema) {
            hideSchema(true);
        }

        toggle.click(function () {
            var self = $(this);

            if (self.hasClass('hidden')) {
                showSchema();
            } else {
{'fraction_non_alphanumeric': 0.14316423043852106, 'fraction_numerical': 0.006233877901977644, 'mean_word_length': 1.388831835686778, 'pattern_counts': {'":': 0, '<': 11, '<?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': '5208938', 'n_tokens_mistral': 5057, 'n_tokens_neox': 4703, 'n_words': 1028}