update js
This commit is contained in:
		
							
								
								
									
										3382
									
								
								lib/core/parse/generic/genericAutocompleteParser.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3382
									
								
								lib/core/parse/generic/genericAutocompleteParser.js
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										3347
									
								
								lib/core/parse/generic/genericSyntaxParser.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3347
									
								
								lib/core/parse/generic/genericSyntaxParser.js
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										1983
									
								
								lib/core/parse/generic/sqlParseSupport.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1983
									
								
								lib/core/parse/generic/sqlParseSupport.js
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										5705
									
								
								lib/core/parse/hive/hiveAutocompleteParser.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5705
									
								
								lib/core/parse/hive/hiveAutocompleteParser.js
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										5644
									
								
								lib/core/parse/hive/hiveSyntaxParser.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5644
									
								
								lib/core/parse/hive/hiveSyntaxParser.js
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										2208
									
								
								lib/core/parse/hive/sqlParseSupport.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2208
									
								
								lib/core/parse/hive/sqlParseSupport.js
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										5407
									
								
								lib/core/parse/impala/impalaAutocompleteParser.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5407
									
								
								lib/core/parse/impala/impalaAutocompleteParser.js
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										5364
									
								
								lib/core/parse/impala/impalaSyntaxParser.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5364
									
								
								lib/core/parse/impala/impalaSyntaxParser.js
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										2289
									
								
								lib/core/parse/impala/sqlParseSupport.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2289
									
								
								lib/core/parse/impala/sqlParseSupport.js
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										4518
									
								
								lib/core/parse/sqlFunctions.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4518
									
								
								lib/core/parse/sqlFunctions.js
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										84
									
								
								lib/core/parse/sqlParserRepository.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								lib/core/parse/sqlParserRepository.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,84 @@
 | 
			
		||||
"use strict";
 | 
			
		||||
// Licensed to Cloudera, Inc. under one
 | 
			
		||||
// or more contributor license agreements.  See the NOTICE file
 | 
			
		||||
// distributed with this work for additional information
 | 
			
		||||
// regarding copyright ownership.  Cloudera, Inc. licenses this file
 | 
			
		||||
// to you under the Apache License, Version 2.0 (the
 | 
			
		||||
// "License"); you may not use this file except in compliance
 | 
			
		||||
// with the License.  You may obtain a copy of the License at
 | 
			
		||||
//
 | 
			
		||||
//     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
//
 | 
			
		||||
// Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
// distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
// See the License for the specific language governing permissions and
 | 
			
		||||
// limitations under the License.
 | 
			
		||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
 | 
			
		||||
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
 | 
			
		||||
    return new (P || (P = Promise))(function (resolve, reject) {
 | 
			
		||||
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
 | 
			
		||||
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
 | 
			
		||||
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
 | 
			
		||||
        step((generator = generator.apply(thisArg, _arguments || [])).next());
 | 
			
		||||
    });
 | 
			
		||||
};
 | 
			
		||||
Object.defineProperty(exports, "__esModule", { value: true });
 | 
			
		||||
/* eslint-disable */
 | 
			
		||||
/**
 | 
			
		||||
 * AUTOCOMPLETE_MODULES and SYNTAX_MODULES are generated, do not edit manually, see tools/jison/generateParsers.js
 | 
			
		||||
 */
 | 
			
		||||
const AUTOCOMPLETE_MODULES = {
 | 
			
		||||
    calcite: require("calcite/calciteAutocompleteParser"),
 | 
			
		||||
    druid: require("druid/druidAutocompleteParser"),
 | 
			
		||||
    elasticsearch: require("elasticsearch/elasticsearchAutocompleteParser"),
 | 
			
		||||
    flink: require("flink/flinkAutocompleteParser"),
 | 
			
		||||
    generic: require("generic/genericAutocompleteParser"),
 | 
			
		||||
    hive: require("hive/hiveAutocompleteParser"),
 | 
			
		||||
    impala: require("impala/impalaAutocompleteParser"),
 | 
			
		||||
    ksql: require("ksql/ksqlAutocompleteParser"),
 | 
			
		||||
    phoenix: require("phoenix/phoenixAutocompleteParser"),
 | 
			
		||||
    presto: require("presto/prestoAutocompleteParser")
 | 
			
		||||
};
 | 
			
		||||
const SYNTAX_MODULES = {
 | 
			
		||||
    calcite: require("calcite/calciteSyntaxParser"),
 | 
			
		||||
    druid: require("druid/druidSyntaxParser"),
 | 
			
		||||
    elasticsearch: require("elasticsearch/elasticsearchSyntaxParser"),
 | 
			
		||||
    flink: require("flink/flinkSyntaxParser"),
 | 
			
		||||
    generic: require("generic/genericSyntaxParser"),
 | 
			
		||||
    hive: require("hive/hiveSyntaxParser"),
 | 
			
		||||
    impala: require("impala/impalaSyntaxParser"),
 | 
			
		||||
    ksql: require("ksql/ksqlSyntaxParser"),
 | 
			
		||||
    phoenix: require("phoenix/phoenixSyntaxParser"),
 | 
			
		||||
    presto: require("presto/prestoSyntaxParser")
 | 
			
		||||
};
 | 
			
		||||
/* eslint-enable */
 | 
			
		||||
class SqlParserRepository {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        this.modulePromises = {};
 | 
			
