You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kylin.apache.org by xx...@apache.org on 2023/03/28 03:05:13 UTC
[kylin] 05/12: KYLIN-5482 special character of col name issue
This is an automated email from the ASF dual-hosted git repository.
xxyu pushed a commit to branch kylin5
in repository https://gitbox.apache.org/repos/asf/kylin.git
commit 5fd4475cb6c4a89fa1560eac72a4d62b07f86cdf
Author: Qian Xia <la...@gmail.com>
AuthorDate: Fri Mar 24 15:34:58 2023 +0800
KYLIN-5482 special character of col name issue
---
.../studio/StudioModel/AddMeasure/index.vue | 13 ----
.../studio/StudioModel/BatchMeasureModal/index.vue | 33 +++++---
.../studio/StudioModel/DimensionsModal/index.vue | 87 +++++++---------------
kystudio/src/config/index.js | 1 +
4 files changed, 50 insertions(+), 84 deletions(-)
diff --git a/kystudio/src/components/studio/StudioModel/AddMeasure/index.vue b/kystudio/src/components/studio/StudioModel/AddMeasure/index.vue
index cc4b55ef62..bf07683e19 100644
--- a/kystudio/src/components/studio/StudioModel/AddMeasure/index.vue
+++ b/kystudio/src/components/studio/StudioModel/AddMeasure/index.vue
@@ -280,19 +280,6 @@ export default class AddMeasure extends Vue {
ccGroups = []
newCCList = []
allTableColumns = []
- // expressionsConf = [
- // {label: 'SUM (column)', value: 'SUM(column)'},
- // {label: 'SUM (constant)', value: 'SUM(constant)'},
- // {label: 'MIN', value: 'MIN'},
- // {label: 'MAX', value: 'MAX'},
- // {label: 'TOP_N', value: 'TOP_N'},
- // {label: 'COUNT (column)', value: 'COUNT(column)'},
- // // {label: 'COUNT (constant)', value: 'COUNT(constant)'}, 去除 count(constant) 函数,默认添加 count_all 度量
- // {label: 'COUNT_DISTINCT', value: 'COUNT_DISTINCT'},
- // {label: 'CORR (column1, column2)', value: 'CORR'},
- // {label: 'PERCENTILE_APPROX', value: 'PERCENTILE_APPROX'},
- // {label: 'COLLECT_SET', value: 'COLLECT_SET'}
- // ]
topNTypes = [
{name: 'Top 10', value: 'topn(10)'},
{name: 'Top 100', value: 'topn(100)'},
diff --git a/kystudio/src/components/studio/StudioModel/BatchMeasureModal/index.vue b/kystudio/src/components/studio/StudioModel/BatchMeasureModal/index.vue
index d01d6d9dff..b1ac218c7d 100644
--- a/kystudio/src/components/studio/StudioModel/BatchMeasureModal/index.vue
+++ b/kystudio/src/components/studio/StudioModel/BatchMeasureModal/index.vue
@@ -197,8 +197,8 @@ import { mapState, mapGetters, mapMutations } from 'vuex'
import vuex from '../../../../store'
import locales from './locales'
import store, { types } from './store'
-import { objectClone, sampleGuid } from '../../../../util'
-import { pageCount, measuresDataType, measureSumAndTopNDataType, pageRefTags } from '../../../../config'
+import { objectClone, sampleGuid, indexOfObjWithSomeKey, getObjectBySomeKeys } from '../../../../util'
+import { pageCount, measuresDataType, measureSumAndTopNDataType, pageRefTags, unIncludedNameRegex } from '../../../../config'
vuex.registerModule(['modals', 'BatchMeasureModal'], store)
@Component({
computed: {
@@ -258,14 +258,22 @@ export default class BatchMeasureModal extends Vue {
}
checkHasSameName (arr, val, column) {
- let flag = false
- for (let i = 0; i < arr.length; i++) {
- if (arr[i].name === val && (arr[i].table_guid || arr[i].guid) !== column.table_guid) {
- flag = true
- break
+ const arrrReverse = objectClone(arr).reverse()
+ let uniqueName = val
+ while(indexOfObjWithSomeKey(arrrReverse, 'name' ,uniqueName) !== -1) {
+ const lastIndex = uniqueName.lastIndexOf('_')
+ let sameCount = +uniqueName.substring(lastIndex + 1)
+ const sameNameMes = getObjectBySomeKeys(arrrReverse, 'name' ,uniqueName)
+ if ((sameNameMes.table_guid || sameNameMes.guid) !== column.table_guid) {
+ uniqueName = uniqueName + '_' + column.table_alias
+ } else if (!isNaN(parseFloat(sameCount))) { // 是数字
+ sameCount++
+ uniqueName = uniqueName.substring(0, lastIndex + 1) + sameCount
+ } else {
+ uniqueName = uniqueName + '_1'
}
}
- return flag
+ return uniqueName
}
submit () {
let allMeasureArr = [...this.modelDesc.all_measures]
@@ -287,10 +295,11 @@ export default class BatchMeasureModal extends Vue {
}
columns.forEach((column) => {
if (column.isMeasureCol) {
+ const colName = column.name.replace(unIncludedNameRegex, '') // 去除不符合度量命名的字符
if (column.SUM.value && !column.SUM.isShouldDisable) {
// 如果存在同名的,添加上表别名,如果不同名,就是列名+函数
const measure = {
- name: this.checkHasSameName(allMeasureArr, column.name + '_SUM', column) ? column.name + '_SUM_' + column.table_alias : column.name + '_SUM',
+ name: this.checkHasSameName(allMeasureArr, colName + '_SUM', column),
guid: sampleGuid(),
expression: 'SUM',
parameter_value: [{type: 'column', value: column.table_alias + '.' + (column.column ?? column.columnName), table_guid: column.table_guid}],
@@ -301,7 +310,7 @@ export default class BatchMeasureModal extends Vue {
}
if (column.MIN.value && !column.MIN.isShouldDisable) {
const measure = {
- name: this.checkHasSameName(allMeasureArr, column.name + '_MIN', column) ? column.name + '_MIN_' + column.table_alias : column.name + '_MIN',
+ name: this.checkHasSameName(allMeasureArr, colName + '_MIN', column),
guid: sampleGuid(),
expression: 'MIN',
parameter_value: [{type: 'column', value: column.table_alias + '.' + (column.column ?? column.columnName), table_guid: column.table_guid}],
@@ -312,7 +321,7 @@ export default class BatchMeasureModal extends Vue {
}
if (column.MAX.value && !column.MAX.isShouldDisable) {
const measure = {
- name: this.checkHasSameName(allMeasureArr, column.name + '_MAX', column) ? column.name + '_MAX_' + column.table_alias : column.name + '_MAX',
+ name: this.checkHasSameName(allMeasureArr, colName + '_MAX', column),
guid: sampleGuid(),
expression: 'MAX',
parameter_value: [{type: 'column', value: column.table_alias + '.' + (column.column ?? column.columnName), table_guid: column.table_guid}],
@@ -323,7 +332,7 @@ export default class BatchMeasureModal extends Vue {
}
if (column.COUNT.value && !column.COUNT.isShouldDisable) {
const measure = {
- name: this.checkHasSameName(allMeasureArr, column.name + '_COUNT', column) ? column.name + '_COUNT_' + column.table_alias : column.name + '_COUNT',
+ name: this.checkHasSameName(allMeasureArr, colName + '_COUNT', column),
guid: sampleGuid(),
expression: 'COUNT',
parameter_value: [{type: 'column', value: column.table_alias + '.' + (column.column ?? column.columnName), table_guid: column.table_guid}],
diff --git a/kystudio/src/components/studio/StudioModel/DimensionsModal/index.vue b/kystudio/src/components/studio/StudioModel/DimensionsModal/index.vue
index ece5442666..6e6ffdf5af 100644
--- a/kystudio/src/components/studio/StudioModel/DimensionsModal/index.vue
+++ b/kystudio/src/components/studio/StudioModel/DimensionsModal/index.vue
@@ -94,7 +94,6 @@
</el-table-column>
</el-table>
</div>
- <!-- <div class="same-name-tip" v-if="filterErrorContent(table)">{{$t('sameNameTip')}}</div> -->
</div>
<!-- 维度表 -->
<div v-for="(table, index) in lookupTable" class="ksd-mb-10" :key="index">
@@ -174,7 +173,6 @@
</el-table-column>
</el-table>
</div>
- <!-- <div class="same-name-tip" v-if="filterErrorContent(table)">{{$t('sameNameTip')}}</div> -->
</div>
<!-- 可计算列 -->
<template v-if="ccTable.columns.length">
@@ -237,7 +235,6 @@
</el-table-column>
</el-table>
</div>
- <!-- <div class="same-name-tip" v-if="filterErrorContent(ccTable)">{{$t('sameNameTip')}}</div> -->
</div>
</template>
</div>
@@ -307,8 +304,8 @@ import { mapState, mapGetters, mapMutations, mapActions } from 'vuex'
import vuex from '../../../../store'
import locales from './locales'
import store, { types } from './store'
-import { NamedRegex1, pageCount, pageRefTags } from '../../../../config'
-import { objectClone, sampleGuid, filterObjectArray, countObjWithSomeKey } from '../../../../util'
+import { NamedRegex1, pageCount, pageRefTags, unIncludedNameRegex } from '../../../../config'
+import { objectClone, sampleGuid, filterObjectArray, countObjWithSomeKey, indexOfObjWithSomeKey, indexOfObjWithSomeKeys } from '../../../../util'
vuex.registerModule(['modals', 'DimensionsModal'], store)
@Component({
computed: {
@@ -372,6 +369,8 @@ export default class DimensionsModal extends Vue {
}
isClickSubmit = false
errorGuidList = []
+ uniqueAliasObj = {}
+ uniqueAliasCommentObj = {}
filterErrorContent (table) {
return this.isClickSubmit && table.columns.filter(item => item.validateSameName || item.validateNameRule || item.validateNameMaxLen).length
@@ -430,18 +429,13 @@ export default class DimensionsModal extends Vue {
}
syncCommentName () {
- let tempArr = [];
+ this.uniqueAliasCommentObj = {};
[...this.factTable, ...this.lookupTable].forEach((item, index, self) => {
for (let it of item.columns) {
- if ('comment' in it && it.comment && it.comment.trim() && this.checkDimensionNameRegex(it.comment)) {
- let name = it.comment.slice(0, 100)
+ if ('comment' in it && it.comment && it.comment.trim()) {
+ let name = it.comment.replace(unIncludedNameRegex, '').slice(0, 100)
it.oldName = it.alias
- if (tempArr.includes(name)) {
- this.$set(it, 'alias', `${it.name}_${name}`.slice(0, 100))
- } else {
- tempArr.push(name)
- this.$set(it, 'alias', name)
- }
+ this.$set(it, 'alias', this.getUniqueAlias(this.uniqueAliasCommentObj, name))
} else {
continue
}
@@ -458,33 +452,6 @@ export default class DimensionsModal extends Vue {
})
}
- // renderNameHeader (h, { column, $index }) {
- // return (<span class="ky-hover-icon" onClick={e => (e.stopPropagation())}>
- // <span>{this.$t('name')}</span>
- // <common-tip placement="top" content={this.$t('nameTip')}>
- // <span class='el-icon-ksd-what'></span>
- // </common-tip>
- // </span>)
- // }
-
- // renderCardinalityHeader (h, { column, $index }) {
- // return (<span class="ky-hover-icon" onClick={e => (e.stopPropagation())}>
- // <span>{this.$t('cardinality')}</span>
- // <common-tip placement="top" content={this.$t('cardinalityTip')}>
- // <span class='el-icon-ksd-what'></span>
- // </common-tip>
- // </span>)
- // }
-
- // renderCommentHeader (h, { column, $index }) {
- // return (<span class="ky-hover-icon" onClick={e => (e.stopPropagation())}>
- // <span>{this.$t('comment')}</span>
- // <common-tip placement="top" content={this.$t('commentTip')}>
- // <span class='el-icon-ksd-what'></span>
- // </common-tip>
- // </span>)
- // }
-
changeSearchVal (val) {
clearTimeout(this.ST)
this.ST = setTimeout(() => {
@@ -577,6 +544,15 @@ export default class DimensionsModal extends Vue {
})
this.renderTableColumnSelected(this.ccTable)
}
+ getUniqueAlias (obj, name) {
+ if (obj[name] === undefined) {
+ obj[name] = 0
+ return name
+ } else {
+ obj[name]++
+ return name + '_' + obj[name]
+ }
+ }
// 获取所有的table columns,并渲染已经选择过的dimension
getRenderDimensionData () {
this.getRenderCCData()
@@ -601,27 +577,21 @@ export default class DimensionsModal extends Vue {
// 将已经选上的dimension回显到界面上
table.columns && table.columns.forEach((col, index) => {
this.$set(col, 'tableName', table.alias)
- this.$set(col, 'alias', col.name)
+ this.$set(col, 'alias', this.getUniqueAlias(this.uniqueAliasObj, col.name.replace(unIncludedNameRegex, ''))) // 去除不符合维度命名的字符)
this.$set(col, 'isSelected', false)
this.$set(col, 'guid', null)
- let len = this.usedColumns.length
- for (let i = 0; i < len; i++) {
- let d = this.usedColumns[i]
- if (table.alias + '.' + col.name === d.column && d.status === 'DIMENSION') {
- col.alias = d.name
- col.isSelected = true
- col.guid = d.guid
- break
- }
+ const selectedColIndex = indexOfObjWithSomeKeys(this.usedColumns, 'column', table.alias + '.' + col.name, 'status', 'DIMENSION' )
+ if (selectedColIndex !== -1) {
+ col.alias = col.name.replace(unIncludedNameRegex, '') !== this.usedColumns[selectedColIndex].name.replace(unIncludedNameRegex, '') ? this.getUniqueAlias(this.uniqueAliasObj, this.usedColumns[selectedColIndex].name.replace(unIncludedNameRegex, '')) : col.alias
+ col.isSelected = true
+ col.guid = this.usedColumns[selectedColIndex].guid
}
- for (let it of others) {
- if (`${table.alias}.${col.name}` === it.column && !selectedColumns.includes(it.column)) {
- this.$set(col, 'alias', it.name)
- break
- }
+ const otherColIndex = indexOfObjWithSomeKey(others, 'column', `${table.alias}.${col.name}`)
+ if (otherColIndex !== -1 && !selectedColumns.includes(others[otherColIndex].column) && others[otherColIndex].name.replace(unIncludedNameRegex, '') !== col.name.replace(unIncludedNameRegex, '')) {
+ this.$set(col, 'alias', this.getUniqueAlias(this.uniqueAliasObj, others[otherColIndex].name.replace(unIncludedNameRegex, ''))) // 去除不符合维度命名的字符)
}
if (names.indexOf(col.name) !== names.lastIndexOf(col.name) && !col.isSelected) {
- this.$set(col, 'alias', col.name + '_' + table.alias)
+ this.$set(col, 'alias', this.getUniqueAlias(this.uniqueAliasObj, col.name.replace(unIncludedNameRegex, '') + '_' + table.alias))// 去除不符合维度命名的字符)
}
})
this.renderTableColumnSelected(table)
@@ -718,10 +688,9 @@ export default class DimensionsModal extends Vue {
}, 200)
}
}
- mounted () {
- }
handleClose (isSubmit, data) {
this.hideModal()
+ this.uniqueAliasObj = {}
setTimeout(() => {
this.resetModalForm()
this.callback && this.callback({
diff --git a/kystudio/src/config/index.js b/kystudio/src/config/index.js
index df910cb3a2..9b51bf0819 100644
--- a/kystudio/src/config/index.js
+++ b/kystudio/src/config/index.js
@@ -183,6 +183,7 @@ export const SystemPwdRegex = /^(?=.*\d)(?=.*[a-zA-Z])(?=.*[~!@#$%^&*(){}|:"<>?[
export const NamedRegex = /^\w+$/
export const NamedRegex1 = /^[\u4e00-\u9fa5_\-(()%?)a-zA-Z0-9\s]+$/
export const measureNameRegex = /^[\u4e00-\u9fa5_\-(()%?).a-zA-Z0-9\s]+$/
+export const unIncludedNameRegex = /[^\u4e00-\u9fa5_\-(()%?).a-zA-Z0-9\s]/g
export const positiveNumberRegex = /^[1-9][0-9]*$/ // 的正整数
export const DatePartitionRule = [/^date$/, /^timestamp$/, /^string$/, /^bigint$/, /^int$/, /^integer$/, /^varchar/]
export const TimePartitionRule = [/^long$/, /^bigint$/, /^int$/, /^short$/, /^integer$/, /^tinyint$/, /^string$/, /^varchar/, /^char/]