refs #703: route schema metadata through MyBatis
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
package com.cloudhandson.vpdbackoffice.domain.schemametadata;
|
||||
|
||||
/**
|
||||
* Database row from ALL_ANNOTATIONS_USAGE for one table or column annotation.
|
||||
*/
|
||||
public record SchemaMetadataAnnotationRow(
|
||||
String columnName,
|
||||
String annotationName,
|
||||
String annotationValue
|
||||
) {
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.cloudhandson.vpdbackoffice.domain.schemametadata;
|
||||
|
||||
/**
|
||||
* Database row used only while assembling the schema metadata screen.
|
||||
*/
|
||||
public record SchemaMetadataColumnRow(
|
||||
String columnName,
|
||||
String dataType,
|
||||
String nullable,
|
||||
String comment
|
||||
) {
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
package com.cloudhandson.vpdbackoffice.mapper;
|
||||
|
||||
import com.cloudhandson.vpdbackoffice.domain.schemametadata.SchemaMetadataAnnotationRow;
|
||||
import com.cloudhandson.vpdbackoffice.domain.schemametadata.SchemaMetadataColumnRow;
|
||||
import java.util.List;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
/**
|
||||
* All database access for the schema metadata screen. Identifier parameters
|
||||
* are validated against the screen's closed table list before mapper calls.
|
||||
*/
|
||||
@Mapper
|
||||
public interface SchemaMetadataMapper {
|
||||
|
||||
String findTableComment(@Param("owner") String owner, @Param("tableName") String tableName);
|
||||
|
||||
List<SchemaMetadataColumnRow> findColumns(
|
||||
@Param("owner") String owner,
|
||||
@Param("tableName") String tableName
|
||||
);
|
||||
|
||||
List<SchemaMetadataAnnotationRow> findAnnotations(
|
||||
@Param("owner") String owner,
|
||||
@Param("tableName") String tableName
|
||||
);
|
||||
|
||||
int countColumn(
|
||||
@Param("owner") String owner,
|
||||
@Param("tableName") String tableName,
|
||||
@Param("columnName") String columnName
|
||||
);
|
||||
|
||||
int countTableAnnotation(
|
||||
@Param("owner") String owner,
|
||||
@Param("tableName") String tableName,
|
||||
@Param("annotationName") String annotationName
|
||||
);
|
||||
|
||||
int countColumnAnnotation(
|
||||
@Param("owner") String owner,
|
||||
@Param("tableName") String tableName,
|
||||
@Param("columnName") String columnName,
|
||||
@Param("annotationName") String annotationName
|
||||
);
|
||||
|
||||
void updateTableComment(
|
||||
@Param("owner") String owner,
|
||||
@Param("tableName") String tableName,
|
||||
@Param("commentLiteral") String commentLiteral
|
||||
);
|
||||
|
||||
void updateColumnComment(
|
||||
@Param("owner") String owner,
|
||||
@Param("tableName") String tableName,
|
||||
@Param("columnName") String columnName,
|
||||
@Param("commentLiteral") String commentLiteral
|
||||
);
|
||||
|
||||
void dropTableAnnotation(
|
||||
@Param("owner") String owner,
|
||||
@Param("tableName") String tableName,
|
||||
@Param("annotationName") String annotationName
|
||||
);
|
||||
|
||||
void addTableAnnotation(
|
||||
@Param("owner") String owner,
|
||||
@Param("tableName") String tableName,
|
||||
@Param("annotationName") String annotationName,
|
||||
@Param("annotationValueLiteral") String annotationValueLiteral
|
||||
);
|
||||
|
||||
void dropColumnAnnotation(
|
||||
@Param("owner") String owner,
|
||||
@Param("tableName") String tableName,
|
||||
@Param("columnName") String columnName,
|
||||
@Param("annotationName") String annotationName
|
||||
);
|
||||
|
||||
void addColumnAnnotation(
|
||||
@Param("owner") String owner,
|
||||
@Param("tableName") String tableName,
|
||||
@Param("columnName") String columnName,
|
||||
@Param("annotationName") String annotationName,
|
||||
@Param("annotationValueLiteral") String annotationValueLiteral
|
||||
);
|
||||
}
|
||||
@@ -1,20 +1,25 @@
|
||||
package com.cloudhandson.vpdbackoffice.service;
|
||||
|
||||
import com.cloudhandson.vpdbackoffice.domain.schemametadata.SchemaAnnotation;
|
||||
import com.cloudhandson.vpdbackoffice.domain.schemametadata.SchemaMetadataAnnotationRow;
|
||||
import com.cloudhandson.vpdbackoffice.domain.schemametadata.SchemaMetadataColumn;
|
||||
import com.cloudhandson.vpdbackoffice.domain.schemametadata.SchemaMetadataColumnRow;
|
||||
import com.cloudhandson.vpdbackoffice.domain.schemametadata.SchemaMetadataView;
|
||||
import com.cloudhandson.vpdbackoffice.domain.structured.StructuredDataTable;
|
||||
import com.cloudhandson.vpdbackoffice.mapper.SchemaMetadataMapper;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* Screen-level orchestration for schema metadata. Database reads and DDL are
|
||||
* intentionally delegated only to {@link SchemaMetadataMapper}.
|
||||
*/
|
||||
@Service
|
||||
public class SchemaMetadataService {
|
||||
|
||||
@@ -22,11 +27,14 @@ public class SchemaMetadataService {
|
||||
private static final int MAX_ANNOTATION_VALUE_LENGTH = 4000;
|
||||
private static final Pattern ORACLE_SIMPLE_NAME = Pattern.compile("[A-Z][A-Z0-9_$#]{0,127}");
|
||||
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
private final SchemaMetadataMapper mapper;
|
||||
private final StructuredDataService structuredDataService;
|
||||
|
||||
public SchemaMetadataService(JdbcTemplate jdbcTemplate, StructuredDataService structuredDataService) {
|
||||
this.jdbcTemplate = jdbcTemplate;
|
||||
public SchemaMetadataService(
|
||||
SchemaMetadataMapper mapper,
|
||||
StructuredDataService structuredDataService
|
||||
) {
|
||||
this.mapper = mapper;
|
||||
this.structuredDataService = structuredDataService;
|
||||
}
|
||||
|
||||
@@ -44,14 +52,12 @@ public class SchemaMetadataService {
|
||||
|
||||
public SchemaMetadataView find(String tableKey) {
|
||||
StructuredDataTable table = structuredDataService.requireTable(tableKey);
|
||||
String tableName = table.tableName();
|
||||
String tableComment = tableComment(tableName);
|
||||
Map<String, List<SchemaAnnotation>> annotations =
|
||||
table.isTable() ? annotationsByTarget(tableName) : Map.of();
|
||||
String tableName = requireSimpleName(table.tableName(), "table name");
|
||||
Map<String, List<SchemaAnnotation>> annotations = annotationsByTarget(tableName);
|
||||
List<SchemaMetadataColumn> columns = columns(tableName, annotations);
|
||||
return new SchemaMetadataView(
|
||||
table,
|
||||
nullToEmpty(tableComment),
|
||||
nullToEmpty(mapper.findTableComment(OWNER, tableName)),
|
||||
annotations.getOrDefault(tableTargetKey(), List.of()),
|
||||
columns
|
||||
);
|
||||
@@ -60,25 +66,24 @@ public class SchemaMetadataService {
|
||||
@Transactional
|
||||
public void updateTableComment(String tableKey, String comment) {
|
||||
StructuredDataTable table = structuredDataService.requireTable(tableKey);
|
||||
String tableName = requireSimpleName(table.tableName(), "table name");
|
||||
String normalizedComment = normalizeText(comment, MAX_COMMENT_LENGTH, "테이블 comment");
|
||||
jdbcTemplate.execute("COMMENT ON TABLE " + qualifiedTable(table.tableName())
|
||||
+ " IS " + quoteLiteral(normalizedComment));
|
||||
mapper.updateTableComment(OWNER, tableName, quoteLiteral(normalizedComment));
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void updateColumnComment(String tableKey, String columnName, String comment) {
|
||||
StructuredDataTable table = structuredDataService.requireTable(tableKey);
|
||||
String column = requireColumn(table.tableName(), columnName);
|
||||
String tableName = requireSimpleName(table.tableName(), "table name");
|
||||
String column = requireColumn(tableName, columnName);
|
||||
String normalizedComment = normalizeText(comment, MAX_COMMENT_LENGTH, "컬럼 comment");
|
||||
jdbcTemplate.execute("COMMENT ON COLUMN " + qualifiedTable(table.tableName()) + "."
|
||||
+ quoteName(column) + " IS " + quoteLiteral(normalizedComment));
|
||||
mapper.updateColumnComment(OWNER, tableName, column, quoteLiteral(normalizedComment));
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void updateTableAnnotation(String tableKey, String annotationName, String annotationValue) {
|
||||
StructuredDataTable table = structuredDataService.requireTable(tableKey);
|
||||
requireAnnotationTable(table);
|
||||
updateAnnotation(table.tableName(), null, annotationName, annotationValue);
|
||||
updateAnnotation(requireSimpleName(table.tableName(), "table name"), null, annotationName, annotationValue);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@@ -89,9 +94,9 @@ public class SchemaMetadataService {
|
||||
String annotationValue
|
||||
) {
|
||||
StructuredDataTable table = structuredDataService.requireTable(tableKey);
|
||||
requireAnnotationTable(table);
|
||||
String column = requireColumn(table.tableName(), columnName);
|
||||
updateAnnotation(table.tableName(), column, annotationName, annotationValue);
|
||||
String tableName = requireSimpleName(table.tableName(), "table name");
|
||||
String column = requireColumn(tableName, columnName);
|
||||
updateAnnotation(tableName, column, annotationName, annotationValue);
|
||||
}
|
||||
|
||||
private void updateAnnotation(
|
||||
@@ -103,75 +108,55 @@ public class SchemaMetadataService {
|
||||
String key = requireSimpleName(annotationName, "annotation name");
|
||||
String value = normalizeText(annotationValue, MAX_ANNOTATION_VALUE_LENGTH, "annotation value");
|
||||
if (annotationExists(tableName, columnName, key)) {
|
||||
jdbcTemplate.execute(annotationSql(tableName, columnName, "DROP " + quoteName(key)));
|
||||
if (columnName == null) {
|
||||
mapper.dropTableAnnotation(OWNER, tableName, key);
|
||||
} else {
|
||||
mapper.dropColumnAnnotation(OWNER, tableName, columnName, key);
|
||||
}
|
||||
}
|
||||
if (!value.isBlank()) {
|
||||
jdbcTemplate.execute(annotationSql(tableName, columnName,
|
||||
"ADD " + quoteName(key) + " " + quoteLiteral(value)));
|
||||
if (columnName == null) {
|
||||
mapper.addTableAnnotation(OWNER, tableName, key, quoteLiteral(value));
|
||||
} else {
|
||||
mapper.addColumnAnnotation(OWNER, tableName, columnName, key, quoteLiteral(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String tableComment(String tableName) {
|
||||
List<String> values = jdbcTemplate.query("""
|
||||
SELECT comments
|
||||
FROM all_tab_comments
|
||||
WHERE owner = ?
|
||||
AND table_name = ?
|
||||
""", (rs, rowNum) -> rs.getString(1), owner(), tableName);
|
||||
return values.isEmpty() ? "" : values.getFirst();
|
||||
}
|
||||
|
||||
private List<SchemaMetadataColumn> columns(
|
||||
String tableName,
|
||||
Map<String, List<SchemaAnnotation>> annotations
|
||||
) {
|
||||
return jdbcTemplate.query("""
|
||||
SELECT c.column_name,
|
||||
CASE
|
||||
WHEN c.data_type IN ('VARCHAR2', 'CHAR', 'NVARCHAR2', 'NCHAR')
|
||||
THEN c.data_type || '(' || c.char_length || ')'
|
||||
WHEN c.data_type = 'NUMBER' AND c.data_precision IS NOT NULL AND c.data_scale IS NOT NULL
|
||||
THEN c.data_type || '(' || c.data_precision || ',' || c.data_scale || ')'
|
||||
WHEN c.data_type = 'NUMBER' AND c.data_precision IS NOT NULL
|
||||
THEN c.data_type || '(' || c.data_precision || ')'
|
||||
ELSE c.data_type
|
||||
END AS display_type,
|
||||
c.nullable,
|
||||
cc.comments
|
||||
FROM all_tab_columns c
|
||||
LEFT JOIN all_col_comments cc
|
||||
ON cc.owner = c.owner
|
||||
AND cc.table_name = c.table_name
|
||||
AND cc.column_name = c.column_name
|
||||
WHERE c.owner = ?
|
||||
AND c.table_name = ?
|
||||
ORDER BY c.column_id
|
||||
""", (rs, rowNum) -> new SchemaMetadataColumn(
|
||||
rs.getString("column_name"),
|
||||
rs.getString("display_type"),
|
||||
"Y".equalsIgnoreCase(rs.getString("nullable")),
|
||||
nullToEmpty(rs.getString("comments")),
|
||||
annotations.getOrDefault(columnTargetKey(rs.getString("column_name")), List.of())
|
||||
), owner(), tableName);
|
||||
return mapper.findColumns(OWNER, tableName).stream()
|
||||
.map(row -> toColumn(row, annotations))
|
||||
.toList();
|
||||
}
|
||||
|
||||
private SchemaMetadataColumn toColumn(
|
||||
SchemaMetadataColumnRow row,
|
||||
Map<String, List<SchemaAnnotation>> annotations
|
||||
) {
|
||||
String columnName = requireSimpleName(row.columnName(), "column name");
|
||||
return new SchemaMetadataColumn(
|
||||
columnName,
|
||||
row.dataType(),
|
||||
"Y".equalsIgnoreCase(row.nullable()),
|
||||
nullToEmpty(row.comment()),
|
||||
annotations.getOrDefault(columnTargetKey(columnName), List.of())
|
||||
);
|
||||
}
|
||||
|
||||
private Map<String, List<SchemaAnnotation>> annotationsByTarget(String tableName) {
|
||||
Map<String, LinkedHashMap<String, List<String>>> grouped = new LinkedHashMap<>();
|
||||
jdbcTemplate.query("""
|
||||
SELECT column_name, annotation_name, annotation_value
|
||||
FROM all_annotations_usage
|
||||
WHERE object_name = ?
|
||||
AND object_type = 'TABLE'
|
||||
ORDER BY column_name NULLS FIRST, annotation_name, annotation_value
|
||||
""", rs -> {
|
||||
String target = rs.getString("column_name") == null
|
||||
? tableTargetKey()
|
||||
: columnTargetKey(rs.getString("column_name"));
|
||||
grouped
|
||||
.computeIfAbsent(target, ignored -> new LinkedHashMap<>())
|
||||
.computeIfAbsent(rs.getString("annotation_name"), ignored -> new ArrayList<>())
|
||||
.add(nullToEmpty(rs.getString("annotation_value")));
|
||||
}, tableName);
|
||||
for (SchemaMetadataAnnotationRow row : mapper.findAnnotations(OWNER, tableName)) {
|
||||
String target = row.columnName() == null
|
||||
? tableTargetKey()
|
||||
: columnTargetKey(row.columnName());
|
||||
grouped
|
||||
.computeIfAbsent(target, ignored -> new LinkedHashMap<>())
|
||||
.computeIfAbsent(row.annotationName(), ignored -> new ArrayList<>())
|
||||
.add(nullToEmpty(row.annotationValue()));
|
||||
}
|
||||
|
||||
Map<String, List<SchemaAnnotation>> result = new LinkedHashMap<>();
|
||||
grouped.forEach((target, valuesByName) -> {
|
||||
@@ -186,44 +171,14 @@ public class SchemaMetadataService {
|
||||
}
|
||||
|
||||
private boolean annotationExists(String tableName, String columnName, String annotationName) {
|
||||
Integer count = columnName == null
|
||||
? jdbcTemplate.queryForObject("""
|
||||
SELECT COUNT(*)
|
||||
FROM all_annotations_usage
|
||||
WHERE object_name = ?
|
||||
AND object_type = 'TABLE'
|
||||
AND annotation_name = ?
|
||||
AND column_name IS NULL
|
||||
""", Integer.class, tableName, annotationName)
|
||||
: jdbcTemplate.queryForObject("""
|
||||
SELECT COUNT(*)
|
||||
FROM all_annotations_usage
|
||||
WHERE object_name = ?
|
||||
AND object_type = 'TABLE'
|
||||
AND annotation_name = ?
|
||||
AND column_name = ?
|
||||
""", Integer.class, tableName, annotationName, columnName);
|
||||
return count != null && count > 0;
|
||||
}
|
||||
|
||||
private String annotationSql(String tableName, String columnName, String operation) {
|
||||
if (columnName == null) {
|
||||
return "ALTER TABLE " + qualifiedTable(tableName) + " ANNOTATIONS (" + operation + ")";
|
||||
}
|
||||
return "ALTER TABLE " + qualifiedTable(tableName) + " MODIFY " + quoteName(columnName)
|
||||
+ " ANNOTATIONS (" + operation + ")";
|
||||
return columnName == null
|
||||
? mapper.countTableAnnotation(OWNER, tableName, annotationName) > 0
|
||||
: mapper.countColumnAnnotation(OWNER, tableName, columnName, annotationName) > 0;
|
||||
}
|
||||
|
||||
private String requireColumn(String tableName, String columnName) {
|
||||
String column = requireSimpleName(columnName, "column name");
|
||||
Integer count = jdbcTemplate.queryForObject("""
|
||||
SELECT COUNT(*)
|
||||
FROM all_tab_columns
|
||||
WHERE owner = ?
|
||||
AND table_name = ?
|
||||
AND column_name = ?
|
||||
""", Integer.class, owner(), tableName, column);
|
||||
if (count == null || count == 0) {
|
||||
if (mapper.countColumn(OWNER, tableName, column) == 0) {
|
||||
throw new AppException("선택한 테이블에 존재하지 않는 컬럼입니다.");
|
||||
}
|
||||
return column;
|
||||
@@ -254,18 +209,6 @@ public class SchemaMetadataService {
|
||||
return normalized;
|
||||
}
|
||||
|
||||
private String qualifiedTable(String tableName) {
|
||||
return quoteName(owner()) + "." + quoteName(requireSimpleName(tableName, "table name"));
|
||||
}
|
||||
|
||||
private String owner() {
|
||||
return structuredDataService.owner();
|
||||
}
|
||||
|
||||
private String quoteName(String value) {
|
||||
return "\"" + value.replace("\"", "\"\"") + "\"";
|
||||
}
|
||||
|
||||
private String quoteLiteral(String value) {
|
||||
return "'" + value.replace("'", "''") + "'";
|
||||
}
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.cloudhandson.vpdbackoffice.mapper.SchemaMetadataMapper">
|
||||
<select id="findTableComment" resultType="string">
|
||||
SELECT comments
|
||||
FROM all_tab_comments
|
||||
WHERE owner = #{owner,jdbcType=VARCHAR}
|
||||
AND table_name = #{tableName,jdbcType=VARCHAR}
|
||||
</select>
|
||||
|
||||
<select id="findColumns"
|
||||
resultType="com.cloudhandson.vpdbackoffice.domain.schemametadata.SchemaMetadataColumnRow">
|
||||
SELECT c.column_name AS column_name,
|
||||
CASE
|
||||
WHEN c.data_type IN ('VARCHAR2', 'CHAR', 'NVARCHAR2', 'NCHAR')
|
||||
THEN c.data_type || '(' || c.char_length || ')'
|
||||
WHEN c.data_type = 'NUMBER' AND c.data_precision IS NOT NULL AND c.data_scale IS NOT NULL
|
||||
THEN c.data_type || '(' || c.data_precision || ',' || c.data_scale || ')'
|
||||
WHEN c.data_type = 'NUMBER' AND c.data_precision IS NOT NULL
|
||||
THEN c.data_type || '(' || c.data_precision || ')'
|
||||
ELSE c.data_type
|
||||
END AS data_type,
|
||||
c.nullable,
|
||||
cc.comments
|
||||
FROM all_tab_columns c
|
||||
LEFT JOIN all_col_comments cc
|
||||
ON cc.owner = c.owner
|
||||
AND cc.table_name = c.table_name
|
||||
AND cc.column_name = c.column_name
|
||||
WHERE c.owner = #{owner,jdbcType=VARCHAR}
|
||||
AND c.table_name = #{tableName,jdbcType=VARCHAR}
|
||||
ORDER BY c.column_id
|
||||
</select>
|
||||
|
||||
<select id="findAnnotations"
|
||||
resultType="com.cloudhandson.vpdbackoffice.domain.schemametadata.SchemaMetadataAnnotationRow">
|
||||
SELECT column_name,
|
||||
annotation_name,
|
||||
annotation_value
|
||||
FROM all_annotations_usage
|
||||
WHERE object_owner = #{owner,jdbcType=VARCHAR}
|
||||
AND object_name = #{tableName,jdbcType=VARCHAR}
|
||||
AND object_type = 'TABLE'
|
||||
ORDER BY column_name NULLS FIRST, annotation_name, annotation_value
|
||||
</select>
|
||||
|
||||
<select id="countColumn" resultType="int">
|
||||
SELECT COUNT(*)
|
||||
FROM all_tab_columns
|
||||
WHERE owner = #{owner,jdbcType=VARCHAR}
|
||||
AND table_name = #{tableName,jdbcType=VARCHAR}
|
||||
AND column_name = #{columnName,jdbcType=VARCHAR}
|
||||
</select>
|
||||
|
||||
<select id="countTableAnnotation" resultType="int">
|
||||
SELECT COUNT(*)
|
||||
FROM all_annotations_usage
|
||||
WHERE object_owner = #{owner,jdbcType=VARCHAR}
|
||||
AND object_name = #{tableName,jdbcType=VARCHAR}
|
||||
AND object_type = 'TABLE'
|
||||
AND annotation_name = #{annotationName,jdbcType=VARCHAR}
|
||||
AND column_name IS NULL
|
||||
</select>
|
||||
|
||||
<select id="countColumnAnnotation" resultType="int">
|
||||
SELECT COUNT(*)
|
||||
FROM all_annotations_usage
|
||||
WHERE object_owner = #{owner,jdbcType=VARCHAR}
|
||||
AND object_name = #{tableName,jdbcType=VARCHAR}
|
||||
AND object_type = 'TABLE'
|
||||
AND annotation_name = #{annotationName,jdbcType=VARCHAR}
|
||||
AND column_name = #{columnName,jdbcType=VARCHAR}
|
||||
</select>
|
||||
|
||||
<!-- Identifiers are server-side validated names. Oracle DDL comments require a literal. -->
|
||||
<update id="updateTableComment">
|
||||
COMMENT ON TABLE "${owner}"."${tableName}" IS ${commentLiteral}
|
||||
</update>
|
||||
|
||||
<update id="updateColumnComment">
|
||||
COMMENT ON COLUMN "${owner}"."${tableName}"."${columnName}" IS ${commentLiteral}
|
||||
</update>
|
||||
|
||||
<update id="dropTableAnnotation">
|
||||
ALTER TABLE "${owner}"."${tableName}" ANNOTATIONS (DROP "${annotationName}")
|
||||
</update>
|
||||
|
||||
<update id="addTableAnnotation">
|
||||
ALTER TABLE "${owner}"."${tableName}"
|
||||
ANNOTATIONS (ADD "${annotationName}" ${annotationValueLiteral})
|
||||
</update>
|
||||
|
||||
<update id="dropColumnAnnotation">
|
||||
ALTER TABLE "${owner}"."${tableName}" MODIFY "${columnName}"
|
||||
ANNOTATIONS (DROP "${annotationName}")
|
||||
</update>
|
||||
|
||||
<update id="addColumnAnnotation">
|
||||
ALTER TABLE "${owner}"."${tableName}" MODIFY "${columnName}"
|
||||
ANNOTATIONS (ADD "${annotationName}" ${annotationValueLiteral})
|
||||
</update>
|
||||
</mapper>
|
||||
Reference in New Issue
Block a user