		||||
    }
 | 
			
		||||
    getParser(sourceType, parserType) {
 | 
			
		||||
        return __awaiter(this, void 0, void 0, function* () {
 | 
			
		||||
            if (!this.modulePromises[sourceType + parserType]) {
 | 
			
		||||
                const modules = parserType === 'Autocomplete' ? AUTOCOMPLETE_MODULES : SYNTAX_MODULES;
 | 
			
		||||
                this.modulePromises[sourceType + parserType] = new Promise((resolve, reject) => {
 | 
			
		||||
                    const targetModule = modules[sourceType] || modules.generic;
 | 
			
		||||
                    resolve(targetModule);
 | 
			
		||||
                });
 | 
			
		||||
            }
 | 
			
		||||
            return this.modulePromises[sourceType + parserType];
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
    getAutocompleter(sourceType) {
 | 
			
		||||
        return __awaiter(this, void 0, void 0, function* () {
 | 
			
		||||
            return this.getParser(sourceType, 'Autocomplete');
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
    getSyntaxParser(sourceType) {
 | 
			
		||||
        return __awaiter(this, void 0, void 0, function* () {
 | 
			
		||||
            return this.getParser(sourceType, 'Syntax');
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
const sqlParserRepository = new SqlParserRepository();
 | 
			
		||||
exports.default = sqlParserRepository;
 | 
			
		||||
							
								
								
									
										75
									
								
								lib/core/parse/stringDistance.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								lib/core/parse/stringDistance.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,75 @@
 | 
			
		||||
"use strict";
 | 
			
		||||
// Licensed to Cloudera, Inc. under one
 | 
			
		||||
// or more contributor license agreements.  See the NOTICE file
 | 
			
		||||
// distributed with this work for additional information
 | 
			
		||||
// regarding copyright ownership.  Cloudera, Inc. licenses this file
 | 
			
		||||
// to you under the Apache License, Version 2.0 (the
 | 
			
		||||
// "License"); you may not use this file except in compliance
 | 
			
		||||
// with the License.  You may obtain a copy of the License at
 | 
			
		||||
//
 | 
			
		||||
//     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
//
 | 
			
		||||
// Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
// distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
// See the License for the specific language governing permissions and
 | 
			
		||||
// limitations under the License.
 | 
			
		||||
Object.defineProperty(exports, "__esModule", { value: true });
 | 
			
		||||
/**
 | 
			
		||||
 * Calculates the Optimal String Alignment distance between two strings. Returns 0 when the strings are equal and the
 | 
			
		||||
 * distance when not, distances is less than or equal to the length of the longest string.
 | 
			
		||||
 *
 | 
			
		||||
 * @param strA
 | 
			
		||||
 * @param strB
 | 
			
		||||
 * @param [ignoreCase]
 | 
			
		||||
 * @returns {number} The similarity
 | 
			
		||||
 */
 | 
			
		||||
const stringDistance = function (strA, strB, ignoreCase) {
 | 
			
		||||
    if (ignoreCase) {
 | 
			
		||||
        strA = strA.toLowerCase();
 | 
			
		||||
        strB = strB.toLowerCase();
 | 
			
		||||
    }
 | 
			
		||||
    // TODO: Consider other algorithms for performance
 | 
			
		||||
    const strALength = strA.length;
 | 
			
		||||
    const strBLength = strB.length;
 | 
			
		||||
    if (strALength === 0) {
 | 
			
		||||
        return strBLength;
 | 
			
		||||
    }
 | 
			
		||||
    if (strBLength === 0) {
 | 
			
		||||
        return strALength;
 | 
			
		||||
    }
 | 
			
		||||
    const distances = new Array(strALength);
 | 
			
		||||
    let cost, deletion, insertion, substitution, transposition;
 | 
			
		||||
    for (let i = 0; i <= strALength; i++) {
 | 
			
		||||
        distances[i] = new Array(strBLength);
 | 
			
		||||
        distances[i][0] = i;
 | 
			
		||||
        for (let j = 1; j <= strBLength; j++) {
 | 
			
		||||
            if (!i) {
 | 
			
		||||
                distances[0][j] = j;
 | 
			
		||||
            }
 | 
			
		||||
            else {
 | 
			
		||||
                cost = strA[i - 1] === strB[j - 1] ? 0 : 1;
 | 
			
		||||
                deletion = distances[i - 1][j] + 1;
 | 
			
		||||
                insertion = distances[i][j - 1] + 1;
 | 
			
		||||
                substitution = distances[i - 1][j - 1] + cost;
 | 
			
		||||
                if (deletion <= insertion && deletion <= substitution) {
 | 
			
		||||
                    distances[i][j] = deletion;
 | 
			
		||||
                }
 | 
			
		||||
                else if (insertion <= deletion && insertion <= substitution) {
 | 
			
		||||
                    distances[i][j] = insertion;
 | 
			
		||||
                }
 | 
			
		||||
                else {
 | 
			
		||||
                    distances[i][j] = substitution;
 | 
			
		||||
                }
 | 
			
		||||
                if (i > 1 && j > 1 && strA[i] === strB[j - 1] && strA[i - 1] === strB[j]) {
 | 
			
		||||
                    transposition = distances[i - 2][j - 2] + cost;
 | 
			
		||||
                    if (transposition < distances[i][j]) {
 | 
			
		||||
                        distances[i][j] = transposition;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return distances[strALength][strBLength];
 | 
			
		||||
};
 | 
			
		||||
exports.default = stringDistance;
 | 
			
		||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							@ -1,8 +1,44 @@
 | 
			
		||||
"use strict";
 | 
			
		||||
Object.defineProperty(exports, "__esModule", { value: true });
 | 
			
		||||
// import * as sqlSyntaxParser from '../core/sqlSyntaxParser';
 | 
			
		||||
const sqlSyntaxParser = require("../core/sqlSyntaxParser");
 | 
			
		||||
const sqlAutoCompleteParser = require("../core/sqlAutoCompleteParser");
 | 
			
		||||
const hiveSyntaxParser_1 = require("../core/parse/hive/hiveSyntaxParser");
 | 
			
		||||
const hiveAutocompleteParser_1 = require("../core/parse/hive/hiveAutocompleteParser");
 | 
			
		||||
const impalaSyntaxParser_1 = require("../core/parse/impala/impalaSyntaxParser");
 | 
			
		||||
const impalaAutocompleteParser_1 = require("../core/parse/impala/impalaAutocompleteParser");
 | 
			
		||||
const genericSyntaxParser_1 = require("../core/parse/generic/genericSyntaxParser");
 | 
			
		||||
const genericAutocompleteParser_1 = require("../core/parse/generic/genericAutocompleteParser");
 | 
			
		||||
function getSyntaxParser(type) {
 | 
			
		||||
    switch (type) {
 | 
			
		||||
        case sqlType.Hive: {
 | 
			
		||||
            return hiveSyntaxParser_1.default;
 | 
			
		||||
        }
 | 
			
		||||
        case sqlType.Impala: {
 | 
			
		||||
            return impalaSyntaxParser_1.default;
 | 
			
		||||
        }
 | 
			
		||||
        case sqlType.None: {
 | 
			
		||||
            return genericSyntaxParser_1.default;
 | 
			
		||||
        }
 | 
			
		||||
        default: {
 | 
			
		||||
            return hiveSyntaxParser_1.default;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
function getAutoCompleteParser(type) {
 | 
			
		||||
    switch (type) {
 | 
			
		||||
        case sqlType.Hive: {
 | 
			
		||||
            return hiveAutocompleteParser_1.default;
 | 
			
		||||
        }
 | 
			
		||||
        case sqlType.Impala: {
 | 
			
		||||
            return impalaAutocompleteParser_1.default;
 | 
			
		||||
        }
 | 
			
		||||
        case sqlType.None: {
 | 
			
		||||
            return genericAutocompleteParser_1.default;
 | 
			
		||||
        }
 | 
			
		||||
        default: {
 | 
			
		||||
            return hiveAutocompleteParser_1.default;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
var sqlType;
 | 
			
		||||
(function (sqlType) {
 | 
			
		||||
    sqlType["Hive"] = "hive";
 | 
			
		||||
@ -26,7 +62,8 @@ function sqlToParserArgs(sql) {
 | 
			
		||||
 */
 | 
			
		||||
function parseSyntax(sql, type = sqlType.Hive) {
 | 
			
		||||
    const parserArgs = sqlToParserArgs(sql);
 | 
			
		||||
    return sqlSyntaxParser.parser.parseSyntax(parserArgs[0], parserArgs[1], type, false);
 | 
			
		||||
    console.log(getSyntaxParser(type));
 | 
			
		||||
    return getSyntaxParser(type).parseSyntax(parserArgs[0], parserArgs[1], type, false);
 | 
			
		||||
}
 | 
			
		||||
exports.parseSyntax = parseSyntax;
 | 
			
		||||
/**
 | 
			
		||||
@ -34,6 +71,6 @@ exports.parseSyntax = parseSyntax;
 | 
			
		||||
 */
 | 
			
		||||
function parserSql(sql, type = sqlType.Hive) {
 | 
			
		||||
    const parserArgs = sqlToParserArgs(sql);
 | 
			
		||||
    return sqlAutoCompleteParser.parser.parseSql(parserArgs[0], parserArgs[1], type, false);
 | 
			
		||||
    return getAutoCompleteParser(type).parseSql(parserArgs[0], parserArgs[1], type, false);
 | 
			
		||||
}
 | 
			
		||||
exports.parserSql = parserSql;
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										467
									
								
								lib/scripts/generateParsers.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										467
									
								
								lib/scripts/generateParsers.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,467 @@
 | 
			
		||||
const fs = require('fs');
 | 
			
		||||
const path = require('path');
 | 
			
		||||
const exec = require('child_process').exec;
 | 
			
		||||
const LICENSE = '// Licensed to Cloudera, Inc. under one\n' +
 | 
			
		||||
    '// or more contributor license agreements.  See the NOTICE file\n' +
 | 
			
		||||
    '// distributed with this work for additional information\n' +
 | 
			
		||||
    '// regarding copyright ownership.  Cloudera, Inc. licenses this file\n' +
 | 
			
		||||
    '// to you under the Apache License, Version 2.0 (the\n' +
 | 
			
		||||
    '// "License"); you may not use this file except in compliance\n' +
 | 
			
		||||
    '// with the License.  You may obtain a copy of the License at\n' +
 | 
			
		||||
    '//\n' +
 | 
			
		||||
    '//     http://www.apache.org/licenses/LICENSE-2.0\n' +
 | 
			
		||||
    '//\n' +
 | 
			
		||||
    '// Unless required by applicable law or agreed to in writing, software\n' +
 | 
			
		||||
    '// distributed under the License is distributed on an "AS IS" BASIS,\n' +
 | 
			
		||||
    '// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n' +
 | 
			
		||||
    '// See the License for the specific language governing permissions and\n' +
 | 
			
		||||
    '// limitations under the License.\n';
 | 
			
		||||
const SQL_STATEMENTS_PARSER_JSDOC = '/**\n' +
 | 
			
		||||
    ' * @param {string} input\n' +
 | 
			
		||||
    ' *\n' +
 | 
			
		||||
    ' * @return {SqlStatementsParserResult}\n' +
 | 
			
		||||
    ' */\n';
 | 
			
		||||
const PARSER_FOLDER = path.join(process.cwd(), 'src/core/parse/');
 | 
			
		||||
const JISON_FOLDER = path.join(process.cwd(), 'src/jison/');
 | 
			
		||||
const SQL_PARSER_REPOSITORY_PATH = path.join(PARSER_FOLDER, 'sqlParserRepository.js');
 | 
			
		||||
const SYNTAX_PARSER_IMPORT_TEMPLATE = '  KEY: require("KEY/KEYSyntaxParser")';
 | 
			
		||||
const AUTOCOMPLETE_PARSER_IMPORT_TEMPLATE = '  KEY: require("KEY/KEYAutocompleteParser")';
 | 
			
		||||
const parserDefinitions = {
 | 
			
		||||
    globalSearchParser: {
 | 
			
		||||
        sources: [path.join(JISON_FOLDER, 'globalSearchParser.jison')],
 | 
			
		||||
        target: path.join(JISON_FOLDER, 'globalSearchParser.jison'),
 | 
			
		||||
        outputFolder: PARSER_FOLDER,
 | 
			
		||||
        afterParse: contents => new Promise(resolve => {
 | 
			
		||||
            resolve(LICENSE +
 | 
			
		||||
                contents.replace('var globalSearchParser = ', "import SqlParseSupport from './sqlParseSupport';\n\nvar globalSearchParser = ") +
 | 
			
		||||
                '\nexport default globalSearchParser;\n');
 | 
			
		||||
        })
 | 
			
		||||
    },
 | 
			
		||||
    solrFormulaParser: {
 | 
			
		||||
        sources: [path.join(JISON_FOLDER, 'solrFormulaParser.jison')],
 | 
			
		||||
        target: path.join(JISON_FOLDER, 'solrFormulaParser.jison'),
 | 
			
		||||
        outputFolder: PARSER_FOLDER,
 | 
			
		||||
        afterParse: contents => new Promise(resolve => {
 | 
			
		||||
            resolve(LICENSE + contents + 'export default solrFormulaParser;\n');
 | 
			
		||||
        })
 | 
			
		||||
    },
 | 
			
		||||
    solrQueryParser: {
 | 
			
		||||
        sources: [path.join(JISON_FOLDER, 'solrQueryParser.jison')],
 | 
			
		||||
        target: path.join(JISON_FOLDER, 'solrQueryParser.jison'),
 | 
			
		||||
        outputFolder: PARSER_FOLDER,
 | 
			
		||||
        afterParse: contents => new Promise(resolve => {
 | 
			
		||||
            resolve(LICENSE + contents + 'export default solrQueryParser;\n');
 | 
			
		||||
        })
 | 
			
		||||
    },
 | 
			
		||||
    sqlStatementsParser: {
 | 
			
		||||
        sources: [path.join(JISON_FOLDER, 'sqlStatementsParser.jison')],
 | 
			
		||||
        target: path.join(JISON_FOLDER, 'sqlStatementsParser.jison'),
 | 
			
		||||
        outputFolder: PARSER_FOLDER,
 | 
			
		||||
        afterParse: contents => new Promise(resolve => {
 | 
			
		||||
            resolve(LICENSE +
 | 
			
		||||
                contents.replace('parse: function parse', SQL_STATEMENTS_PARSER_JSDOC + 'parse: function parse') +
 | 
			
		||||
                'export default sqlStatementsParser;\n');
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
const mkdir = path => new Promise((resolve, reject) => {
 | 
			
		||||
    if (fs.existsSync(path)) {
 | 
			
		||||
        resolve();
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        fs.mkdir(path, err => {
 | 
			
		||||
            if (err) {
 | 
			
		||||
                reject(err);
 | 
			
		||||
            }
 | 
			
		||||
            resolve();
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
const readFile = path => new Promise((resolve, reject) => {
 | 
			
		||||
    fs.readFile(path, (err, buf) => {
 | 
			
		||||
        if (err) {
 | 
			
		||||
            reject(err);
 | 
			
		||||
        }
 | 
			
		||||
        resolve(buf ? buf.toString() : '');
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
const writeFile = (path, contents) => new Promise((resolve, reject) => {
 | 
			
		||||
    fs.writeFile(path, contents, err => {
 | 
			
		||||
        if (err) {
 | 
			
		||||
            reject();
 | 
			
		||||
        }
 | 
			
		||||
        resolve();
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
const copyFile = (source, destination, contentsCallback) => new Promise((resolve, reject) => {
 | 
			
		||||
    readFile(source)
 | 
			
		||||
        .then(contents => {
 | 
			
		||||
        writeFile(destination, contentsCallback ? contentsCallback(contents) : contents)
 | 
			
		||||
            .then(resolve)
 | 
			
		||||
            .catch(reject);
 | 
			
		||||
    })
 | 
			
		||||
        .catch(reject);
 | 
			
		||||
});
 | 
			
		||||
const deleteFile = path => {
 | 
			
		||||
    fs.unlinkSync(path);
 | 
			
		||||
};
 | 
			
		||||
const execCmd = cmd => new Promise((resolve, reject) => {
 | 
			
		||||
    exec(cmd, (err, stdout, stderr) => {
 | 
			
		||||
        if (err) {
 | 
			
		||||
            reject('stderr:\n' + stderr + '\n\nstdout:\n' + stdout);
 | 
			
		||||
        }
 | 
			
		||||
        resolve(stdout);
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
const generateParser = parserName => new Promise((resolve, reject) => {
 | 
			
		||||
    const parserConfig = parserDefinitions[parserName];
 | 
			
		||||
    /**
 | 
			
		||||
     * 合并jison文件,生成待编译文件
 | 
			
		||||
     */
 | 
			
		||||
    const concatPromise = new Promise((resolve, reject) => {
 | 
			
		||||
        if (parserConfig.sources.length > 1 && parserConfig.target) {
 | 
			
		||||
            console.log('Concatenating files...');
 | 
			
		||||
            const promises = parserConfig.sources.map(fileName => readFile(fileName));
 | 
			
		||||
            Promise.all(promises)
 | 
			
		||||
                .then(contents => {
 | 
			
		||||
                writeFile(parserConfig.target, contents.join('')).then(() => {
 | 
			
		||||
                    resolve(parserConfig.target);
 | 
			
		||||
                });
 | 
			
		||||
            })
 | 
			
		||||
                .catch(reject);
 | 
			
		||||
        }
 | 
			
		||||
        else if (parserConfig.sources.length === 1) {
 | 
			
		||||
            resolve(parserConfig.sources[0]);
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            reject('No jison source specified');
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
    concatPromise
 | 
			
		||||
        .then(targetPath => {
 | 
			
		||||
        console.log(`Generate precomplier jison success(${targetPath})...`);
 | 
			
		||||
        let jisonCommand = 'jison ' + targetPath;
 | 
			
		||||
        if (parserConfig.lexer) {
 | 
			
		||||
            jisonCommand += ' ' + parserConfig.lexer;
 | 
			
		||||
        }
 | 
			
		||||
        jisonCommand += ' -m js';
 | 
			
		||||
        console.log('Generating parser...');
 | 
			
		||||
        execCmd(jisonCommand)
 | 
			
		||||
            .then(stdout => {
 | 
			
		||||
            if (/\S/.test(stdout)) {
 | 
			
		||||
                console.log('got output for: ' + jisonCommand);
 | 
			
		||||
                console.log(stdout);
 | 
			
		||||
            }
 | 
			
		||||
            if (parserConfig.sources.length > 1) {
 | 
			
		||||
                deleteFile(targetPath); // Remove concatenated file
 | 
			
		||||
            }
 | 
			
		||||
            console.log('Adjusting JS...');
 | 
			
		||||
            /**
 | 
			
		||||
             * 删除生成文件,复制到配置的文件夹中
 | 
			
		||||
             */
 | 
			
		||||
            const generatedJsFileName = parserConfig.target
 | 
			
		||||
                .replace('.jison', '.js')
 | 
			
		||||
                .replace(/^.*\/([^/]+)$/, '$1');
 | 
			
		||||
            readFile(generatedJsFileName)
 | 
			
		||||
                .then(contents => {
 | 
			
		||||
                parserConfig
 | 
			
		||||
                    .afterParse(contents)
 | 
			
		||||
                    .then(finalContents => {
 | 
			
		||||
                    writeFile(path.join(parserConfig.outputFolder, generatedJsFileName), finalContents)
 | 
			
		||||
                        .then(() => {
 | 
			
		||||
                        deleteFile(generatedJsFileName);
 | 
			
		||||
                        resolve();
 | 
			
		||||
                    })
 | 
			
		||||
                        .catch(reject);
 | 
			
		||||
                })
 | 
			
		||||
                    .catch(reject);
 | 
			
		||||
            })
 | 
			
		||||
                .catch(reject);
 | 
			
		||||
        })
 | 
			
		||||
            .catch(reject);
 | 
			
		||||
    })
 | 
			
		||||
        .catch(reject);
 | 
			
		||||
});
 | 
			
		||||
let parsersToGenerate = [];
 | 
			
		||||
const invalid = [];
 | 
			
		||||
let all = false;
 | 
			
		||||
const listDir = folder => new Promise(resolve => {
 | 
			
		||||
    fs.readdir(folder, (err, files) => {
 | 
			
		||||
        resolve(files);
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
/**
 | 
			
		||||
 * 构造,添加子语言模块编译配置
 | 
			
		||||
 * @param {*} fileIndex 文件的存在表
 | 
			
		||||
 * @param {*} folder 对应的子语言文件夹
 | 
			
		||||
 * @param {*} sharedFiles 子语言核心jison文件
 | 
			
		||||
 * @param {*} autocomplete 是否为补全文件
 | 
			
		||||
 */
 | 
			
		||||
const findParser = (fileIndex, folder, sharedFiles, autocomplete) => {
 | 
			
		||||
    const prefix = autocomplete ? 'autocomplete' : 'syntax';
 | 
			
		||||
    if (fileIndex[prefix + '_header.jison'] && fileIndex[prefix + '_footer.jison']) {
 | 
			
		||||
        const parserName = folder + (autocomplete ? 'AutocompleteParser' : 'SyntaxParser');
 | 
			
		||||
        const parserDefinition = {
 | 
			
		||||
            sources: [path.join(JISON_FOLDER, 'sql', folder, prefix + '_header.jison')].concat(sharedFiles),
 | 
			
		||||
            lexer: path.join(JISON_FOLDER, 'sql', folder, '/sql.jisonlex'),
 | 
			
		||||
            target: path.join(JISON_FOLDER, 'sql', folder, parserName + '.jison'),
 | 
			
		||||
            sqlParser: autocomplete ? 'AUTOCOMPLETE' : 'SYNTAX',
 | 
			
		||||
            outputFolder: path.join(PARSER_FOLDER, folder),
 | 
			
		||||
            afterParse: contents => new Promise(resolve => {
 | 
			
		||||
                resolve(LICENSE +
 | 
			
		||||
                    contents
 | 
			
		||||
                        .replace('var ' + parserName + ' = ', "import SqlParseSupport from " +
 | 
			
		||||
                        "'./sqlParseSupport';\n\nvar " +
 | 
			
		||||
                        parserName +
 | 
			
		||||
                        ' = ')
 | 
			
		||||
                        .replace('loc: yyloc,', "loc: lexer.yylloc, ruleId: stack.slice(stack.length - 2, stack.length).join(''),") +
 | 
			
		||||
                    '\nexport default ' +
 | 
			
		||||
                    parserName +
 | 
			
		||||
                    ';\n');
 | 
			
		||||
            })
 | 
			
		||||
        };
 | 
			
		||||
        parserDefinition.sources.push(path.join(JISON_FOLDER, 'sql', folder, prefix + '_footer.jison'));
 | 
			
		||||
        parserDefinitions[parserName] = parserDefinition;
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        console.log("Warn: Could not find '" +
 | 
			
		||||
            prefix +
 | 
			
		||||
            "_header.jison' or '" +
 | 
			
		||||
            prefix +
 | 
			
		||||
            "_footer.jison' in " +
 | 
			
		||||
            JISON_FOLDER +
 | 
			
		||||
            'sql/' +
 | 
			
		||||
            folder +
 | 
			
		||||
            '/');
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
/**
 | 
			
		||||
 * 添加所有子语言编译配置
 | 
			
		||||
 */
 | 
			
		||||
const identifySqlParsers = () => new Promise(resolve => {
 | 
			
		||||
    listDir(JISON_FOLDER + 'sql').then(files => {
 | 
			
		||||
        const promises = [];
 | 
			
		||||
        files.forEach(folder => {
 | 
			
		||||
            const subLanguageJisonFolder = path.join(JISON_FOLDER, 'sql', folder);
 | 
			
		||||
            promises.push(
 | 
			
		||||
            /**
 | 
			
		||||
             * 遍历具体的语言目录
 | 
			
		||||
             */
 | 
			
		||||
            listDir(subLanguageJisonFolder).then(jisonFiles => {
 | 
			
		||||
                /**
 | 
			
		||||
                 * 文件目录记录表
 | 
			
		||||
                 */
 | 
			
		||||
                const fileIndex = {};
 | 
			
		||||
                jisonFiles.forEach(jisonFile => {
 | 
			
		||||
                    fileIndex[jisonFile] = true;
 | 
			
		||||
                });
 | 
			
		||||
                /**
 | 
			
		||||
                 * 挑选核心的jison文件(剥除autocomplate,syntax的功能文件)
 | 
			
		||||
                 */
 | 
			
		||||
                const sharedFiles = jisonFiles
 | 
			
		||||
                    .filter(jisonFile => jisonFile.indexOf('sql_') !== -1)
 | 
			
		||||
                    .map(jisonFile => path.join(subLanguageJisonFolder, jisonFile));
 | 
			
		||||
                if (fileIndex['sql.jisonlex']) {
 | 
			
		||||
                    /**
 | 
			
		||||
                     * 添加子语言自动补全编译配置
 | 
			
		||||
                     * 加入了error.jison,为了在校验失败的情况下也能够提示?
 | 
			
		||||
                     */
 | 
			
		||||
                    findParser(fileIndex, folder, sharedFiles, true);
 | 
			
		||||
                    /**
 | 
			
		||||
                     * 添加子语言语法检查配置
 | 
			
		||||
                     */
 | 
			
		||||
                    findParser(fileIndex, folder, sharedFiles.filter(path => path.indexOf('_error.jison') === -1), false);
 | 
			
		||||
                }
 | 
			
		||||
                else {
 | 
			
		||||
                    console.log("Warn: Could not find 'sql.jisonlex' in " + JISON_FOLDER + 'sql/' + folder + '/');
 | 
			
		||||
                }
 | 
			
		||||
            }));
 | 
			
		||||
        });
 | 
			
		||||
        Promise.all(promises).then(resolve);
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
const copyTests = (source, target) => new Promise((resolve, reject) => {
 | 
			
		||||
    const replaceRegexp = new RegExp(source + '(Autocomplete|Syntax)Parser', 'g');
 | 
			
		||||
    mkdir(PARSER_FOLDER + target)
 | 
			
		||||
        .then(() => {
 | 
			
		||||
        mkdir(PARSER_FOLDER + target + '/test')
 | 
			
		||||
            .then(() => {
 | 
			
		||||
            listDir(PARSER_FOLDER + source + '/test')
 | 
			
		||||
                .then(testFiles => {
 | 
			
		||||
                const copyPromises = [];
 | 
			
		||||
                testFiles.forEach(testFile => {
 | 
			
		||||
                    copyPromises.push(copyFile(PARSER_FOLDER + source + '/test/' + testFile, PARSER_FOLDER + target + '/test/' + testFile.replace(source, target), contents => contents.replace(replaceRegexp, target + '$1Parser')));
 | 
			
		||||
                });
 | 
			
		||||
                Promise.all(copyPromises)
 | 
			
		||||
                    .then(resolve)
 | 
			
		||||
                    .catch(reject);
 | 
			
		||||
            })
 | 
			
		||||
                .catch(reject);
 | 
			
		||||
        })
 | 
			
		||||
            .catch(reject);
 | 
			
		||||
    })
 | 
			
		||||
        .catch(reject);
 | 
			
		||||
});
 | 
			
		||||
/**
 | 
			
		||||
 * 校验,配置自定义语言
 | 
			
		||||
 */
 | 
			
		||||
const prepareForNewParser = () => new Promise((resolve, reject) => {
 | 
			
		||||
    /**
 | 
			
		||||
     * 根据一个子语言文件夹来生成一个特殊sql名字的语法文件
 | 
			
		||||
     * -new generic postgresql
 | 
			
		||||
     * 根据generic文件夹生成postgresql语法文件
 | 
			
		||||
     */
 | 
			
		||||
    if (process.argv.length === 3 && process.argv[0] === '-new') {
 | 
			
		||||
        process.argv.shift();
 | 
			
		||||
        const source = process.argv.shift();
 | 
			
		||||
        const target = process.argv.shift();
 | 
			
		||||
        console.log("Generating new parser '" + target + "' based on '" + source + "'...");
 | 
			
		||||
        process.argv.push(target);
 | 
			
		||||
        if (!Object.keys(parserDefinitions).some(key => {
 | 
			
		||||
            if (key.indexOf(source) === 0) {
 | 
			
		||||
                copyTests(source, target)
 | 
			
		||||
                    .then(() => {
 | 
			
		||||
                    mkdir(JISON_FOLDER + 'sql/' + target)
 | 
			
		||||
                        .then(() => {
 | 
			
		||||
                        listDir(JISON_FOLDER + 'sql/' + source).then(files => {
 | 
			
		||||
                            const copyPromises = [];
 | 
			
		||||
                            files.forEach(file => {
 | 
			
		||||
                                copyPromises.push(copyFile(JISON_FOLDER + 'sql/' + source + '/' + file, JISON_FOLDER + 'sql/' + target + '/' + file));
 | 
			
		||||
                            });
 | 
			
		||||
                            Promise.all(copyPromises).then(() => {
 | 
			
		||||
                                const autocompleteSources = [
 | 
			
		||||
                                    'sql/' + target + '/autocomplete_header.jison'
 | 
			
		||||
                                ];
 | 
			
		||||
                                const syntaxSources = ['sql/' + target + '/syntax_header.jison'];
 | 
			
		||||
                                files.forEach(file => {
 | 
			
		||||
                                    if (file.indexOf('sql_') === 0) {
 | 
			
		||||
                                        autocompleteSources.push('sql/' + target + '/' + file);
 | 
			
		||||
                                        syntaxSources.push('sql/' + target + '/' + file);
 | 
			
		||||
                                    }
 | 
			
		||||
                                });
 | 
			
		||||
                                autocompleteSources.push('sql/' + target + '/autocomplete_footer.jison');
 | 
			
		||||
                                syntaxSources.push('sql/' + target + '/syntax_footer.jison');
 | 
			
		||||
                                mkdir('desktop/core/src/desktop/js/parse/sql/' + target).then(() => {
 | 
			
		||||
                                    copyFile('desktop/core/src/desktop/js/parse/sql/' +
 | 
			
		||||
                                        source +
 | 
			
		||||
                                        '/sqlParseSupport.js', 'desktop/core/src/desktop/js/parse/sql/' +
 | 
			
		||||
                                        target +
 | 
			
		||||
                                        '/sqlParseSupport.js', contents => contents.replace(/parser\.yy\.activeDialect = '[^']+';'/g, "parser.yy.activeDialect = '" + target + "';")).then(() => {
 | 
			
		||||
                                        identifySqlParsers()
 | 
			
		||||
                                            .then(resolve)
 | 
			
		||||
                                            .catch(reject);
 | 
			
		||||
                                    });
 | 
			
		||||
                                });
 | 
			
		||||
                            });
 | 
			
		||||
                        });
 | 
			
		||||
                    })
 | 
			
		||||
                        .catch(err => {
 | 
			
		||||
                        console.log(err);
 | 
			
		||||
                    });
 | 
			
		||||
                })
 | 
			
		||||
                    .catch(reject);
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
        })) {
 | 
			
		||||
            reject("No existing parser found for '" + source + "'");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        resolve();
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
identifySqlParsers().then(() => {
 | 
			
		||||
    process.argv.shift();
 | 
			
		||||
    process.argv.shift();
 | 
			
		||||
    console.log('Generate sub language success...');
 | 
			
		||||
    prepareForNewParser().then(() => {
 | 
			
		||||
        console.log('Generate custom language success...');
 | 
			
		||||
        process.argv.forEach(arg => {
 | 
			
		||||
            if (arg === 'all') {
 | 
			
		||||
                /**
 | 
			
		||||
                 * 编译全部
 | 
			
		||||
                 */
 | 
			
		||||
                all = true;
 | 
			
		||||
            }
 | 
			
		||||
            else if (parserDefinitions[arg]) {
 | 
			
		||||
                /**
 | 
			
		||||
                 * 特点编译目标
 | 
			
		||||
                 */
 | 
			
		||||
                parsersToGenerate.push(arg);
 | 
			
		||||
            }
 | 
			
		||||
            else {
 | 
			
		||||
                /**
 | 
			
		||||
                 * 根据关键字匹配编译目标
 | 
			
		||||
                 */
 | 
			
		||||
                let prefixFound = false;
 | 
			
		||||
                Object.keys(parserDefinitions).forEach(key => {
 | 
			
		||||
                    if (key.indexOf(arg) === 0) {
 | 
			
		||||
                        prefixFound = true;
 | 
			
		||||
                        parsersToGenerate.push(key);
 | 
			
		||||
                    }
 | 
			
		||||
                });
 | 
			
		||||
                if (!prefixFound) {
 | 
			
		||||
                    invalid.push(arg);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
        if (all) {
 | 
			
		||||
            parsersToGenerate = Object.keys(parserDefinitions);
 | 
			
		||||
        }
 | 
			
		||||
        if (invalid.length) {
 | 
			
		||||
            console.log("No parser config found for: '" + invalid.join("', '") + "'");
 | 
			
		||||
            console.log('\nPossible options are:\n  ' +
 | 
			
		||||
                ['all'].concat(Object.keys(parserDefinitions)).join('\n  ') +
 | 
			
		||||
                '\n');
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        const parserCount = parsersToGenerate.length;
 | 
			
		||||
        let idx = 0;
 | 
			
		||||
        /**
 | 
			
		||||
         * 执行编译
 | 
			
		||||
         */
 | 
			
		||||
        const generateRecursive = () => {
 | 
			
		||||
            idx++;
 | 
			
		||||
            if (parsersToGenerate.length) {
 | 
			
		||||
                const parserName = parsersToGenerate.pop();
 | 
			
		||||
                if (parserCount > 1) {
 | 
			
		||||
                    console.log("Generating '" + parserName + "' (" + idx + '/' + parserCount + ')...');
 | 
			
		||||
                }
 | 
			
		||||
                else {
 | 
			
		||||
                    console.log("Generating '" + parserName + "'...");
 | 
			
		||||
                }
 | 
			
		||||
                generateParser(parserName)
 | 
			
		||||
                    .then(generateRecursive)
 | 
			
		||||
                    .catch(error => {
 | 
			
		||||
                    console.log(error);
 | 
			
		||||
                    console.log('FAIL!');
 | 
			
		||||
                });
 | 
			
		||||
            }
 | 
			
		||||
            else {
 | 
			
		||||
                const autocompParsers = [];
 | 
			
		||||
                const syntaxParsers = [];
 | 
			
		||||
                console.log('Updating sqlParserRepository.js...');
 | 
			
		||||
                Object.keys(parserDefinitions).forEach(key => {
 | 
			
		||||
                    if (parserDefinitions[key].sqlParser === 'AUTOCOMPLETE') {
 | 
			
		||||
                        autocompParsers.push(AUTOCOMPLETE_PARSER_IMPORT_TEMPLATE.replace(/KEY/g, key.replace('AutocompleteParser', '')));
 | 
			
		||||
                    }
 | 
			
		||||
                    else if (parserDefinitions[key].sqlParser === 'SYNTAX') {
 | 
			
		||||
                        syntaxParsers.push(SYNTAX_PARSER_IMPORT_TEMPLATE.replace(/KEY/g, key.replace('SyntaxParser', '')));
 | 
			
		||||
                    }
 | 
			
		||||
                });
 | 
			
		||||
                readFile(SQL_PARSER_REPOSITORY_PATH).then(contents => {
 | 
			
		||||
                    contents = contents.replace(/const SYNTAX_MODULES = [^}]+}/, 'const SYNTAX_MODULES = {\n' + syntaxParsers.sort().join(',\n') + '\n}');
 | 
			
		||||
                    contents = contents.replace(/const AUTOCOMPLETE_MODULES = [^}]+}/, 'const AUTOCOMPLETE_MODULES = {\n' + autocompParsers.sort().join(',\n') + '\n}');
 | 
			
		||||
                    writeFile(SQL_PARSER_REPOSITORY_PATH, contents).then(() => {
 | 
			
		||||
                        console.log('Done!\n');
 | 
			
		||||
                    });
 | 
			
		||||
                });
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
        /**
 | 
			
		||||
         * 集中精力办大事
 | 
			
		||||
         */
 | 
			
		||||
        generateRecursive();
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
/* eslint-enable no-restricted-syntax */
 | 
			
		||||
		Reference in New Issue
	
	Block a user