Bootstrap

版本比对sql

弹窗  index

<template>
  <el-dialog
    title="版本"
    :visible.sync="dialogVisible"
    width="55%"
    center
    :close-on-click-modal="false"
    :close-on-press-escape="false"
    :before-close="beforeClose"
    @open="open"
    custom-class="dialogClass"
  >
    <template v-slot:title>
      <div>版本</div>
      <el-button
        v-if="isShowVersion"
        style="position: absolute; top: 12px; right: 10%"
        type="primary" size="mini"
        @click="goVersionComparisonPage">
        版本对比
      </el-button>
    </template>
    <div v-loading="dialogLoading || dialogLoading2">
      <el-table
        :data="tableData"
        ref="Table"
        size="mini"
        empty-text="暂无数据"
        :header-cell-style="headerCellStyle"
        :cell-style="cellStyle"
        :header-cell-class-name="cellClass"
        :row-key="getRowKeys"
        @selection-change="selectionChange"
        style="width: 100%"
      >
        <el-table-column v-if="isShowVersion" type="selection" width="55" :reserve-selection="true" :selectable="selectable"></el-table-column>
        <el-table-column label="提交时间" width="160">
          <template slot-scope="scope">
            {{ scope.row.createdAt | formatDate }}
          </template>
        </el-table-column>
        <el-table-column label="提交人" prop="createdBy"></el-table-column>
        <el-table-column label="变更内容" prop="modifyContent">
          <template slot-scope="scope">
            <el-tooltip
              effect="dark"
              placement="top-start"
              v-if="
                !isOverflow(scope.row.modifyContent, scope.column.realWidth)
              "
            >
              <div slot="content" style="white-space: pre-line">
                {{ scope.row.modifyContent }}
              </div>
              <div class="ellipsis-container">
                {{ scope.row.modifyContent }}
              </div>
            </el-tooltip>
            <div v-else>
              {{ scope.row.modifyContent }}
            </div>
          </template>
        </el-table-column>
        <el-table-column label="操作" width="100" v-if="!isShowVersion">
          <template slot-scope="scope">
            <el-button
              type="text"
              size="mini"
              @click="rollback(scope)"
              :disabled="!disabledRollback"
            >
              回滚
            </el-button>
          </template>
        </el-table-column>
        <el-table-column label="操作" width="100" v-if="realTime == 'real'">
          <template slot-scope="scope">
            <el-button
              type="text"
              size="mini"
              @click="detailBack(scope)"
              :disabled="!disabledRollback"
            >
              详情
            </el-button>
            <el-button
              type="text"
              size="mini"
              @click="rollback(scope)"
              :disabled="!disabledRollback"
            >
              回滚
            </el-button>
          </template>
        </el-table-column>
      </el-table>
      <div class="pagination" v-if="realTime !== 'real'">
        <el-pagination
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
          :current-page="currentPage"
          :page-sizes="[10, 50, 100]"
          :page-size="pageSize"
          layout="total, sizes, prev, pager, next, jumper"
          :total="total"
          background
        >
        </el-pagination>
      </div>
    </div>
    <span slot="footer">
      <el-button
        type="primary"
        size="mini"
        @click="save"
        :disabled="dialogLoading || dialogLoading2"
        >确 定</el-button
      >
    </span>
  </el-dialog>
</template>

<script>
import { debounce, formatDate } from "@/utils/index.js";
import dataDevelopment from "@/components/pages/dataDevelopment/schedulinJobs/api/index";
import reatimeJobService from '@/components/pages/dataDevelopment/realtimeJob/api/index.js'

