@@ -7,12 +7,25 @@ import {format} from "sql-formatter"; | |||||
import editorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker' | import editorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker' | ||||
import jsonWorker from 'monaco-editor/esm/vs/language/json/json.worker?worker' | import jsonWorker from 'monaco-editor/esm/vs/language/json/json.worker?worker' | ||||
import cssWorker from 'monaco-editor/esm/vs/language/css/css.worker?worker' | |||||
import htmlWorker from 'monaco-editor/esm/vs/language/html/html.worker?worker' | |||||
import tsWorker from 'monaco-editor/esm/vs/language/typescript/ts.worker?worker' | |||||
self.MonacoEnvironment = { | |||||
getWorker(_, label) { | |||||
// @ts-ignore | |||||
(self as any).MonacoEnvironment = { | |||||
getWorker(_: any, label: any) { | |||||
if (label === 'json') { | if (label === 'json') { | ||||
return new jsonWorker() | return new jsonWorker() | ||||
} | } | ||||
if (label === 'css' || label === 'scss' || label === 'less') { | |||||
return new cssWorker() | |||||
} | |||||
if (label === 'html' || label === 'handlebars' || label === 'razor') { | |||||
return new htmlWorker() | |||||
} | |||||
if (label === 'typescript' || label === 'javascript') { | |||||
return new tsWorker() | |||||
} | |||||
return new editorWorker() | return new editorWorker() | ||||
} | } | ||||
} | } | ||||
@@ -33,6 +46,10 @@ const getSQL = () => { | |||||
} | } | ||||
} | } | ||||
const getInvokeTree = () => { | |||||
} | |||||
const initJSONValue = "{\n" + | const initJSONValue = "{\n" + | ||||
" \"main\": {\n" + | " \"main\": {\n" + | ||||
" \"sql\": \"select * from @union_all_layer(分区 = 2021) where 分区 = #{分区}\",\n" + | " \"sql\": \"select * from @union_all_layer(分区 = 2021) where 分区 = #{分区}\",\n" + | ||||
@@ -82,8 +99,13 @@ onMounted(() => { | |||||
<template> | <template> | ||||
<h1> | <h1> | ||||
SQL 生成器 | |||||
<t-button size="large" theme="primary" @click="getSQL" style="float: right"> 生成 SQL</t-button> | |||||
SQL 生成器 - 用 JSON 来写 SQL | |||||
<div style="float: right"> | |||||
<t-button size="large" theme="primary" @click="getSQL" > 生成 SQL</t-button> | |||||
<t-divider theme="vertical" /> | |||||
<t-button size="large" theme="default" @click="getInvokeTree"> 查看调用树</t-button> | |||||
</div> | |||||
<t-tree :data="[]" activable hover /> | |||||
</h1> | </h1> | ||||
<t-row :gutter="24"> | <t-row :gutter="24"> | ||||
<t-col :xs="12" :sm="6"> | <t-col :xs="12" :sm="6"> | ||||
@@ -93,7 +115,10 @@ onMounted(() => { | |||||
<div id="outputContainer" ref="outputContainer" style="height: 80vh; max-width: 100%"/> | <div id="outputContainer" ref="outputContainer" style="height: 80vh; max-width: 100%"/> | ||||
</t-col> | </t-col> | ||||
</t-row> | </t-row> | ||||
<div>yupi:你能体会手写 1500 行 SQL、牵一发而动全身的恐惧么?</div> | |||||
<br/> | |||||
<div> | |||||
yupi:你能体会手写 1500 行 SQL、牵一发而动全身的恐惧么? | |||||
</div> | |||||
</template> | </template> | ||||
<style> | <style> | ||||
@@ -51,10 +51,9 @@ function replaceSubSql(sql: string, context: InputJSON): string { | |||||
if (!sql) { | if (!sql) { | ||||
return ""; | return ""; | ||||
} | } | ||||
const regExp = /@([\u4e00-\u9fa5_a-zA-Z0-9]+)\((.*?)\)/; | |||||
let result = sql; | let result = sql; | ||||
result = String(result); | result = String(result); | ||||
let regExpMatchArray = result.match(regExp); | |||||
let regExpMatchArray = matchSubQuery(result); | |||||
// 依次替换 | // 依次替换 | ||||
while (regExpMatchArray && regExpMatchArray.length > 2) { | while (regExpMatchArray && regExpMatchArray.length > 2) { | ||||
// 找到结果 | // 找到结果 | ||||
@@ -72,11 +71,12 @@ function replaceSubSql(sql: string, context: InputJSON): string { | |||||
paramsStr = paramsStr.trim(); | paramsStr = paramsStr.trim(); | ||||
} | } | ||||
// e.g. ["a = b", "c = d"] | // e.g. ["a = b", "c = d"] | ||||
const singleParamsStrArray = paramsStr.split(','); | |||||
const singleParamsStrArray = paramsStr.split('|||'); | |||||
// string => object | // string => object | ||||
const params: Record<string, string> = {}; | const params: Record<string, string> = {}; | ||||
for (const singleParamsStr of singleParamsStrArray) { | for (const singleParamsStr of singleParamsStrArray) { | ||||
const keyValueArray = singleParamsStr.split('='); | |||||
// 必须分成 2 段 | |||||
const keyValueArray = singleParamsStr.split('=', 2); | |||||
if (keyValueArray.length < 2) { | if (keyValueArray.length < 2) { | ||||
continue; | continue; | ||||
} | } | ||||
@@ -85,7 +85,51 @@ function replaceSubSql(sql: string, context: InputJSON): string { | |||||
} | } | ||||
const replacement = replaceParams(replacementNode, context, params); | const replacement = replaceParams(replacementNode, context, params); | ||||
result = result.replaceAll(regExpMatchArray[0], replacement); | result = result.replaceAll(regExpMatchArray[0], replacement); | ||||
regExpMatchArray = result.match(regExp); | |||||
regExpMatchArray = matchSubQuery(result); | |||||
} | } | ||||
return result; | return result; | ||||
} | |||||
/** | |||||
* 匹配子查询 | |||||
* @param str | |||||
*/ | |||||
function matchSubQuery(str: string) { | |||||
if (!str) { | |||||
return null; | |||||
} | |||||
const regExp = /@([\u4e00-\u9fa5_a-zA-Z0-9]+)\((.*?)\)/; | |||||
let regExpMatchArray = str.match(regExp); | |||||
if (!regExpMatchArray || regExpMatchArray.index === undefined) { | |||||
return null; | |||||
} | |||||
// @ 开始位置 | |||||
let startPos = regExpMatchArray.index; | |||||
// 左括号右侧 | |||||
let leftParenthesisPos = startPos + regExpMatchArray[1].length + 2; | |||||
// 遍历游标 | |||||
let currPos = leftParenthesisPos; | |||||
// 默认匹配结束位置,需要对此结果进行修正 | |||||
let endPos = startPos + regExpMatchArray[0].length; | |||||
// 剩余待匹配左括号数量 | |||||
let leftCount = 1; | |||||
while (currPos < str.length) { | |||||
const currentChar = str.charAt(currPos); | |||||
if (currentChar === '(') { | |||||
leftCount++; | |||||
} else if (currentChar === ')') { | |||||
leftCount--; | |||||
} | |||||
// 匹配结束 | |||||
if (leftCount == 0) { | |||||
endPos = currPos + 1; | |||||
break; | |||||
} | |||||
currPos++; | |||||
} | |||||
return [ | |||||
str.slice(startPos, endPos), | |||||
regExpMatchArray[1], | |||||
str.slice(leftParenthesisPos, endPos - 1) | |||||
] | |||||
} | } |