single_file_eva

This commit is contained in:
郑明仁 2019-08-14 11:11:18 +08:00
parent e53f48af44
commit 25cdc66972
12 changed files with 619 additions and 5 deletions

View File

@ -84,6 +84,9 @@ public class AppConfig {
@Value("${k8s.serverUrl}")
private String k8sServerUrl;
@Value("${singleEvaCodePath}")
private String singleEvaCodePath;
private String bridgeInstanceName = IpUtils.getLocalIp();
public String getServerUrl() {
@ -222,4 +225,7 @@ public class AppConfig {
return bridgeInstanceName;
}
public String getSingleEvaCodePath() {
return singleEvaCodePath;
}
}

View File

@ -1,8 +1,10 @@
package com.educoder.bridge.game.controller;
import java.io.File;
import java.nio.channels.InterruptibleChannel;
import java.time.LocalDateTime;
import com.educoder.bridge.game.thread.SingleEvaThread;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -212,6 +214,112 @@ public class GameController {
return response;
}
/**
* 单个文件评测
*/
@RequestMapping(path = "/singleEvaluate")
@ApiOperation(value = "单个文件评测", httpMethod = "POST", produces = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public JSONObject singleEvaluate(
@ApiParam(name = "tpiID", required = true, value = "实训实例的ID") @RequestParam String tpiID,
@ApiParam(name = "buildID", required = true, value = "本次评测ID") @RequestParam String buildID,
@ApiParam(name = "isPublished", required = false, value = "实训是否已经发布1代表调试模式实训未发布") @RequestParam Integer isPublished,
@ApiParam(name = "instanceChallenge", required = true, value = "当前处在第几关") @RequestParam String instanceChallenge,
@ApiParam(name = "testCases", required = true, value = "测试用例") @RequestParam String testCases,
@ApiParam(name = "codeFileName", required = true, value = "代码文件名") @RequestParam String codeFileName,
@ApiParam(name = "evaScriptType", required = true, value = "代码评测脚本类型") @RequestParam String evaScriptType,
@ApiParam(name = "codeFile", required = true, value = "代码文件") @RequestParam String codeFile,
@ApiParam(name = "timeLimit", required = false, value = "时间限制") Integer timeLimit,
@ApiParam(name = "resubmit", required = true, value = "是否是重复评测") @RequestParam String resubmit,
@ApiParam(name = "needPortMapping", required = false, value = "容器中需要被映射的端口") Integer needPortMapping,
@ApiParam(name = "podType", required = true, value = "pod类型(0.evaluate1.webssh2.evassh)") @RequestParam Integer podType,
@ApiParam(name = "file", required = false, value = "需要传文件的实训,给出文件存放路径(一个目录)及文件类型") String file,
@ApiParam(name = "containers", required = true, value = "需要使用的容器,base64编码") @RequestParam String containers,
@ApiParam(name = "sec_key", required = false, value = "每一次评测的唯一标识") String sec_key) throws Exception {
logger.info("[start]单个文件评测tpiID: {}, buildID: {}, isPublished: {}, instanceChallenge: {}, "
+ "testCases: {}, codeFile: {}, timeLimit: {}, resubmit: {}, "
+ "needPortMapping: {}, podType: {}, file: {}, containers: {}, sec_key: {}",
tpiID, buildID, isPublished, instanceChallenge, testCases, codeFile, timeLimit, resubmit,
needPortMapping, podType, file, containers, sec_key);
// 记录开始时间
LocalDateTime requestTime = LocalDateTime.now();
String evaluateStartTime = requestTime.toString();
JSONObject cost = new JSONObject();
cost.put("evaluateStartTime", evaluateStartTime);
JedisUtil.set("timeCost:" + tpiID + ":" + buildID, cost.toJSONString());
JSONObject response = new JSONObject();
// 参数处理
needPortMapping = needPortMapping == null ? 0 : needPortMapping;
timeLimit = timeLimit == null ? Integer.parseInt(appConfig.getDefaultTimeLimit()) : timeLimit;
testCases = Base64Util.decode(testCases);
containers = Base64Util.decode(containers);
// 每次评测均生成新TPI评测脚本
String tpiWorkspace = TpUtils.buildTpiWorkspace(appConfig.getWorkspace(), tpiID);
gameService.generateEvaluateShellScript(tpiWorkspace, evaScriptType);
codeFile = Base64Util.decode(codeFile);
gameService.generateEvaluateCodeFile(tpiWorkspace, codeFileName, codeFile, instanceChallenge);
String tpiRepoPath = TpUtils.buildTpiRepoPath(tpiWorkspace, appConfig.getSingleEvaCodePath().split("/")[0]);
JSONObject buildParams = new JSONObject(true);
buildParams.put("tpiID", tpiID);
buildParams.put("buildID", buildID);
buildParams.put("isPublished", isPublished);
buildParams.put("instanceChallenge", instanceChallenge);
buildParams.put("testCases", testCases);
buildParams.put("timeLimit", timeLimit);
buildParams.put("resubmit", resubmit);
buildParams.put("needPortMapping", needPortMapping);
buildParams.put("podType", podType);
buildParams.put("containers", containers);
buildParams.put("codeFileName", codeFileName);
buildParams.put("sec_key", sec_key);
buildParams.put("tpiRepoPath", tpiRepoPath);
// 若实训生成文件 todo:这个处理方式好2b扩展性极差
if (!StringUtils.isEmpty(file)) {
file = Base64Util.decode(file);
buildParams.put("file", file);
// 清空目标文件夹以防止影响此次评测结果
GameHelper.clearFiles(tpiRepoPath + File.separator
+ JSONObject.parseObject(file).getString("path"));
}
// podName
String podName = podType != 2 ? "evaluate-" + tpiID : "evassh-" + tpiID;
BridgePod bridgePod = bridgePodService.createBridgePod(podName, tpiID, requestTime, sec_key);
buildParams.put("bridgePodId", bridgePod.getId());
// 若需要端口映射服务则分配端口将podName-port键值对存储于redis
String port = "-1";
if (needPortMapping != -1) {
port = portService.allocatePort() + "";
JedisUtil.hset("port", podName, port);
}
// sendSingleToKafka(buildParams, tpiID, requestTime);
response.put("ableToCreate", 1);
response.put("costTime", System.currentTimeMillis() - TimeHelper.convertTimeToMillis(evaluateStartTime));
response.put("waitNum", 0);
response.put("code", 0);
response.put("port", port);
response.put("msg", "评测完成");
logger.info("[end]单个文件评测tpiID: {}, buildID: {}", tpiID, buildID);
return response;
}
private void sendSingleToKafka(JSONObject buildparams, String tpiID, final LocalDateTime requestTime) {
SingleEvaThread singleEvaThread = gameService.getSingleEvaThread(buildparams);
threadPoolTaskExecutor.execute(singleEvaThread);
}
private void sendToKafka(JSONObject buildParams, String tpiID, final LocalDateTime requestTime) {
BuildThread buildThread = gameService.getBuildThread(buildParams);
threadPoolTaskExecutor.execute(buildThread);

View File

@ -13,11 +13,12 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.educoder.bridge.game.thread.SingleEvaThread;
import com.educoder.bridge.k8s.service.EvaScriptService;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
@ -67,6 +68,9 @@ public class GameService {
@Autowired
ResourceFileService resourceFileService;
@Autowired
private EvaScriptService evaScriptService;
private static final Logger logger = LoggerFactory.getLogger(GameService.class);
/**
@ -679,7 +683,18 @@ public class GameService {
BuildThread buildThread = (BuildThread) BeanFactory.getObejct("BuildThread");
buildThread.setBuildParams(buildParams);
return buildThread;
}
/**
* 根据单个文件评测信息构建一个singleEvaThread
*
* @param buildParams
* @return
*/
public SingleEvaThread getSingleEvaThread(JSONObject buildParams) {
SingleEvaThread singleEvaThread = (SingleEvaThread) BeanFactory.getObejct("singleEvaThread");
singleEvaThread.setBuildParams(buildParams);
return singleEvaThread;
}
/**
@ -824,4 +839,51 @@ public class GameService {
return result;
}
public void generateEvaluateShellScript(String tpiWorkspace, String evaScriptType) throws GameException {
logger.debug("tpiWorkspace: {}, evaScriptType: {}", tpiWorkspace, evaScriptType);
// 获取脚本
String script = evaScriptService.getScriptByType(evaScriptType);
if (StringUtils.isEmpty(script)) {
logger.error("生成评测脚本失败: 无评测脚本");
throw new GameException(-1, "生成评测脚本失败: 无评测脚本");
}
script = Base64Util.decode(script);
try {
// 写脚本到工作空间目录下
FileUtils.deleteQuietly(new File(tpiWorkspace + File.separator + "evaluate.sh"));
FileUtils.writeStringToFile(new File(tpiWorkspace + File.separator + "evaluate.sh"), script, "UTF-8");
} catch (Exception e) {
logger.error("生成评测脚本失败!{}", e);
throw new GameException(-1, "生成评测脚本失败");
}
try {
String content = resourceFileService.getResourceFileContent("evaluate/execeva.sh");
FileUtils.deleteQuietly(new File(tpiWorkspace + File.separator + "execeva.sh"));
FileUtils.writeStringToFile(new File(tpiWorkspace + File.separator + "execeva.sh"), content, "UTF-8");
} catch (Exception e) {
logger.error("生成评测脚本execeva失败!{}", e);
throw new GameException(-1, "生成评测脚本execeva失败");
}
}
public void generateEvaluateCodeFile(String tpiWorkspace, String codeFileName, String codeFile, String instanceChallenge) throws GameException {
logger.debug("生成评测代码文件: tpiWorkspace: {}, codeFileName: {}, codeFile: {}, instanceChallenge: {}", tpiWorkspace, codeFileName, codeFile, instanceChallenge);
String codeFilePath = tpiWorkspace + File.separator + appConfig.getSingleEvaCodePath() + instanceChallenge + File.separator + codeFileName;
try {
// 写脚本到工作空间目录下
FileUtils.deleteQuietly(new File(codeFilePath));
FileUtils.writeStringToFile(new File(codeFilePath), codeFile, "UTF-8");
} catch (Exception e) {
logger.error("生成评测代码文件失败!{}", e);
throw new GameException(-1, "生成评测代码文件失败");
}
}
}

View File

@ -1,6 +1,7 @@
package com.educoder.bridge.game.service;
import java.io.File;
import java.time.Duration;
import java.time.Instant;
@ -50,7 +51,7 @@ public class KubernetesService {
* 在pod中执行评测脚本
*/
public void executeShellInPod(JSONObject buildParams, Pod pod, int needPortMapping, int timeLimit, int isPublished,
int instanceChallenge, String testCases) {
int instanceChallenge, String testCases, Boolean isSingleEva) {
String podName = pod.getMetadata().getName();
logger.debug("podName: {}, needPortMapping: {}, timeLimit: {}, isPublished: {}, instanceChallenge: {}", podName,
needPortMapping, timeLimit, isPublished, instanceChallenge);
@ -67,7 +68,12 @@ public class KubernetesService {
String buildID = buildParams.getString("buildID");
String tpiWorkspace = TpUtils.buildTpiWorkspace(appConfig.getWorkspace(), tpiID);
String shFile = tpiWorkspace + "/evaluate.sh";
String command = " timeout " + timeLimit + " kubectl exec " + podName + " timeout " + timeLimit + " bash " + shFile + " " + instanceChallenge + " " + ins;
String command = " timeout " + timeLimit + " kubectl exec " + podName + " timeout " + timeLimit + " bash " + shFile + " " + instanceChallenge + " " + ins;
if (isSingleEva) {
String codeFileName = buildParams.getString("codeFileName");
String challengeProgramName = tpiWorkspace + File.separator + appConfig.getSingleEvaCodePath() + instanceChallenge + File.separator + codeFileName;
command = " timeout " + timeLimit + " kubectl exec " + podName + " timeout " + timeLimit + " bash " + shFile + " " + challengeProgramName + " " + ins;
}
logger.info("evaluate command: {}", command);
// 为pod的score加1若pod之前不存在则score为1
JedisUtil.zup("taskNum", podName);

View File

@ -179,7 +179,7 @@ public class BuildThread extends Thread {
: buildParams.getInteger("executeTime");
kubernetesService.executeShellInPod(buildParams, podRef.getPod(), buildParams.getInteger("needPortMapping"),
executeTimeLimit, buildParams.getInteger("isPublished"), buildParams.getInteger("instanceChallenge"),
buildParams.getString("testCases"));
buildParams.getString("testCases"), Boolean.FALSE);
}

View File

@ -0,0 +1,129 @@
package com.educoder.bridge.game.thread;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.educoder.bridge.common.constant.BuildResultCsts;
import com.educoder.bridge.common.settings.AppConfig;
import com.educoder.bridge.common.utils.GameHelper;
import com.educoder.bridge.game.model.PodRef;
import com.educoder.bridge.game.service.GameService;
import com.educoder.bridge.game.service.K8sService;
import com.educoder.bridge.game.service.KubernetesService;
import com.educoder.bridge.k8s.service.RunPodService;
import io.fabric8.kubernetes.api.model.Pod;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import java.time.Duration;
import java.time.Instant;
import java.util.HashMap;
import java.util.Map;
/**
* 单个文件评测线程
*/
@Service("singleEvaThread")
@Scope("prototype")
public class SingleEvaThread extends Thread {
private final Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
private GameService gameService;
@Autowired
private KubernetesService kubernetesService;
@Autowired
private AppConfig appConfig;
@Autowired
private K8sService k8sService;
@Autowired
private RunPodService runPodService;
private JSONObject buildParams;
public SingleEvaThread() {
}
public SingleEvaThread(JSONObject buildParams) {
this();
this.buildParams = buildParams;
}
public void setBuildParams(JSONObject buildParams) {
this.buildParams = buildParams;
}
public JSONObject getBuildParams() {
return buildParams;
}
@Override
public void run() {
String tpiID = buildParams.getString("tpiID");
String buildID = buildParams.getString("buildID");
Map<String, String> podInLabels = new HashMap<>(1);
Map<String, String> podNotInLabels = new HashMap<>(1);
podInLabels.put("tpiID", tpiID);
podInLabels.put("type", "evaluate,evassh");
String type = buildParams.getInteger("podType") != 2 ? "evaluate" : "evassh";
String testCases = buildParams.getString("testCases");
String out = GameHelper.getTextMsgResult("服务启动中...");
gameService.encapsulateStepByStepResult(out, buildParams, testCases);
Instant podStartInstant = Instant.now();
// 设立(重设)对应pod的定时删除任务这个时间必须大于${timeLimit}确保脚本执行期间pod不会中途死 单位
int timeLimit = buildParams.getInteger("timeLimit");
gameService.reTiming(type + "-" + tpiID, timeLimit + 60);
// 查询 pod
Pod pod = k8sService.getK8sRunningPod(podInLabels, podNotInLabels);
// 如果pod不存在还将创建
pod = runPodService.createRunPod(pod, buildParams, tpiID, type, timeLimit);
final PodRef podRef = new PodRef();
if (pod != null) {
podRef.setPod(pod);
String podName = pod.getMetadata().getName();
double createPodAndSvcCost = (double) Duration.between(podStartInstant, Instant.now()).toMillis()
/ 1000;
podRef.setCreatePodAndSvcCost(createPodAndSvcCost);
// 设立(重设)对应pod的定时删除任务这个时间必须大于${timeLimit}确保脚本执行期间pod不会中途死 单位
gameService.reTiming(podName, timeLimit + 60);
}
JSONArray cases = JSONArray.parseArray(testCases);
if (podRef.getPod() == null) {
logger.error("实训 {} 创建 pod 失败", tpiID);
String msg = GameHelper.getResult("系统繁忙,请稍后重试", cases.size(), BuildResultCsts.DOWNLOAD_STATUS_SUCCESS,
BuildResultCsts.CREATE_POD_STATUS_FAIL);
gameService.encapsulateBuildResult(msg, buildParams, testCases);
return;
}
// 记录创建pod耗时
GameHelper.setTimeCostInJedis("timeCost:" + tpiID + ":" + buildID, "createPod",
String.format("%.3f", podRef.getCreatePodAndSvcCost()));
out = GameHelper.getTextMsgResult("服务启动完成");
gameService.encapsulateStepByStepResult(out, buildParams, testCases);
// 在pod中执行评测脚本
Integer executeTimeLimit = buildParams.getInteger("executeTime") == null ? buildParams.getInteger("timeLimit")
: buildParams.getInteger("executeTime");
kubernetesService.executeShellInPod(buildParams, podRef.getPod(), buildParams.getInteger("needPortMapping"),
executeTimeLimit, buildParams.getInteger("isPublished"), buildParams.getInteger("instanceChallenge"),
buildParams.getString("testCases"), Boolean.TRUE);
}
@Override
public String toString() {
return "singleEvaThread{" + buildParams.toJSONString() + '}';
}
}

View File

@ -0,0 +1,66 @@
package com.educoder.bridge.k8s.controller;
import com.alibaba.fastjson.JSONObject;
import com.educoder.bridge.common.constant.ApiResultCodeCsts;
import com.educoder.bridge.common.model.ApiResult;
import com.educoder.bridge.common.model.BridgePage;
import com.educoder.bridge.game.service.K8sService;
import com.educoder.bridge.k8s.model.BridgePod;
import com.educoder.bridge.k8s.model.EvaluatingScript;
import com.educoder.bridge.k8s.model.PodQueryParam;
import com.educoder.bridge.k8s.service.BridgePodService;
import com.educoder.bridge.k8s.service.EvaScriptService;
import com.github.pagehelper.Page;
import io.fabric8.kubernetes.api.model.Pod;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.commons.lang.StringEscapeUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDateTime;
import java.util.List;
/**
* 评测脚本相关的接口
*/
@Api(value = "script", hidden = true)
@RestController
@RequestMapping("/script")
public class ScriptController {
private final Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
private EvaScriptService evaScriptService;
/**
* 设置评测脚本
*/
@RequestMapping(path = "/set", method = RequestMethod.POST)
@ApiOperation(value = "设置评测脚本", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public JSONObject set(
@ApiParam(name = "scriptType", required = true, value = "脚本类型") @RequestParam("scriptType") String scriptType,
@ApiParam(name = "script", required = true, value = "脚本") @RequestParam("script") String script
) throws Exception {
logger.info("[start]设置评测脚本, type: {}, script: {}", scriptType, script);
JSONObject response = new JSONObject();
LocalDateTime now = LocalDateTime.now();
EvaluatingScript evaluatingScript = new EvaluatingScript();
evaluatingScript.setScriptType(scriptType);
evaluatingScript.setScript(script);
evaluatingScript.setCreateTime(now);
evaluatingScript.setUpdateTime(now);
evaScriptService.savaEvaluationScript(evaluatingScript);
response.put("code", 0);
response.put("msg", "设置评测脚本成功");
logger.info("[end]获取Pod列表");
return response;
}
}

View File

@ -0,0 +1,17 @@
package com.educoder.bridge.k8s.dao;
import com.educoder.bridge.k8s.model.EvaluatingScript;
public interface EvaScriptMapper {
int deleteByPrimaryKey(Long id);
int insert(EvaluatingScript record);
int insertSelective(EvaluatingScript record);
EvaluatingScript selectByPrimaryKey(Long id);
int updateByPrimaryKey(EvaluatingScript record);
String selectScriptByType(String scriptType);
}

View File

@ -0,0 +1,66 @@
package com.educoder.bridge.k8s.model;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.time.LocalDateTime;
/**
* 单个文件评测脚本
*/
@ApiModel(value = "evaluating_script", description = "单个文件评测脚本")
public class EvaluatingScript {
@ApiModelProperty(value = "脚本ID")
private long id;
@ApiModelProperty(value = "脚本类型")
private String scriptType;
@ApiModelProperty(value = "脚本")
private String script;
private LocalDateTime createTime;
private LocalDateTime updateTime;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getScriptType() {
return scriptType;
}
public void setScriptType(String scriptType) {
this.scriptType = scriptType;
}
public String getScript() {
return script;
}
public void setScript(String script) {
this.script = script;
}
public LocalDateTime getCreateTime() {
return createTime;
}
public void setCreateTime(LocalDateTime createTime) {
this.createTime = createTime;
}
public LocalDateTime getUpdateTime() {
return updateTime;
}
public void setUpdateTime(LocalDateTime updateTime) {
this.updateTime = updateTime;
}
}

View File

@ -0,0 +1,28 @@
package com.educoder.bridge.k8s.service;
import com.educoder.bridge.k8s.dao.EvaScriptMapper;
import com.educoder.bridge.k8s.model.EvaluatingScript;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* Created by macbookpro on 2019/8/13.
*/
@Service("evaScriptService")
public class EvaScriptService {
private final Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
private EvaScriptMapper evaScriptMapper;
public void savaEvaluationScript(EvaluatingScript evaluatingScript) {
evaScriptMapper.insert(evaluatingScript);
}
public String getScriptByType(String evaScriptType) {
return evaScriptMapper.selectScriptByType(evaScriptType);
}
}

View File

@ -74,4 +74,6 @@ dbpool.minIdle=100
vncPort=6901
#kafka
bootstrapServersConfig=172.16.94.173:9092
bootstrapServersConfig=172.16.94.173:9092
singleEvaCodePath=code/src/step

View File

@ -0,0 +1,124 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.educoder.bridge.k8s.dao.EvaScriptMapper">
<resultMap id="BaseResultMap"
type="com.educoder.bridge.k8s.model.EvaluatingScript">
<id column="id" property="id" jdbcType="BIGINT" />
<result column="script_type" property="scriptType" jdbcType="VARCHAR" />
<result column="script" property="script" jdbcType="VARCHAR" />
<result column="create_time" property="createTime"
jdbcType="TIMESTAMP" />
<result column="update_time" property="updateTime"
jdbcType="TIMESTAMP" />
</resultMap>
<sql id="Base_Column_List">
id, script_type, script, create_time, update_time
</sql>
<select id="selectByPrimaryKey" resultMap="BaseResultMap"
parameterType="java.lang.Long">
select
<include refid="Base_Column_List" />
from evaluating_script
where id = #{id,jdbcType=BIGINT}
</select>
<delete id="deleteByPrimaryKey" parameterType="java.lang.Long">
delete from
evaluating_script
where id = #{id,jdbcType=BIGINT}
</delete>
<insert id="insert"
parameterType="com.educoder.bridge.k8s.model.EvaluatingScript">
insert into evaluating_script (id, script_type, script,
create_time,
update_time)
values (#{id,jdbcType=BIGINT}, #{scriptType,jdbcType=VARCHAR},
#{script,jdbcType=VARCHAR},
#{createTime,jdbcType=TIMESTAMP},
#{updateTime,jdbcType=TIMESTAMP})
</insert>
<insert id="insertSelective"
parameterType="com.educoder.bridge.k8s.model.EvaluatingScript">
insert into evaluating_script
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="id != null">
id,
</if>
<if test="scriptType != null">
script_type,
</if>
<if test="script != null">
script,
</if>
<if test="createTime != null">
create_time,
</if>
<if test="updateTime != null">
update_time,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="id != null">
#{id,jdbcType=BIGINT},
</if>
<if test="scriptType != null">
#{scriptType,jdbcType=VARCHAR},
</if>
<if test="script != null">
#{script,jdbcType=VARCHAR},
</if>
<if test="createTime != null">
#{createTime,jdbcType=TIMESTAMP},
</if>
<if test="updateTime != null">
#{updateTime,jdbcType=TIMESTAMP},
</if>
</trim>
</insert>
<update id="updateByPrimaryKeySelective"
parameterType="com.educoder.bridge.k8s.model.EvaluatingScript">
update evaluating_script
<set>
<if test="scriptType != null">
script_type = #{scriptType,jdbcType=VARCHAR},
</if>
<if test="script != null">
script = #{script,jdbcType=VARCHAR},
</if>
<if test="createTime != null">
create_time = #{createTime,jdbcType=TIMESTAMP},
</if>
<if test="updateTime != null">
update_time = #{updateTime,jdbcType=TIMESTAMP},
</if>
</set>
where id = #{id,jdbcType=BIGINT}
</update>
<update id="updateByPrimaryKey"
parameterType="com.educoder.bridge.k8s.model.EvaluatingScript">
update evaluating_script
set script_type = #{scriptType,jdbcType=VARCHAR},
script = #{script,jdbcType=VARCHAR},
create_time =
#{createTime,jdbcType=TIMESTAMP},
update_time =
#{updateTime,jdbcType=TIMESTAMP}
where id = #{id,jdbcType=BIGINT}
</update>
<select id="selectScriptByType" resultMap="java.lang.String"
parameterType="java.lang.String">
select
<include refid="Base_Column_List" />
from evaluating_script
where script_type = #{scriptType,jdbcType=VARCHAR}
</select>
<select id="selectEvaScriptForUpdate" resultMap="BaseResultMap"
parameterType="java.lang.String">
select
script
from evaluating_script
where script_type = #{scriptType,jdbcType=VARCHAR} for update
</select>
</mapper>