This is an automated email from the ASF dual-hosted git repository. liyang pushed a commit to branch kylin5 in repository https://gitbox.apache.org/repos/asf/kylin.git
The following commit(s) were added to refs/heads/kylin5 by this push: new 16f8da9071 KYLIN-5822,support history table adds left-closed and right-closed time interval 16f8da9071 is described below commit 16f8da90718a2104729fb2a0c8d3cf61b1f8617f Author: huangchunyan <qingyanxiaon...@163.com> AuthorDate: Sat Apr 6 16:31:37 2024 +0800 KYLIN-5822,support history table adds left-closed and right-closed time interval --- .../components/setting/SettingAdvanced/locales.js | 6 +- .../ModelList/Components/ModelTitleDescription.vue | 118 ++++++++++----------- .../studio/StudioModel/ModelList/locales.js | 2 +- .../studio/StudioModel/TableJoinModal/index.vue | 75 ++++++------- .../studio/StudioModel/TableJoinModal/locales.js | 2 +- 5 files changed, 95 insertions(+), 108 deletions(-) diff --git a/kystudio/src/components/setting/SettingAdvanced/locales.js b/kystudio/src/components/setting/SettingAdvanced/locales.js index 121517fd63..1c38df5169 100644 --- a/kystudio/src/components/setting/SettingAdvanced/locales.js +++ b/kystudio/src/components/setting/SettingAdvanced/locales.js @@ -51,9 +51,9 @@ export default { confirmOpenTip: 'Do you want to continue?', SCD2Settings: 'Support History table', nonEqualJoin: 'Show non-equal join conditions for History table', - noEqualDecription: 'With this switch ON, you may use the history table for slowly changing dimension (as was): Non-equal join conditions (≥, <) could be used for modeling, building and queries. ', + noEqualDecription: 'With this switch ON, you may use the history table for slowly changing dimension (as was): Non-equal join conditions could be used for modeling, building and queries. ', confirmOpen: 'Turn On', - closeSCDTip: 'With this switch OFF, non-equal join conditions (≥, <) couldn\'t be used when editing model. The following models will go offline automatically as they include non-equal join conditions:', + closeSCDTip: 'With this switch OFF, non-equal join conditions couldn\'t be used when editing model. The following models will go offline automatically as they include non-equal join conditions:', closeSCDTip1: 'To make these models online, please delete the non-equal join conditions, or turn this switch ON. Do you want to continue?', confirmClose: 'Turn Off', mulPartitionSettings: 'Multilevel Partitioning', @@ -63,7 +63,7 @@ export default { openMulPartitionTip: 'Please note that this feature is still in BETA phase. Potential risks or known limitations might exist. Check ', openMulPartitionTip1: ' for details.', closeMulPartitionSetting: 'Turn Off Multilevel Partitioning', - closeMulPartitionTip: 'With this switch OFF, multilevel partitioning couldn’t be used. The following models would go offline automatically as they used multilevel partitioning:', + closeMulPartitionTip: 'With this switch OFF, multilevel partitioning couldn\'t be used. The following models would go offline automatically as they used multilevel partitioning:', closeMulPartitionTip1: 'To make these models online, please delete all subpartitions, or turn this switch ON. Do you want to continue?', snapshotTitle: 'Snapshot Management', snapshotManagment: 'Support Snapshot Management', diff --git a/kystudio/src/components/studio/StudioModel/ModelList/Components/ModelTitleDescription.vue b/kystudio/src/components/studio/StudioModel/ModelList/Components/ModelTitleDescription.vue index b66af1b080..71390cda59 100644 --- a/kystudio/src/components/studio/StudioModel/ModelList/Components/ModelTitleDescription.vue +++ b/kystudio/src/components/studio/StudioModel/ModelList/Components/ModelTitleDescription.vue @@ -1,64 +1,64 @@ <template> - <div class="model-alias-label" v-if="modelData"> - <div class="alias"> - <el-popover - ref="statusPopover" - popper-class="status-tooltip" - placement="top-start" - trigger="hover" - :disabled="!modelData.status" - > - <span v-html="$t('modelStatus_c')" /> - <span>{{modelData.status}}</span> - <div v-if="modelData.status === 'WARNING' && modelData.empty_indexes_count">{{$t('emptyIndexTips')}}</div> - <div v-if="modelData.status === 'WARNING' && (modelData.segment_holes && modelData.segment_holes.length && modelData.model_type === 'BATCH') || (modelData.batch_segment_holes && modelData.batch_segment_holes.length && modelData.model_type === 'HYBRID')"> - <span>{{modelData.model_type === 'HYBRID' ? $t('modelSegmentHoleTips1') : $t('modelSegmentHoleTips')}}</span><span - v-if="!['modelEdit'].includes(source)" - style="color:#0988DE;cursor: pointer;" - @click="autoFix(modelData.alias, modelData.model_type === 'HYBRID' ? modelData.batch_id : modelData.uuid, modelData.model_type === 'HYBRID' ? modelData.batch_segment_holes : modelData.segment_holes)">{{$t('seeDetail')}}</span> + <div class="model-alias-label" v-if="modelData"> + <div class="alias"> + <el-popover + ref="statusPopover" + popper-class="status-tooltip" + placement="top-start" + trigger="hover" + :disabled="!modelData.status" + > + <span v-html="$t('modelStatus_c')" /> + <span>{{modelData.status}}</span> + <div v-if="modelData.status === 'WARNING' && modelData.empty_indexes_count">{{$t('emptyIndexTips')}}</div> + <div v-if="modelData.status === 'WARNING' && (modelData.segment_holes && modelData.segment_holes.length && modelData.model_type === 'BATCH') || (modelData.batch_segment_holes && modelData.batch_segment_holes.length && modelData.model_type === 'HYBRID')"> + <span>{{modelData.model_type === 'HYBRID' ? $t('modelSegmentHoleTips1') : $t('modelSegmentHoleTips')}}</span><span + v-if="!['modelEdit'].includes(source)" + style="color:#0988DE;cursor: pointer;" + @click="autoFix(modelData.alias, modelData.model_type === 'HYBRID' ? modelData.batch_id : modelData.uuid, modelData.model_type === 'HYBRID' ? modelData.batch_segment_holes : modelData.segment_holes)">{{$t('seeDetail')}}</span> + </div> + <div v-if="modelData.status === 'WARNING' && (modelData.segment_holes && modelData.segment_holes.length && modelData.model_type !== 'BATCH')"> + <span>{{$t('modelSegmentHoleTips2')}}</span> + </div> + <div v-if="modelData.status === 'WARNING' && modelData.inconsistent_segment_count"> + <span>{{$t('modelMetadataChangedTips')}}</span><span + v-if="!['modelEdit'].includes(source)" + style="color:#0988DE;cursor: pointer;" + @click="openComplementSegment(modelData, true)">{{$t('seeDetail')}}</span> + </div> + <div v-if="modelData.status === 'OFFLINE' && modelData.forbidden_online"> + <span>{{$t('SCD2ModalOfflineTip')}}</span> + </div> + <div v-if="modelData.status === 'OFFLINE' && !modelData.has_segments"> + <span>{{$t('noSegmentOnlineTip')}}</span> + </div> + <div v-if="modelData.status === 'OFFLINE' && !$store.state.project.multi_partition_enabled && modelData.multi_partition_desc"> + <span>{{$t('multilParTip')}}</span> + </div> + </el-popover> + <el-popover + ref="titlePopover" + placement="top-start" + width="250" + trigger="hover" + popper-class="title-popover-layout" + > + <div class="title-popover"> + <p class="title ksd-mb-20">{{modelData.alias || modelData.name}}</p> + <div :class="['label', {'en': $lang === 'en'}]"> + <div class="group ksd-mb-8" v-if="!onlyShowModelName"><span class="title">{{$t('kylinLang.model.ownerGrid')}}</span><span class="item">{{modelData.owner}}</span></div> + <div class="group"><span class="title">{{$t('description')}}</span><span class="item">{{modelData.description || '-'}}</span></div> </div> - <div v-if="modelData.status === 'WARNING' && (modelData.segment_holes && modelData.segment_holes.length && modelData.model_type !== 'BATCH')"> - <span>{{$t('modelSegmentHoleTips2')}}</span> - </div> - <div v-if="modelData.status === 'WARNING' && modelData.inconsistent_segment_count"> - <span>{{$t('modelMetadataChangedTips')}}</span><span - v-if="!['modelEdit'].includes(source)" - style="color:#0988DE;cursor: pointer;" - @click="openComplementSegment(modelData, true)">{{$t('seeDetail')}}</span> - </div> - <div v-if="modelData.status === 'OFFLINE' && modelData.forbidden_online"> - <span>{{$t('SCD2ModalOfflineTip')}}</span> - </div> - <div v-if="modelData.status === 'OFFLINE' && !modelData.has_segments"> - <span>{{$t('noSegmentOnlineTip')}}</span> - </div> - <div v-if="modelData.status === 'OFFLINE' && !$store.state.project.multi_partition_enabled && modelData.multi_partition_desc"> - <span>{{$t('multilParTip')}}</span> - </div> - </el-popover> - <el-popover - ref="titlePopover" - placement="top-start" - width="250" - trigger="hover" - popper-class="title-popover-layout" - > - <div class="title-popover"> - <p class="title ksd-mb-20">{{modelData.alias || modelData.name}}</p> - <div :class="['label', {'en': $lang === 'en'}]"> - <div class="group ksd-mb-8" v-if="!onlyShowModelName"><span class="title">{{$t('kylinLang.model.ownerGrid')}}</span><span class="item">{{modelData.owner}}</span></div> - <div class="group"><span class="title">{{$t('description')}}</span><span class="item">{{modelData.description || '-'}}</span></div> - </div> - </div> - </el-popover> - <span :class="['filter-status', (modelData.status || 'OFFLINE')]" v-popover:statusPopover v-if="!onlyShowModelName"></span> - <span class="model-alias-title" @mouseenter.prevent v-popover:titlePopover>{{modelData.alias || modelData.name}}</span> - </div> - <el-tooltip class="last-modified-tooltip" effect="dark" :content="`${$t('dataLoadTime')}${modelData.gmtTime}`" placement="bottom" :disabled="hideTimeTooltip" v-if="!onlyShowModelName"> - <span>{{getLastTime}}</span> - </el-tooltip> + </div> + </el-popover> + <span :class="['filter-status', (modelData.status || 'OFFLINE')]" v-popover:statusPopover v-if="!onlyShowModelName"></span> + <span class="model-alias-title" @mouseenter.prevent v-popover:titlePopover>{{modelData.alias || modelData.name}}</span> </div> - </template> + <el-tooltip class="last-modified-tooltip" effect="dark" :content="`${$t('dataLoadTime')}${modelData.gmtTime}`" placement="bottom" :disabled="hideTimeTooltip" v-if="!onlyShowModelName"> + <span>{{getLastTime}}</span> + </el-tooltip> + </div> +</template> <script> import Vue from 'vue' @@ -96,7 +96,7 @@ seeDetail: 'View Details', description: 'Description', dataLoadTime: 'Last Updated Time: ', - SCD2ModalOfflineTip: 'This model includes non-equal join conditions (≥, <), which are not supported at the moment. Please delete those join conditions, or turn on `Support History table` in project settings.', + SCD2ModalOfflineTip: 'This model includes non-equal join conditions, which are not supported at the moment. Please delete those join conditions, or turn on `Support History table` in project settings.', noSegmentOnlineTip: 'This model can\'t go online as it doesn\'t have segments. Models with no segment couldn\'t serve queries. Please add a segment.', multilParTip: 'This model used multilevel partitioning, which are not supported at the moment. Please set subpartition as \'None\' in model partition dialog, or turn on \'Multilevel Partitioning\' in project settings.', lastUpdate: 'Last Updated: ' diff --git a/kystudio/src/components/studio/StudioModel/ModelList/locales.js b/kystudio/src/components/studio/StudioModel/ModelList/locales.js index c73e7e054c..51a3b5fdba 100644 --- a/kystudio/src/components/studio/StudioModel/ModelList/locales.js +++ b/kystudio/src/components/studio/StudioModel/ModelList/locales.js @@ -93,7 +93,7 @@ export default { buildIndex: 'Build Index', batchBuildSubTitle: 'Please choose which data ranges you\'d like to build with the added indexes.', refrashWarningSegment: 'Only ONLINE segments could be refreshed', - closeSCD2ModalOnlineTip: 'This model can\'t go online as it includes non-equal join conditions(≥, <). Please delete those join conditions, or turn on `Support History table` in project settings.', + closeSCD2ModalOnlineTip: 'This model can\'t go online as it includes non-equal join conditions. Please delete those join conditions, or turn on `Support History table` in project settings.', storageTip: 'Calculates the amount of data built in this model', subPartitionValuesManage: 'Manage Sub-Partition Values', segmentHoletips: 'There exists a gap in the segment range, and the data of this range cannot be queried. Please confirm whether to add the following segments to fix.', diff --git a/kystudio/src/components/studio/StudioModel/TableJoinModal/index.vue b/kystudio/src/components/studio/StudioModel/TableJoinModal/index.vue index 6f9b978861..23f3d4011e 100644 --- a/kystudio/src/components/studio/StudioModel/TableJoinModal/index.vue +++ b/kystudio/src/components/studio/StudioModel/TableJoinModal/index.vue @@ -154,7 +154,9 @@ export default class TableJoinModal extends Vue { columnsLinkKind = [ {label: '=', value: 'EQUAL'}, {label: '>=', value: 'GREATER_THAN_OR_EQUAL'}, - {label: '<', value: 'LESS_THAN'} + {label: '<', value: 'LESS_THAN'}, + {label: '>', value: 'GREATER_THAN'}, + {label: '<=', value: 'LESS_THAN_OR_EQUAL'} ] columnJoinType = 0 isErrorValue = [] @@ -455,8 +457,10 @@ export default class TableJoinModal extends Vue { this.isErrorValue = [] this.errorFlag = [] let joins = joinColumns.foreign_key.map((item, index) => ({fk: item, op: joinColumns.op[index], pk: joinColumns.primary_key[index], index, joinExpression: `${item}&${joinColumns.primary_key[index]}`})) - let greater_than = joins.filter(it => it.op === 'GREATER_THAN_OR_EQUAL' && it.fk && it.pk) + let greater_than_or_equal = joins.filter(it => it.op === 'GREATER_THAN_OR_EQUAL' && it.fk && it.pk) let less_than = joins.filter(it => it.op === 'LESS_THAN' && it.fk && it.pk) + let less_than_or_equal = joins.filter(it => it.op === 'LESS_THAN_OR_EQUAL' && it.fk && it.pk) + let greater_than = joins.filter(it => it.op === 'GREATER_THAN' && it.fk && it.pk) // let equals = joins.filter(it => it.op === 'EQUAL' && it.fk && it.pk) // 两张表仅可使用同一关联关系一次 const pAlias = this.form.tables[this.form.pid].name.split('.')[1] @@ -472,43 +476,6 @@ export default class TableJoinModal extends Vue { this.isErrorValue.push(4) flag = false } - // let correctTableName = (pid, fid) => { - // return { - // pTable: this.form.tables[pid].name.replace(/^(\w+)\./, ''), - // tTable: this.form.tables[fid].name.replace(/^(\w+)\./, '') - // } - // } - // let fk = joinColumns.foreign_key.map(it => it.replace(/(\w+)\./, `${correctTableName(this.form.pid, this.form.fid).tTable}.`)) - // let pk = joinColumns.primary_key.map(it => it.replace(/(\w+)\./, `${correctTableName(this.form.pid, this.form.fid).pTable}.`)) - // let combination = fk.map((item, index) => `${item}&${pk[index]}`) - // let joinInfoHistory = Object.keys(this.form.modelInstance.linkUsedColumns).filter(it => it.indexOf(this.form.fid) >= 0 && it !== `${this.form.pid}${this.form.fid}`) - // if (joinInfoHistory.length) { - // let tables = [] - // joinInfoHistory.map(item => this.form.modelInstance.linkUsedColumns[item]).forEach((list, idx) => { - // let joinId = joinInfoHistory[idx] - // let start = joinId.indexOf(this.form.fid) - // let uid = [] - // if (start === 0) { - // uid = [joinId.slice(0, this.form.fid.length), joinId.slice(this.form.fid.length, joinId.length)] - // } else { - // uid = [joinId.slice(joinId.length - this.form.fid.length, joinId.length), joinId.slice(0, joinId.length - this.form.fid.length)] - // } - // for (let i = 0; i <= list.length / 2 - 1; i++) { - // tables.push(`${list[i + list.length / 2].replace(/(\w+)\./, `${correctTableName(uid[1], uid[0]).tTable}.`)}&${list[i].replace(/(\w+)\./, `${correctTableName(uid[1], uid[0]).pTable}.`)}`) - // } - // }) - // if (tables.length) { - // let cludesIndex = [] - // combination.forEach((v, index) => { - // tables.includes(v) && cludesIndex.push(index) - // }) - // if (cludesIndex.length) { - // this.errorFlag = [...this.errorFlag, ...cludesIndex] - // this.isErrorValue.push(4) - // flag = false - // } - // } - // } // 至少有一个equal连接关系 if (!joinColumns.op.includes('EQUAL')) { this.isErrorValue.push(3) @@ -525,21 +492,41 @@ export default class TableJoinModal extends Vue { // 连接关系 >= 和 < 成对出现, 且位于中间的列必须一致(此处判断放在最后处理) let checkFun = () => { let fl = true - let firstV = greater_than.shift(0) + let firstV = greater_than_or_equal.shift(0) while (firstV) { - let idx = less_than.findIndex(it => it.fk === firstV.fk) + let idx = less_than.findIndex(it => it.fk === firstV.fk || it.pk === firstV.pk) + let idx2 = less_than_or_equal.findIndex(it => it.fk === firstV.fk || it.pk === firstV.pk) if (idx >= 0) { less_than.splice(idx, 1) + } else if (idx2 >= 0) { + less_than_or_equal.splice(idx2, 1) } else { this.errorFlag.push(firstV.index) fl = false } - firstV = greater_than.shift(0) + firstV = greater_than_or_equal.shift(0) } - if (less_than.length) { - this.errorFlag = [...this.errorFlag, ...less_than.map(it => it.index)] + if (firstV && (less_than.length || less_than_or_equal.length)) { + this.errorFlag = [...this.errorFlag, ...less_than.map(it => it.index), ...less_than_or_equal.map(it => it.index)] fl = false } + if (fl) { + let firstV2 = greater_than.shift(0) + while (firstV2) { + let idx3 = less_than_or_equal.findIndex(it => it.fk === firstV2.fk || it.pk === firstV2.pk) + if (idx3 >= 0) { + less_than_or_equal.splice(idx3, 1) + } else { + this.errorFlag.push(firstV2.index) + fl = false + } + firstV2 = greater_than.shift(0) + } + if (less_than_or_equal.length) { + this.errorFlag = [...this.errorFlag, ...less_than_or_equal.map(it => it.index)] + fl = false + } + } return fl } if (!checkFun()) { diff --git a/kystudio/src/components/studio/StudioModel/TableJoinModal/locales.js b/kystudio/src/components/studio/StudioModel/TableJoinModal/locales.js index 0f5cd1b9c1..572ef3f492 100644 --- a/kystudio/src/components/studio/StudioModel/TableJoinModal/locales.js +++ b/kystudio/src/components/studio/StudioModel/TableJoinModal/locales.js @@ -11,7 +11,7 @@ export default { joinErrorNotice: 'The join condition can\'t be saved. Please modify and try again.', details: 'View Details', notice1: 'Can\'t define multiple join conditions for the same columns', - notice2: 'Join relationship ≥ and < must be used in pairs, and same column must be joint in both conditions', + notice2: 'Non-equal join condition only supports the following three pairs:1) >= and < ,2)>= and <=,3)> and<=, and same column must be joint in both conditions', notice3: 'Join relationship for columns should include at least one equal-join condition (=)', notice4: 'Two tables could only be joined by the same condition for one time', manyToOne: 'One-to-One or Many-to-One',