Skip to content

Commit

Permalink
refactor extra global variables (DataLinkDC#2441)
Browse files Browse the repository at this point in the history
* Spotless Apply

* Spotless Apply

* refactor extra global variables

* refactor extra global variables

* Spotless Apply

---------

Co-authored-by: zhu-mingye <[email protected]>
  • Loading branch information
Zzm0809 and zhu-mingye authored Oct 26, 2023
1 parent ffadb0f commit 2bcc490
Show file tree
Hide file tree
Showing 9 changed files with 120 additions and 202 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,4 @@ public interface FlinkSQLConstant {

/** The define identifier of FlinkSQL Variable */
String VARIABLES = ":=";

/** The define identifier of FlinkSQL Date Variable */
String INNER_DATE_KEY = "_CURRENT_DATE_";

/** The define identifier of FlinkSQL Timestamp Variable */
String INNER_TIMESTAMP_KEY = "_CURRENT_TIMESTAMP_";

/** 内置日期变量格式 确定后不能修改 */
String INNER_DATE_FORMAT = "yyyy-MM-dd";
}
134 changes: 33 additions & 101 deletions dinky-executor/src/main/java/org/dinky/executor/VariableManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,17 +33,20 @@
import org.apache.flink.types.Row;
import org.apache.flink.util.StringUtils;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.extra.expression.engine.jexl.JexlEngine;

/**
* Flink Sql Variable Manager
*
Expand All @@ -55,6 +58,22 @@ public final class VariableManager {
static final String SHOW_VARIABLES = "SHOW VARIABLES";
private final Map<String, String> variables;

public static final JexlEngine ENGINE = new JexlEngine();

/**
* <p>
* engine , key is variable name , value is class .
* for example:
* random -> RandomUtil -> about random operation
* date -> DateUtil -> about date operation
* id -> IdUtil -> to generate random uuid
* ...
*/
public static final Dict ENGINE_CONTEXT = Dict.create()
.set("random", RandomUtil.class)
.set("date", DateUtil.class)
.set("id", IdUtil.class);

public VariableManager() {
variables = new HashMap<>();
}
Expand Down Expand Up @@ -127,21 +146,18 @@ public void unregisterVariable(String variableName, boolean ignoreIfNotExists) {
* @throws CatalogException if the unregistration of the sql variable under the given name
* failed. But at the moment, with CatalogException, not SqlException
*/
public String getVariable(String variableName) {
public Object getVariable(String variableName) {
checkArgument(
!StringUtils.isNullOrWhitespaceOnly(variableName), "sql variableName name cannot be null or empty.");

if (variables.containsKey(variableName)) {
return variables.get(variableName);
}

if (isInnerDateVariable(variableName)) {
return parseDateVariable(variableName);
} else if (isInnerTimestampVariable(variableName)) {
return parseTimestampVar(variableName);
try {
if (variables.containsKey(variableName)) {
return variables.get(variableName);
}
// use jexl to parse variable value
return ENGINE.eval(variableName, ENGINE_CONTEXT);
} catch (Exception e) {
throw new CatalogException(format("The variable of sql %s does not exist.", variableName));
}

throw new CatalogException(format("The variable of sql %s does not exist.", variableName));
}

/**
Expand Down Expand Up @@ -188,7 +204,7 @@ public Table getVariablesTable(CustomTableEnvironmentImpl environment) {
}

public boolean checkShowVariables(String sql) {
return SHOW_VARIABLES.equals(sql.trim().toUpperCase());
return SHOW_VARIABLES.equalsIgnoreCase(sql.trim());
}

/**
Expand Down Expand Up @@ -229,95 +245,11 @@ private String replaceVariable(String statement) {
StringBuffer sb = new StringBuffer();
while (m.find()) {
String key = m.group(1);
String value = getVariable(key);
Object value = getVariable(key);
m.appendReplacement(sb, "");

// if value is null, parse inner date variable
if (value == null) {
if (isInnerDateVariable(key)) {
value = parseDateVariable(key);
} else if (isInnerTimestampVariable(key)) {
value = parseTimestampVar(key);
}
}

sb.append(value == null ? "" : value);
}
m.appendTail(sb);
return sb.toString();
}

/**
* verify if key is inner variable, such as _CURRENT_DATE_ - 1
*
* @param key
* @return
*/
private boolean isInnerDateVariable(String key) {
return key.startsWith(FlinkSQLConstant.INNER_DATE_KEY);
}

/**
* verify if key is inner variable, such as _CURRENT_TIMESTAMP_ - 100
*
* @param key
* @return
*/
private boolean isInnerTimestampVariable(String key) {
return key.startsWith(FlinkSQLConstant.INNER_TIMESTAMP_KEY);
}

/**
* parse date variable
*
* @param key
* @return
*/
private String parseDateVariable(String key) {
int days = 0;
if (key.contains("+")) {
int s = key.indexOf("+") + 1;
String num = key.substring(s).trim();
days = Integer.parseInt(num);
} else if (key.contains("-")) {
int s = key.indexOf("-") + 1;
String num = key.substring(s).trim();
days = Integer.parseInt(num) * -1;
}

SimpleDateFormat dtf = new SimpleDateFormat(FlinkSQLConstant.INNER_DATE_FORMAT);
Date endDate = new Date();
Calendar calendar = Calendar.getInstance();
calendar.setTime(endDate);
calendar.add(Calendar.DAY_OF_YEAR, days);
Date startDate = calendar.getTime();

return dtf.format(startDate);
}

/**
* parse timestamp variable
*
* @param key
* @return
*/
private String parseTimestampVar(String key) {
long millisecond = 0;
try {
if (key.contains("+")) {
int s = key.indexOf("+") + 1;
String num = key.substring(s).trim();
millisecond = Long.parseLong(num);
} else if (key.contains("-")) {
int s = key.indexOf("-") + 1;
String num = key.substring(s).trim();
millisecond = Long.parseLong(num) * -1;
}
} catch (Exception e) {
e.printStackTrace();
return null;
}

return String.valueOf(System.currentTimeMillis() + millisecond);
}
}
4 changes: 2 additions & 2 deletions dinky-web/src/global.less
Original file line number Diff line number Diff line change
Expand Up @@ -399,8 +399,8 @@ h5 {
scrollbar-width: thin;
}

.editor-full-screen{
.ant-tabs-tabpane{
.editor-full-screen {
.ant-tabs-tabpane {
height: 100vh;
}
}
Expand Down
2 changes: 1 addition & 1 deletion dinky-web/src/pages/DataStudio/FooterContainer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
import useThemeValue from '@/hooks/useThemeValue';
import JobRunningModal from '@/pages/DataStudio/FooterContainer/JobRunningModal';
import { getCurrentTab } from '@/pages/DataStudio/function';
import { StateType,TabsPageType,VIEW} from '@/pages/DataStudio/model';
import { StateType, TabsPageType, VIEW } from '@/pages/DataStudio/model';
import { getSseData } from '@/services/api';
import { l } from '@/utils/intl';
import { connect } from '@@/exports';
Expand Down
5 changes: 3 additions & 2 deletions dinky-web/src/pages/DataStudio/HeaderContainer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ const HeaderContainer = (props: any) => {
const routes: ButtonRoute[] = [
// 保存按钮 icon
{
hotKey: (e: KeyboardEvent) => e.ctrlKey && e.key === 's' || e.metaKey && e.key === 's',
hotKey: (e: KeyboardEvent) => (e.ctrlKey && e.key === 's') || (e.metaKey && e.key === 's'),
hotKeyDesc: 'Ctrl/Command +S',
isShow: projectCommonShow(currentTab?.type),
icon: <SaveOutlined />,
Expand All @@ -237,7 +237,8 @@ const HeaderContainer = (props: any) => {
{
// 检查 sql按钮
icon: <ScheduleOutlined />,
hotKey: (e: KeyboardEvent) => e.altKey && e.code === 'Digit2' || e.altKey && e.key === '@',
hotKey: (e: KeyboardEvent) =>
(e.altKey && e.code === 'Digit2') || (e.altKey && e.key === '@'),
hotKeyDesc: 'Alt+2/@',
title: l('pages.datastudio.editor.check'),
click: () => showExplain(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
*
*/

import { useEditor } from '@/hooks/useEditor';
import { getCurrentTab } from '@/pages/DataStudio/function';
import { TASK_VAR_FILTER } from '@/pages/DataStudio/MiddleContainer/Editor/constants';
import DiffModal from '@/pages/DataStudio/MiddleContainer/Editor/DiffModal';
Expand All @@ -37,7 +38,6 @@ import { Button, Spin } from 'antd';
import { editor, KeyCode, KeyMod } from 'monaco-editor';
import React, { useState } from 'react';
import { format } from 'sql-formatter';
import { useEditor } from '@/hooks/useEditor';

export type EditorProps = {
taskId: number;
Expand All @@ -49,7 +49,7 @@ const CodeEditor: React.FC<EditorProps & any> = (props) => {
taskId,
tabs: { panes, activeKey },
dispatch,
height,
height
} = props;

const [isModalOpen, setIsModalOpen] = useState(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export const KEY_BOARD_MIDDLE = [
key: 'alt3',
label: 'Alt + 3',
description: l('shortcut.key.beautify')
},
}
// {
// key: 'f2',
// label: 'F2',
Expand Down
93 changes: 44 additions & 49 deletions dinky-web/src/pages/DataStudio/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
*/

import { AuthorizedObject, useAccess } from '@/hooks/useAccess';
import { FullScreenProvider, useEditor } from '@/hooks/useEditor';
import { useEditor } from '@/hooks/useEditor';
import useThemeValue from '@/hooks/useThemeValue';
import BottomContainer from '@/pages/DataStudio/BottomContainer';
import FooterContainer from '@/pages/DataStudio/FooterContainer';
Expand Down Expand Up @@ -199,57 +199,52 @@ const DataStudio = (props: any) => {
/>
);

return (
fullscreen ? (
<MiddleContainer />
) : (
<PageContainer title={false} breadcrumb={{ style: { display: 'none' } }}>
<PersistGate loading={null} persistor={persist}>
<div style={{ marginInline: -10, marginTop: -6, width: size.width }}>
<SecondHeaderContainer size={size} activeBreadcrumbTitle={activeBreadcrumbTitle} />
<Layout
hasSider
style={{
minHeight: size.contentHeight,
maxHeight: size.contentHeight,
paddingInline: 0
}}
>
<Sider collapsed collapsedWidth={40}>
<div style={{ display: 'flex', flexDirection: 'column', height: '100%' }}>
{LeftTopMenu}
{LeftBottomMenu}
</div>
</Sider>
return fullscreen ? (
<MiddleContainer />
) : (
<PageContainer title={false} breadcrumb={{ style: { display: 'none' } }}>
<PersistGate loading={null} persistor={persist}>
<div style={{ marginInline: -10, marginTop: -6, width: size.width }}>
<SecondHeaderContainer size={size} activeBreadcrumbTitle={activeBreadcrumbTitle} />
<Layout
hasSider
style={{
minHeight: size.contentHeight,
maxHeight: size.contentHeight,
paddingInline: 0
}}
>
<Sider collapsed collapsedWidth={40}>
<div style={{ display: 'flex', flexDirection: 'column', height: '100%' }}>
{LeftTopMenu}
{LeftBottomMenu}
</div>
</Sider>

<Content style={{ display: 'flex', flexDirection: 'column', minWidth: 0 }}>
<div style={{ display: 'flex' }}>
<LeftContainer size={size} />
<Content
style={{
width:
size.width -
2 * VIEW.sideWidth -
leftContainer.width -
rightContainer.width
}}
>
<MiddleContainer />
</Content>
<RightContainer size={size} bottomHeight={bottomHeight} />
</div>
{<BottomContainer size={size} />}
<Content style={{ display: 'flex', flexDirection: 'column', minWidth: 0 }}>
<div style={{ display: 'flex' }}>
<LeftContainer size={size} />
<Content
style={{
width:
size.width - 2 * VIEW.sideWidth - leftContainer.width - rightContainer.width
}}
>
<MiddleContainer />
</Content>
<RightContainer size={size} bottomHeight={bottomHeight} />
</div>
{<BottomContainer size={size} />}
</Content>

<Sider collapsed collapsedWidth={40}>
{RightTopMenu}
</Sider>
</Layout>
{<FooterContainer token={token} />}
</div>
</PersistGate>
</PageContainer>
)
<Sider collapsed collapsedWidth={40}>
{RightTopMenu}
</Sider>
</Layout>
{<FooterContainer token={token} />}
</div>
</PersistGate>
</PageContainer>
);
};

Expand Down
Loading

0 comments on commit 2bcc490

Please sign in to comment.