Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 39 additions & 10 deletions src/store/modules/logquery/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ const useLogQueryStore = defineStore('logQuery', () => {

const rangeTime = ref<Array<string>>([])
const time = ref(10)
const inputTableName = ref('')
const inputTableName = ref('') // table after query
const editingTableName = ref('') // table in editing

const columns = computed(() => {
if (!inputTableName.value) {
Expand Down Expand Up @@ -82,8 +83,10 @@ const useLogQueryStore = defineStore('logQuery', () => {
type Multiple = 1000 | 1000000 | 1000000000
const multipleRe = /timestamp\((\d)\)/
const dataLoadFlag = ref(0)
const tsColumn = computed<TSColumn>(() => {
const fields = tableMap.value[inputTableName.value] || []
const tsColumn = shallowRef<TSColumn>()

const getTsColumn = (tableName: string) => {
const fields = tableMap.value[tableName] || []
const field = fields.filter((column) => column.data_type.toLowerCase().indexOf('timestamp') > -1)[0]
if (!field) {
return null
Expand All @@ -94,7 +97,7 @@ const useLogQueryStore = defineStore('logQuery', () => {
multiple: (1000 ** (Number(timescale[1]) / 3)) as Multiple,
...field,
}
})
}

const query = () => {
queryLoading.value = true
Expand Down Expand Up @@ -204,12 +207,12 @@ const useLogQueryStore = defineStore('logQuery', () => {
let val = escapeSqlString(condition.value)
if (condition.op === 'not contains') {
val = `-"${val}"`
} else if (condition.op === 'match sequence') {
} else if (condition.op === 'contains') {
val = `"${val}"`
}
return `MATCHES(${condition.field.name},'"${val}"')`
return `MATCHES(${condition.field.name},'${val}')`
}
return `${condition.field.name} ${condition.op} '"${escapeSqlString(condition.value)}"'`
return `${condition.field.name} ${condition.op} '${escapeSqlString(condition.value)}'`
Comment on lines 208 to +215
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this use switch case?

}

function buildCondition() {
Expand Down Expand Up @@ -242,15 +245,16 @@ const useLogQueryStore = defineStore('logQuery', () => {
}

watch(
[queryForm, unifiedRange, limit],
[queryForm, unifiedRange, limit, editingTableName],
() => {
if (!inputTableName.value) {
if (!editingTableName.value) {
return
}
if (editorType.value !== 'builder') {
return
}
let str = `SELECT * FROM ${inputTableName.value}`
tsColumn.value = getTsColumn(editingTableName.value)
let str = `SELECT * FROM ${editingTableName.value}`
const where = buildCondition()
if (where.length) {
str += ` WHERE ${where.join('')}`
Expand All @@ -273,13 +277,34 @@ const useLogQueryStore = defineStore('logQuery', () => {
}
})

type TypeKey = keyof typeof typeMap
const opMap = {
String: ['=', 'contains', 'not contains', '!=', 'like'],
Number: ['=', '!=', '>', '>=', '<', '<='],
Time: ['>', '>=', '<', '<='],
}
type OpKey = keyof typeof opMap

function getOpByField(field: string): string[] {
const fields = tableMap.value[editingTableName.value]
const index = fields.findIndex((f) => f.name === field)
if (index === -1) {
return []
}
const type = fields[index].data_type as TypeKey
const opKey = typeMap[type] as OpKey
return opMap[opKey] || []
}

function reset() {
editingTableName.value = ''
inputTableName.value = ''
sql.value = ''
editingSql.value = ''
queryForm.conditions = []
rows.value = []
}

return {
sql,
query,
Expand All @@ -290,6 +315,7 @@ const useLogQueryStore = defineStore('logQuery', () => {
selectedRowKey,
rangeTime,
inputTableName,
editingTableName,
tsColumn,
time,
unifiedRange,
Expand All @@ -311,7 +337,10 @@ const useLogQueryStore = defineStore('logQuery', () => {
dataLoadFlag,
showKeys,
queryColumns,
getOpByField,
reset,
getTsColumn,
}
})

export default useLogQueryStore
54 changes: 54 additions & 0 deletions src/views/dashboard/logs/query/ChartContainer.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<template lang="pug">
a-card
template(#extra)
a-dropdown-button(size="small" type="text" @select="select")
| {{ menuStr }}
template(#icon)
icon-down
template(#content)
a-doption(value="count") Write Count
a-dsubmenu(trigger="hover" position="lt")
template(#default)
| Frequency Distribution
template(#content)
a-doption(v-for="field in filterFields" :value="`frequency_${field}`") {{ field }}

CountChart(v-if="currChart == 'count'")
FunnelChart(v-if="currChart == 'frequency'" :key="frequencyField" :column="frequencyField")
</template>

<script setup name="ChartContainer" lang="ts">
import useLogQueryStore from '@/store/modules/logquery'
import CountChart from './CountChart.vue'
import FunnelChart from './FunnelChart.vue'

const currChart = ref('count')
const { columns, inputTableName } = storeToRefs(useLogQueryStore())
const frequencyField = ref('')
const filterFields = computed(() =>
columns.value.filter((column) => column.data_type === 'string').map((column) => column.name)
)
function select(action) {
currChart.value = action.split('_')[0]
if (currChart.value === 'frequency') {
frequencyField.value = action.substring('frequency'.length + 1)
}
}
const menuStr = computed(() => {
if (currChart.value === 'count') {
return 'Write Count '
}
return 'Frequency Distribution'
})

watch(inputTableName, () => {
currChart.value = 'count'
})
</script>

<style scoped lang="less">
.arco-card :deep(.arco-card-header) {
height: 18px;
padding: 0 10px;
}
</style>
2 changes: 1 addition & 1 deletion src/views/dashboard/logs/query/CountChart.vue
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ VCharts(
})

const countSql = computed(() => {
if (!tsColumn.value) {
if (!tsColumn.value || !inputTableName.value) {
return ''
}

Expand Down
2 changes: 0 additions & 2 deletions src/views/dashboard/logs/query/ExportLog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
a-button(size="small" type="text" @click="exportSql")
| Export as csv
</template>

<script setup name="ExportLog" lang="ts">
import fileDownload from 'js-file-download'
import editorAPI from '@/api/editor'
Expand Down Expand Up @@ -34,5 +33,4 @@ a-button(size="small" type="text" @click="exportSql")
})
}
</script>

<style scoped lang="less"></style>
115 changes: 115 additions & 0 deletions src/views/dashboard/logs/query/FunnelChart.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
<template lang="pug">
VCharts(
ref="chart"
style="width: 100%; height: 120px"
:option="chartOptions"
:autoresize="true"
)
</template>

<script setup name="LogCountChart" lang="ts">
import VCharts from 'vue-echarts'
import { useI18n } from 'vue-i18n'
import * as echarts from 'echarts'
import { watchOnce } from '@vueuse/core'
import editorAPI from '@/api/editor'
import useLogQueryStore from '@/store/modules/logquery'
import { calculateInterval, generateTimeRange, toMs, TimeTypes, getWhereClause, addTsCondition, toObj } from './until'
import type { TimeType } from './until'

const props = defineProps(['column'])
const data = shallowRef<Array<any>>([])
const { t } = useI18n()
const chart = ref()
const chartOptions = computed(() => ({
grid: {
left: '55px',
bottom: '20px',
right: '55px',
top: '10px',
},
tooltip: {
trigger: 'axis',
axisPointer: { type: 'shadow' },
},
xAxis: {
type: 'category',
position: 'bottom',
show: !!data.value.length,
},
yAxis: {
type: 'value',
},
series: [
{
type: 'bar',
data: data.value,
itemStyle: {
color: '#bdc4cd',
},
barMaxWidth: 50,
},
],
graphic: {
elements: [
{
type: 'text',
left: 'center',
top: 'middle',
style: {
text: data.value.length ? '' : 'No Chart data',
fill: '#999',
fontSize: 18,
},
},
],
},
}))

const { inputTableName, unifiedRange, tsColumn, queryNum, sql, editorType, rows, tableIndex } = storeToRefs(
useLogQueryStore()
)
const { getRelativeRange, buildCondition, query } = useLogQueryStore()

const chartSql = computed(() => {
if (!tsColumn.value) {
return ''
}

let condition = ''
if (editorType.value === 'text') {
condition += getWhereClause(sql.value)
}
if (editorType.value === 'builder') {
condition += buildCondition().join('')
}
if (condition !== '') {
condition = `Where ${condition}`
}

return `SELECT ${props.column} ,count(*) AS c FROM ${inputTableName.value} ${condition} GROUP BY ${props.column} ORDER BY c DESC`
})

function chartQuery() {
if (!chartSql.value) {
return
}
editorAPI.runSQL(chartSql.value).then((result) => {
const {
rows: countRows,
schema: { column_schemas: columnSchemas },
} = result.output[0].records
data.value = countRows
})
}

if (chartSql.value) {
chartQuery()
}

watch(queryNum, () => {
chartQuery()
})
</script>

<style scoped lang="less"></style>
12 changes: 0 additions & 12 deletions src/views/dashboard/logs/query/InputEditor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -61,18 +61,6 @@
})
})

// parse table name
watch(
editingSql,
() => {
inputTableName.value = parseTable(editingSql.value)
limit.value = parseLimit(editingSql.value)
},
{
immediate: true,
}
)

const customSelectionTheme = EditorView.theme({
'&.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground, .cm-selectionBackground, .cm-content ::selection':
{
Expand Down
2 changes: 1 addition & 1 deletion src/views/dashboard/logs/query/Pagination.vue
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ a-space(v-if="pages.length")
function loadPage(start: number, end: number, pageIndex: number) {
pages.value[pageIndex].loading = true
const tsName = tsColumn.value?.name as string
const pageSql = addTsCondition(sql.value, tsName, start, end)
const pageSql = addTsCondition(sql.value, tsName, start, end + 1)
queryPage(pageSql)
.then(() => {
const index = pages.value.findIndex((page) => page.start === start && page.end === end)
Expand Down
Loading
Loading