export default {
  name: "versionsDialog",
  props: {
    sqlType: String,
    taskSqlCode: {
      type: String,
      default: "",
    },
    taskSqlName: {
      type: String,
      default: "",
    },
    dialogVisible: {
      type: Boolean,
      default: false,
    },
    dialogLoading: {
      type: Boolean,
      default: false,
    },
    taskCode: {
      type: String,
      default: "",
    },
    taskStatus: {
      type: String,
      default: "",
    },
    taskName: {
      type: String,
      default: "",
    },
    isShowVersion: {
      type: Boolean,
      default: false,
    },
    sqlStatus: {
      type: Boolean,
      default: false,
    },
    realTime: {
      type: String,
      default: "",
    },
  },
  filters: {
    formatDate,
  },
  data() {
    return {
      tableData: [],
      total: 0,
      currentPage: 1,
      pageSize: 10,
      dialogLoading2: false,
      multipleSelection: []
    };
  },
  computed: {
    disabledRollback() {
      if (this.sqlType) {
        return this.sqlStatus
      }
      return this.taskStatus === "1" || this.taskStatus === "0";
    },

  },
  methods: {
    /** 去除全选框 */
    cellClass(row) {
      //若是第一行,即全选框所在的那一行
      if (row.columnIndex === 0) {
        this.$nextTick(() => {
          // 每次触发 headerCell 判断如果是第一个 单元格 调用该方法
          // row.column.id 是该单元格的 class 样式
          // 通过 class 样式连续找两层 children 节点 如果存在 执行 remove()
          let selectBox = document.querySelector(`.${row.column.id}`);
          selectBox.children[0].children[0]?.remove();
        })
      }
    },
    /** 分页保持选择框 */
    getRowKeys(row) {
      return row.id;
    },
    /** 获取选中的数据 */
    selectionChange(list) {
      if (list.length > 2) {
        this.$refs.Table.clearSelection(); //用于多选表格,清空用户的选择
        for (let i = 0; i < 2; i++) {
          this.$refs.Table.toggleRowSelection(list[i]); //用于多选表格,切换某一行的选中状态,如果使用了第二个参数,则是设置这一行选中与否(selected 为 true 则选中)
        }
        return;
      }
      this.multipleSelection = [...list];
    },
    /** Checkbox是否禁用 */
    selectable(row) {
      let index = this.multipleSelection.findIndex((v) => v.id === row.id);
      return this.multipleSelection.length >= 2 ? index !== -1 ? true : false : true;
    },
    /** 跳转去版本对比页面 */
    goVersionComparisonPage() {
      const newList = this.multipleSelection.map(item => item.id);
      if (this.realTime == 'real') {
        this.$router.push({
          name: 'DetailComparison',
          query: {
            realTime: this.realTime,
            multipleSelection: JSON.stringify(newList),
            taskCode: this.taskSqlCode,
            taskName: this.taskSqlName
          }
        })
      } else {
        this.$router.push({
          name: 'versionComparison',
          query: {
            multipleSelection: JSON.stringify(newList),
            taskCode: this.taskCode,
            taskName: this.taskName
          }
        })
      }
    },
    /** 每页条数变更 */
    handleSizeChange(val) {
      this.pageSize = val;
      this.queryHistoryPage();
    },
    /** 当前页码变更 */
    handleCurrentChange(val) {
      this.currentPage = val;
      this.queryHistoryPage();
    },
    /** 回滚 */
    rollback: debounce(function ({ row }) {
      if (this.sqlType) {
        this.$confirm(
        "当前未提交的内容将会被覆盖。",
        "提示",
        {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning",
        }
      )
        .then(() => {
          this.$emit("realSqlback", row);
        })
        .catch(() => {});
      } else {
        this.$confirm(
        "1. 当前未提交的内容将会被覆盖。2. 回滚后要“提交”才能生效。确定要回滚当前版本?",
        "提示",
        {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning",
        }
      )
        .then(() => {
          this.$emit("rollback", row);
        })
        .catch(() => {});
      }
    }, 300),
    /** 版本详情 */
    async detailBack(row) {
      let params = {
        taskCode: this.taskSqlCode,
        versionId: row.row.id
      }
      let res = await reatimeJobService.getVersionDetail(params)
      let rowDetail
      if (res.data.success) {
        rowDetail = res.data?.result

      } else {
        this.$notification.error(res.data.errorMsg);
      }
      this.$router.push({
        name: 'DetailComparison',
        query: {
          ...rowDetail
        }
      })
    },
    /** 弹框关闭 */
    beforeClose() {
      this.$emit("close");
    },
    /** 弹框打开 */
    open() {
      this.pageSize = 10;
      this.currentPage = 1;
      this.queryHistoryPage();
      this.$nextTick(() => {
        this.$refs.Table.clearSelection();
      })
    },
    /** 获取版本列表 */
    async queryHistoryPage() {
      try {
        this.dialogLoading2 = true;
        let taskCode = this.taskCode;
        let res
        if (this.sqlType) {
           let taskSqlCode = this.taskSqlCode
            res = await reatimeJobService.getVersionList(taskSqlCode);
        } else {
          const params = {
            taskCode,
            pageSize: this.pageSize,
            pageNo: this.currentPage,
          };
          res = await dataDevelopment.queryHistoryPage(params);
        }
        if (res.data?.success) {
          const result = res.data.result;
          if (this.sqlType) {
            this.total = result?.length;
            this.tableData = result
             this.tableData =  this.tableData.map(item => {
              return {
                id: item.versionId,
                createdAt: item.submitTime,
                createdBy: item.submittedBy,
                modifyContent: item.content,
              }
             })
          } else {
            this.tableData = result.records;
            this.total = result.total;
          }
        } else {
          this.$notification.error(res.data.errorMsg);
        }
      } catch (error) {
        this.tableData = [];
        this.total = 0;
        console.error(error);
      } finally {
        this.dialogLoading2 = false;
      }
    },
    /** 确定 */
    save() {
      this.beforeClose();
    },
    // 表格居中
    cellStyle() {
      return "text-align: center;font-size: 12px;";
    },
    // 表格样式
    headerCellStyle() {
      return "text-align: center;color: #000000;";
    },
    /** 是否开启了隐藏 */
    isOverflow(text, width) {
      const el = document.createElement("span");
      el.innerHTML = text;
      document.body.appendChild(el);
      const flag = el.offsetWidth < width;
      document.body.removeChild(el);
      return flag;
    },
  },
};
</script>

<style lang="scss" scoped>
::v-deep .dialogClass {
  max-height: 78%;
  display: flex;
  flex-direction: column;

  .el-dialog__body {
    padding: 10px;
    flex: 1;
    overflow-y: auto;
  }
}
.pagination {
  display: flex;
  justify-content: flex-end;
  margin: 20px 10px;
}

