This is an automated email from the ASF dual-hosted git repository.

nicholasjiang pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/paimon-webui.git


The following commit(s) were added to refs/heads/main by this push:
     new 501b608a [Feature] Introduce statement interface (#251)
501b608a is described below

commit 501b608a0edc16cf66b13b8acac2bc1a92fbfc50
Author: s7monk <[email protected]>
AuthorDate: Tue May 28 11:27:03 2024 +0800

    [Feature] Introduce statement interface (#251)
---
 .../web/server/controller/StatementController.java | 100 +++++++++++
 .../web/server/data/model/StatementInfo.java       |  50 ++++++
 .../web/server/data/result/enums/Status.java       |   6 +-
 .../paimon/web/server/mapper/StatementMapper.java  |  36 ++++
 .../web/server/service/StatementService.java       |  57 +++++++
 .../server/service/impl/StatementServiceImpl.java  |  58 +++++++
 .../src/main/resources/i18n/messages.properties    |   2 +
 .../main/resources/i18n/messages_en_US.properties  |   2 +
 .../main/resources/i18n/messages_zh_CN.properties  |   2 +
 .../src/main/resources/mapper/StatementMapper.xml  |  49 ++++++
 .../server/controller/StatementControllerTest.java | 183 +++++++++++++++++++++
 scripts/sql/paimon-mysql.sql                       |  14 ++
 12 files changed, 558 insertions(+), 1 deletion(-)

diff --git 
a/paimon-web-server/src/main/java/org/apache/paimon/web/server/controller/StatementController.java
 
b/paimon-web-server/src/main/java/org/apache/paimon/web/server/controller/StatementController.java
new file mode 100644
index 00000000..ea4e491c
--- /dev/null
+++ 
b/paimon-web-server/src/main/java/org/apache/paimon/web/server/controller/StatementController.java
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.paimon.web.server.controller;
+
+import org.apache.paimon.web.server.data.model.StatementInfo;
+import org.apache.paimon.web.server.data.result.PageR;
+import org.apache.paimon.web.server.data.result.R;
+import org.apache.paimon.web.server.data.result.enums.Status;
+import org.apache.paimon.web.server.service.StatementService;
+import org.apache.paimon.web.server.util.PageSupport;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+/** Statement api controller. */
+@RestController
+@RequestMapping("/api/statement")
+public class StatementController {
+
+    @Autowired private StatementService statementService;
+
+    @SaCheckPermission("playground:statement:query")
+    @GetMapping("/{id}")
+    public R<StatementInfo> getStatement(@PathVariable("id") Integer id) {
+        StatementInfo statementInfo = statementService.getById(id);
+        if (statementInfo == null) {
+            return R.failed(Status.STATEMENT_NOT_EXIST);
+        }
+        return R.succeed(statementInfo);
+    }
+
+    @SaCheckPermission("playground:statement:list")
+    @GetMapping("/list")
+    public PageR<StatementInfo> listStatements(StatementInfo statementInfo) {
+        IPage<StatementInfo> page = PageSupport.startPage();
+        List<StatementInfo> statementInfos = 
statementService.listStatements(page, statementInfo);
+        return PageR.<StatementInfo>builder()
+                .success(true)
+                .total(page.getTotal())
+                .data(statementInfos)
+                .build();
+    }
+
+    @SaCheckPermission("playground:statement:query")
+    @GetMapping("/all")
+    public R<List<StatementInfo>> all() {
+        return R.succeed(statementService.list());
+    }
+
+    @SaCheckPermission("playground:statement:add")
+    @PostMapping
+    public R<Void> add(@RequestBody StatementInfo statementInfo) {
+        if (!statementService.checkStatementNameUnique(statementInfo)) {
+            return R.failed(Status.STATEMENT_NAME_ALREADY_EXISTS, 
statementInfo);
+        }
+        return statementService.saveStatement(statementInfo) ? R.succeed() : 
R.failed();
+    }
+
+    @SaCheckPermission("playground:statement:update")
+    @PutMapping
+    public R<Void> update(@RequestBody StatementInfo statementInfo) {
+        if (!statementService.checkStatementNameUnique(statementInfo)) {
+            return R.failed(Status.STATEMENT_NAME_ALREADY_EXISTS, 
statementInfo);
+        }
+        return statementService.updateById(statementInfo) ? R.succeed() : 
R.failed();
+    }
+
+    @SaCheckPermission("system:cluster:delete")
+    @DeleteMapping("/{statementId}")
+    public R<Void> delete(@PathVariable Integer statementId) {
+        return statementService.removeById(statementId) ? R.succeed() : 
R.failed();
+    }
+}
diff --git 
a/paimon-web-server/src/main/java/org/apache/paimon/web/server/data/model/StatementInfo.java
 
b/paimon-web-server/src/main/java/org/apache/paimon/web/server/data/model/StatementInfo.java
new file mode 100644
index 00000000..f3cbe174
--- /dev/null
+++ 
b/paimon-web-server/src/main/java/org/apache/paimon/web/server/data/model/StatementInfo.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.paimon.web.server.data.model;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+/** Statement info table model. */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+@TableName("statement")
+public class StatementInfo extends BaseModel {
+
+    private String statementName;
+
+    private String taskType;
+
+    private Boolean isStreaming;
+
+    private Integer uid;
+
+    private Integer clusterId;
+
+    private String statements;
+
+    private static final long serialVersionUID = 1L;
+}
diff --git 
a/paimon-web-server/src/main/java/org/apache/paimon/web/server/data/result/enums/Status.java
 
b/paimon-web-server/src/main/java/org/apache/paimon/web/server/data/result/enums/Status.java
index 4ebb1308..50e4b4a8 100644
--- 
a/paimon-web-server/src/main/java/org/apache/paimon/web/server/data/result/enums/Status.java
+++ 
b/paimon-web-server/src/main/java/org/apache/paimon/web/server/data/result/enums/Status.java
@@ -89,7 +89,11 @@ public enum Status {
     JOB_SUBMIT_ERROR(10701, "job.submit.error"),
     RESULT_FETCH_ERROR(10702, "result.fetch.error"),
     JOB_STOP_ERROR(10703, "job.stop.error"),
-    JOB_UPDATE_STATUS_ERROR(10704, "job.update.status.error");
+    JOB_UPDATE_STATUS_ERROR(10704, "job.update.status.error"),
+
+    /** ------------cluster-----------------. */
+    STATEMENT_NOT_EXIST(10801, "statement.not.exist"),
+    STATEMENT_NAME_ALREADY_EXISTS(10802, "statement.name.exist");
 
     private final int code;
     private final String msg;
diff --git 
a/paimon-web-server/src/main/java/org/apache/paimon/web/server/mapper/StatementMapper.java
 
b/paimon-web-server/src/main/java/org/apache/paimon/web/server/mapper/StatementMapper.java
new file mode 100644
index 00000000..221f6747
--- /dev/null
+++ 
b/paimon-web-server/src/main/java/org/apache/paimon/web/server/mapper/StatementMapper.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.paimon.web.server.mapper;
+
+import org.apache.paimon.web.server.data.model.StatementInfo;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/** Statement mapper. */
+@Mapper
+public interface StatementMapper extends BaseMapper<StatementInfo> {
+
+    List<StatementInfo> listStatements(
+            IPage<StatementInfo> page, @Param("statement") StatementInfo 
statement);
+}
diff --git 
a/paimon-web-server/src/main/java/org/apache/paimon/web/server/service/StatementService.java
 
b/paimon-web-server/src/main/java/org/apache/paimon/web/server/service/StatementService.java
new file mode 100644
index 00000000..fcd522f8
--- /dev/null
+++ 
b/paimon-web-server/src/main/java/org/apache/paimon/web/server/service/StatementService.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.paimon.web.server.service;
+
+import org.apache.paimon.web.server.data.model.StatementInfo;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.service.IService;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/** Statement Service. */
+public interface StatementService extends IService<StatementInfo> {
+
+    /**
+     * Check if the statement name is unique.
+     *
+     * @param statementInfo the statement to check
+     * @return true if unique, false otherwise
+     */
+    boolean checkStatementNameUnique(StatementInfo statementInfo);
+
+    /**
+     * Saves a statement information entity.
+     *
+     * @param statementInfo The statement information to save
+     * @return true if the statement was saved successfully, false otherwise
+     */
+    boolean saveStatement(StatementInfo statementInfo);
+
+    /**
+     * Retrieves a paginated list of statement information entities.
+     *
+     * @param page the pagination information
+     * @param statement the filter criteria
+     * @return A list of StatementInfo entities for the specified page
+     */
+    List<StatementInfo> listStatements(
+            IPage<StatementInfo> page, @Param("statement") StatementInfo 
statement);
+}
diff --git 
a/paimon-web-server/src/main/java/org/apache/paimon/web/server/service/impl/StatementServiceImpl.java
 
b/paimon-web-server/src/main/java/org/apache/paimon/web/server/service/impl/StatementServiceImpl.java
new file mode 100644
index 00000000..b0ac2774
--- /dev/null
+++ 
b/paimon-web-server/src/main/java/org/apache/paimon/web/server/service/impl/StatementServiceImpl.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.paimon.web.server.service.impl;
+
+import org.apache.paimon.web.server.data.model.StatementInfo;
+import org.apache.paimon.web.server.mapper.StatementMapper;
+import org.apache.paimon.web.server.service.StatementService;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/** The implementation of {@link StatementService}. */
+@Service
+public class StatementServiceImpl extends ServiceImpl<StatementMapper, 
StatementInfo>
+        implements StatementService {
+
+    @Autowired private StatementMapper statementMapper;
+
+    @Override
+    public boolean checkStatementNameUnique(StatementInfo statementInfo) {
+        int statementId = statementInfo.getId() == null ? -1 : 
statementInfo.getId();
+        StatementInfo info =
+                this.lambdaQuery()
+                        .eq(StatementInfo::getStatementName, 
statementInfo.getStatementName())
+                        .one();
+        return info == null || info.getId() == statementId;
+    }
+
+    @Override
+    public boolean saveStatement(StatementInfo statementInfo) {
+        return this.save(statementInfo);
+    }
+
+    @Override
+    public List<StatementInfo> listStatements(IPage<StatementInfo> page, 
StatementInfo statement) {
+        return statementMapper.listStatements(page, statement);
+    }
+}
diff --git a/paimon-web-server/src/main/resources/i18n/messages.properties 
b/paimon-web-server/src/main/resources/i18n/messages.properties
index 546bf8d7..c9443a74 100644
--- a/paimon-web-server/src/main/resources/i18n/messages.properties
+++ b/paimon-web-server/src/main/resources/i18n/messages.properties
@@ -57,3 +57,5 @@ job.submit.error=Exception submitting a job.
 result.fetch.error=Exception fetching result data.
 job.stop.error=Exception stopping a job.
 job.update.status.error=Exception updating the job status.
+statement.not.exist=This statement is not exist.
+statement.name.exist=This statement name {0} already exists.
diff --git 
a/paimon-web-server/src/main/resources/i18n/messages_en_US.properties 
b/paimon-web-server/src/main/resources/i18n/messages_en_US.properties
index 546bf8d7..c9443a74 100644
--- a/paimon-web-server/src/main/resources/i18n/messages_en_US.properties
+++ b/paimon-web-server/src/main/resources/i18n/messages_en_US.properties
@@ -57,3 +57,5 @@ job.submit.error=Exception submitting a job.
 result.fetch.error=Exception fetching result data.
 job.stop.error=Exception stopping a job.
 job.update.status.error=Exception updating the job status.
+statement.not.exist=This statement is not exist.
+statement.name.exist=This statement name {0} already exists.
diff --git 
a/paimon-web-server/src/main/resources/i18n/messages_zh_CN.properties 
b/paimon-web-server/src/main/resources/i18n/messages_zh_CN.properties
index 3ea53d88..7ababa39 100644
--- a/paimon-web-server/src/main/resources/i18n/messages_zh_CN.properties
+++ b/paimon-web-server/src/main/resources/i18n/messages_zh_CN.properties
@@ -57,3 +57,5 @@ 
job.submit.error=\u63D0\u4EA4\u4F5C\u4E1A\u65F6\u53D1\u751F\u5F02\u5E38
 
result.fetch.error=\u83B7\u53D6\u7ED3\u679C\u6570\u636E\u65F6\u53D1\u751F\u5F02\u5E38
 job.stop.error=\u505C\u6B62\u4F5C\u4E1A\u65F6\u53D1\u751F\u5F02\u5E38
 
job.update.status.error=\u66F4\u65B0\u4F5C\u4E1A\u72B6\u6001\u65F6\u53D1\u751F\u5F02\u5E38
+statement.not.exist=\u6B64 Statement \u4E0D\u5B58\u5728
+statement.name.exist=\u6B64 Statement \u540D\u79F0 {0} \u5DF2\u7ECF\u5B58\u5728
diff --git a/paimon-web-server/src/main/resources/mapper/StatementMapper.xml 
b/paimon-web-server/src/main/resources/mapper/StatementMapper.xml
new file mode 100644
index 00000000..abc78f80
--- /dev/null
+++ b/paimon-web-server/src/main/resources/mapper/StatementMapper.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd";>
+<mapper namespace="org.apache.paimon.web.server.mapper.StatementMapper">
+
+    <resultMap id="StatementResult" 
type="org.apache.paimon.web.server.data.model.StatementInfo">
+        <id     property="id"       column="id"      />
+        <result property="statementName"     column="statement_name"    />
+        <result property="taskType"     column="task_type"    />
+        <result property="isStreaming"     column="is_streaming"    />
+        <result property="uid"        column="uid"        />
+        <result property="clusterId"     column="cluster_id"     />
+        <result property="statements"     column="statements"     />
+        <result property="createTime"   column="create_time"  />
+        <result property="updateTime"   column="update_time"  />
+    </resultMap>
+
+    <sql id="selectStatementVo">
+        select id, statement_name, task_type, is_streaming, uid, cluster_id, 
statements, create_time, update_time from statement order by create_time desc
+    </sql>
+
+    <select id="listStatements" 
parameterType="org.apache.paimon.web.server.data.model.StatementInfo" 
resultMap="StatementResult">
+        <include refid="selectStatementVo"/>
+        <where>
+            <if test="statement.statementName != null and 
statement.statementName != ''">
+                AND statement_name like concat('%', 
#{statement.statementName}, '%')
+            </if>
+        </where>
+    </select>
+</mapper>
\ No newline at end of file
diff --git 
a/paimon-web-server/src/test/java/org/apache/paimon/web/server/controller/StatementControllerTest.java
 
b/paimon-web-server/src/test/java/org/apache/paimon/web/server/controller/StatementControllerTest.java
new file mode 100644
index 00000000..466afb10
--- /dev/null
+++ 
b/paimon-web-server/src/test/java/org/apache/paimon/web/server/controller/StatementControllerTest.java
@@ -0,0 +1,183 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.paimon.web.server.controller;
+
+import org.apache.paimon.web.server.data.model.StatementInfo;
+import org.apache.paimon.web.server.data.result.PageR;
+import org.apache.paimon.web.server.data.result.R;
+import org.apache.paimon.web.server.util.ObjectMapperUtils;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import org.junit.jupiter.api.MethodOrderer;
+import org.junit.jupiter.api.Order;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestMethodOrder;
+import 
org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.http.MediaType;
+import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
+import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
+import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/** Test for {@link StatementController}. */
+@SpringBootTest
+@AutoConfigureMockMvc
+@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
+public class StatementControllerTest extends ControllerTestBase {
+
+    private static final String statementPath = "/api/statement";
+
+    private static final int statementId = 1;
+    private static final String statementName = "test_query";
+
+    @Test
+    @Order(1)
+    public void testAddStatement() throws Exception {
+        StatementInfo statementInfo = new StatementInfo();
+        statementInfo.setId(statementId);
+        statementInfo.setStatementName(statementName);
+        statementInfo.setTaskType("Flink");
+        statementInfo.setIsStreaming(false);
+        statementInfo.setStatements("select * from table");
+
+        String responseString =
+                mockMvc.perform(
+                                MockMvcRequestBuilders.post(statementPath)
+                                        .cookie(cookie)
+                                        
.content(ObjectMapperUtils.toJSON(statementInfo))
+                                        
.contentType(MediaType.APPLICATION_JSON_VALUE)
+                                        
.accept(MediaType.APPLICATION_JSON_VALUE))
+                        .andExpect(MockMvcResultMatchers.status().isOk())
+                        .andDo(MockMvcResultHandlers.print())
+                        .andReturn()
+                        .getResponse()
+                        .getContentAsString();
+
+        R<?> result = ObjectMapperUtils.fromJSON(responseString, R.class);
+        assertEquals(200, result.getCode());
+
+        StatementInfo statement = getStatementInfo();
+        assertEquals(statementName, statement.getStatementName());
+        assertEquals(false, statement.getIsStreaming());
+        assertEquals("Flink", statement.getTaskType());
+        assertEquals("select * from table", statement.getStatements());
+    }
+
+    @Test
+    @Order(2)
+    public void testGetStatement() throws Exception {
+        StatementInfo statementInfo = getStatementInfo();
+        assertEquals(statementName, statementInfo.getStatementName());
+        assertEquals(false, statementInfo.getIsStreaming());
+        assertEquals("Flink", statementInfo.getTaskType());
+        assertEquals("select * from table", statementInfo.getStatements());
+    }
+
+    @Test
+    @Order(3)
+    public void testListStatements() throws Exception {
+        String responseString =
+                mockMvc.perform(
+                                MockMvcRequestBuilders.get(statementPath + 
"/list")
+                                        .cookie(cookie)
+                                        
.contentType(MediaType.APPLICATION_JSON_VALUE)
+                                        
.accept(MediaType.APPLICATION_JSON_VALUE))
+                        .andExpect(MockMvcResultMatchers.status().isOk())
+                        .andDo(MockMvcResultHandlers.print())
+                        .andReturn()
+                        .getResponse()
+                        .getContentAsString();
+
+        PageR<StatementInfo> r =
+                ObjectMapperUtils.fromJSON(
+                        responseString, new 
TypeReference<PageR<StatementInfo>>() {});
+        assertTrue(
+                r.getData() != null
+                        && ((r.getTotal() > 0 && r.getData().size() > 0)
+                                || (r.getTotal() == 0 && r.getData().size() == 
0)));
+
+        StatementInfo statementInfo = r.getData().get(0);
+        assertEquals(statementName, statementInfo.getStatementName());
+        assertEquals(false, statementInfo.getIsStreaming());
+        assertEquals("Flink", statementInfo.getTaskType());
+        assertEquals("select * from table", statementInfo.getStatements());
+    }
+
+    @Test
+    @Order(4)
+    public void testUpdateStatement() throws Exception {
+        StatementInfo statementInfo = new StatementInfo();
+        statementInfo.setId(statementId);
+        statementInfo.setStatements("select * from table limit 10");
+
+        mockMvc.perform(
+                        MockMvcRequestBuilders.put(statementPath)
+                                .cookie(cookie)
+                                
.content(ObjectMapperUtils.toJSON(statementInfo))
+                                .contentType(MediaType.APPLICATION_JSON_VALUE)
+                                .accept(MediaType.APPLICATION_JSON_VALUE))
+                .andExpect(MockMvcResultMatchers.status().isOk());
+
+        assertNotNull(getStatementInfo());
+        assertEquals("select * from table limit 10", 
getStatementInfo().getStatements());
+    }
+
+    @Test
+    @Order(5)
+    public void testDeleteStatement() throws Exception {
+        String delResponseString =
+                mockMvc.perform(
+                                MockMvcRequestBuilders.delete(statementPath + 
"/" + statementId)
+                                        .cookie(cookie)
+                                        
.contentType(MediaType.APPLICATION_JSON_VALUE)
+                                        
.accept(MediaType.APPLICATION_JSON_VALUE))
+                        .andExpect(MockMvcResultMatchers.status().isOk())
+                        .andDo(MockMvcResultHandlers.print())
+                        .andReturn()
+                        .getResponse()
+                        .getContentAsString();
+
+        R<?> result = ObjectMapperUtils.fromJSON(delResponseString, R.class);
+        assertEquals(200, result.getCode());
+    }
+
+    private StatementInfo getStatementInfo() throws Exception {
+        String responseString =
+                mockMvc.perform(
+                                MockMvcRequestBuilders.get(statementPath + "/" 
+ statementId)
+                                        .cookie(cookie)
+                                        
.contentType(MediaType.APPLICATION_JSON_VALUE)
+                                        
.accept(MediaType.APPLICATION_JSON_VALUE))
+                        .andExpect(MockMvcResultMatchers.status().isOk())
+                        .andDo(MockMvcResultHandlers.print())
+                        .andReturn()
+                        .getResponse()
+                        .getContentAsString();
+
+        R<StatementInfo> r =
+                ObjectMapperUtils.fromJSON(
+                        responseString, new TypeReference<R<StatementInfo>>() 
{});
+        assertEquals(200, r.getCode());
+        return r.getData();
+    }
+}
diff --git a/scripts/sql/paimon-mysql.sql b/scripts/sql/paimon-mysql.sql
index b83f9355..e348358e 100644
--- a/scripts/sql/paimon-mysql.sql
+++ b/scripts/sql/paimon-mysql.sql
@@ -173,6 +173,20 @@ CREATE TABLE if not exists `job`
     `update_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'update 
time'
     )  ENGINE = InnoDB DEFAULT CHARSET=utf8;
 
+DROP TABLE IF EXISTS `statement`;
+CREATE TABLE if not exists `statement`
+(
+    `id`          int(11)     not null auto_increment primary key comment 'id',
+    `statement_name`     varchar(200)  not null comment 'task type',
+    `task_type`     varchar(100)  not null comment 'task type',
+    `is_streaming`  tinyint(1)  comment 'is steaming',
+    `uid`     int(11)  comment 'user id',
+    `cluster_id`     int(11)  comment 'cluster id',
+    `statements`   text COMMENT 'statements',
+    `create_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'create 
time',
+    `update_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'update 
time'
+    )  ENGINE = InnoDB DEFAULT CHARSET=utf8;
+    
 DROP TABLE IF EXISTS `history`;
 CREATE TABLE if not exists `history`
 (

Reply via email to