Browse Source

update 优化匹配子查询的方法,支持匹配多层级括号

pull/3/head
yupi 2 years ago
parent
commit
391bac0b45
2 changed files with 79 additions and 10 deletions
  1. +30
    -5
      src/App.vue
  2. +49
    -5
      src/generator/index.ts

+ 30
- 5
src/App.vue View File

@@ -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>


+ 49
- 5
src/generator/index.ts View File

@@ -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)
]
} }

Loading…
Cancel
Save