.ellipsis-container {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
</style>

sql编辑器

<template>
  <div class="monaco">
    <div ref="container" class="monaco-editor" style="height: 400px"></div>
  </div>
</template>

<script>
import * as monaco from "monaco-editor";
import sqlInfo from "./sql";

export default {
  name: "Monaco",
  data() {
    return {
      // 编辑器对象
      monacoDiffInstance: null,
    }
  },

  methods: {
    init(event) {
      if (this.monacoDiffInstance) {
        this.monacoDiffInstance.dispose()
      }
      // 初始化container的内容,销毁之前生成的编辑器
      this.$refs.container.innerHTML = '';
      this.theme();
      this.registerSQL();
      if (event.realTime) {
        // 版本对比
        this.monacoDiffInstance = monaco.editor.createDiffEditor(this.$refs['container'], {
          value: '', // 编辑器的值
          theme: 'vs-dark', // 编辑器主题:vs, hc-black, or vs-dark,更多选择详见官网
          roundedSelection: false, // 右侧不显示编辑器预览框
          autoIndent: true, // 自动缩进
          readOnly: true,
          // language: 'json',
          automaticLayout: true // 自动布局
        });
        const { sourceTaskScript, targetTaskScript } = event;
        const originalModel = monaco.editor.createModel(sourceTaskScript, 'sql');
        const modifiedModel = monaco.editor.createModel(targetTaskScript, 'sql');
        this.monacoDiffInstance.setModel({
          // oldValue为以前的值
          original: originalModel,
          // oldValue为新的值
          modified: modifiedModel
        })
      } else {
        // 详情
        const sqlCode = event;
        // 初始化编辑器实例
        this.monacoDiffInstance = monaco.editor.create(this.$refs['container'], {
          value: sqlCode, // 编辑器的值
          language: 'sql', // 设置语言为 SQL
          theme: 'vs-dark', // 编辑器主题
          readOnly: true,
          automaticLayout: true // 自动布局
        });
      }
    },

    //自定义主题
    theme() {
      monaco.editor.defineTheme('hiveTheme', {
        base: 'vs-dark',
        inherit: true,
        rules: [
          { token: 'builtFunc', foreground: 'FF00FF' },//内置方法以及变量、伪列
          { token: 'opera', foreground: '778899' }//运算符
        ]
      })
    },
    registerSQL() {
      monaco.languages.register({ id: 'customSql' });
      monaco.languages.setMonarchTokensProvider('customSql', {
        ignoreCase: true,//关键字大小写都可高亮
        brackets: sqlInfo.brackets,
        keywords: sqlInfo.keywords,
        operators: sqlInfo.operators,
        builtinFunctions: sqlInfo.builtinFunctions,
        builtinVariables: sqlInfo.builtinVariables,
        pseudoColumns: sqlInfo.pseudoColumns,
        tokenizer: sqlInfo.tokenizer
      })
    }
  }


}
</script>

<style scoped>
</style>

filter

<template>
  <div class="filter-item">
    <div>
      <div class="task-desc">
        任务:{{ taskName }}
      </div>
      <div class="form-box">
        <el-form class="source-form" ref="sourceForm" :model="sourceForm" label-width="80px" size="mini">
          <el-form-item label="版本:" v-if="this.$route.query.realTime == 'real'">
            <el-select v-model="sourceForm.version"
                       placeholder="请选择版本"
                       filterable
                       :loading="loading"
                       @change="getCodeCompareScript('source')">
              <el-option v-for="v in sourceVersionList" :label="v.createdAt" :value="v.id" :key="v.id">
              </el-option>
            </el-select>
          </el-form-item>
          <el-form-item label="版本:" v-else>
            <el-select v-model="sourceForm.version"
                       placeholder="请选择版本"
                       filterable
                       disabled
                       :loading="loading"
                       @change="getCodeCompareScript('source')">
              <el-option v-for="v in sourceVersionList" :label="v.createdAt" :value="v.id" :key="v.id">
              </el-option>
            </el-select>
          </el-form-item>
          <el-form-item label="提交人:">{{ sourceForm.createdBy  }}</el-form-item>
          <el-form-item label="提交时间:">{{ sourceForm.createdAt }}</el-form-item>
        </el-form>
        <div v-if="this.$route.query.realTime == 'real'">
          <el-divider direction="vertical" class="vertical-form"></el-divider>
          <el-form class="target-form" ref="targetForm" :model="targetForm" label-width="80px" size="mini">
            <el-form-item label="版本:">
              <el-select v-model="targetForm.version" placeholder="请选择版本" @change="getCodeCompareScript('target')">
                <el-option v-for="v in sourceVersionList" :label="v.createdAt" :value="v.id" :key="v.id">
                </el-option>
              </el-select>
            </el-form-item>
            <el-form-item label="提交人:">{{ targetForm.createdBy }}</el-form-item>
            <el-form-item label="提交时间:">{{ targetForm.createdAt }}</el-form-item>
          </el-form>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import dayjs from "dayjs";
import {DateFormatEnum} from "@/modal/public-enum";
import reatimeJobService from "../../../realtimeJob/api";

export default {
  name: "FilterItems",
  data() {
    return {
      sourceForm: {
        version: '',
        createdAt: '',
        createdBy: ''
      },
      targetForm: {
        version: '',
        createdAt: '',
        createdBy: ''
      },
      sourceVersionList: [],
      taskCode: '',
      taskName: '',
      pageSize: 100,
      currentPage: 1,
      multipleSelection: [],
      loading: false
    }
  },
  mounted() {
    if (this.$route.query.realTime == 'real') {
      this.multipleSelection = JSON.parse(this.$route.query.multipleSelection);
      this.taskCode = this.$route.query.taskCode;
      this.taskName = this.$route.query.taskName;
      this.queryHistoryPage();
    } else {
      this.sourceForm = this.$route.query
      this.sourceForm.version = this.createAt(this.$route.query.createAt)
      this.sourceForm.createdAt = this.createAt(this.$route.query.createAt)
      this.sourceForm.createdBy = this.$route.query.createBy || '--'
      this.getCodeCompareScript()
    }
  },
  methods: {
    createAt(val) {
      return dayjs(Number(val)).format(DateFormatEnum.DATETIME_FORM)
    },
    /** 获取版本列表 */
    async queryHistoryPage() {
      this.loading = true;
      try {
        const params = {
          taskCode: this.taskCode,
          pageSize: this.pageSize,
          pageNo: this.currentPage,
        };
        console.log(this.$route.query);
        const res = await reatimeJobService.getVersionList(params.taskCode);
        if (res.data?.success) {
          const result = res.data.result;
          if (result.length > 0) {
            this.sourceVersionList = result.map(item => {
              return {
                ...item,
                id: item.versionId,
                createdAt: dayjs(item.submitTime).format(DateFormatEnum.DATETIME_FORM),
              }
            });
            if (this.multipleSelection.length === 0) {
              const {  id } = this.sourceVersionList[0];
              this.sourceForm.version = id;
              this.getCodeCompareScript('source');
              return;
            }
            if (this.multipleSelection[0]) {
              const { id } = this.setDefaultVersion(this.multipleSelection[0]);
              this.sourceForm.version = id;

              this.getCodeCompareScript('source');
            }
            if (this.multipleSelection[1]) {
              const { id } = this.setDefaultVersion(this.multipleSelection[1]);
              this.targetForm.version = id;
              this.getCodeCompareScript();
            }

          }
        } else {
          this.$notification.error(res.data.errorMsg);
        }
      } catch (error) {
        this.sourceVersionList = [];
        this.total = 0;
      } finally {
        this.loading = false;
      }
    },
    /**
     * 设置默认版本
     */
    setDefaultVersion(val) {
      return this.sourceVersionList.find(item => item.id === val);
    },

    /**
     * 版本对比
     */
    getCodeCompareScript(type) {
      if (this.$route.query.realTime == 'real') {
        const sourceItem = this.setDefaultVersion(this.sourceForm.version);
        const targetItem = this.setDefaultVersion(this.targetForm.version);
        this.$emit('codeCompare', {
          sourceTaskScript: sourceItem.script,
          targetTaskScript: targetItem ? targetItem.script : null,
          realTime: this.$route.query.realTime
        })
        if (type === 'source') {
          this.sourceForm.createdBy = sourceItem.submittedBy;
          this.sourceForm.createdAt = dayjs(sourceItem.submitTime).format(DateFormatEnum.DATETIME_FORM)
        } else {
          this.targetForm.createdBy = targetItem.submittedBy;
          this.targetForm.createdAt = dayjs(targetItem.submitTime).format(DateFormatEnum.DATETIME_FORM)
        }
      } else {
        const sourceItem = this.sourceForm;
        this.$emit('codeCompare', sourceItem.script)
        this.sourceForm.createdBy = sourceItem.createdBy;
        this.sourceForm.createdAt = sourceItem.createdAt;
      }
    }
  }
}
</script>

<style scoped lang="scss">
.filter-item {
  .form-box {
    display: flex;
    .source-form, target-form {
      width: 49%;
    }
    .target-form {
      padding-left: 12px;
    }
  }
  .task-desc {
    margin-bottom: 12px;
  }
}
</style>

task

<template>
  <div class="task">
    <FilterItems @codeCompare="codeCompare"></FilterItems>
    <el-tabs v-model="activeName" >
      <el-tab-pane label="代码" name="code">
        <Monaco ref="MonacoRef"></Monaco>
      </el-tab-pane>
    </el-tabs>
  </div>
</template>

<script>
import FilterItems from '../FilterItems/FilterItems'
import Monaco from "./components/Monaco/Monaco";

export default {
  name: "task",
  components: { FilterItems, Monaco },
  data() {
    return {
      activeName: 'code',
    }
  },
  mounted() {
  },
  methods: {
    codeCompare(event) {
      this.$refs.MonacoRef.init(event);
    }

  }
}
</script>

<style scoped lang="scss">
.task {
  .form-box {
    display: flex;
    .source-form, target-form {
      width: 49%;
    }
    .target-form {
      padding-left: 12px;
    }
  }
  .task-desc {
    margin-bottom: 12px;
    text-align: center;
  }
}
</style>

sql

const sqlInfo = {
  //括号
  brackets:[
    { open: '[', close: ']', token: 'delimiter.square' },
    { open: '(', close: ')', token: 'delimiter.parenthesis' }
  ],
  //关键字
  keywords:[
    //Non-reserved Keywords
    //1.2.0
    'ADD','ADMIN','AFTER','ANALYZE','ARCHIVE','ASC','BEFORE','BUCKET',
    'BUCKETS','CASCADE','CHANGE','CLUSTER','CLUSTERED','CLUSTERSTATUS',
    'COLLECTION','COLUMNS','COMMENT','COMPACT','COMPACTIONS','COMPUTE',
    'CONCATENATE','CONTINUE','DATA','DATABASES','DATETIME','DAY',
    'DBPROPERTIES','DEFERRED','DEFINED','DELIMITED','DEPENDENCY','DESC',
    'DIRECTORIES','DIRECTORY','DISABLE','DISTRIBUTE','ELEM_TYPE',
    'ENABLE','ESCAPED','EXCLUSIVE','EXPLAIN', 'EXPORT', 'FIELDS', 'FILE',
    'FILEFORMAT','FIRST','FORMAT','FORMATTED','FUNCTIONS','HOLD_DDLTIME',
    'HOUR','IDXPROPERTIES','IGNORE','INDEX','INDEXES','INPATH',
    'INPUTDRIVER','INPUTFORMAT','ITEMS','JAR','KEYS','KEY_TYPE','LIMIT',
    'LINES','LOAD','LOCATION','LOCK','LOCKS','LOGICAL','LONG','MAPJOIN',
    'MATERIALIZED','METADATA','MINUS','MINUTE','MONTH','MSCK','NOSCAN',
    'NO_DROP', 'OFFLINE','OPTION','OUTPUTDRIVER', 'OUTPUTFORMAT',
    'OVERWRITE', 'OWNER', 'PARTITIONED', 'PARTITIONS', 'PLUS', 'PRETTY',
    'PRINCIPALS', 'PROTECTION', 'PURGE', 'READ', 'READONLY', 'REBUILD',
    'RECORDREADER', 'RECORDWRITER', 'REGEXP', 'RELOAD', 'RENAME',
    'REPAIR', 'REPLACE', 'REPLICATION', 'RESTRICT', 'REWRITE', 'RLIKE',
    'ROLE', 'ROLES', 'SCHEMA', 'SCHEMAS', 'SECOND', 'SEMI', 'SERDE',
    'SERDEPROPERTIES', 'SERVER', 'SETS', 'SHARED', 'SHOW', 'SHOW_DATABASE',
    'SKEWED', 'SORT', 'SORTED', 'SSL', 'STATISTICS', 'STORED', 'STREAMTABLE',
    'STRING', 'STRUCT', 'TABLES', 'TBLPROPERTIES', 'TEMPORARY', 'TERMINATED',
    'TINYINT', 'TOUCH', 'TRANSACTIONS', 'UNARCHIVE', 'UNDO', 'UNIONTYPE',
    'UNLOCK', 'UNSET', 'UNSIGNED', 'URI', 'USE', 'UTC', 'UTCTIMESTAMP',
    'VALUE_TYPE', 'VIEW', 'WHILE', 'YEAR',
    //2.0.0 add  remove:REGEXP, RLIKE
    'AUTOCOMMIT','ISOLATION', 'LEVEL', 'OFFSET', 'SNAPSHOT', 'TRANSACTION', 'WORK', 'WRITE',
    //2.1.0 add
    'ABORT', 'KEY', 'LAST', 'NORELY', 'NOVALIDATE', 'NULLS', 'RELY', 'VALIDATE',
    //2.2.0 add
    'DETAIL', 'DOW', 'EXPRESSION', 'OPERATOR', 'QUARTER', 'SUMMARY', 'VECTORIZATION', 'WEEK', 'YEARS', 'MONTHS', 'WEEKS', 'DAYS', 'HOURS', 'MINUTES', 'SECONDS',
    //3.0.0 add
    'TIMESTAMPTZ', 'ZONE',

    //Reserved Keywords
    //2.0.0 add
    'COMMIT', 'ONLY', 'REGEXP', 'RLIKE', 'ROLLBACK', 'START',
    //2.1.0 add
    'CACHE', 'CONSTRAINT', 'FOREIGN', 'PRIMARY', 'REFERENCES',
    //2.2.0 add
    'DAYOFWEEK', 'EXTRACT', 'FLOOR', 'INTEGER', 'PRECISION', 'VIEWS',
    //3.0.0 add
    'TIME', 'NUMERIC', 'SYNC',
    //1.2.0
    'ALL', 'ALTER', 'AND', 'ARRAY', 'AS', 'AUTHORIZATION', 'BETWEEN',
    'BIGINT', 'BINARY', 'BOOLEAN', 'BOTH', 'BY', 'CASE', 'CAST', 'CHAR',
    'COLUMN', 'CONF', 'CREATE', 'CROSS', 'CUBE', 'CURRENT', 'CURRENT_DATE',
    'CURRENT_TIMESTAMP', 'CURSOR', 'DATABASE', 'DATE', 'DECIMAL', 'DELETE',
    'DESCRIBE', 'DISTINCT', 'DOUBLE', 'DROP', 'ELSE', 'END', 'EXCHANGE',
    'EXISTS', 'EXTENDED', 'EXTERNAL', 'FALSE', 'FETCH', 'FLOAT', 'FOLLOWING',
    'FOR', 'FROM', 'FULL', 'FUNCTION', 'GRANT', 'GROUP', 'GROUPING',
    'HAVING', 'IF', 'IMPORT', 'IN', 'INNER', 'INSERT', 'INT', 'INTERSECT',
    'INTERVAL', 'INTO', 'IS', 'JOIN', 'LATERAL', 'LEFT', 'LESS', 'LIKE',
    'LOCAL', 'MACRO', 'MAP', 'MORE', 'NONE', 'NOT', 'NULL', 'OF', 'ON',
    'OR', 'ORDER', 'OUT', 'OUTER', 'OVER', 'PARTIALSCAN', 'PARTITION',
    'PERCENT', 'PRECEDING', 'PRESERVE', 'PROCEDURE', 'RANGE', 'READS',
    'REDUCE', 'REVOKE', 'RIGHT', 'ROLLUP', 'ROW', 'ROWS', 'SELECT',
    'SET', 'SMALLINT', 'TABLE', 'TABLESAMPLE', 'THEN', 'TIMESTAMP', 'TO',
    'TRANSFORM', 'TRIGGER', 'TRUE', 'TRUNCATE', 'UNBOUNDED', 'UNION',
    'UNIQUEJOIN', 'UPDATE', 'USER', 'USING', 'UTC_TMESTAMP', 'VALUES',
    'VARCHAR', 'WHEN', 'WHERE', 'WINDOW', 'WITH'
  ],
  //运算符
  operators:[
    'DIV',
    // Logical
    'ALL', 'AND', 'ANY', 'BETWEEN', 'EXISTS', 'IN', 'LIKE', 'NOT', 'OR', 'SOME',
    // Set
    'EXCEPT', 'INTERSECT', 'UNION',
    // Join
    'APPLY', 'CROSS', 'FULL', 'INNER', 'JOIN', 'LEFT', 'OUTER', 'RIGHT',
    // Predicates
    'CONTAINS', 'FREETEXT', 'IS', 'NULL',
    // Pivoting
    'PIVOT', 'UNPIVOT',
    // Merging
    'MATCHED'
  ],
  //内置方法
  builtinFunctions:[
    //Complex Type Constructors
    'MAP','STRUCT','NAMED_STRUCT','ARRAY','CREATE_UNION',
    //Mathematical Functions
    'BROUND','CEIL','IN','ln','LOG2','POW','BIN','HEX','UNHEX','CONV','POSITIVE','PMOD','NEGATIVE',
    'E','FACTORIAL','CBRT','SHIFTLEFT','SHIFTRIGHT','SHIFTRIGHTUNSIGNED','GREATEST','LEAST','WIDTH_BUCKET',
    //Collection Functions
    'SIZE','MAP_KEYS','MAP_VALUES','ARRAY_CONTAINS','SORT_ARRAY',
    //Type Conversion Functions
    'BINARY',
    //Date Functions
    'FROM_UNIXTIME','UNIX_TIMESTAMP','TO_DATE','QUARTER','HOUR','MINUTE',
    'SECOND','WEEKOFYEAR','EXTRACT','DATE_ADD','DATE_SUB','FROM_UTC_TIMESTAMP',
    'TO_UTC_TIMESTAMP','CURRENT_DATE','ADD_MONTHS','LAST_DAY','NEXT_DAY',
    'TRUNC','MONTHS_BETWEEN','DATE_FORMAT',
    //Conditional Functions
    'IF','ISNOTNULL','NVL','ASSERT_TRUE',
    //String Functions
    'BASE64','CHARACTER_LENGTH','CHR','CONTEXT_NGRAMS','CONCAT_WS','DECODE',
    'ELT','ENCODE','FIELD','FIND_IN_SET','FORMAT_NUMBER','GET_JSON_OBJECT',
    'IN_FILE','INSTR','LENGTH','LOCATE','LPAD','NGRAMS','OCTET_LENGTH',
    'PARSE_URL','PRINTF','QUOTE','REGEXP_EXTRACT','REGEXP_REPLACE','REPEAT',
    'RPAD','SENTENCES','SPLIT','STR_TO_MAP','SUBSTR','SUBSTRING_INDEX',
    'TRANSLATE','TRIM','UNBASE64','INITCAP','LEVENSHTEIN',
    //Data Masking Functions
    'MASK','MASK_FIRST_N','MASK_LAST_N','MASK_SHOW_FIRST_N','MASK_SHOW_LAST_N','MASK_HASH',
    //Misc. Functions
    'JAVA_METHOD','REFLECT','HASH','LOGGED_IN_USER','CURRENT_DATABASE','MD5','SHA1','SHA',
    'CRC32','SHA2','AES_ENCRYPT','AES_DECRYPT','SURROGATE_KEY','VERSION',
    //Built-in Aggregate Functions (UDAF)
    'VARIANCE','VAR_SAMP','STDDEV_POP','STDDEV_SAMP','COVAR_POP','COVAR_SAMP',
    'CORR','PERCENTILE','PERCENTILE_APPROX','REGR_AVGX','REGR_AVGY','REGR_COUNT',
    'REGR_INTERCEPT','REGR_R2','REGR_SLOPE','REGR_SXX','REGR_SXY','REGR_SYY',
    'HISTOGRAM_NUMERIC','COLLECT_SET','COLLECT_LIST',
    //Built-in Table-Generating Functions (UDTF)
    'EXPLODE','POSEXPLODE','INLINE','STACK','JSON_TUPLE','PARSE_URL_TUPLE',
    // Aggregate
    'AVG', 'CHECKSUM_AGG', 'COUNT', 'COUNT_BIG', 'GROUPING', 'GROUPING_ID', 'MAX', 'MIN', 'SUM', 'STDEV', 'STDEVP', 'VAR', 'VARP',
    // Analytic
    'CUME_DIST', 'FIRST_VALUE', 'LAG', 'LAST_VALUE', 'LEAD', 'PERCENTILE_CONT', 'PERCENTILE_DISC', 'PERCENT_RANK',
    // Collation
    'COLLATE', 'COLLATIONPROPERTY', 'TERTIARY_WEIGHTS',
    // Azure
    'FEDERATION_FILTERING_VALUE',
    // Conversion
    'CAST', 'CONVERT', 'PARSE', 'TRY_CAST', 'TRY_CONVERT', 'TRY_PARSE',
    // Cryptographic
    'ASYMKEY_ID', 'ASYMKEYPROPERTY', 'CERTPROPERTY', 'CERT_ID', 'CRYPT_GEN_RANDOM',
    'DECRYPTBYASYMKEY', 'DECRYPTBYCERT', 'DECRYPTBYKEY', 'DECRYPTBYKEYAUTOASYMKEY', 'DECRYPTBYKEYAUTOCERT', 'DECRYPTBYPASSPHRASE',
    'ENCRYPTBYASYMKEY', 'ENCRYPTBYCERT', 'ENCRYPTBYKEY', 'ENCRYPTBYPASSPHRASE', 'HASHBYTES', 'IS_OBJECTSIGNED',
    'KEY_GUID', 'KEY_ID', 'KEY_NAME', 'SIGNBYASYMKEY', 'SIGNBYCERT', 'SYMKEYPROPERTY', 'VERIFYSIGNEDBYCERT', 'VERIFYSIGNEDBYASYMKEY',
    // Cursor
    'CURSOR_STATUS',
    // Datatype
    'DATALENGTH', 'IDENT_CURRENT', 'IDENT_INCR', 'IDENT_SEED', 'IDENTITY', 'SQL_VARIANT_PROPERTY',
    // Datetime
    'CURRENT_TIMESTAMP', 'DATEADD', 'DATEDIFF', 'DATEFROMPARTS', 'DATENAME', 'DATEPART', 'DATETIME2FROMPARTS', 'DATETIMEFROMPARTS',
    'DATETIMEOFFSETFROMPARTS', 'DAY', 'EOMONTH', 'GETDATE', 'GETUTCDATE', 'ISDATE', 'MONTH', 'SMALLDATETIMEFROMPARTS', 'SWITCHOFFSET',
    'SYSDATETIME', 'SYSDATETIMEOFFSET', 'SYSUTCDATETIME', 'TIMEFROMPARTS', 'TODATETIMEOFFSET', 'YEAR',
    // Logical
    'CHOOSE', 'COALESCE', 'IIF', 'NULLIF',
    // Mathematical
    'ABS', 'ACOS', 'ASIN', 'ATAN', 'ATN2', 'CEILING', 'COS', 'COT', 'DEGREES', 'EXP', 'FLOOR', 'LOG', 'LOG10',
    'PI', 'POWER', 'RADIANS', 'RAND', 'ROUND', 'SIGN', 'SIN', 'SQRT', 'SQUARE', 'TAN',
    // Metadata
    'APP_NAME', 'APPLOCK_MODE', 'APPLOCK_TEST', 'ASSEMBLYPROPERTY', 'COL_LENGTH', 'COL_NAME', 'COLUMNPROPERTY',
    'DATABASE_PRINCIPAL_ID', 'DATABASEPROPERTYEX', 'DB_ID', 'DB_NAME', 'FILE_ID', 'FILE_IDEX', 'FILE_NAME', 'FILEGROUP_ID',
    'FILEGROUP_NAME', 'FILEGROUPPROPERTY', 'FILEPROPERTY', 'FULLTEXTCATALOGPROPERTY', 'FULLTEXTSERVICEPROPERTY',
    'INDEX_COL', 'INDEXKEY_PROPERTY', 'INDEXPROPERTY', 'OBJECT_DEFINITION', 'OBJECT_ID',
    'OBJECT_NAME', 'OBJECT_SCHEMA_NAME', 'OBJECTPROPERTY', 'OBJECTPROPERTYEX', 'ORIGINAL_DB_NAME', 'PARSENAME',
    'SCHEMA_ID', 'SCHEMA_NAME', 'SCOPE_IDENTITY', 'SERVERPROPERTY', 'STATS_DATE', 'TYPE_ID', 'TYPE_NAME', 'TYPEPROPERTY',
    // Ranking
    'DENSE_RANK', 'NTILE', 'RANK', 'ROW_NUMBER',
    // Replication
    'PUBLISHINGSERVERNAME',
    // Rowset
    'OPENDATASOURCE', 'OPENQUERY', 'OPENROWSET', 'OPENXML',
    // Security
    'CERTENCODED', 'CERTPRIVATEKEY', 'CURRENT_USER', 'HAS_DBACCESS', 'HAS_PERMS_BY_NAME', 'IS_MEMBER', 'IS_ROLEMEMBER', 'IS_SRVROLEMEMBER',
    'LOGINPROPERTY', 'ORIGINAL_LOGIN', 'PERMISSIONS', 'PWDENCRYPT', 'PWDCOMPARE', 'SESSION_USER', 'SESSIONPROPERTY', 'SUSER_ID', 'SUSER_NAME',
    'SUSER_SID', 'SUSER_SNAME', 'SYSTEM_USER', 'USER', 'USER_ID', 'USER_NAME',
    // String
    'ASCII', 'CHAR', 'CHARINDEX', 'CONCAT', 'DIFFERENCE', 'FORMAT', 'LEFT', 'LEN', 'LOWER', 'LTRIM', 'NCHAR', 'PATINDEX',
    'QUOTENAME', 'REPLACE', 'REPLICATE', 'REVERSE', 'RIGHT', 'RTRIM', 'SOUNDEX', 'SPACE', 'STR', 'STUFF', 'SUBSTRING', 'UNICODE', 'UPPER',
    // System
    'BINARY_CHECKSUM', 'CHECKSUM', 'CONNECTIONPROPERTY', 'CONTEXT_INFO', 'CURRENT_REQUEST_ID', 'ERROR_LINE', 'ERROR_NUMBER', 'ERROR_MESSAGE',
    'ERROR_PROCEDURE', 'ERROR_SEVERITY', 'ERROR_STATE', 'FORMATMESSAGE', 'GETANSINULL', 'GET_FILESTREAM_TRANSACTION_CONTEXT', 'HOST_ID',
    'HOST_NAME', 'ISNULL', 'ISNUMERIC', 'MIN_ACTIVE_ROWVERSION', 'NEWID', 'NEWSEQUENTIALID', 'ROWCOUNT_BIG', 'XACT_STATE',
    // TextImage
    'TEXTPTR', 'TEXTVALID',
    // Trigger
    'COLUMNS_UPDATED', 'EVENTDATA', 'TRIGGER_NESTLEVEL', 'UPDATE',
    // ChangeTracking
    'CHANGETABLE', 'CHANGE_TRACKING_CONTEXT', 'CHANGE_TRACKING_CURRENT_VERSION', 'CHANGE_TRACKING_IS_COLUMN_IN_MASK', 'CHANGE_TRACKING_MIN_VALID_VERSION',
    // FullTextSearch
    'CONTAINSTABLE', 'FREETEXTTABLE',
    // SemanticTextSearch
    'SEMANTICKEYPHRASETABLE', 'SEMANTICSIMILARITYDETAILSTABLE', 'SEMANTICSIMILARITYTABLE',
    // FileStream
    'FILETABLEROOTPATH', 'GETFILENAMESPACEPATH', 'GETPATHLOCATOR', 'PATHNAME',
    // ServiceBroker
    'GET_TRANSMISSION_STATUS',

    //SPARK SQL FN
    'ACOSH','AGGREGATE','APPROX_COUNT_DISTINCT','APPROX_PRECENTILE','ARRAY_DISTINCT',
    'ARRAY_EXCEPT','ARRAY_INTERSECT','ARRAY_JOIN','ARRAY_MAX','ARRAY_MIN','ARRAY_POSITION',
    'ARRAY_REMOVE','ARRAY_REPEAT','ARRAY_SORT','ARRAY_UNION','ARRAYS_OVERLAP',
    'ARRAYS_ZIP','SAINH','ATANH','ATAN2','BIT_AND','BIT_COUNT','BIT_LENGTH',
    'BIT_OR','BIT_XOR','BOOL_AND','BOOL_OR','CARDINALITY','CHAR_LENGTH',
    'COSH','COUNT_IF','COUNT_MIN_SKETCH','DATE_PART','DATE_TRUNC','DATEOFMONTH',
    'DATEOFYEAR','ELEMENT_AT','EVERY','EXPLODE_OUTER','EXPM1','FILTER','FLATTEN',
    'FORALL','FORMAT_STRING','FROM_CSV','FROM_JSON','GROUPING','GROUPING_ID',
    'HYPOT','IFNULL','INLINE_OUTER','INPUT_FILR_BLOCK_LENGTH','INPUT_FILR_BLOCK_START',
    'INPUT_FILR_NAME','ISNAN','KURTOSIS','LCASE','LOG1P','IPAD','ITRIM','MAKE_DATE','MAKE_INTERVAL','MAKE_TIMESTAMP',
    'MAP_CONCAT','MAP_ENTRIES','MAP_FROM_ARRAYS','MAP_FROM_ENTRIES','MAP_ZIP_WITH',
    'MAX_BY','MEAN','MIN_BY','MOD','MONOTONICALLY_INCREASING_ID','NANVL','NOW','NVL2',
    'OVERLAY','POSEXPLODE_OUTER','POSITION','RANDN','RANDOM','RINT','SCHEMA_OF_CSV',
    'SCHEMA_OF_JSON','SEQUENCE','SHUFFLE','SIGNUM','SINH','SKEWNESS','SLICE','SPARK_PARTITION_ID',
    'STD','TANH','TO_CSV','TO_JSON','TO_TIMESTAMP','TO_UBIX_TIMESTAMP','TYPEOF',
    'UCASE','UUID','WEEKDAY','XPATH','XPATH_BOOLEAN','XPATH_DOUBEL','XPATH_FLOAT','XPATH_INT',
    'XPATH_LONG','XPATH_NUMBER','XPATH_SHORT','XPATH_STRING','XXHASH64','ZIP_WITH'
  ],
  //内置变量
  builtinVariables:[
    // Configuration
    '@@DATEFIRST', '@@DBTS', '@@LANGID', '@@LANGUAGE', '@@LOCK_TIMEOUT', '@@MAX_CONNECTIONS', '@@MAX_PRECISION', '@@NESTLEVEL',
    '@@OPTIONS', '@@REMSERVER', '@@SERVERNAME', '@@SERVICENAME', '@@SPID', '@@TEXTSIZE', '@@VERSION',
    // Cursor
    '@@CURSOR_ROWS', '@@FETCH_STATUS',
    // Datetime
    '@@DATEFIRST',
    // Metadata
    '@@PROCID',
    // System
    '@@ERROR', '@@IDENTITY', '@@ROWCOUNT', '@@TRANCOUNT',
    // Stats
    '@@CONNECTIONS', '@@CPU_BUSY', '@@IDLE', '@@IO_BUSY', '@@PACKET_ERRORS', '@@PACK_RECEIVED', '@@PACK_SENT',
    '@@TIMETICKS', '@@TOTAL_ERRORS', '@@TOTAL_READ', '@@TOTAL_WRITE'
  ],
  //伪列
  pseudoColumns: [
    '$ACTION', '$IDENTITY', '$ROWGUID', '$PARTITION'
  ],
  tokenizer: {
    root: [
      { include: '@comments' },
      { include: '@whitespace' },
      { include: '@pseudoColumns' },
      { include: '@numbers' },
      { include: '@strings' },
      { include: '@complexIdentifiers' },
      { include: '@scopes' },
      [/[;,.]/, 'delimiter'],
      [/[()]/, '@brackets'],
      [/[\w@#$]+/, {
        cases: {
          '@keywords': 'keyword',
          '@operators': 'opera',
          '@builtinVariables': 'builtFunc',
          '@builtinFunctions': 'builtFunc',
          '@default': 'identifier'
        }
      }],
      [/[<>=!%&+\-*/|~^]/, 'opera'],
    ],
    whitespace: [
      [/\s+/, 'white']
    ],
    comments: [
      [/--+.*/, 'comment'],
      [/\/\*/, { token: 'comment.quote', next: '@comment' }]
    ],
    comment: [
      [/[^*/]+/, 'comment'],
      [/\*\//, { token: 'comment.quote', next: '@pop' }],
      [/./, 'comment']
    ],
    pseudoColumns: [
      [/[$][A-Za-z_][\w@#$]*/, {
        cases: {
          '@pseudoColumns': 'builtFunc',
          '@default': 'identifier'
        }
      }],
    ],
    numbers: [
      [/0[xX][0-9a-fA-F]*/, 'number'],
      [/[$][+-]*\d*(\.\d*)?/, 'number'],
      [/((\d+(\.\d*)?)|(\.\d+))([eE][\-+]?\d+)?/, 'number']
    ],
    strings: [
      [/N'/, { token: 'string', next: '@string' }],
      [/'/, { token: 'string', next: '@string' }]
    ],
    string: [
      [/[^']+/, 'string'],
      [/''/, 'string'],
      [/'/, { token: 'string', next: '@pop' }]
    ],
    complexIdentifiers: [
      [/\[/, { token: 'identifier.quote', next: '@bracketedIdentifier' }],
      [/"/, { token: 'identifier.quote', next: '@quotedIdentifier' }]
    ],
    bracketedIdentifier: [
      [/[^\]]+/, 'identifier'],
      [/]]/, 'identifier'],
      [/]/, { token: 'identifier.quote', next: '@pop' }]
    ],
    quotedIdentifier: [
      [/[^"]+/, 'identifier'],
      [/""/, 'identifier'],
      [/"/, { token: 'identifier.quote', next: '@pop' }]
    ],
    scopes: [
      [/BEGIN\s+(DISTRIBUTED\s+)?TRAN(SACTION)?\b/i, 'keyword'],
      [/BEGIN\s+TRY\b/i, { token: 'keyword.try' }],
      [/END\s+TRY\b/i, { token: 'keyword.try' }],
      [/BEGIN\s+CATCH\b/i, { token: 'keyword.catch' }],
      [/END\s+CATCH\b/i, { token: 'keyword.catch' }],
      [/(BEGIN|CASE)\b/i, { token: 'keyword.block' }],
      [/END\b/i, { token: 'keyword.block' }],
      [/WHEN\b/i, { token: 'keyword.choice' }],
      [/THEN\b/i, { token: 'keyword.choice' }]
    ]
  }
}
export default sqlInfo

;