From 369399c786d1c915ca4e281c85674b2d2296d6ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=87=8E=E8=BF=82=E8=BF=82?= Date: Wed, 15 Nov 2023 20:26:16 +0800 Subject: [PATCH] [feat/sql-languages][taier-ui] improve sql-parser for editor --- taier-ui/.umirc.ts | 59 +++++++++++++----- taier-ui/package.json | 6 +- taier-ui/pnpm-lock.yaml | 60 +++++++++--------- taier-ui/public/assets/functions.json | 1 - taier-ui/public/assets/keywords.json | 1 - taier-ui/src/constant/index.ts | 18 ++++++ taier-ui/src/extensions/editor/index.tsx | 20 +++--- taier-ui/src/extensions/languages/index.tsx | 63 +++++-------------- taier-ui/src/utils/__tests__/index.test.tsx | 22 +------ taier-ui/src/utils/completion.ts | 69 --------------------- taier-ui/src/utils/enums.tsx | 7 +-- taier-ui/src/utils/index.ts | 11 ---- taier-ui/src/utils/is.ts | 9 +++ 13 files changed, 133 insertions(+), 213 deletions(-) delete mode 100644 taier-ui/public/assets/functions.json delete mode 100644 taier-ui/public/assets/keywords.json diff --git a/taier-ui/.umirc.ts b/taier-ui/.umirc.ts index c6e079a1b1..423b7d4f3f 100644 --- a/taier-ui/.umirc.ts +++ b/taier-ui/.umirc.ts @@ -29,25 +29,54 @@ export default defineConfig({ }, ], chainWebpack(memo, { env }) { - memo.output.globalObject('this').set('globalObject', 'this'); - memo.entry('sparksql.worker').add('monaco-sql-languages/out/esm/sparksql/sparksql.worker.js'); - memo.entry('sql.worker').add('monaco-sql-languages/out/esm/sql/sql.worker.js'); - memo.entry('hivesql.worker').add('monaco-sql-languages/out/esm/hivesql/hivesql.worker.js'); - memo.entry('mysql.worker').add('monaco-sql-languages/out/esm/mysql/mysql.worker.js'); - memo.entry('flinksql.worker').add('monaco-sql-languages/out/esm/flinksql/flinksql.worker.js'); memo.plugin('monaco-editor').use(MonacoWebpackPlugin, [ { - languages: ['json', 'python', 'shell'], + languages: ['json', 'python', 'shell', 'sql'], + customLanguages: [ + { + label: 'mysql', + entry: 'monaco-sql-languages/out/esm/mysql/mysql.contribution', + worker: { + id: 'monaco-sql-languages/out/esm/mysql/mySQLWorker', + entry: 'monaco-sql-languages/out/esm/mysql/mysql.worker', + }, + }, + { + label: 'flinksql', + entry: 'monaco-sql-languages/out/esm/flinksql/flinksql.contribution', + worker: { + id: 'monaco-sql-languages/out/esm/flinksql/flinkSQLWorker', + entry: 'monaco-sql-languages/out/esm/flinksql/flinksql.worker', + }, + }, + { + label: 'sparksql', + entry: 'monaco-sql-languages/out/esm/sparksql/sparksql.contribution', + worker: { + id: 'monaco-sql-languages/out/esm/sparksql/sparkSQLWorker', + entry: 'monaco-sql-languages/out/esm/sparksql/sparksql.worker', + }, + }, + { + label: 'hivesql', + entry: 'monaco-sql-languages/out/esm/hivesql/hivesql.contribution', + worker: { + id: 'monaco-sql-languages/out/esm/hivesql/hiveSQLWorker', + entry: 'monaco-sql-languages/out/esm/hivesql/hivesql.worker', + }, + }, + { + label: 'pgsql', + entry: 'monaco-sql-languages/out/esm/pgsql/pgsql.contribution', + worker: { + id: 'monaco-sql-languages/out/esm/pgsql/PgSQLWorker', + entry: 'monaco-sql-languages/out/esm/pgsql/pgsql.worker', + }, + }, + ], }, ]); - const isDev = env === 'development'; - if (!isDev) { - // ignore *.worker.js hash - memo.output.set('filename', (pathData: any) => { - return pathData.chunk.name.endsWith('.worker') ? '[name].js' : `[name].[contenthash:8].js`; - }); - } return memo; }, esbuild: {}, @@ -58,7 +87,7 @@ export default defineConfig({ tailwindcss: {}, proxy: { '/taier': { - target: 'http://localhost:8090', + target: 'http://localhost:8090', changeOrigin: true, secure: false, }, diff --git a/taier-ui/package.json b/taier-ui/package.json index d071986447..b0412cfe61 100644 --- a/taier-ui/package.json +++ b/taier-ui/package.json @@ -50,7 +50,7 @@ "lodash": "^4.17.21", "md5": "^2.3.0", "moment": "^2.29.1", - "monaco-sql-languages": "^0.9.4", + "monaco-sql-languages": "0.12.0-beta.5", "mxgraph": "4.0.6", "object-assign": "^4.1.1", "react": "~18.2.0", @@ -93,7 +93,7 @@ "jest-canvas-mock": "^2.4.0", "ko-lint-config": "^2.2.16", "lint-staged": "^10.0.7", - "monaco-editor-webpack-plugin": "^6.0.0", + "monaco-editor-webpack-plugin": "^7.0.0", "mustache": "^4.2.0", "progress": "^2.0.3", "request-promise": "^4.2.6", @@ -106,6 +106,6 @@ "yorkie": "^2.0.0" }, "resolutions": { - "dt-sql-parser": "4.0.0-beta.3.2" + "antlr4-c3": "3.0.x" } } \ No newline at end of file diff --git a/taier-ui/pnpm-lock.yaml b/taier-ui/pnpm-lock.yaml index aa4d004b6a..6112150247 100644 --- a/taier-ui/pnpm-lock.yaml +++ b/taier-ui/pnpm-lock.yaml @@ -1,7 +1,7 @@ lockfileVersion: 5.4 overrides: - dt-sql-parser: 4.0.0-beta.3.2 + antlr4-c3: 3.0.x specifiers: '@ant-design/icons': ^4.7.0 @@ -48,8 +48,8 @@ specifiers: lodash: ^4.17.21 md5: ^2.3.0 moment: ^2.29.1 - monaco-editor-webpack-plugin: ^6.0.0 - monaco-sql-languages: ^0.9.4 + monaco-editor-webpack-plugin: ^7.0.0 + monaco-sql-languages: 0.12.0-beta.5 mustache: ^4.2.0 mxgraph: 4.0.6 object-assign: ^4.1.1 @@ -88,7 +88,7 @@ dependencies: lodash: registry.npmmirror.com/lodash/4.17.21 md5: registry.npmmirror.com/md5/2.3.0 moment: registry.npmmirror.com/moment/2.29.4 - monaco-sql-languages: registry.npmmirror.com/monaco-sql-languages/0.9.4 + monaco-sql-languages: registry.npmmirror.com/monaco-sql-languages/0.12.0-beta.5 mxgraph: registry.npmmirror.com/mxgraph/4.0.6 object-assign: registry.npmmirror.com/object-assign/4.1.1 react: registry.npmmirror.com/react/18.2.0 @@ -131,7 +131,7 @@ devDependencies: jest-canvas-mock: registry.npmmirror.com/jest-canvas-mock/2.5.2 ko-lint-config: registry.npmmirror.com/ko-lint-config/2.2.21_typescript@4.7.4 lint-staged: registry.npmmirror.com/lint-staged/10.5.4 - monaco-editor-webpack-plugin: registry.npmmirror.com/monaco-editor-webpack-plugin/6.0.0 + monaco-editor-webpack-plugin: registry.npmmirror.com/monaco-editor-webpack-plugin/7.1.0 mustache: registry.npmmirror.com/mustache/4.2.0 progress: registry.npmmirror.com/progress/2.0.3 request-promise: registry.npmmirror.com/request-promise/4.2.6 @@ -1503,12 +1503,6 @@ packages: version: 1.0.8 dev: true - registry.npmmirror.com/@types/antlr4/4.7.0: - resolution: {integrity: sha512-WdyHH4PHxBQkeWoRTbuC/dvf0QErJpJE4UpESQSRmKoMER15DCLFHAHQjkwevMKQie0kqawS/eTY563GGMbz/g==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@types/antlr4/-/antlr4-4.7.0.tgz} - name: '@types/antlr4' - version: 4.7.0 - dev: false - registry.npmmirror.com/@types/aria-query/5.0.3: resolution: {integrity: sha512-0Z6Tr7wjKJIk4OUEjVUQMtyunLDy339vcMaj38Kpj6jM2OE1p3S4kXExKZ7a3uXQAPCoy3sbrP1wibDKaf39oA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@types/aria-query/-/aria-query-5.0.3.tgz} name: '@types/aria-query' @@ -3059,10 +3053,18 @@ packages: react-dom: registry.npmmirror.com/react-dom/18.2.0_react@18.2.0 scroll-into-view-if-needed: registry.npmmirror.com/scroll-into-view-if-needed/2.2.31 - registry.npmmirror.com/antlr4/4.7.2: - resolution: {integrity: sha512-vZA1xYufXLe3LX+ja9rIVxjRmILb1x3k7KYZHltRbfJtXjJ1DlFIqt+CbPYmghx0EuzY9DajiDw+MdyEt1qAsQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/antlr4/-/antlr4-4.7.2.tgz} - name: antlr4 - version: 4.7.2 + registry.npmmirror.com/antlr4-c3/3.0.1: + resolution: {integrity: sha512-Vbizas0WK4Id6l1f48ANYHFZgfzmj82LZx4OuB/a87vCpyoUwofrlJ+sCiL1qT/D2SWf8HEcBPCsgskdx8NnzQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/antlr4-c3/-/antlr4-c3-3.0.1.tgz} + name: antlr4-c3 + version: 3.0.1 + dependencies: + antlr4ts: registry.npmmirror.com/antlr4ts/0.5.0-alpha.4 + dev: false + + registry.npmmirror.com/antlr4ts/0.5.0-alpha.4: + resolution: {integrity: sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/antlr4ts/-/antlr4ts-0.5.0-alpha.4.tgz} + name: antlr4ts + version: 0.5.0-alpha.4 dev: false registry.npmmirror.com/anymatch/2.0.0: @@ -5186,13 +5188,13 @@ packages: minimatch: registry.npmmirror.com/minimatch/3.1.2 dev: false - registry.npmmirror.com/dt-sql-parser/4.0.0-beta.3.2: - resolution: {integrity: sha512-QrgsWzpqqUy6vAGkK4Ep4WdZfhy0s2SNR7QuwQ3RsdDNQ4rMzH1jQTdEBK6oU+16o1xpStwjnzk3vuxMOhiisw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/dt-sql-parser/-/dt-sql-parser-4.0.0-beta.3.2.tgz} + registry.npmmirror.com/dt-sql-parser/4.0.0-beta.4.5: + resolution: {integrity: sha512-zp7L4h6i5bU5U38ZLi66iL8BZ7LfBvLqqI9laQks4f18X19K/CMdXqWzmk90cNIeH7Jh8MhNBYyeWMUyjXcjRQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/dt-sql-parser/-/dt-sql-parser-4.0.0-beta.4.5.tgz} name: dt-sql-parser - version: 4.0.0-beta.3.2 + version: 4.0.0-beta.4.5 dependencies: - '@types/antlr4': registry.npmmirror.com/@types/antlr4/4.7.0 - antlr4: registry.npmmirror.com/antlr4/4.7.2 + antlr4-c3: registry.npmmirror.com/antlr4-c3/3.0.1 + antlr4ts: registry.npmmirror.com/antlr4ts/0.5.0-alpha.4 dev: false registry.npmmirror.com/dva-core/2.0.4_redux@4.2.1: @@ -9192,12 +9194,12 @@ packages: name: moment version: 2.29.4 - registry.npmmirror.com/monaco-editor-webpack-plugin/6.0.0: - resolution: {integrity: sha512-vC886Mzpd2AkSM35XLkfQMjH+Ohz6RISVwhAejDUzZDheJAiz6G34lky1vyO8fZ702v7IrcKmsGwL1rRFnwvUA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/monaco-editor-webpack-plugin/-/monaco-editor-webpack-plugin-6.0.0.tgz} + registry.npmmirror.com/monaco-editor-webpack-plugin/7.1.0: + resolution: {integrity: sha512-ZjnGINHN963JQkFqjjcBtn1XBtUATDZBMgNQhDQwd78w2ukRhFXAPNgWuacaQiDZsUr4h1rWv5Mv6eriKuOSzA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/monaco-editor-webpack-plugin/-/monaco-editor-webpack-plugin-7.1.0.tgz} name: monaco-editor-webpack-plugin - version: 6.0.0 + version: 7.1.0 peerDependencies: - monaco-editor: 0.30.x + monaco-editor: '>= 0.31.0' webpack: ^4.5.0 || 5.x dependencies: loader-utils: registry.npmmirror.com/loader-utils/2.0.4 @@ -9209,12 +9211,14 @@ packages: version: 0.31.1 dev: false - registry.npmmirror.com/monaco-sql-languages/0.9.4: - resolution: {integrity: sha512-2LaIQ2Fc37lBiPx8lL9tlYRzxzns5NQeHkR4h3o+ysBOML5KhUDuscNDiTN8ailuas83OphR9fhe3Hkn5I2oZQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/monaco-sql-languages/-/monaco-sql-languages-0.9.4.tgz} + registry.npmmirror.com/monaco-sql-languages/0.12.0-beta.5: + resolution: {integrity: sha512-YpCModmff5k9Gkk8v8cTKG1T123BkWct2BKtl+Sp+7RLu0oQdaYybjROBcxya5xkcWqhrwcVFAcGbfa0qglQ2A==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/monaco-sql-languages/-/monaco-sql-languages-0.12.0-beta.5.tgz} name: monaco-sql-languages - version: 0.9.4 + version: 0.12.0-beta.5 + peerDependencies: + monaco-editor: 0.31.0 dependencies: - dt-sql-parser: registry.npmmirror.com/dt-sql-parser/4.0.0-beta.3.2 + dt-sql-parser: registry.npmmirror.com/dt-sql-parser/4.0.0-beta.4.5 dev: false registry.npmmirror.com/moo-color/1.0.3: diff --git a/taier-ui/public/assets/functions.json b/taier-ui/public/assets/functions.json deleted file mode 100644 index 1dc96a162d..0000000000 --- a/taier-ui/public/assets/functions.json +++ /dev/null @@ -1 +0,0 @@ -[{"keyword":"ASCII","description":"Returns the ASCII value for the specific character"},{"keyword":"CHAR_LENGTH","description":"Returns the length of a string (in characters)"},{"keyword":"CHARACTER_LENGTH","description":"Returns the length of a string (in characters)"},{"keyword":"CONCAT","description":"Adds two or more expressions together"},{"keyword":"CONCAT_WS","description":"Adds two or more expressions together with a separator"},{"keyword":"FIELD","description":"Returns the index position of a value in a list of values"},{"keyword":"FIND_IN_SET","description":"Returns the position of a string within a list of strings"},{"keyword":"FORMAT","description":"Formats a number to a format like \"#,###,###.##\", rounded to a \nspecified number \nof decimal places"},{"keyword":"INSERT","description":"Inserts a string within a string at the specified position and for a certain \nnumber of characters"},{"keyword":"INSTR","description":"Returns the position of the first occurrence of a string in another string"},{"keyword":"LCASE","description":"Converts a string to lower-case"},{"keyword":"LEFT","description":"Extracts a number of characters from a string (starting from left)"},{"keyword":"LENGTH","description":"Returns the length of a string (in bytes)"},{"keyword":"LOCATE","description":"Returns the position of the first occurrence of a substring in a string"},{"keyword":"LOWER","description":"Converts a string to lower-case"},{"keyword":"LPAD","description":"Left-pads a string with another string, to a certain length"},{"keyword":"LTRIM","description":"Removes leading spaces from a string"},{"keyword":"MID","description":"Extracts a substring from a string (starting at any position)"},{"keyword":"POSITION","description":"Returns the position of the first occurrence of a substring in a string"},{"keyword":"REPEAT","description":"Repeats a string as many times as specified"},{"keyword":"REPLACE","description":"Replaces all occurrences of a substring within a string, with a new \nsubstring"},{"keyword":"REVERSE","description":"Reverses a string and returns the result"},{"keyword":"RIGHT","description":"Extracts a number of characters from a string (starting from right)"},{"keyword":"RPAD","description":"Right-pads a string with another string, to a certain length"},{"keyword":"RTRIM","description":"Removes trailing spaces from a string"},{"keyword":"SPACE","description":"Returns a string of the specified number of space characters"},{"keyword":"STRCMP","description":"Compares two strings"},{"keyword":"SUBSTR","description":"Extracts a substring from a string (starting at any position)"},{"keyword":"SUBSTRING","description":"Extracts a substring from a string (starting at any position)"},{"keyword":"SUBSTRING_INDEX","description":"Returns a substring of a string before a specified number of \ndelimiter occurs"},{"keyword":"TRIM","description":"Removes leading and trailing spaces from a string"},{"keyword":"UCASE","description":"Converts a string to upper-case"},{"keyword":"UPPER","description":"Converts a string to upper-case"},{"keyword":"ABS","description":"Returns the absolute value of a number"},{"keyword":"ACOS","description":"Returns the arc cosine of a number"},{"keyword":"ASIN","description":"Returns the arc sine of a number"},{"keyword":"ATAN","description":"Returns the arc tangent of one or two numbers"},{"keyword":"ATAN2","description":"Returns the arc tangent of two numbers"},{"keyword":"AVG","description":"Returns the average value of an expression"},{"keyword":"CEIL","description":"Returns the smallest integer value that is >= to a number"},{"keyword":"CEILING","description":"Returns the smallest integer value that is >= to a number"},{"keyword":"COS","description":"Returns the cosine of a number"},{"keyword":"COT","description":"Returns the cotangent of a number"},{"keyword":"COUNT","description":"Returns the number of records returned by a select query"},{"keyword":"DEGREES","description":"Converts a value in radians to degrees"},{"keyword":"DIV","description":"Used for integer division"},{"keyword":"EXP","description":"Returns e raised to the power of a specified number"},{"keyword":"FLOOR","description":"Returns the largest integer value that is <= to a number"},{"keyword":"GREATEST","description":"Returns the greatest value of the list of arguments"},{"keyword":"LEAST","description":"Returns the smallest value of the list of arguments"},{"keyword":"LN","description":"Returns the natural logarithm of a number"},{"keyword":"LOG","description":"Returns the natural logarithm of a number, or the logarithm of a number to a \nspecified base"},{"keyword":"LOG10","description":"Returns the natural logarithm of a number to base 10"},{"keyword":"LOG2","description":"Returns the natural logarithm of a number to base 2"},{"keyword":"MAX","description":"Returns the maximum value in a set of values"},{"keyword":"MIN","description":"Returns the minimum value in a set of values"},{"keyword":"MOD","description":"Returns the remainder of a number divided by another number"},{"keyword":"PI","description":"Returns the value of PI"},{"keyword":"POW","description":"Returns the value of a number raised to the power of another number"},{"keyword":"POWER","description":"Returns the value of a number raised to the power of another number"},{"keyword":"RADIANS","description":"Converts a degree value into radians"},{"keyword":"RAND","description":"Returns a random number"},{"keyword":"ROUND","description":"Rounds a number to a specified number of decimal places"},{"keyword":"SIGN","description":"Returns the sign of a number"},{"keyword":"SIN","description":"Returns the sine of a number"},{"keyword":"SQRT","description":"Returns the square root of a number"},{"keyword":"SUM","description":"Calculates the sum of a set of values"},{"keyword":"TAN","description":"Returns the tangent of a number"},{"keyword":"TRUNCATE","description":"Truncates a number to the specified number of decimal places"},{"keyword":"ADDDATE","description":"Adds a time/date interval to a date and then returns the date"},{"keyword":"ADDTIME","description":"Adds a time interval to a time/datetime and then returns the time/datetime"},{"keyword":"CURDATE","description":"Returns the current date"},{"keyword":"CURRENT_DATE","description":"Returns the current date"},{"keyword":"CURRENT_TIME","description":"Returns the current time"},{"keyword":"CURRENT_TIMESTAMP","description":"Returns the current date and time"},{"keyword":"CURTIME","description":"Returns the current time"},{"keyword":"DATE","description":"Extracts the date part from a datetime expression"},{"keyword":"DATEDIFF","description":"Returns the number of days between two date values"},{"keyword":"DATE_ADD","description":"Adds a time/date interval to a date and then returns the date"},{"keyword":"DATE_FORMAT","description":"Formats a date"},{"keyword":"DATE_SUB","description":"Subtracts a time/date interval from a date and then returns the date"},{"keyword":"DAY","description":"Returns the day of the month for a given date"},{"keyword":"DAYNAME","description":"Returns the weekday name for a given date"},{"keyword":"DAYOFMONTH","description":"Returns the day of the month for a given date"},{"keyword":"DAYOFWEEK","description":"Returns the weekday index for a given date"},{"keyword":"DAYOFYEAR","description":"Returns the day of the year for a given date"},{"keyword":"EXTRACT","description":"Extracts a part from a given date"},{"keyword":"FROM_DAYS","description":"Returns a date from a numeric datevalue"},{"keyword":"HOUR","description":"Returns the hour part for a given date"},{"keyword":"LAST_DAY","description":"Extracts the last day of the month for a given date"},{"keyword":"LOCALTIME","description":"Returns the current date and time"},{"keyword":"LOCALTIMESTAMP","description":"Returns the current date and time"},{"keyword":"MAKEDATE","description":"Creates and returns a date based on a year and a number of days value"},{"keyword":"MAKETIME","description":"Creates and returns a time based on an hour, minute, and second value"},{"keyword":"MICROSECOND","description":"Returns the microsecond part of a time/datetime"},{"keyword":"MINUTE","description":"Returns the minute part of a time/datetime"},{"keyword":"MONTH","description":"Returns the month part for a given date"},{"keyword":"MONTHNAME","description":"Returns the name of the month for a given date"},{"keyword":"NOW","description":"Returns the current date and time"},{"keyword":"PERIOD_ADD","description":"Adds a specified number of months to a period"},{"keyword":"PERIOD_DIFF","description":"Returns the difference between two periods"},{"keyword":"QUARTER","description":"Returns the quarter of the year for a given date value"},{"keyword":"SECOND","description":"Returns the seconds part of a time/datetime"},{"keyword":"SEC_TO_TIME","description":"Returns a time value based on the specified seconds"},{"keyword":"STR_TO_DATE","description":"Returns a date based on a string and a format"},{"keyword":"SUBDATE","description":"Subtracts a time/date interval from a date and then returns the date"},{"keyword":"SUBTIME","description":"Subtracts a time interval from a datetime and then returns the time/datetime"},{"keyword":"SYSDATE","description":"Returns the current date and time"},{"keyword":"TIME","description":"Extracts the time part from a given time/datetime"},{"keyword":"TIME_FORMAT","description":"Formats a time by a specified format"},{"keyword":"TIME_TO_SEC","description":"Converts a time value into seconds"},{"keyword":"TIMEDIFF","description":"Returns the difference between two time/datetime expressions"},{"keyword":"TIMESTAMP","description":"Returns a datetime value based on a date or datetime value"},{"keyword":"TO_DAYS","description":"Returns the number of days between a date and date \"0000-00-00\""},{"keyword":"WEEK","description":"Returns the week number for a given date"},{"keyword":"WEEKDAY","description":"Returns the weekday number for a given date"},{"keyword":"WEEKOFYEAR","description":"Returns the week number for a given date"},{"keyword":"YEAR","description":"Returns the year part for a given date"},{"keyword":"YEARWEEK","description":"Returns the year and week number for a given date"},{"keyword":"BIN","description":"Returns a binary representation of a number"},{"keyword":"BINARY","description":"Converts a value to a binary string"},{"keyword":"CASE","description":"Goes through conditions and return a value when the first condition is \nmet"},{"keyword":"CAST","description":"Converts a value (of any type) into a specified datatype"},{"keyword":"COALESCE","description":"Returns the first non-null value in a list"},{"keyword":"CONNECTION_ID","description":"Returns the unique connection ID for the current connection"},{"keyword":"CONV","description":"Converts a number from one numeric base system to another"},{"keyword":"CONVERT","description":"Converts a value into the specified datatype or character set"},{"keyword":"CURRENT_USER","description":"Returns the user name and host name for the MySQL account that the server \nused to authenticate the current client"},{"keyword":"DATABASE","description":"Returns the name of the current database"},{"keyword":"IF","description":"Returns a value if a condition is TRUE, or another value if a condition is FALSE"},{"keyword":"IFNULL","description":"Return a specified value if the expression is NULL, otherwise return the \nexpression"},{"keyword":"ISNULL","description":"Returns 1 or 0 depending on whether an expression is NULL"},{"keyword":"LAST_INSERT_ID","description":"Returns the AUTO_INCREMENT id of the last row that has been inserted or \nupdated in a table"},{"keyword":"NULLIF","description":"Compares two expressions and returns NULL if they are equal. Otherwise, the \nfirst expression is returned"},{"keyword":"SESSION_USER","description":"Returns the current MySQL user name and host name"},{"keyword":"SYSTEM_USER","description":"Returns the current MySQL user name and host name"},{"keyword":"USER","description":"Returns the current MySQL user name and host name"},{"keyword":"VERSION","description":"Returns the current version of the MySQL database"}] \ No newline at end of file diff --git a/taier-ui/public/assets/keywords.json b/taier-ui/public/assets/keywords.json deleted file mode 100644 index fe9a1f149e..0000000000 --- a/taier-ui/public/assets/keywords.json +++ /dev/null @@ -1 +0,0 @@ -[{"keyword":"ADD","description":"Adds a column in an existing table"},{"keyword":"ADD CONSTRAINT","description":"Adds a constraint after a table is already created"},{"keyword":"ALL","description":"Returns true if all of the subquery values meet the \ncondition"},{"keyword":"ALTER","description":"Adds, deletes, or modifies columns in a table, or changes the data \ntype of a column in a table"},{"keyword":"ALTER COLUMN","description":"Changes the data type of a column in a table"},{"keyword":"ALTER TABLE","description":"Adds, deletes, or modifies columns in a table"},{"keyword":"AND","description":"Only includes rows where both conditions is true"},{"keyword":"ANY","description":"Returns true if any of the subquery values meet the \ncondition"},{"keyword":"AS","description":"Renames a column or table with an alias"},{"keyword":"ASC","description":"Sorts the result set in ascending order"},{"keyword":"BACKUP DATABASE","description":"Creates a back up of an existing database"},{"keyword":"BETWEEN","description":"Selects values within a given range"},{"keyword":"CASE","description":"Creates different outputs based on conditions"},{"keyword":"CHECK","description":"A constraint that limits the value that can be placed in a \ncolumn"},{"keyword":"COLUMN","description":"Changes the data type of a column or deletes a column in a table"},{"keyword":"CONSTRAINT","description":"Adds or deletes a constraint"},{"keyword":"CREATE","description":"Creates a database, index, view, table, or procedure"},{"keyword":"CREATE DATABASE","description":"Creates a new SQL database"},{"keyword":"CREATE INDEX","description":"Creates an index on a table (allows duplicate values)"},{"keyword":"CREATE OR REPLACE VIEW","description":"Updates a view"},{"keyword":"CREATE TABLE","description":"Creates a new table in the database"},{"keyword":"CREATE PROCEDURE","description":"Creates a stored procedure"},{"keyword":"CREATE UNIQUE INDEX","description":"Creates a unique index on a table (no duplicate values)"},{"keyword":"CREATE VIEW","description":"Creates a view based on the result set of a SELECT statement"},{"keyword":"DATABASE","description":"Creates or deletes an SQL database"},{"keyword":"DEFAULT","description":"A constraint that provides a default value for a column"},{"keyword":"DELETE","description":"Deletes rows from a table"},{"keyword":"DESC","description":"Sorts the result set in descending order"},{"keyword":"DISTINCT","description":"Selects only distinct (different) values"},{"keyword":"DROP","description":"Deletes a column, constraint, database, index, table, or view"},{"keyword":"DROP COLUMN","description":"Deletes a column in a table"},{"keyword":"DROP CONSTRAINT","description":"Deletes a UNIQUE, PRIMARY KEY, FOREIGN KEY, or CHECK constraint"},{"keyword":"DROP DATABASE","description":"Deletes an existing SQL database"},{"keyword":"DROP DEFAULT","description":"Deletes a DEFAULT constraint"},{"keyword":"DROP INDEX","description":"Deletes an index in a table"},{"keyword":"DROP TABLE","description":"Deletes an existing table in the database"},{"keyword":"DROP VIEW","description":"Deletes a view"},{"keyword":"EXEC","description":"Executes a stored procedure"},{"keyword":"EXISTS","description":"Tests for the existence of any record in a subquery"},{"keyword":"FOREIGN KEY","description":"A constraint that is a key used to link two tables together"},{"keyword":"FROM","description":"Specifies which table to select or delete data from"},{"keyword":"FULL OUTER JOIN","description":"Returns all rows when there is a match in either left table or right table"},{"keyword":"GROUP BY","description":"Groups the result set (used with aggregate functions: COUNT, MAX, MIN, SUM, \nAVG)"},{"keyword":"HAVING","description":"Used instead of WHERE with aggregate functions"},{"keyword":"IN","description":"Allows you to specify multiple values in a WHERE clause"},{"keyword":"INDEX","description":"Creates or deletes an index in a table "},{"keyword":"INNER JOIN","description":"Returns rows that have matching values in both tables"},{"keyword":"INSERT INTO","description":"Inserts new rows in a table"},{"keyword":"INSERT INTO SELECT","description":"Copies data from one table into another table"},{"keyword":"IS NULL","description":"Tests for empty values"},{"keyword":"IS NOT NULL","description":"Tests for non-empty values"},{"keyword":"JOIN","description":"Joins tables"},{"keyword":"LEFT JOIN","description":"Returns all rows from the left table, and the matching rows from the right \ntable"},{"keyword":"LIKE","description":"Searches for a specified pattern in a column"},{"keyword":"LIMIT","description":"Specifies the number of records to return in the result set"},{"keyword":"NOT","description":"Only includes rows where a condition is not true"},{"keyword":"NOT NULL","description":"A constraint that enforces a column to not accept NULL values"},{"keyword":"OR","description":"Includes rows where either condition is true"},{"keyword":"ORDER BY","description":"Sorts the result set in ascending or descending order"},{"keyword":"OUTER JOIN","description":"Returns all rows when there is a match in either left table or right table"},{"keyword":"PRIMARY KEY","description":"A constraint that uniquely identifies each record in a database table"},{"keyword":"PROCEDURE","description":"A stored procedure"},{"keyword":"RIGHT JOIN","description":"Returns all rows from the right table, and the matching rows from the \nleft table"},{"keyword":"ROWNUM","description":"Specifies the number of records to return in the result set"},{"keyword":"SELECT","description":"Selects data from a database"},{"keyword":"SELECT DISTINCT","description":"Selects only distinct (different) values"},{"keyword":"SELECT INTO","description":"Copies data from one table into a new table"},{"keyword":"SELECT TOP","description":"Specifies the number of records to return in the result set"},{"keyword":"SET","description":"Specifies which columns and values that should be updated in a table"},{"keyword":"TABLE","description":"Creates a table, or adds, deletes, or modifies columns in a table, or \ndeletes a table or data inside a table"},{"keyword":"TOP","description":"Specifies the number of records to return in the result set"},{"keyword":"TRUNCATE TABLE","description":"Deletes the data inside a table, but not the table itself"},{"keyword":"UNION","description":"Combines the result set of two or more SELECT statements (only \ndistinct values)"},{"keyword":"UNION ALL","description":"Combines the result set of two or more SELECT statements (allows \nduplicate values)"},{"keyword":"UNIQUE","description":"A constraint that ensures that all values in a column are unique"},{"keyword":"UPDATE","description":"Updates existing rows in a table"},{"keyword":"VALUES","description":"Specifies the values of an INSERT INTO statement"},{"keyword":"VIEW","description":"Creates, updates, or deletes a view"},{"keyword":"WHERE","description":"Filters a result set to include only records that fulfill a specified \ncondition"}] \ No newline at end of file diff --git a/taier-ui/src/constant/index.ts b/taier-ui/src/constant/index.ts index 0540b0f362..977556bd08 100644 --- a/taier-ui/src/constant/index.ts +++ b/taier-ui/src/constant/index.ts @@ -1288,6 +1288,7 @@ export enum TASK_LANGUAGE { FLINKSQL = 'flinksql', MYSQL = 'mysql', PLSQL = 'plsql', + PGSQL = 'pgsql', SQL = 'sql', JSON = 'json', PYTHON = 'python', @@ -1609,3 +1610,20 @@ export enum PythonVersionKind { * So the one named `path` and another named `path|FTP` */ export const NAME_SEPARATOR = '|'; + +/** + * Support problems analyse SQL languages + */ +export const SUPPORT_VALID_LANGUEGES = [TASK_LANGUAGE.FLINKSQL, TASK_LANGUAGE.HIVESQL, TASK_LANGUAGE.SPARKSQL] as const; + +/** + * For support snippets SQL languages + */ +export const COMPLETION_SQL = [ + TASK_LANGUAGE.SPARKSQL, + TASK_LANGUAGE.HIVESQL, + TASK_LANGUAGE.SQL, + TASK_LANGUAGE.FLINKSQL, + TASK_LANGUAGE.MYSQL, + TASK_LANGUAGE.PGSQL, +] as const; diff --git a/taier-ui/src/extensions/editor/index.tsx b/taier-ui/src/extensions/editor/index.tsx index 953e3b0b02..fe69579cb4 100644 --- a/taier-ui/src/extensions/editor/index.tsx +++ b/taier-ui/src/extensions/editor/index.tsx @@ -30,15 +30,16 @@ import api from '@/api'; import type { IGeometryPosition } from '@/components/mxGraph/container'; import notification from '@/components/notification'; import Publish, { CONTAINER_ID } from '@/components/task/publish'; -import { DRAWER_MENU_ENUM, ID_COLLECTIONS, TASK_LANGUAGE, TASK_TYPE_ENUM } from '@/constant'; +import { COMPLETION_SQL, DRAWER_MENU_ENUM, ID_COLLECTIONS, TASK_TYPE_ENUM } from '@/constant'; import type { CatalogueDataProps, IOfflineTaskProps } from '@/interface'; import { IComputeType } from '@/interface'; import { isEditing } from '@/pages/editor/workflow'; -import { editorActionBarService, executeService, taskParamsService,taskRenderService } from '@/services'; +import { editorActionBarService, executeService, taskParamsService, taskRenderService } from '@/services'; import type { IParamsProps } from '@/services/taskParamsService'; import taskSaveService from '@/services/taskSaveService'; import viewStoreService from '@/services/viewStoreService'; -import { createSQLProposals, prettierJSONstring } from '@/utils'; +import { prettierJSONstring } from '@/utils'; +import { Snippets } from '@/utils/completion'; import { mappingTaskTypeToLanguage } from '@/utils/enums'; import { onTaskSwitch, runTask, syntaxValidate } from '@/utils/extensions'; @@ -273,14 +274,7 @@ const updateTaskVariables = debounce((tab: molecule.model.IEditorTab) => { }); }, 300); -// 注册自动补全 -function registerCompletion() { - const COMPLETION_SQL = [ - TASK_LANGUAGE.SPARKSQL, - TASK_LANGUAGE.HIVESQL, - TASK_LANGUAGE.SQL, - TASK_LANGUAGE.FLINKSQL, - ] as const; +function registerSnippets() { COMPLETION_SQL.forEach((sql) => languages.registerCompletionItemProvider(sql, { async provideCompletionItems(model, position) { @@ -292,7 +286,7 @@ function registerCompletion() { endColumn: word.endColumn, }; - const suggestions = await createSQLProposals(range); + const suggestions = Snippets(range); return { suggestions, }; @@ -309,7 +303,7 @@ export default class EditorExtension implements IExtension { } activate() { emitEvent(); - registerCompletion(); + registerSnippets(); molecule.editor.onOpenTab((tab) => { viewStoreService.clearStorage(tab.id.toString()); diff --git a/taier-ui/src/extensions/languages/index.tsx b/taier-ui/src/extensions/languages/index.tsx index abf68994a1..261b4fbf69 100644 --- a/taier-ui/src/extensions/languages/index.tsx +++ b/taier-ui/src/extensions/languages/index.tsx @@ -21,14 +21,10 @@ import type { UniqueId } from '@dtinsight/molecule/esm/common/types'; import type { IEditorTab, IExtension, IProblemsItem } from '@dtinsight/molecule/esm/model'; import { MarkerSeverity } from '@dtinsight/molecule/esm/model'; import { debounce } from 'lodash'; +import { LanguageIdEnum, setupLanguageFeatures } from 'monaco-sql-languages'; import { LanguageService } from 'monaco-sql-languages/out/esm/languageService'; -import 'monaco-sql-languages/out/esm/sparksql/sparksql.contribution'; -import 'monaco-sql-languages/out/esm/hivesql/hivesql.contribution'; -import 'monaco-sql-languages/out/esm/sql/sql.contribution'; -import 'monaco-sql-languages/out/esm/mysql/mysql.contribution'; -import 'monaco-sql-languages/out/esm/flinksql/flinksql.contribution'; -import { TASK_LANGUAGE } from '@/constant'; +import { isValidLanguage } from '@/utils/is'; interface ValidMessage { endCol: number; @@ -81,12 +77,9 @@ function convertMsgToProblemItem(tab: IEditorTab, msgs: ValidMessage[] = []): IP } function analyseProblems(tab: IEditorTab) { - if (tab.data && tab.data.language) { - const NOT_ANAYLSE_LANGUAGE: string[] = [TASK_LANGUAGE.JSON]; - if (NOT_ANAYLSE_LANGUAGE.includes(tab.data.language)) return; + if (tab.data && tab.data.language && isValidLanguage(tab.data.language)) { const sql = tab.data.value || ''; - - languageService.valid(tab.data.language || TASK_LANGUAGE.SQL, sql).then((res: ValidMessage[]) => { + languageService.valid(tab.data.language, sql).then((res: ValidMessage[]) => { if (res.length) { const problems = convertMsgToProblemItem(tab, res); molecule.problems.add(problems); @@ -102,41 +95,6 @@ function analyseProblems(tab: IEditorTab) { } } -function registerWorkers() { - (window as any).MonacoEnvironment = { - getWorkerUrl(moduleId: string, label: TASK_LANGUAGE) { - switch (label) { - case TASK_LANGUAGE.SPARKSQL: { - return './sparksql.worker.js'; - } - case TASK_LANGUAGE.FLINKSQL: { - return './flinksql.worker.js'; - } - case TASK_LANGUAGE.HIVESQL: { - return './hivesql.worker.js'; - } - case TASK_LANGUAGE.MYSQL: { - return './mysql.worker.js'; - } - case TASK_LANGUAGE.PLSQL: { - return './plsql.worker.js'; - } - case TASK_LANGUAGE.JSON: { - return './json.worker.js'; - } - case TASK_LANGUAGE.SQL: { - return './sql.worker.js'; - } - case TASK_LANGUAGE.PYTHON: - case TASK_LANGUAGE.SHELL: - default: { - return './editor.worker.js'; - } - } - }, - }; -} - /** * This is for loading language.work for parsing the sql language */ @@ -147,7 +105,18 @@ export class ExtendsSparkSQL implements IExtension { throw new Error('Method not implemented.'); } activate(): void { - registerWorkers(); + // Close code analyse for MYSQL + setupLanguageFeatures({ + languageId: LanguageIdEnum.MYSQL, + diagnostics: false, + }); + + // Close code analyse for PGSQL + setupLanguageFeatures({ + languageId: LanguageIdEnum.PG, + diagnostics: false, + }); + molecule.editor.onUpdateTab(debounce(analyseProblems, 600)); molecule.editor.onOpenTab(analyseProblems); diff --git a/taier-ui/src/utils/__tests__/index.test.tsx b/taier-ui/src/utils/__tests__/index.test.tsx index 3106dab2c4..bdf25f2c74 100644 --- a/taier-ui/src/utils/__tests__/index.test.tsx +++ b/taier-ui/src/utils/__tests__/index.test.tsx @@ -11,7 +11,6 @@ import { copyText, createElement, createSeries, - createSQLProposals, deleteCookie, disableRangeCreater, filterComments, @@ -187,7 +186,7 @@ describe('utils/index', () => { ); // default - expect(getVertexStyle(99999)).toBe( + expect(getVertexStyle(99999 as any)).toBe( 'whiteSpace=wrap;fillColor=var(--badge-common-background);strokeColor=var(--badge-common-border);' ); }); @@ -376,25 +375,6 @@ describe('utils/index', () => { expect(isValidFormatType('abc')).toBe(false); }); - it('Should have completion for sql', () => { - window.fetch = jest - .fn() - .mockResolvedValueOnce({ - json: () => Promise.resolve(require('../../../public/assets/keywords.json')), - }) - .mockResolvedValueOnce({ - json: () => Promise.resolve(require('../../../public/assets/functions.json')), - }); - const completions = createSQLProposals({ - startLineNumber: 0, - startColumn: 0, - endLineNumber: 0, - endColumn: 0, - }); - - expect(completions).resolves.toMatchSnapshot(); - }); - it('disableRangeCreater', () => { expect(disableRangeCreater(null, null, 'hour')).toEqual([]); diff --git a/taier-ui/src/utils/completion.ts b/taier-ui/src/utils/completion.ts index fe9dad495a..b0d5d7f9fc 100644 --- a/taier-ui/src/utils/completion.ts +++ b/taier-ui/src/utils/completion.ts @@ -1,74 +1,5 @@ import { languages } from '@dtinsight/molecule/esm/monaco'; -interface ICompletionProps { - keyword: string; - description: string; -} - -let keywords: ICompletionProps[] = []; -let functions: ICompletionProps[] = []; -export const Keywords = async (range: languages.CompletionItem['range']): Promise => { - if (!keywords.length || !functions.length) { - return Promise.all([ - fetch('./assets/keywords.json', { method: 'get' }).then((res) => res.json()), - fetch('./assets/functions.json', { method: 'get' }).then((res) => res.json()), - ]) - .then(([keywordList, functionList]) => { - keywords = keywordList; - functions = functionList; - }) - .then(() => { - return [ - ...keywords.map((keyword) => ({ - label: keyword.keyword, - kind: languages.CompletionItemKind.Keyword, - documentation: keyword.description, - insertText: keyword.keyword, - range, - })), - ...functions.map((fn) => ({ - label: fn.keyword, - kind: languages.CompletionItemKind.Function, - documentation: fn.description, - insertText: fn.keyword, - range, - })), - { - label: 'NULL', - kind: languages.CompletionItemKind.Value, - documentation: 'A field with a NULL value is a field with no value.', - insertText: 'NULL', - range, - }, - ]; - }); - } - - return [ - ...keywords.map((keyword) => ({ - label: keyword.keyword, - kind: languages.CompletionItemKind.Keyword, - documentation: keyword.description, - insertText: keyword.keyword, - range, - })), - ...functions.map((fn) => ({ - label: fn.keyword, - kind: languages.CompletionItemKind.Function, - documentation: fn.description, - insertText: fn.keyword, - range, - })), - { - label: 'NULL', - kind: languages.CompletionItemKind.Value, - documentation: 'A field with a NULL value is a field with no value.', - insertText: 'NULL', - range, - }, - ]; -}; - export const Snippets = (range: languages.CompletionItem['range']): languages.CompletionItem[] => [ { label: 'INSERT:snippet', diff --git a/taier-ui/src/utils/enums.tsx b/taier-ui/src/utils/enums.tsx index 81bde15607..0341775434 100644 --- a/taier-ui/src/utils/enums.tsx +++ b/taier-ui/src/utils/enums.tsx @@ -343,15 +343,11 @@ export function resourceNameMapping(type?: RESOURCE_TYPE) { export function mappingTaskTypeToLanguage(taskType: TASK_TYPE_ENUM) { switch (taskType) { case TASK_TYPE_ENUM.SPARK_SQL: - case TASK_TYPE_ENUM.DORIS: - case TASK_TYPE_ENUM.CLICKHOUSE: return TASK_LANGUAGE.SPARKSQL; case TASK_TYPE_ENUM.HIVE_SQL: return TASK_LANGUAGE.HIVESQL; case TASK_TYPE_ENUM.SQL: return TASK_LANGUAGE.FLINKSQL; - case TASK_TYPE_ENUM.OCEANBASE: - return TASK_LANGUAGE.SQL; case TASK_TYPE_ENUM.SYNC: case TASK_TYPE_ENUM.DATA_ACQUISITION: case TASK_TYPE_ENUM.DATAX: @@ -361,7 +357,10 @@ export function mappingTaskTypeToLanguage(taskType: TASK_TYPE_ENUM) { case TASK_TYPE_ENUM.SHELL: return TASK_LANGUAGE.SHELL; case TASK_TYPE_ENUM.MYSQL: + case TASK_TYPE_ENUM.DORIS: return TASK_LANGUAGE.MYSQL; + case TASK_TYPE_ENUM.POSTGRE_SQL: + return TASK_LANGUAGE.PGSQL; default: return TASK_LANGUAGE.SQL; } diff --git a/taier-ui/src/utils/index.ts b/taier-ui/src/utils/index.ts index 80f5986799..e0dad4a8ab 100644 --- a/taier-ui/src/utils/index.ts +++ b/taier-ui/src/utils/index.ts @@ -17,7 +17,6 @@ */ import { Utils } from '@dtinsight/dt-utils'; -import type { languages } from '@dtinsight/molecule/esm/monaco'; import { endsWith, get, pickBy, range as lodashRange } from 'lodash'; import moment from 'moment'; import { history } from 'umi'; @@ -36,7 +35,6 @@ import { WAIT_STATUS, } from '@/constant'; import { taskRenderService } from '@/services'; -import { Keywords, Snippets } from './completion'; /** * 返回今日 [00:00:00, 23:59:69] @@ -434,15 +432,6 @@ export function prettierJSONstring(str: string) { } } -/** - * 生成 SQL 关键字 - */ -export async function createSQLProposals( - range: languages.CompletionItem['range'] -): Promise { - return (await Keywords(range)).concat(Snippets(range)); -} - /** * 获取 13 位的随机 id */ diff --git a/taier-ui/src/utils/is.ts b/taier-ui/src/utils/is.ts index 58c7e22563..3e7255a80c 100644 --- a/taier-ui/src/utils/is.ts +++ b/taier-ui/src/utils/is.ts @@ -7,6 +7,7 @@ import { ID_COLLECTIONS, KAFKA_DATA_TYPE, RDB_TYPE_ARRAY, + SUPPORT_VALID_LANGUEGES, } from '@/constant'; /** @@ -444,3 +445,11 @@ export function isTaskTab(id?: UniqueId) { return !NON_TASK_TAB.some((prefix) => id.startsWith(prefix)); } + +/** + * 判断当前语法是否支持错误解析,如果不支持则跳过错误信息 + */ +export function isValidLanguage(language?: string): language is typeof SUPPORT_VALID_LANGUEGES[number] { + if (!language) return false; + return SUPPORT_VALID_LANGUEGES.includes(language as any); +}