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 <lauraxiaq...@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/]