diff --git a/libs/db-browser/pom.xml b/libs/db-browser/pom.xml
index bef24d5df9..0342882018 100644
--- a/libs/db-browser/pom.xml
+++ b/libs/db-browser/pom.xml
@@ -4,7 +4,7 @@
4.0.0
com.oceanbase
db-browser
- 1.0.5
+ 1.1.0
db-browser
https://github.com/oceanbase/odc/tree/main/libs/db-browser
@@ -97,6 +97,7 @@
2.9.1
2.2.1
3.0
+ 21.1.0.0
@@ -195,6 +196,11 @@
jackson-dataformat-yaml
${jackson.version}
+
+ com.oracle.database.jdbc
+ ojdbc8
+ ${oracle.jdbc.version}
+
mysql
mysql-connector-java
@@ -297,6 +303,10 @@
com.fasterxml.jackson.dataformat
jackson-dataformat-yaml
+
+ com.oracle.database.jdbc
+ ojdbc8
+
diff --git a/libs/db-browser/src/main/java/com/oceanbase/tools/dbbrowser/model/DBPLParamMode.java b/libs/db-browser/src/main/java/com/oceanbase/tools/dbbrowser/model/DBPLParamMode.java
index c51e99b782..80f09ac0dc 100644
--- a/libs/db-browser/src/main/java/com/oceanbase/tools/dbbrowser/model/DBPLParamMode.java
+++ b/libs/db-browser/src/main/java/com/oceanbase/tools/dbbrowser/model/DBPLParamMode.java
@@ -41,8 +41,9 @@ public static DBPLParamMode getEnum(String name) {
return IN;
} else if (PLConstants.PL_OUT_PARAM.equalsIgnoreCase(name)) {
return OUT;
- } else if (PLConstants.ORACLE_PL_INOUT_PARAM.equalsIgnoreCase(name)
- || PLConstants.MYSQL_PL_INOUT_PARAM.equalsIgnoreCase(name)) {
+ } else if (PLConstants.OB_ORACLE_PL_INOUT_PARAM.equalsIgnoreCase(name)
+ || PLConstants.MYSQL_PL_INOUT_PARAM.equalsIgnoreCase(name)
+ || PLConstants.ORACLE_PL_INOUT_PARAM.equalsIgnoreCase(name)) {
return INOUT;
} else {
return UNKNOWN;
diff --git a/libs/db-browser/src/main/java/com/oceanbase/tools/dbbrowser/model/DBSession.java b/libs/db-browser/src/main/java/com/oceanbase/tools/dbbrowser/model/DBSession.java
index 03434de3aa..dbac2785f3 100644
--- a/libs/db-browser/src/main/java/com/oceanbase/tools/dbbrowser/model/DBSession.java
+++ b/libs/db-browser/src/main/java/com/oceanbase/tools/dbbrowser/model/DBSession.java
@@ -77,7 +77,7 @@ public class DBSession {
/**
* 当前命令执行时间
*/
- private int executeTime;
+ private Integer executeTime;
public static DBSession unknown() {
diff --git a/libs/db-browser/src/main/java/com/oceanbase/tools/dbbrowser/model/PLConstants.java b/libs/db-browser/src/main/java/com/oceanbase/tools/dbbrowser/model/PLConstants.java
index d92bb45f27..0e91b2f0f8 100644
--- a/libs/db-browser/src/main/java/com/oceanbase/tools/dbbrowser/model/PLConstants.java
+++ b/libs/db-browser/src/main/java/com/oceanbase/tools/dbbrowser/model/PLConstants.java
@@ -18,7 +18,8 @@
public class PLConstants {
public static final String PL_IN_PARAM = "in";
public static final String PL_OUT_PARAM = "out";
- public static final String ORACLE_PL_INOUT_PARAM = "in out";
+ public static final String OB_ORACLE_PL_INOUT_PARAM = "in out";
+ public static final String ORACLE_PL_INOUT_PARAM = "IN/OUT";
public static final String MYSQL_PL_INOUT_PARAM = "inout";
public static final String PL_OBJECT_STATUS_INVALID = "INVALID";
}
diff --git a/libs/db-browser/src/main/java/com/oceanbase/tools/dbbrowser/schema/DBSchemaAccessorSqlMappers.java b/libs/db-browser/src/main/java/com/oceanbase/tools/dbbrowser/schema/DBSchemaAccessorSqlMappers.java
index c7f20f9b1f..09378e3ad2 100644
--- a/libs/db-browser/src/main/java/com/oceanbase/tools/dbbrowser/schema/DBSchemaAccessorSqlMappers.java
+++ b/libs/db-browser/src/main/java/com/oceanbase/tools/dbbrowser/schema/DBSchemaAccessorSqlMappers.java
@@ -53,7 +53,8 @@ public class DBSchemaAccessorSqlMappers {
StatementsFiles.OBMYSQL_1479,
StatementsFiles.MYSQL_5_7_40,
StatementsFiles.OBORACLE_3_x,
- StatementsFiles.OBORACLE_4_0_x));
+ StatementsFiles.OBORACLE_4_0_x,
+ StatementsFiles.ORACLE_11_g));
for (String path : SQL_MAPPER_FILE_PATHS) {
URL url = DBSchemaAccessorSqlMappers.class.getClassLoader().getResource(path);
if (url == null) {
diff --git a/libs/db-browser/src/main/java/com/oceanbase/tools/dbbrowser/schema/constant/Statements.java b/libs/db-browser/src/main/java/com/oceanbase/tools/dbbrowser/schema/constant/Statements.java
index 408cd92735..7d8608562f 100644
--- a/libs/db-browser/src/main/java/com/oceanbase/tools/dbbrowser/schema/constant/Statements.java
+++ b/libs/db-browser/src/main/java/com/oceanbase/tools/dbbrowser/schema/constant/Statements.java
@@ -45,4 +45,8 @@ public final class Statements {
public static final String LIST_SCHEMA_INDEX = "list-schema-index";
+ public static final String LIST_DATABASE = "list-database";
+
+ public static final String GET_DATABASE = "get-database";
+
}
diff --git a/libs/db-browser/src/main/java/com/oceanbase/tools/dbbrowser/schema/constant/StatementsFiles.java b/libs/db-browser/src/main/java/com/oceanbase/tools/dbbrowser/schema/constant/StatementsFiles.java
index 73b1567e64..d94cd9fcf8 100644
--- a/libs/db-browser/src/main/java/com/oceanbase/tools/dbbrowser/schema/constant/StatementsFiles.java
+++ b/libs/db-browser/src/main/java/com/oceanbase/tools/dbbrowser/schema/constant/StatementsFiles.java
@@ -37,4 +37,6 @@ public final class StatementsFiles {
public static final String OBORACLE_3_x = "schema/sql/oboracle/oboracle_3_x.yaml";
+ public static final String ORACLE_11_g = "schema/sql/oracle/oracle_11g.yaml";
+
}
diff --git a/libs/db-browser/src/main/java/com/oceanbase/tools/dbbrowser/schema/oracle/OBOracleSchemaAccessor.java b/libs/db-browser/src/main/java/com/oceanbase/tools/dbbrowser/schema/oracle/OBOracleSchemaAccessor.java
index 35db802534..95239c2564 100644
--- a/libs/db-browser/src/main/java/com/oceanbase/tools/dbbrowser/schema/oracle/OBOracleSchemaAccessor.java
+++ b/libs/db-browser/src/main/java/com/oceanbase/tools/dbbrowser/schema/oracle/OBOracleSchemaAccessor.java
@@ -17,24 +17,22 @@
import java.sql.ResultSetMetaData;
import java.sql.Timestamp;
-import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
+import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
-import javax.validation.constraints.NotEmpty;
-
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.Validate;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcOperations;
import org.springframework.jdbc.core.RowMapper;
-import com.oceanbase.tools.dbbrowser.model.DBBasicPLObject;
import com.oceanbase.tools.dbbrowser.model.DBColumnTypeDisplay;
import com.oceanbase.tools.dbbrowser.model.DBDatabase;
import com.oceanbase.tools.dbbrowser.model.DBFunction;
@@ -51,12 +49,14 @@
import com.oceanbase.tools.dbbrowser.model.DBSequence;
import com.oceanbase.tools.dbbrowser.model.DBSynonym;
import com.oceanbase.tools.dbbrowser.model.DBSynonymType;
+import com.oceanbase.tools.dbbrowser.model.DBTable.DBTableOptions;
import com.oceanbase.tools.dbbrowser.model.DBTableColumn;
import com.oceanbase.tools.dbbrowser.model.DBTableColumn.CharUnit;
import com.oceanbase.tools.dbbrowser.model.DBTableIndex;
import com.oceanbase.tools.dbbrowser.model.DBTrigger;
import com.oceanbase.tools.dbbrowser.model.DBType;
import com.oceanbase.tools.dbbrowser.model.DBTypeCode;
+import com.oceanbase.tools.dbbrowser.model.DBVariable;
import com.oceanbase.tools.dbbrowser.model.DBView;
import com.oceanbase.tools.dbbrowser.model.OracleConstants;
import com.oceanbase.tools.dbbrowser.model.PLConstants;
@@ -65,6 +65,8 @@
import com.oceanbase.tools.dbbrowser.parser.SqlParser;
import com.oceanbase.tools.dbbrowser.parser.result.ParseOraclePLResult;
import com.oceanbase.tools.dbbrowser.parser.result.ParseSqlResult;
+import com.oceanbase.tools.dbbrowser.schema.DBSchemaAccessorSqlMappers;
+import com.oceanbase.tools.dbbrowser.schema.constant.StatementsFiles;
import com.oceanbase.tools.dbbrowser.util.DBSchemaAccessorUtil;
import com.oceanbase.tools.dbbrowser.util.OracleDataDictTableNames;
import com.oceanbase.tools.dbbrowser.util.OracleSqlBuilder;
@@ -82,61 +84,83 @@
*/
@Slf4j
public class OBOracleSchemaAccessor extends OracleSchemaAccessor {
+ private static final Set ESCAPE_USER_SET = new HashSet<>(4);
+
+ static {
+ ESCAPE_USER_SET.add("PUBLIC");
+ ESCAPE_USER_SET.add("LBACSYS");
+ ESCAPE_USER_SET.add("ORAAUDITOR");
+ ESCAPE_USER_SET.add("__public");
+ }
public OBOracleSchemaAccessor(JdbcOperations jdbcOperations,
OracleDataDictTableNames dataDictTableNames) {
super(jdbcOperations, dataDictTableNames);
+ this.sqlMapper = DBSchemaAccessorSqlMappers.get(StatementsFiles.OBORACLE_4_0_x);
}
@Override
- public DBDatabase getDatabase(String schemaName) {
- DBDatabase database = new DBDatabase();
- OracleSqlBuilder sb = new OracleSqlBuilder();
- sb.append("SELECT USERNAME, USERID from ")
- .append(dataDictTableNames.USERS())
- .append(" WHERE USERNAME = ").value(schemaName);
- jdbcOperations.query(sb.toString(), rs -> {
- database.setId(rs.getString("USERID"));
- database.setName(rs.getString("USERNAME"));
- });
- String sql = "select value from v$nls_parameters where PARAMETER = 'NLS_CHARACTERSET'";
- jdbcOperations.query(sql, rs -> {
- database.setCharset(rs.getString(1));
- });
- sql = "SELECT value from v$nls_parameters where parameter = 'NLS_SORT'";
- jdbcOperations.query(sql, rs -> {
- database.setCollation(rs.getString(1));
- });
- return database;
+ public List showDatabases() {
+ return super.showDatabases().stream().filter(user -> !ESCAPE_USER_SET.contains(user))
+ .collect(Collectors.toList());
}
@Override
public List listDatabases() {
- List databases = new ArrayList<>();
- String sql = "SELECT USERNAME from " + dataDictTableNames.USERS();
- jdbcOperations.query(sql, rs -> {
- DBDatabase database = new DBDatabase();
- String userName = rs.getString("USERNAME");
- database.setId(userName);
- database.setName(userName);
- databases.add(database);
- });
- sql = "select value from v$nls_parameters where PARAMETER = 'NLS_CHARACTERSET'";
- AtomicReference charset = new AtomicReference<>();
- jdbcOperations.query(sql, rs -> {
- charset.set(rs.getString(1));
+ return super.listDatabases().stream().filter(user -> !ESCAPE_USER_SET.contains(user))
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ public List showCharset() {
+ OracleSqlBuilder sb = new OracleSqlBuilder();
+ sb.append("show character set");
+
+ return jdbcOperations.query(sb.toString(), (rs, rowNum) -> rs.getString(1));
+ }
+
+ @Override
+ public List showCollation() {
+ OracleSqlBuilder sb = new OracleSqlBuilder();
+ sb.append("show collation");
+
+ return jdbcOperations.query(sb.toString(), (rs, rowNum) -> rs.getString(1));
+ }
+
+ @Override
+ public List showVariables() {
+ String sql = "show variables";
+
+ return jdbcOperations.query(sql, (rs, rowNum) -> {
+ DBVariable variable = new DBVariable();
+ variable.setName(rs.getString(1));
+ variable.setValue(rs.getString(2));
+ return variable;
});
- sql = "SELECT value from v$nls_parameters where parameter = 'NLS_SORT'";
- AtomicReference collation = new AtomicReference<>();
- jdbcOperations.query(sql, rs -> {
- collation.set(rs.getString(1));
+ }
+
+ @Override
+ public List showSessionVariables() {
+ String sql = "show session variables";
+
+ return jdbcOperations.query(sql, (rs, rowNum) -> {
+ DBVariable variable = new DBVariable();
+ variable.setName(rs.getString(1));
+ variable.setValue(rs.getString(2));
+ return variable;
});
- databases.forEach(item -> {
- item.setCharset(charset.get());
- item.setCollation(collation.get());
+ }
+
+ @Override
+ public List showGlobalVariables() {
+ String sql = "show global variables";
+
+ return jdbcOperations.query(sql, (rs, rowNum) -> {
+ DBVariable variable = new DBVariable();
+ variable.setName(rs.getString(1));
+ variable.setValue(rs.getString(2));
+ return variable;
});
- return databases.stream().filter(database -> !ESCAPE_USER_SET.contains(database.getName()))
- .collect(Collectors.toList());
}
@Override
@@ -158,6 +182,16 @@ public List listTableIndexes(String schemaName, String tableName)
return indexList;
}
+ @Override
+ protected boolean isTableIndexAvailable(String status) {
+ return "VALID".equals(status);
+ }
+
+ @Override
+ protected boolean judgeIndexGlobalOrLocalFromDataDict() {
+ return false;
+ }
+
protected void fillIndexRange(List indexList) {
for (DBTableIndex index : indexList) {
try {
@@ -272,72 +306,40 @@ protected RowMapper listColumnsRowMapper() {
}
@Override
- public List listFunctions(String schemaName) {
- List functions = super.listFunctions(schemaName);
-
- Map errorText = PLObjectErrMsgUtils.acquireErrorMessage(jdbcOperations,
- schemaName, DBObjectType.FUNCTION.name(), null);
- for (DBPLObjectIdentity function : functions) {
- if (StringUtils.containsIgnoreCase(function.getStatus(), PLConstants.PL_OBJECT_STATUS_INVALID)) {
- function.setErrorMessage(errorText.get(function.getName()));
+ protected String getTableDDLOnly(String schemaName, String tableName) {
+ OracleSqlBuilder sb = new OracleSqlBuilder();
+ sb.append("SHOW CREATE TABLE ");
+ sb.identifier(schemaName);
+ sb.append(".");
+ sb.identifier(tableName);
+
+ AtomicReference ddlRef = new AtomicReference<>();
+ jdbcOperations.query(sb.toString(), t -> {
+ // Create table ddl like this: CREATE [GLOBAL TEMPORARY|SHARDED|DUPLICATED] TABLE T...
+ String ddl = t.getString(2);
+ if (Objects.nonNull(ddl)) {
+ // fix: Replace " TABLE " to " TABLE schemaName."
+ ddlRef.set(StringUtils.replace(ddl, " TABLE ",
+ " TABLE " + StringUtils.quoteOracleIdentifier(schemaName) + ".", 1));
}
- }
-
- return functions;
+ });
+ return ddlRef.get();
}
@Override
- public List listProcedures(String schemaName) {
- List procedures = super.listProcedures(schemaName);
-
-
- Map errorText = PLObjectErrMsgUtils.acquireErrorMessage(jdbcOperations,
- schemaName, DBObjectType.PROCEDURE.name(), null);
- for (DBPLObjectIdentity procedure : procedures) {
- if (StringUtils.containsIgnoreCase(procedure.getStatus(), PLConstants.PL_OBJECT_STATUS_INVALID)) {
- procedure.setErrorMessage(errorText.get(procedure.getName()));
- }
- }
-
- return procedures;
+ protected void obtainTableCharset(DBTableOptions tableOptions) {
+ String sql = "SHOW VARIABLES LIKE 'nls_characterset'";
+ jdbcOperations.query(sql, t -> {
+ tableOptions.setCharsetName(t.getString("VALUE"));
+ });
}
@Override
- public List listPackages(String schemaName) {
- List packages = super.listPackages(schemaName);
- List filtered = new ArrayList<>();
- Map name2Status = new HashMap<>();
- for (DBPLObjectIdentity dbPackage : packages) {
- String pkgName = dbPackage.getName();
- String status = dbPackage.getStatus();
- // merge status of 'package' and 'package body'
- if (name2Status.containsKey(pkgName)) {
- if (PLConstants.PL_OBJECT_STATUS_INVALID.equalsIgnoreCase(status)) {
- name2Status.put(pkgName, status);
- }
- } else {
- name2Status.put(pkgName, status);
- }
- }
- Map errorText = PLObjectErrMsgUtils.acquireErrorMessage(jdbcOperations,
- schemaName, DBObjectType.PACKAGE.name(), null);
- String pkgName = null;
- for (DBPLObjectIdentity pkg : packages) {
- if (Objects.isNull(pkgName) || !StringUtils.equals(pkgName, pkg.getName())) {
- pkgName = pkg.getName();
- DBPLObjectIdentity dbPackage = new DBPLObjectIdentity();
- dbPackage.setName(pkg.getName());
- dbPackage.setStatus(name2Status.get(pkg.getName()));
- dbPackage.setSchemaName(pkg.getSchemaName());
- dbPackage.setType(pkg.getType());
- if (StringUtils.containsIgnoreCase(dbPackage.getStatus(),
- PLConstants.PL_OBJECT_STATUS_INVALID)) {
- dbPackage.setErrorMessage(errorText.get(dbPackage.getName()));
- }
- filtered.add(dbPackage);
- }
- }
- return filtered;
+ protected void obtainTableCollation(DBTableOptions tableOptions) {
+ String sql = "SHOW VARIABLES LIKE 'nls_sort'";
+ jdbcOperations.query(sql, t -> {
+ tableOptions.setCollationName(t.getString("VALUE"));
+ });
}
@Override
@@ -374,7 +376,8 @@ public DBFunction getFunction(String schemaName, String functionName) {
return parseFunctionDDL(function);
}
- private DBFunction parseFunctionDDL(DBFunction function) {
+ @Override
+ protected DBFunction parseFunctionDDL(DBFunction function) {
try {
ParseOraclePLResult result = PLParser.parseObOracle(function.getDdl());
List functionList = result.getFunctionList();
@@ -507,7 +510,8 @@ public DBProcedure getProcedure(String schemaName, String procedureName) {
return parseProcedureDDL(procedure);
}
- private DBProcedure parseProcedureDDL(DBProcedure procedure) {
+ @Override
+ protected DBProcedure parseProcedureDDL(DBProcedure procedure) {
Validate.notBlank(procedure.getDdl(), "procedure.ddl");
String ddl = procedure.getDdl();
ParseOraclePLResult result;
@@ -617,24 +621,7 @@ public DBPackage getPackage(String schemaName, String packageName) {
}
@Override
- public List listTriggers(String schemaName) {
- List triggers = super.listTriggers(schemaName);
-
- Map errorText = PLObjectErrMsgUtils.acquireErrorMessage(jdbcOperations,
- schemaName, DBObjectType.TRIGGER.name(), null);
- for (DBPLObjectIdentity trigger : triggers) {
- if (StringUtils.containsIgnoreCase(trigger.getStatus(), PLConstants.PL_OBJECT_STATUS_INVALID)) {
- trigger.setErrorMessage(errorText.get(trigger.getName()));
- }
- }
-
- return triggers;
- }
-
- @Override
- public List listTypes(String schemaName) {
- List types = super.listTypes(schemaName);
-
+ protected List fillTypeErrorMessage(List types, String schemaName) {
Map errorText = PLObjectErrMsgUtils.acquireErrorMessage(jdbcOperations,
schemaName, DBObjectType.TYPE.name(), null);
for (DBPLObjectIdentity type : types) {
@@ -835,98 +822,28 @@ public DBType getType(String schemaName, String typeName) {
return parseTypeDDL(type);
}
- private DBType parseTypeDDL(DBType type) {
- OracleSqlBuilder sb = new OracleSqlBuilder();
- sb.append("select dbms_metadata.get_ddl('TYPE', ");
- sb.value(type.getTypeName());
- sb.append(", ");
- sb.value(type.getOwner());
- sb.append(") from dual");
-
- String typeDdl = jdbcOperations.query(sb.toString(), rs -> {
+ @Override
+ protected String queryTypeDdl(String querySql) {
+ return jdbcOperations.query(querySql, rs -> {
if (!rs.next()) {
return null;
}
return rs.getClob(1).toString();
});
+ }
- OracleSqlBuilder sb2 = new OracleSqlBuilder();
- sb2.append("select dbms_metadata.get_ddl('TYPE_SPEC', ");
- sb2.value(type.getTypeName());
- sb2.append(", ");
- sb2.value(type.getOwner());
- sb2.append(") from dual");
-
- String typeHeadDdl = jdbcOperations.query(sb2.toString(), rs -> {
+ @Override
+ protected String queryTypeSpecDdl(String querySql) {
+ return jdbcOperations.query(querySql, rs -> {
if (!rs.next()) {
return null;
}
return rs.getClob(1).toString();
});
- Validate.notBlank(typeDdl, "typeDdl");
- Validate.notBlank(typeHeadDdl, "typeHeadDdl");
-
- type.setDdl(typeDdl);
-
- DBBasicPLObject typeDetail = new DBBasicPLObject();
- try {
- ParseOraclePLResult oraclePLResult = PLParser.parseObOracle(typeHeadDdl);
- typeDetail.setVariables(oraclePLResult.getVaribaleList());
- typeDetail.setTypes(oraclePLResult.getTypeList());
- typeDetail.setProcedures(oraclePLResult.getProcedureList());
- typeDetail.setFunctions(oraclePLResult.getFunctionList());
- } catch (Exception e) {
- log.warn("Parse ddl failed, ddl={}, errorMessage={}", typeHeadDdl, e.getMessage());
- typeDetail.setParseErrorMessage(e.getMessage());
- }
-
- type.setTypeDetail(typeDetail);
- String errorText = PLObjectErrMsgUtils.getOraclePLObjErrMsg(jdbcOperations,
- type.getOwner(), DBObjectType.TYPE.name(), type.getTypeName());
- if (StringUtils.isNotBlank(errorText)) {
- type.setStatus(PLConstants.PL_OBJECT_STATUS_INVALID);
- type.setErrorMessage(errorText);
- }
- return type;
}
@Override
- public DBSequence getSequence(String schemaName, String sequenceName) {
- OracleSqlBuilder sb = new OracleSqlBuilder();
- sb.append("select * from ");
- sb.append(dataDictTableNames.SEQUENCES());
- sb.append(" where sequence_owner=");
- sb.value(schemaName);
- sb.append(" and sequence_name=");
- sb.value(sequenceName);
-
- DBSequence sequence = new DBSequence();
- sequence.setName(sequenceName);
- jdbcOperations.query(sb.toString(), rs -> {
- sequence.setUser(rs.getString("SEQUENCE_OWNER"));
- sequence.setMinValue(rs.getBigDecimal("MIN_VALUE").toString());
- sequence.setMaxValue(rs.getBigDecimal("MAX_VALUE").toString());
- sequence.setIncreament(rs.getBigDecimal("INCREMENT_BY").longValue());
- sequence.setCycled("Y".equalsIgnoreCase(rs.getString("CYCLE_FLAG")));
- sequence.setOrderd("Y".equalsIgnoreCase(rs.getString("ORDER_FLAG")));
- long cacheSize = rs.getBigDecimal("CACHE_SIZE").longValue();
- if (cacheSize > 1) {
- sequence.setCacheSize(cacheSize);
- sequence.setCached(true);
- } else {
- sequence.setCached(false);
- }
- sequence.setNextCacheValue(rs.getBigDecimal("LAST_NUMBER").toString());
-
- });
-
- // 生成ddl
- String ddl = fullfillSequenceDdl(sequence);
- sequence.setDdl(ddl);
- return sequence;
- }
-
- private String fullfillSequenceDdl(DBSequence sequence) {
+ protected String getSequenceDDL(DBSequence sequence) {
Validate.notNull(sequence, "sequence");
Validate.notBlank(sequence.getName(), "sequence.name");
@@ -979,48 +896,22 @@ private String fullfillSequenceDdl(DBSequence sequence) {
public List listSynonyms(String schemaName, DBSynonymType synonymType) {
OracleSqlBuilder sb = new OracleSqlBuilder();
- sb.append(
- "select s.OWNER as schema_name, s.SYNONYM_NAME as name, o.OBJECT_TYPE as type from ");
- sb.append(dataDictTableNames.SYNONYMS());
- sb.append(" s left join (select * from ");
- sb.append(dataDictTableNames.OBJECTS());
- sb.append(" where OBJECT_TYPE='SYNONYM') o on s.SYNONYM_NAME=o.OBJECT_NAME and s.OWNER=o.OWNER where s.OWNER=");
- sb.value(getSynonymOwnerSymbol(synonymType, schemaName));
- sb.append(" order by name asc");
+ sb.append("select s.OWNER as schema_name, s.SYNONYM_NAME as name, o.OBJECT_TYPE as type from ")
+ .append(dataDictTableNames.SYNONYMS())
+ .append(" s left join (select * from ")
+ .append(dataDictTableNames.OBJECTS())
+ .append(" where OBJECT_TYPE='SYNONYM') o on s.SYNONYM_NAME=o.OBJECT_NAME and s.OWNER=o.OWNER where s.OWNER=")
+ .value(getSynonymOwnerSymbol(synonymType, schemaName))
+ .append(" order by name asc");
return jdbcOperations.query(sb.toString(), new BeanPropertyRowMapper<>(DBObjectIdentity.class));
}
@Override
- public DBSynonym getSynonym(String schemaName, @NotEmpty String synonymName,
- @NonNull DBSynonymType synonymType) {
- OracleSqlBuilder sb = new OracleSqlBuilder();
- sb.append(
- "select s.OWNER,s.SYNONYM_NAME,s.TABLE_OWNER,s.TABLE_NAME,s.DB_LINK,o.CREATED,o.LAST_DDL_TIME,o.STATUS from ");
- sb.append(dataDictTableNames.SYNONYMS());
- sb.append(" s left join (select * from ");
- sb.append(dataDictTableNames.OBJECTS());
- sb.append(" where OBJECT_TYPE='SYNONYM') o on s.SYNONYM_NAME=o.OBJECT_NAME and s.OWNER=o.OWNER where s.OWNER=");
- sb.value(getSynonymOwnerSymbol(synonymType, schemaName));
- sb.append(" and s.SYNONYM_NAME=");
- sb.value(synonymName);
-
- DBSynonym synonym = new DBSynonym();
- synonym.setSynonymType(synonymType);
- jdbcOperations.query(sb.toString(), rs -> {
- synonym.setOwner(rs.getString("OWNER"));
- synonym.setSynonymName(rs.getString("SYNONYM_NAME"));
- synonym.setTableOwner(rs.getString("TABLE_OWNER"));
- synonym.setTableName(rs.getString("TABLE_NAME"));
- synonym.setDbLink(rs.getString("DB_LINK"));
- synonym.setCreated(rs.getTimestamp("CREATED"));
- synonym.setLastDdlTime(rs.getTimestamp("LAST_DDL_TIME"));
- synonym.setStatus(rs.getString("STATUS"));
- });
-
+ protected String getSynonymDDL(DBSynonym synonym) {
OracleSqlBuilder ddl = new OracleSqlBuilder();
ddl.append("CREATE OR REPLACE ");
- if (synonymType == DBSynonymType.PUBLIC) {
+ if (synonym.getSynonymType() == DBSynonymType.PUBLIC) {
ddl.append("PUBLIC ");
}
ddl.append("SYNONYM ")
@@ -1033,13 +924,10 @@ public DBSynonym getSynonym(String schemaName, @NotEmpty String synonymName,
ddl.identifier(StringUtils.isBlank(synonym.getDbLink()) ? synonym.getTableName()
: synonym.getTableName() + "@" + synonym.getDbLink())
.append(";");
-
- synonym.setSynonymType(synonym.getSynonymType());
- synonym.setDdl(ddl.toString());
-
- return synonym;
+ return ddl.toString();
}
+ @Override
protected String getSynonymOwnerSymbol(DBSynonymType synonymType, String schemaName) {
if (synonymType.equals(DBSynonymType.PUBLIC)) {
return "__public";
diff --git a/libs/db-browser/src/main/java/com/oceanbase/tools/dbbrowser/schema/oracle/OracleSchemaAccessor.java b/libs/db-browser/src/main/java/com/oceanbase/tools/dbbrowser/schema/oracle/OracleSchemaAccessor.java
index cb4070f511..f43f7467f6 100644
--- a/libs/db-browser/src/main/java/com/oceanbase/tools/dbbrowser/schema/oracle/OracleSchemaAccessor.java
+++ b/libs/db-browser/src/main/java/com/oceanbase/tools/dbbrowser/schema/oracle/OracleSchemaAccessor.java
@@ -15,25 +15,26 @@
*/
package com.oceanbase.tools.dbbrowser.schema.oracle;
+import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
-import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang3.Validate;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcOperations;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.lang.NonNull;
+import com.oceanbase.tools.dbbrowser.model.DBBasicPLObject;
import com.oceanbase.tools.dbbrowser.model.DBColumnTypeDisplay;
import com.oceanbase.tools.dbbrowser.model.DBConstraintDeferability;
import com.oceanbase.tools.dbbrowser.model.DBConstraintType;
@@ -45,7 +46,11 @@
import com.oceanbase.tools.dbbrowser.model.DBObjectIdentity;
import com.oceanbase.tools.dbbrowser.model.DBObjectType;
import com.oceanbase.tools.dbbrowser.model.DBPLObjectIdentity;
+import com.oceanbase.tools.dbbrowser.model.DBPLParam;
+import com.oceanbase.tools.dbbrowser.model.DBPLParamMode;
import com.oceanbase.tools.dbbrowser.model.DBPackage;
+import com.oceanbase.tools.dbbrowser.model.DBPackageBasicInfo;
+import com.oceanbase.tools.dbbrowser.model.DBPackageDetail;
import com.oceanbase.tools.dbbrowser.model.DBProcedure;
import com.oceanbase.tools.dbbrowser.model.DBSequence;
import com.oceanbase.tools.dbbrowser.model.DBSynonym;
@@ -65,6 +70,9 @@
import com.oceanbase.tools.dbbrowser.model.DBVariable;
import com.oceanbase.tools.dbbrowser.model.DBView;
import com.oceanbase.tools.dbbrowser.model.OracleConstants;
+import com.oceanbase.tools.dbbrowser.model.PLConstants;
+import com.oceanbase.tools.dbbrowser.parser.PLParser;
+import com.oceanbase.tools.dbbrowser.parser.result.ParseOraclePLResult;
import com.oceanbase.tools.dbbrowser.schema.DBSchemaAccessor;
import com.oceanbase.tools.dbbrowser.schema.DBSchemaAccessorSqlMapper;
import com.oceanbase.tools.dbbrowser.schema.DBSchemaAccessorSqlMappers;
@@ -73,6 +81,7 @@
import com.oceanbase.tools.dbbrowser.util.DBSchemaAccessorUtil;
import com.oceanbase.tools.dbbrowser.util.OracleDataDictTableNames;
import com.oceanbase.tools.dbbrowser.util.OracleSqlBuilder;
+import com.oceanbase.tools.dbbrowser.util.PLObjectErrMsgUtils;
import com.oceanbase.tools.dbbrowser.util.StringUtils;
import lombok.extern.slf4j.Slf4j;
@@ -86,14 +95,6 @@ public class OracleSchemaAccessor implements DBSchemaAccessor {
"COMMENT ON TABLE ${schemaName}.${tableName} IS ${comment}";
private static final String ORACLE_COLUMN_COMMENT_DDL_TEMPLATE =
"COMMENT ON COLUMN ${schemaName}.${tableName}.${columnName} IS ${comment}";
- protected static final Set ESCAPE_USER_SET = new HashSet<>(3);
-
- static {
- ESCAPE_USER_SET.add("PUBLIC");
- ESCAPE_USER_SET.add("LBACSYS");
- ESCAPE_USER_SET.add("ORAAUDITOR");
- ESCAPE_USER_SET.add("__public");
- }
protected OracleDataDictTableNames dataDictTableNames;
protected JdbcOperations jdbcOperations;
protected DBSchemaAccessorSqlMapper sqlMapper;
@@ -102,7 +103,7 @@ public OracleSchemaAccessor(@NonNull JdbcOperations jdbcOperations,
OracleDataDictTableNames dataDictTableNames) {
this.dataDictTableNames = dataDictTableNames;
this.jdbcOperations = jdbcOperations;
- this.sqlMapper = DBSchemaAccessorSqlMappers.get(StatementsFiles.OBORACLE_4_0_x);
+ this.sqlMapper = DBSchemaAccessorSqlMappers.get(StatementsFiles.ORACLE_11_g);
}
@Override
@@ -111,25 +112,60 @@ public List showDatabases() {
sb.append("select USERNAME from ");
sb.append(dataDictTableNames.USERS());
- List users = jdbcOperations.queryForList(sb.toString(), String.class);
- return users.stream().filter(user -> !ESCAPE_USER_SET.contains(user)).collect(Collectors.toList());
+ return jdbcOperations.queryForList(sb.toString(), String.class);
}
@Override
public DBDatabase getDatabase(String schemaName) {
- throw new UnsupportedOperationException("Not supported yet");
+ DBDatabase database = new DBDatabase();
+ String sql = this.sqlMapper.getSql(Statements.GET_DATABASE);
+ jdbcOperations.query(sql, new Object[] {schemaName}, rs -> {
+ database.setId(rs.getString(2));
+ database.setName(rs.getString(1));
+ });
+ sql = "select value from v$nls_parameters where PARAMETER = 'NLS_CHARACTERSET'";
+ jdbcOperations.query(sql, rs -> {
+ database.setCharset(rs.getString(1));
+ });
+ sql = "SELECT value from v$nls_parameters where parameter = 'NLS_SORT'";
+ jdbcOperations.query(sql, rs -> {
+ database.setCollation(rs.getString(1));
+ });
+ return database;
}
@Override
public List listDatabases() {
- throw new UnsupportedOperationException("Not supported yet");
+ List databases = new ArrayList();
+ String sql = this.sqlMapper.getSql(Statements.LIST_DATABASE);
+ this.jdbcOperations.query(sql, (rs) -> {
+ DBDatabase database = new DBDatabase();
+ database.setId(rs.getString(2));
+ database.setName(rs.getString(1));
+ databases.add(database);
+ });
+ sql = "select value from v$nls_parameters where PARAMETER = 'NLS_CHARACTERSET'";
+ AtomicReference charset = new AtomicReference();
+ this.jdbcOperations.query(sql, (rs) -> {
+ charset.set(rs.getString(1));
+ });
+ sql = "SELECT value from v$nls_parameters where parameter = 'NLS_SORT'";
+ AtomicReference collation = new AtomicReference();
+ this.jdbcOperations.query(sql, (rs) -> {
+ collation.set(rs.getString(1));
+ });
+ databases.forEach((item) -> {
+ item.setCharset(charset.get());
+ item.setCollation(collation.get());
+ });
+ return databases;
}
@Override
public void switchDatabase(String schemaName) {
OracleSqlBuilder sb = new OracleSqlBuilder();
sb.append("alter session set current_schema=");
- sb.value(schemaName);
+ sb.identifier(schemaName);
jdbcOperations.execute(sb.toString());
}
@@ -199,7 +235,7 @@ public List listAllViews(String viewNameLike) {
.append(dataDictTableNames.VIEWS())
.append(" where VIEW_NAME LIKE ")
.value('%' + viewNameLike + '%')
- .append(" order by name asc;");
+ .append(" order by name asc");
return jdbcOperations.query(sb.toString(), new BeanPropertyRowMapper<>(DBObjectIdentity.class));
}
@@ -232,7 +268,7 @@ public List showSystemViews(String schemaName) {
@Override
public List showVariables() {
- String sql = "show variables";
+ String sql = "SELECT name, value FROM V$PARAMETER";
return jdbcOperations.query(sql, (rs, rowNum) -> {
DBVariable variable = new DBVariable();
@@ -244,7 +280,7 @@ public List showVariables() {
@Override
public List showSessionVariables() {
- String sql = "show session variables";
+ String sql = "SELECT name, value FROM V$PARAMETER";
return jdbcOperations.query(sql, (rs, rowNum) -> {
DBVariable variable = new DBVariable();
@@ -256,7 +292,7 @@ public List showSessionVariables() {
@Override
public List showGlobalVariables() {
- String sql = "show global variables";
+ String sql = "SELECT name, value FROM V$SYSTEM_PARAMETER";
return jdbcOperations.query(sql, (rs, rowNum) -> {
DBVariable variable = new DBVariable();
@@ -269,17 +305,17 @@ public List showGlobalVariables() {
@Override
public List showCharset() {
OracleSqlBuilder sb = new OracleSqlBuilder();
- sb.append("show character set");
+ sb.append("SELECT DISTINCT VALUE FROM V$NLS_VALID_VALUES WHERE PARAMETER = 'CHARACTERSET' ORDER BY VALUE");
- return jdbcOperations.query(sb.toString(), (rs, rowNum) -> rs.getString(1));
+ return jdbcOperations.queryForList(sb.toString(), String.class);
}
@Override
public List showCollation() {
OracleSqlBuilder sb = new OracleSqlBuilder();
- sb.append("show collation");
+ sb.append("SELECT DISTINCT VALUE FROM V$NLS_VALID_VALUES WHERE PARAMETER = 'SORT' ORDER BY VALUE");
- return jdbcOperations.query(sb.toString(), (rs, rowNum) -> rs.getString(1));
+ return jdbcOperations.queryForList(sb.toString(), String.class);
}
@Override
@@ -292,7 +328,18 @@ public List listFunctions(String schemaName) {
.value(schemaName)
.append(" order by object_name asc");
- return jdbcOperations.query(sb.toString(), new BeanPropertyRowMapper<>(DBPLObjectIdentity.class));
+ List functions =
+ jdbcOperations.query(sb.toString(), new BeanPropertyRowMapper<>(DBPLObjectIdentity.class));
+
+ Map errorText = PLObjectErrMsgUtils.acquireErrorMessage(jdbcOperations,
+ schemaName, DBObjectType.FUNCTION.name(), null);
+ for (DBPLObjectIdentity function : functions) {
+ if (StringUtils.containsIgnoreCase(function.getStatus(), PLConstants.PL_OBJECT_STATUS_INVALID)) {
+ function.setErrorMessage(errorText.get(function.getName()));
+ }
+ }
+
+ return functions;
}
@Override
@@ -305,7 +352,18 @@ public List listProcedures(String schemaName) {
sb.value(schemaName);
sb.append(" order by object_name asc");
- return jdbcOperations.query(sb.toString(), new BeanPropertyRowMapper<>(DBPLObjectIdentity.class));
+ List procedures =
+ jdbcOperations.query(sb.toString(), new BeanPropertyRowMapper<>(DBPLObjectIdentity.class));
+
+ Map errorText = PLObjectErrMsgUtils.acquireErrorMessage(jdbcOperations,
+ schemaName, DBObjectType.PROCEDURE.name(), null);
+ for (DBPLObjectIdentity procedure : procedures) {
+ if (StringUtils.containsIgnoreCase(procedure.getStatus(), PLConstants.PL_OBJECT_STATUS_INVALID)) {
+ procedure.setErrorMessage(errorText.get(procedure.getName()));
+ }
+ }
+
+ return procedures;
}
@Override
@@ -318,7 +376,7 @@ public List listPackages(String schemaName) {
sb.value(schemaName);
sb.append(" order by name asc");
- return jdbcOperations.query(sb.toString(), (rs, rowNum) -> {
+ List packages = jdbcOperations.query(sb.toString(), (rs, rowNum) -> {
DBPLObjectIdentity dbPackage = new DBPLObjectIdentity();
dbPackage.setName(rs.getString("name"));
dbPackage.setStatus(rs.getString("status"));
@@ -326,6 +384,40 @@ public List listPackages(String schemaName) {
dbPackage.setType(DBObjectType.getEnumByName(rs.getString("type")));
return dbPackage;
});
+
+ List filtered = new ArrayList<>();
+ Map name2Status = new HashMap<>();
+ for (DBPLObjectIdentity dbPackage : packages) {
+ String pkgName = dbPackage.getName();
+ String status = dbPackage.getStatus();
+ // merge status of 'package' and 'package body'
+ if (name2Status.containsKey(pkgName)) {
+ if (PLConstants.PL_OBJECT_STATUS_INVALID.equalsIgnoreCase(status)) {
+ name2Status.put(pkgName, status);
+ }
+ } else {
+ name2Status.put(pkgName, status);
+ }
+ }
+ Map errorText = PLObjectErrMsgUtils.acquireErrorMessage(jdbcOperations,
+ schemaName, DBObjectType.PACKAGE.name(), null);
+ String pkgName = null;
+ for (DBPLObjectIdentity pkg : packages) {
+ if (Objects.isNull(pkgName) || !StringUtils.equals(pkgName, pkg.getName())) {
+ pkgName = pkg.getName();
+ DBPLObjectIdentity dbPackage = new DBPLObjectIdentity();
+ dbPackage.setName(pkg.getName());
+ dbPackage.setStatus(name2Status.get(pkg.getName()));
+ dbPackage.setSchemaName(pkg.getSchemaName());
+ dbPackage.setType(pkg.getType());
+ if (StringUtils.containsIgnoreCase(dbPackage.getStatus(),
+ PLConstants.PL_OBJECT_STATUS_INVALID)) {
+ dbPackage.setErrorMessage(errorText.get(dbPackage.getName()));
+ }
+ filtered.add(dbPackage);
+ }
+ }
+ return filtered;
}
@Override
@@ -361,7 +453,7 @@ public List listTriggers(String schemaName) {
sb.value(schemaName);
sb.append(" order by TRIGGER_NAME asc");
- return jdbcOperations.query(sb.toString(), (rs, rowNum) -> {
+ List triggers = jdbcOperations.query(sb.toString(), (rs, rowNum) -> {
DBPLObjectIdentity trigger = new DBPLObjectIdentity();
trigger.setName(rs.getString("TRIGGER_NAME"));
trigger.setSchemaName(rs.getString("OWNER"));
@@ -370,6 +462,16 @@ public List listTriggers(String schemaName) {
trigger.setType(DBObjectType.TRIGGER);
return trigger;
});
+
+ Map errorText = PLObjectErrMsgUtils.acquireErrorMessage(jdbcOperations,
+ schemaName, DBObjectType.TRIGGER.name(), null);
+ for (DBPLObjectIdentity trigger : triggers) {
+ if (StringUtils.containsIgnoreCase(trigger.getStatus(), PLConstants.PL_OBJECT_STATUS_INVALID)) {
+ trigger.setErrorMessage(errorText.get(trigger.getName()));
+ }
+ }
+
+ return triggers;
}
@Override
@@ -382,7 +484,22 @@ public List listTypes(String schemaName) {
sb.value(schemaName);
sb.append(" order by OBJECT_NAME asc");
- return jdbcOperations.query(sb.toString(), new BeanPropertyRowMapper<>(DBPLObjectIdentity.class));
+ List types =
+ jdbcOperations.query(sb.toString(), new BeanPropertyRowMapper<>(DBPLObjectIdentity.class));
+
+ return fillTypeErrorMessage(types, schemaName);
+ }
+
+ protected List fillTypeErrorMessage(List types, String schemaName) {
+ Map errorText = PLObjectErrMsgUtils.acquireErrorMessage(jdbcOperations,
+ schemaName, DBObjectType.TYPE.name(), null);
+ for (DBPLObjectIdentity type : types) {
+ if (StringUtils.containsIgnoreCase(type.getStatus(), PLConstants.PL_OBJECT_STATUS_INVALID)) {
+ type.setErrorMessage(errorText.get(type.getName()));
+ }
+ }
+
+ return types;
}
@Override
@@ -406,7 +523,19 @@ public List listSequences(String schemaName) {
@Override
public List listSynonyms(String schemaName, DBSynonymType synonymType) {
- throw new UnsupportedOperationException("Not supported yet");
+ OracleSqlBuilder sb = new OracleSqlBuilder();
+ if (DBSynonymType.PUBLIC.equals(synonymType)) {
+ sb.append(
+ "SELECT OWNER as schema_name, SYNONYM_NAME as name, 'PUBLIC_SYNONYM' as type FROM ALL_SYNONYMS where owner='PUBLIC'");
+ } else if (DBSynonymType.COMMON.equals(synonymType)) {
+ sb.append(
+ "SELECT OWNER as schema_name, SYNONYM_NAME as name, 'SYNONYM' as type FROM ALL_SYNONYMS where owner=")
+ .value(schemaName);
+ } else {
+ throw new UnsupportedOperationException("Not supported Synonym type");
+ }
+
+ return jdbcOperations.query(sb.toString(), new BeanPropertyRowMapper<>(DBObjectIdentity.class));
}
@Override
@@ -573,7 +702,8 @@ protected RowMapper listColumnsRowMapper() {
hiddenColumnOrdinaryPosition[0]--;
}
tableColumn.setVirtual("YES".equalsIgnoreCase(rs.getString(OracleConstants.COL_VIRTUAL_COLUMN)));
- tableColumn.setDefaultValue(rs.getString(OracleConstants.COL_DATA_DEFAULT));
+ tableColumn.setDefaultValue("NULL".equals(rs.getString(OracleConstants.COL_DATA_DEFAULT)) ? null
+ : rs.getString(OracleConstants.COL_DATA_DEFAULT));
if (tableColumn.getVirtual()) {
tableColumn.setGenExpression(rs.getString(OracleConstants.COL_DATA_DEFAULT));
}
@@ -775,32 +905,27 @@ protected List obtainBasicIndexInfo(String schemaName, String tabl
index.setAlgorithm(DBIndexAlgorithm.fromString(rs.getString(OracleConstants.INDEX_TYPE)));
index.setCompressInfo(rs.getString(OracleConstants.INDEX_COMPRESSION));
index.setColumnNames(new ArrayList<>());
- index.setAvailable("VALID".equals(rs.getString(OracleConstants.INDEX_STATUS)));
+ index.setAvailable(isTableIndexAvailable(rs.getString(OracleConstants.INDEX_STATUS)));
+ if (judgeIndexGlobalOrLocalFromDataDict()) {
+ index.setGlobal("NO".equalsIgnoreCase(rs.getString("PARTITIONED")));
+ }
indexName2Index.putIfAbsent(index.getName(), index);
return index;
});
return new ArrayList<>(indexName2Index.values());
}
+ protected boolean isTableIndexAvailable(String status) {
+ return !"UNUSABLE".equals(status);
+ }
+
+ protected boolean judgeIndexGlobalOrLocalFromDataDict() {
+ return true;
+ }
+
@Override
public String getTableDDL(String schemaName, String tableName) {
- OracleSqlBuilder sb = new OracleSqlBuilder();
- sb.append("SHOW CREATE TABLE ");
- sb.identifier(schemaName);
- sb.append(".");
- sb.identifier(tableName);
-
- AtomicReference ddlRef = new AtomicReference<>();
- jdbcOperations.query(sb.toString(), t -> {
- // Create table ddl like this: CREATE [GLOBAL TEMPORARY|SHARDED|DUPLICATED] TABLE T...
- String ddl = t.getString(2);
- if (Objects.nonNull(ddl)) {
- // fix: Replace " TABLE " to " TABLE schemaName."
- ddlRef.set(StringUtils.replace(ddl, " TABLE ",
- " TABLE " + StringUtils.quoteOracleIdentifier(schemaName) + ".", 1));
- }
- });
- StringBuilder ddl = new StringBuilder(ddlRef.get());
+ StringBuilder ddl = new StringBuilder(getTableDDLOnly(schemaName, tableName));
ddl.append(";\n");
Map variables = new HashMap<>();
DBTableOptions tableOptions = getTableOptions(schemaName, tableName);
@@ -856,6 +981,17 @@ public String getTableDDL(String schemaName, String tableName) {
}
+ protected String getTableDDLOnly(String schemaName, String tableName) {
+ OracleSqlBuilder sb = new OracleSqlBuilder();
+ sb.append("SELECT dbms_metadata.get_ddl('TABLE', ")
+ .value(tableName)
+ .append(", ")
+ .value(schemaName)
+ .append(") as DDL from dual");
+
+ return jdbcOperations.queryForObject(sb.toString(), String.class);
+ }
+
@Override
public DBTableOptions getTableOptions(String schemaName, String tableName) {
DBTableOptions tableOptions = new DBTableOptions();
@@ -872,16 +1008,16 @@ public DBTableOptions getTableOptions(String schemaName, String tableName, Strin
}
protected void obtainTableCharset(DBTableOptions tableOptions) {
- String sql = "SHOW VARIABLES LIKE 'nls_characterset'";
+ String sql = "select value from v$nls_parameters where PARAMETER = 'NLS_CHARACTERSET'";
jdbcOperations.query(sql, t -> {
- tableOptions.setCharsetName(t.getString("VALUE"));
+ tableOptions.setCharsetName(t.getString(1));
});
}
protected void obtainTableCollation(DBTableOptions tableOptions) {
- String sql = "SHOW VARIABLES LIKE 'nls_sort'";
+ String sql = "SELECT value from v$nls_parameters where parameter = 'NLS_SORT'";
jdbcOperations.query(sql, t -> {
- tableOptions.setCollationName(t.getString("VALUE"));
+ tableOptions.setCollationName(t.getString(1));
});
}
@@ -914,42 +1050,501 @@ private void obtainTableCreateAndUpdateTime(String schemaName, String tableName,
@Override
public DBView getView(String schemaName, String viewName) {
- throw new UnsupportedOperationException("Not supported yet");
+ DBView view = new DBView();
+ view.setViewName(viewName);
+ view.setSchemaName(schemaName);
+ view.setDefiner(schemaName);
+ OracleSqlBuilder getDDL = new OracleSqlBuilder();
+ getDDL.append("SELECT dbms_metadata.get_ddl('VIEW', ")
+ .value(viewName)
+ .append(", ")
+ .value(schemaName)
+ .append(") as DDL FROM dual");
+ jdbcOperations.query(getDDL.toString(), rs -> {
+ view.setDdl(rs.getString(1));
+ });
+
+ OracleSqlBuilder getColumns = new OracleSqlBuilder();
+ getColumns.append(
+ "SELECT COLUMN_NAME, DATA_TYPE, NULLABLE, DATA_DEFAULT, COMMENTS FROM SYS.ALL_TAB_COLS NATURAL JOIN SYS.ALL_COL_COMMENTS WHERE OWNER = ")
+ .value(schemaName).append(" AND TABLE_NAME=").value(viewName).append(" ORDER BY COLUMN_ID ASC");
+ List columns = jdbcOperations.query(getColumns.toString(), (rs, rowNum) -> {
+ DBTableColumn column = new DBTableColumn();
+ column.setName(rs.getString("COLUMN_NAME"));
+ column.setTypeName(rs.getString("DATA_TYPE"));
+ column.setNullable("Y".equalsIgnoreCase(rs.getString("NULLABLE")));
+ column.setDefaultValue(rs.getString("DATA_DEFAULT"));
+ column.setOrdinalPosition(rowNum);
+ column.setTableName(view.getViewName());
+ return column;
+ });
+ view.setColumns(columns);
+ return view;
}
@Override
public DBFunction getFunction(String schemaName, String functionName) {
- throw new UnsupportedOperationException("Not supported yet");
+ OracleSqlBuilder info = new OracleSqlBuilder();
+ info.append("select OWNER, STATUS, CREATED, LAST_DDL_TIME from ")
+ .append(dataDictTableNames.OBJECTS())
+ .append(" where object_type='FUNCTION' and owner=")
+ .value(schemaName)
+ .append(" and OBJECT_NAME=")
+ .value(functionName);
+ DBFunction function = new DBFunction();
+ function.setFunName(functionName);
+ function.setDefiner(schemaName);
+
+ jdbcOperations.query(info.toString(), (rs) -> {
+ function.setDefiner(rs.getString("OWNER"));
+ function.setStatus(rs.getString("STATUS"));
+ function.setCreateTime(Timestamp.valueOf(rs.getString("CREATED")));
+ function.setModifyTime(Timestamp.valueOf(rs.getString("LAST_DDL_TIME")));
+ });
+
+ OracleSqlBuilder ddl = new OracleSqlBuilder();
+ ddl.append("SELECT dbms_metadata.get_ddl('FUNCTION', ")
+ .value(functionName)
+ .append(", ")
+ .value(schemaName)
+ .append(") as DDL from dual");
+ jdbcOperations.query(ddl.toString(), rs -> {
+ function.setDdl(rs.getString(1));
+ });
+
+ OracleSqlBuilder getParams = new OracleSqlBuilder();
+ getParams.append("SELECT OWNER, OBJECT_NAME, ARGUMENT_NAME, DATA_TYPE, IN_OUT, PLS_TYPE, POSITION FROM ")
+ .append(dataDictTableNames.ARGUMENTS())
+ .append(" WHERE OWNER=")
+ .value(schemaName)
+ .append(" AND OBJECT_NAME=")
+ .value(functionName)
+ .append("AND PACKAGE_NAME IS NULL ORDER BY POSITION");
+ List params = new ArrayList<>();
+ jdbcOperations.query(getParams.toString(), rs -> {
+ if (Objects.isNull(rs.getString("ARGUMENT_NAME"))) {
+ function.setReturnType(rs.getString("DATA_TYPE"));
+ } else {
+ DBPLParam param = new DBPLParam();
+ param.setParamName(rs.getString("ARGUMENT_NAME"));
+ param.setDataType(rs.getString("DATA_TYPE"));
+ param.setParamMode(DBPLParamMode.getEnum(rs.getString("IN_OUT")));
+ param.setSeqNum(rs.getInt("POSITION"));
+ params.add(param);
+ }
+ });
+ function.setParams(params);
+ if (StringUtils.containsIgnoreCase(function.getStatus(), PLConstants.PL_OBJECT_STATUS_INVALID)) {
+ function.setErrorMessage(PLObjectErrMsgUtils.getOraclePLObjErrMsg(jdbcOperations,
+ function.getDefiner(), DBObjectType.FUNCTION.name(), function.getFunName()));
+ }
+
+ return parseFunctionDDL(function);
+ }
+
+ protected DBFunction parseFunctionDDL(DBFunction function) {
+ // get variables defined in function by parse function ddl
+ try {
+ ParseOraclePLResult result = PLParser.parseOracle(function.getDdl());
+ function.setVariables(result.getVaribaleList());
+ function.setTypes(result.getTypeList());
+ } catch (Exception e) {
+ log.warn("Failed to parse function ddl={}, errorMessage={}", function.getDdl(), e.getMessage());
+ function.setParseErrorMessage(e.getMessage());
+ }
+ return function;
}
@Override
public DBProcedure getProcedure(String schemaName, String procedureName) {
- throw new UnsupportedOperationException("Not supported yet");
+ OracleSqlBuilder info = new OracleSqlBuilder();
+ info.append("select OWNER, STATUS, CREATED, LAST_DDL_TIME from ")
+ .append(dataDictTableNames.OBJECTS())
+ .append(" where object_type='PROCEDURE' and owner=")
+ .value(schemaName)
+ .append(" and OBJECT_NAME=")
+ .value(procedureName);
+ DBProcedure procedure = new DBProcedure();
+ procedure.setProName(procedureName);
+
+ jdbcOperations.query(info.toString(), (rs) -> {
+ procedure.setDefiner(rs.getString("OWNER"));
+ procedure.setStatus(rs.getString("STATUS"));
+ procedure.setCreateTime(Timestamp.valueOf(rs.getString("CREATED")));
+ procedure.setModifyTime(Timestamp.valueOf(rs.getString("LAST_DDL_TIME")));
+ });
+
+ OracleSqlBuilder ddl = new OracleSqlBuilder();
+ ddl.append("SELECT dbms_metadata.get_ddl('PROCEDURE', ")
+ .value(procedureName)
+ .append(", ")
+ .value(schemaName)
+ .append(") as DDL from dual");
+ jdbcOperations.query(ddl.toString(), rs -> {
+ procedure.setDdl(rs.getString(1));
+ });
+
+ OracleSqlBuilder getParams = new OracleSqlBuilder();
+ getParams.append(
+ "SELECT OWNER, OBJECT_NAME, ARGUMENT_NAME, DATA_TYPE, IN_OUT, PLS_TYPE, DEFAULT_VALUE, POSITION FROM ")
+ .append(dataDictTableNames.ARGUMENTS())
+ .append(" WHERE OWNER=")
+ .value(schemaName)
+ .append(" AND OBJECT_NAME=")
+ .value(procedureName)
+ .append(" AND PACKAGE_NAME IS NULL ORDER BY POSITION");
+ List params = new ArrayList<>();
+ jdbcOperations.query(getParams.toString(), rs -> {
+ DBPLParam param = new DBPLParam();
+ param.setParamName(rs.getString("ARGUMENT_NAME"));
+ param.setDataType(rs.getString("DATA_TYPE"));
+ param.setSeqNum(rs.getInt("POSITION"));
+ param.setParamMode(DBPLParamMode.getEnum(rs.getString("IN_OUT")));
+ params.add(param);
+ });
+ procedure.setParams(params);
+ if (StringUtils.containsIgnoreCase(procedure.getStatus(), PLConstants.PL_OBJECT_STATUS_INVALID)) {
+ procedure.setErrorMessage(PLObjectErrMsgUtils.getOraclePLObjErrMsg(jdbcOperations,
+ procedure.getDefiner(), DBObjectType.PROCEDURE.name(), procedure.getProName()));
+ }
+ return parseProcedureDDL(procedure);
+ }
+
+ protected DBProcedure parseProcedureDDL(DBProcedure procedure) {
+ Validate.notBlank(procedure.getDdl(), "procedure.ddl");
+ String ddl = procedure.getDdl();
+ ParseOraclePLResult result;
+ try {
+ result = PLParser.parseOracle(ddl);
+ } catch (Exception e) {
+ log.warn("Failed to parse oracle procedure ddl, ddl={}, errorMessage={}", ddl, e.getMessage());
+ procedure.setParseErrorMessage(e.getMessage());
+ return procedure;
+ }
+ procedure.setVariables(result.getVaribaleList());
+ procedure.setTypes((result.getTypeList()));
+ return procedure;
}
@Override
public DBPackage getPackage(String schemaName, String packageName) {
- throw new UnsupportedOperationException("Not supported yet");
+ OracleSqlBuilder info = new OracleSqlBuilder();
+ info.append(
+ "select OWNER, OBJECT_TYPE, STATUS, CREATED, LAST_DDL_TIME from ")
+ .append(dataDictTableNames.OBJECTS())
+ .append(" where object_type in ('PACKAGE', 'PACKAGE BODY') and owner=")
+ .value(schemaName)
+ .append(" and OBJECT_NAME=")
+ .value(packageName)
+ .append(" order by OBJECT_TYPE");
+
+ DBPackage dbPackage = new DBPackage();
+ dbPackage.setPackageName(packageName);
+
+ DBPackageDetail packageHead = new DBPackageDetail();
+ DBPackageDetail packageBody = new DBPackageDetail();
+ DBPackageBasicInfo packageHeadBasicInfo = new DBPackageBasicInfo();
+ DBPackageBasicInfo packageBodyBasicInfo = new DBPackageBasicInfo();
+ packageHead.setBasicInfo(packageHeadBasicInfo);
+ packageBody.setBasicInfo(packageBodyBasicInfo);
+ dbPackage.setPackageHead(packageHead);
+ dbPackage.setPackageBody(packageBody);
+
+ jdbcOperations.query(info.toString(), (rs) -> {
+ dbPackage.setStatus(rs.getString("STATUS"));
+ if (DBObjectType.PACKAGE.name().equalsIgnoreCase(rs.getString("OBJECT_TYPE"))) {
+ packageHeadBasicInfo.setDefiner(rs.getString("OWNER"));
+ packageHeadBasicInfo.setCreateTime(rs.getTimestamp("CREATED"));
+ packageHeadBasicInfo.setModifyTime(rs.getTimestamp("LAST_DDL_TIME"));
+ } else {
+ packageBodyBasicInfo.setDefiner(rs.getString("OWNER"));
+ packageBodyBasicInfo.setCreateTime(rs.getTimestamp("CREATED"));
+ packageBodyBasicInfo.setModifyTime(rs.getTimestamp("LAST_DDL_TIME"));
+ }
+ });
+
+ OracleSqlBuilder packageHeadDDL = new OracleSqlBuilder();
+ packageHeadDDL.append("SELECT dbms_metadata.get_ddl('PACKAGE_SPEC', ")
+ .value(packageName)
+ .append(", ")
+ .value(schemaName)
+ .append(") as DDL from dual");
+ jdbcOperations.query(packageHeadDDL.toString(), rs -> {
+ packageHeadBasicInfo.setDdl(rs.getString(1));
+ });
+ parsePackageDDL(packageHead);
+
+ OracleSqlBuilder packageBodyDDL = new OracleSqlBuilder();
+ packageBodyDDL.append("SELECT dbms_metadata.get_ddl('PACKAGE_BODY', ")
+ .value(packageName)
+ .append(", ")
+ .value(schemaName)
+ .append(") as DDL from dual");
+ jdbcOperations.query(packageBodyDDL.toString(), rs -> {
+ packageBodyBasicInfo.setDdl(rs.getString(1));
+ });
+ parsePackageDDL(packageBody);
+
+ if (StringUtils.containsIgnoreCase(dbPackage.getStatus(), PLConstants.PL_OBJECT_STATUS_INVALID)) {
+ dbPackage.setErrorMessage(PLObjectErrMsgUtils.getOraclePLObjErrMsg(jdbcOperations,
+ schemaName, DBObjectType.PACKAGE.name(), dbPackage.getPackageName()));
+ }
+ return dbPackage;
+ }
+
+ private void parsePackageDDL(DBPackageDetail packageDetail) {
+ if (Objects.isNull(packageDetail.getBasicInfo().getDdl())) {
+ return;
+ }
+ try {
+ ParseOraclePLResult oraclePLResult = PLParser.parseOracle(packageDetail.getBasicInfo().getDdl());
+ packageDetail.setVariables(oraclePLResult.getVaribaleList());
+ packageDetail.setTypes(oraclePLResult.getTypeList());
+ packageDetail.setFunctions(oraclePLResult.getFunctionList());
+ packageDetail.setProcedures(oraclePLResult.getProcedureList());
+ } catch (Exception e) {
+ log.warn("Failed to parse package ddl={}, errorMessage={}", packageDetail.getBasicInfo().getDdl(),
+ e.getMessage());
+ packageDetail.setParseErrorMessage(e.getMessage());
+ }
}
@Override
- public DBTrigger getTrigger(String schemaName, String packageName) {
- throw new UnsupportedOperationException("Not supported yet");
+ public DBTrigger getTrigger(String schemaName, String triggerName) {
+ DBTrigger trigger = new DBTrigger();
+ OracleSqlBuilder sb = new OracleSqlBuilder();
+ sb.append(
+ "select s.OWNER, s.TRIGGER_NAME, s.BASE_OBJECT_TYPE, s.TABLE_OWNER, s.TABLE_NAME, s.STATUS as ENABLE_STATUS, o.STATUS")
+ .append(" FROM (SELECT * FROM ")
+ .append(dataDictTableNames.OBJECTS())
+ .append(" WHERE OBJECT_TYPE='TRIGGER') o RIGHT JOIN ")
+ .append(dataDictTableNames.TRIGGERS())
+ .append(" s ON o.OBJECT_NAME=s.TRIGGER_NAME AND o.OWNER=s.OWNER")
+ .append(" WHERE s.OWNER=").value(schemaName)
+ .append(" AND s.TRIGGER_NAME=").value(triggerName);
+ jdbcOperations.query(sb.toString(), (rs) -> {
+ trigger.setBaseObjectType(rs.getString("BASE_OBJECT_TYPE"));
+ trigger.setTriggerName(rs.getString("TRIGGER_NAME"));
+ trigger.setOwner(rs.getString("OWNER"));
+ trigger.setSchemaMode(rs.getString("TABLE_OWNER"));
+ trigger.setSchemaName(rs.getString("TABLE_NAME"));
+ trigger.setEnable("ENABLED".equalsIgnoreCase(rs.getString("ENABLE_STATUS")));
+ trigger.setStatus(rs.getString("STATUS"));
+ });
+
+ OracleSqlBuilder ddl = new OracleSqlBuilder();
+ ddl.append("SELECT dbms_metadata.get_ddl('TRIGGER',")
+ .value(triggerName)
+ .append(", ")
+ .value(schemaName)
+ .append(") as DDL FROM dual");
+ jdbcOperations.query(ddl.toString(), rs -> {
+ trigger.setDdl(rs.getString(1));
+ });
+ if (StringUtils.containsIgnoreCase(trigger.getStatus(), PLConstants.PL_OBJECT_STATUS_INVALID)) {
+ trigger.setErrorMessage(PLObjectErrMsgUtils.getOraclePLObjErrMsg(jdbcOperations,
+ trigger.getOwner(), DBObjectType.TRIGGER.name(), trigger.getTriggerName()));
+ }
+ return trigger;
}
@Override
public DBType getType(String schemaName, String typeName) {
- throw new UnsupportedOperationException("Not supported yet");
+ OracleSqlBuilder sb = new OracleSqlBuilder();
+ sb.append("select a.OWNER,a.OBJECT_NAME,u.TYPE_NAME,a.CREATED,a.LAST_DDL_TIME,u.TYPECODE,u.TYPEID from ");
+ sb.append(dataDictTableNames.OBJECTS());
+ sb.append(" a right join ");
+ sb.append(dataDictTableNames.TYPES());
+ sb.append(" u on a.OBJECT_NAME=u.TYPE_NAME where a.OWNER=");
+ sb.value(schemaName);
+ sb.append(" and u.TYPE_NAME=");
+ sb.value(typeName);
+
+ DBType type = new DBType();
+ jdbcOperations.query(sb.toString(), (rs) -> {
+ type.setOwner(rs.getString("OWNER"));
+ type.setTypeName(rs.getString("TYPE_NAME"));
+ type.setCreateTime(rs.getTimestamp("CREATED"));
+ type.setLastDdlTime(rs.getTimestamp("LAST_DDL_TIME"));
+ type.setTypeId(rs.getString("TYPEID"));
+ type.setType(rs.getString("TYPECODE"));
+ });
+ return parseTypeDDL(type);
+ }
+
+ protected DBType parseTypeDDL(DBType type) {
+ OracleSqlBuilder typeDDL = new OracleSqlBuilder();
+ typeDDL.append("select dbms_metadata.get_ddl('TYPE', ")
+ .value(type.getTypeName())
+ .append(", ")
+ .value(type.getOwner())
+ .append(") as DDL from dual");
+
+ String typeDdl = queryTypeDdl(typeDDL.toString());
+
+ OracleSqlBuilder typeSpecDDL = new OracleSqlBuilder();
+ typeSpecDDL.append("select dbms_metadata.get_ddl('TYPE_SPEC', ")
+ .value(type.getTypeName())
+ .append(", ")
+ .value(type.getOwner())
+ .append(") as DDL from dual");
+
+ String typeHeadDdl = queryTypeSpecDdl(typeSpecDDL.toString());
+ Validate.notBlank(typeDdl, "typeDdl");
+ Validate.notBlank(typeHeadDdl, "typeHeadDdl");
+ type.setDdl(typeDdl);
+
+ return parseTypeDDL(type, typeHeadDdl);
+ }
+
+ protected String queryTypeDdl(String querySql) {
+ return jdbcOperations.query(querySql, rs -> {
+ if (!rs.next()) {
+ return null;
+ }
+ return rs.getString(1);
+ });
+ }
+
+ protected String queryTypeSpecDdl(String querySql) {
+ return jdbcOperations.query(querySql, rs -> {
+ if (!rs.next()) {
+ return null;
+ }
+ return rs.getString(1);
+ });
+ }
+
+ protected DBType parseTypeDDL(DBType type, String typeHeadDdl) {
+ DBBasicPLObject typeDetail = new DBBasicPLObject();
+ try {
+ ParseOraclePLResult oraclePLResult = PLParser.parseObOracle(typeHeadDdl);
+ typeDetail.setVariables(oraclePLResult.getVaribaleList());
+ typeDetail.setTypes(oraclePLResult.getTypeList());
+ typeDetail.setProcedures(oraclePLResult.getProcedureList());
+ typeDetail.setFunctions(oraclePLResult.getFunctionList());
+ } catch (Exception e) {
+ log.warn("Parse type ddl failed, ddl={}, errorMessage={}", typeHeadDdl, e.getMessage());
+ typeDetail.setParseErrorMessage(e.getMessage());
+ }
+
+ type.setTypeDetail(typeDetail);
+ String errorText = PLObjectErrMsgUtils.getOraclePLObjErrMsg(jdbcOperations,
+ type.getOwner(), DBObjectType.TYPE.name(), type.getTypeName());
+ if (StringUtils.isNotBlank(errorText)) {
+ type.setStatus(PLConstants.PL_OBJECT_STATUS_INVALID);
+ type.setErrorMessage(errorText);
+ }
+ return type;
}
@Override
public DBSequence getSequence(String schemaName, String sequenceName) {
- throw new UnsupportedOperationException("Not supported yet");
+ OracleSqlBuilder sb = new OracleSqlBuilder();
+ sb.append("select * from ")
+ .append(dataDictTableNames.SEQUENCES())
+ .append(" where sequence_owner=")
+ .value(schemaName)
+ .append(" and sequence_name=")
+ .value(sequenceName);
+
+ DBSequence sequence = new DBSequence();
+ sequence.setName(sequenceName);
+ jdbcOperations.query(sb.toString(), rs -> {
+ sequence.setUser(rs.getString("SEQUENCE_OWNER"));
+ sequence.setMinValue(rs.getBigDecimal("MIN_VALUE").toString());
+ sequence.setMaxValue(rs.getBigDecimal("MAX_VALUE").toString());
+ sequence.setIncreament(rs.getBigDecimal("INCREMENT_BY").longValue());
+ sequence.setCycled("Y".equalsIgnoreCase(rs.getString("CYCLE_FLAG")));
+ sequence.setOrderd("Y".equalsIgnoreCase(rs.getString("ORDER_FLAG")));
+ long cacheSize = rs.getBigDecimal("CACHE_SIZE").longValue();
+ if (cacheSize > 1) {
+ sequence.setCacheSize(cacheSize);
+ sequence.setCached(true);
+ } else {
+ sequence.setCached(false);
+ }
+ sequence.setNextCacheValue(rs.getBigDecimal("LAST_NUMBER").toString());
+
+ });
+
+ String ddl = getSequenceDDL(sequence);
+ sequence.setDdl(ddl);
+ return sequence;
+ }
+
+ protected String getSequenceDDL(DBSequence sequence) {
+ Validate.notNull(sequence, "sequence");
+ Validate.notBlank(sequence.getName(), "sequence.name");
+
+ OracleSqlBuilder ddl = new OracleSqlBuilder();
+ ddl.append("SELECT dbms_metadata.get_ddl('SEQUENCE', ")
+ .value(sequence.getName())
+ .append(", ")
+ .value(sequence.getUser())
+ .append(") as DDL from dual");
+ return jdbcOperations.query(ddl.toString(), rs -> {
+ if (!rs.next()) {
+ return null;
+ }
+ return rs.getString(1);
+ });
}
@Override
public DBSynonym getSynonym(String schemaName, String synonymName, DBSynonymType synonymType) {
- throw new UnsupportedOperationException("Not supported yet");
+ OracleSqlBuilder sb = new OracleSqlBuilder();
+ sb.append(
+ "select s.OWNER,s.SYNONYM_NAME,s.TABLE_OWNER,s.TABLE_NAME,s.DB_LINK,o.CREATED,o.LAST_DDL_TIME,o.STATUS from ");
+ sb.append(dataDictTableNames.SYNONYMS());
+ sb.append(" s left join (select * from ");
+ sb.append(dataDictTableNames.OBJECTS());
+ sb.append(" where OBJECT_TYPE='SYNONYM') o on s.SYNONYM_NAME=o.OBJECT_NAME and s.OWNER=o.OWNER where s.OWNER=");
+ sb.value(getSynonymOwnerSymbol(synonymType, schemaName));
+ sb.append(" and s.SYNONYM_NAME=");
+ sb.value(synonymName);
+
+ DBSynonym synonym = new DBSynonym();
+ synonym.setSynonymType(synonymType);
+ jdbcOperations.query(sb.toString(), rs -> {
+ synonym.setOwner(rs.getString("OWNER"));
+ synonym.setSynonymName(rs.getString("SYNONYM_NAME"));
+ synonym.setTableOwner(rs.getString("TABLE_OWNER"));
+ synonym.setTableName(rs.getString("TABLE_NAME"));
+ synonym.setDbLink(rs.getString("DB_LINK"));
+ synonym.setCreated(rs.getTimestamp("CREATED"));
+ synonym.setLastDdlTime(rs.getTimestamp("LAST_DDL_TIME"));
+ synonym.setStatus(rs.getString("STATUS"));
+ });
+ synonym.setDdl(getSynonymDDL(synonym));
+
+ return synonym;
+ }
+
+ protected String getSynonymDDL(DBSynonym synonym) {
+ OracleSqlBuilder ddl = new OracleSqlBuilder();
+ ddl.append("SELECT dbms_metadata.get_ddl('SYNONYM', ")
+ .value(synonym.getSynonymName())
+ .append(", ")
+ .value(synonym.getOwner())
+ .append(") as DDL from dual");
+
+ return jdbcOperations.query(ddl.toString(), rs -> {
+ if (!rs.next()) {
+ return null;
+ }
+ return rs.getString(1);
+ });
+ }
+
+ protected String getSynonymOwnerSymbol(DBSynonymType synonymType, String schemaName) {
+ if (synonymType.equals(DBSynonymType.PUBLIC)) {
+ return "PUBLIC";
+ } else if (synonymType.equals(DBSynonymType.COMMON)) {
+ return schemaName;
+ } else {
+ throw new UnsupportedOperationException("Not supported Synonym type");
+ }
}
}
diff --git a/libs/db-browser/src/main/java/com/oceanbase/tools/dbbrowser/stats/oracle/OracleStatsAccessor.java b/libs/db-browser/src/main/java/com/oceanbase/tools/dbbrowser/stats/oracle/OracleStatsAccessor.java
new file mode 100644
index 0000000000..c16ddf9e00
--- /dev/null
+++ b/libs/db-browser/src/main/java/com/oceanbase/tools/dbbrowser/stats/oracle/OracleStatsAccessor.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2023 OceanBase.
+ *
+ * Licensed 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 com.oceanbase.tools.dbbrowser.stats.oracle;
+
+import java.util.List;
+
+import org.springframework.jdbc.core.BeanPropertyRowMapper;
+import org.springframework.jdbc.core.JdbcOperations;
+
+import com.oceanbase.tools.dbbrowser.model.DBSession;
+
+/**
+ * @author jingtian
+ * @date 2023/11/17
+ * @since
+ */
+public class OracleStatsAccessor extends BaseOBOracleStatsAccessor {
+
+ private static final String LIST_ALL_SESSIONS = "SELECT \n"
+ + "a.SID || ', ' || a.SERIAL# AS ID,\n"
+ + "a.USERNAME, \n"
+ + "a.SCHEMANAME as DATABASE_NAME, \n"
+ + "a.COMMAND, \n"
+ + "a.STATUS as STATE, \n"
+ + "a.MACHINE as HOST, \n"
+ + "a.PORT, \n"
+ + "a.SQL_ID, \n"
+ + "b.SQL_TEXT as LATEST_QUERIES,\n"
+ + "b.ELAPSED_TIME as EXECUTE_TIME\n"
+ + "FROM V$SESSION a left join V$SQL b on a.SQL_ID = b.SQL_ID";
+
+ private static final String GET_CURRENT_SESSION = LIST_ALL_SESSIONS
+ + " WHERE a.SID = SYS_CONTEXT('USERENV', 'SID') and a.AUDSID=SYS_CONTEXT('USERENV', 'SESSIONID') and a.status = 'ACTIVE'";
+
+ public OracleStatsAccessor(JdbcOperations jdbcOperations) {
+ super(jdbcOperations);
+ }
+
+ @Override
+ public DBSession currentSession() {
+ return jdbcOperations.queryForObject(GET_CURRENT_SESSION,
+ new BeanPropertyRowMapper<>(DBSession.class));
+ }
+
+ @Override
+ public List listAllSessions() {
+ return jdbcOperations.query(LIST_ALL_SESSIONS, new BeanPropertyRowMapper<>(DBSession.class));
+ }
+}
diff --git a/libs/db-browser/src/main/java/com/oceanbase/tools/dbbrowser/template/oracle/BaseOraclePLTemplate.java b/libs/db-browser/src/main/java/com/oceanbase/tools/dbbrowser/template/oracle/BaseOraclePLTemplate.java
index 6b57840a8f..56b0d6d4ac 100644
--- a/libs/db-browser/src/main/java/com/oceanbase/tools/dbbrowser/template/oracle/BaseOraclePLTemplate.java
+++ b/libs/db-browser/src/main/java/com/oceanbase/tools/dbbrowser/template/oracle/BaseOraclePLTemplate.java
@@ -32,7 +32,7 @@ public abstract class BaseOraclePLTemplate extends BasePLTem
@Override
protected String generateInOutString(DBPLParamMode type) {
if (DBPLParamMode.INOUT == type) {
- return PLConstants.ORACLE_PL_INOUT_PARAM;
+ return PLConstants.OB_ORACLE_PL_INOUT_PARAM;
} else if (DBPLParamMode.IN == type) {
return PLConstants.PL_IN_PARAM;
} else if (DBPLParamMode.OUT == type) {
diff --git a/libs/db-browser/src/main/resources/schema/sql/oboracle/oboracle_3_x.yaml b/libs/db-browser/src/main/resources/schema/sql/oboracle/oboracle_3_x.yaml
index e00a6b97c3..41cb2a25b8 100644
--- a/libs/db-browser/src/main/resources/schema/sql/oboracle/oboracle_3_x.yaml
+++ b/libs/db-browser/src/main/resources/schema/sql/oboracle/oboracle_3_x.yaml
@@ -160,4 +160,18 @@ sqls:
SYS.ALL_VIRTUAL_TABLE_REAL_AGENT t
where
d.DATABASE_NAME = ? and t.TABLE_NAME = ?
- and d.DATABASE_ID = t.DATABASE_ID;
\ No newline at end of file
+ and d.DATABASE_ID = t.DATABASE_ID;
+ list-database: |-
+ select
+ USERNAME,
+ USERID
+ from
+ ALL_USERS
+ get-database: |-
+ SELECT
+ USERNAME,
+ USERID
+ from
+ SYS.ALL_USERS
+ WHERE
+ USERNAME = ?
\ No newline at end of file
diff --git a/libs/db-browser/src/main/resources/schema/sql/oboracle/oboracle_4_0_x.yaml b/libs/db-browser/src/main/resources/schema/sql/oboracle/oboracle_4_0_x.yaml
index 29f3f23cbe..8905c658e3 100644
--- a/libs/db-browser/src/main/resources/schema/sql/oboracle/oboracle_4_0_x.yaml
+++ b/libs/db-browser/src/main/resources/schema/sql/oboracle/oboracle_4_0_x.yaml
@@ -192,4 +192,18 @@ sqls:
TABLE_OWNER = ?
AND TABLE_NAME = ?
ORDER BY
- PARTITION_POSITION ASC
\ No newline at end of file
+ PARTITION_POSITION ASC
+ list-database: |-
+ select
+ USERNAME,
+ USERID
+ from
+ ALL_USERS
+ get-database: |-
+ SELECT
+ USERNAME,
+ USERID
+ from
+ SYS.ALL_USERS
+ WHERE
+ USERNAME = ?
\ No newline at end of file
diff --git a/libs/db-browser/src/main/resources/schema/sql/oracle/oracle_11g.yaml b/libs/db-browser/src/main/resources/schema/sql/oracle/oracle_11g.yaml
new file mode 100644
index 0000000000..44731f6f5f
--- /dev/null
+++ b/libs/db-browser/src/main/resources/schema/sql/oracle/oracle_11g.yaml
@@ -0,0 +1,210 @@
+sqls:
+ list-basic-table-columns: |-
+ SELECT
+ OWNER,
+ TABLE_NAME,
+ COLUMN_NAME,
+ DATA_TYPE,
+ COMMENTS
+ FROM
+ SYS.ALL_TAB_COLS NATURAL JOIN SYS.ALL_COL_COMMENTS
+ WHERE
+ OWNER = ? AND TABLE_NAME = ?
+ ORDER BY
+ COLUMN_ID ASC
+ list-basic-schema-table-columns: |-
+ SELECT
+ OWNER,
+ TABLE_NAME,
+ COLUMN_NAME,
+ DATA_TYPE,
+ COMMENTS
+ FROM
+ SYS.ALL_TAB_COLS NATURAL JOIN SYS.ALL_COL_COMMENTS
+ WHERE
+ OWNER = ?
+ AND TABLE_NAME IN (
+ SELECT
+ TABLE_NAME
+ FROM
+ SYS.ALL_TABLES
+ WHERE
+ OWNER = ?
+ )
+ ORDER BY
+ TABLE_NAME ASC,
+ COLUMN_ID ASC
+ list-basic-view-columns: |-
+ SELECT
+ OWNER,
+ TABLE_NAME,
+ COLUMN_NAME,
+ DATA_TYPE,
+ COMMENTS
+ FROM
+ SYS.ALL_TAB_COLS NATURAL JOIN SYS.ALL_COL_COMMENTS
+ WHERE
+ OWNER = ? AND TABLE_NAME = ?
+ ORDER BY
+ COLUMN_ID ASC
+ list-basic-schema-view-columns: |-
+ SELECT
+ OWNER,
+ TABLE_NAME,
+ COLUMN_NAME,
+ DATA_TYPE,
+ COMMENTS
+ FROM
+ SYS.ALL_TAB_COLS NATURAL JOIN SYS.ALL_COL_COMMENTS
+ WHERE
+ OWNER = ?
+ AND TABLE_NAME IN (
+ SELECT
+ VIEW_NAME
+ FROM
+ SYS.ALL_VIEWS
+ WHERE
+ OWNER = ?
+ )
+ ORDER BY
+ TABLE_NAME ASC,
+ COLUMN_ID ASC
+ list-table-columns: |-
+ SELECT
+ OWNER,
+ TABLE_NAME,
+ COLUMN_ID,
+ COLUMN_NAME,
+ DATA_TYPE,
+ DATA_SCALE,
+ DATA_PRECISION,
+ DATA_LENGTH,
+ CHAR_LENGTH,
+ DATA_TYPE_MOD,
+ CHAR_USED,
+ NULLABLE,
+ DATA_DEFAULT,
+ HIDDEN_COLUMN,
+ VIRTUAL_COLUMN
+ FROM
+ SYS.ALL_TAB_COLS
+ WHERE
+ OWNER = ? AND TABLE_NAME = ?
+ ORDER BY
+ COLUMN_ID ASC
+ list-schema-columns: |-
+ SELECT
+ OWNER,
+ TABLE_NAME,
+ COLUMN_ID,
+ COLUMN_NAME,
+ DATA_TYPE,
+ DATA_SCALE,
+ DATA_PRECISION,
+ DATA_LENGTH,
+ CHAR_LENGTH,
+ DATA_TYPE_MOD,
+ CHAR_USED,
+ NULLABLE,
+ DATA_DEFAULT,
+ HIDDEN_COLUMN,
+ VIRTUAL_COLUMN
+ FROM
+ SYS.ALL_TAB_COLS
+ WHERE
+ OWNER = ?
+ ORDER BY
+ COLUMN_ID ASC
+ list-table-indexes: |-
+ SELECT
+ OWNER,
+ INDEX_NAME,
+ INDEX_TYPE,
+ TABLE_OWNER,
+ TABLE_NAME,
+ UNIQUENESS,
+ COMPRESSION,
+ VISIBILITY,
+ STATUS,
+ PARTITIONED
+ FROM
+ SYS.ALL_INDEXES
+ WHERE
+ OWNER = ? AND TABLE_NAME = ?
+ ORDER BY
+ INDEX_NAME ASC
+ list-index-columns: |-
+ SELECT
+ TABLE_OWNER,
+ TABLE_NAME,
+ COLUMN_POSITION,
+ COLUMN_NAME,
+ INDEX_NAME
+ FROM
+ SYS.ALL_IND_COLUMNS
+ WHERE
+ TABLE_OWNER = ? AND TABLE_NAME = ?
+ ORDER BY
+ COLUMN_POSITION ASC
+ list-table-constraints: |-
+ SELECT
+ t1.OWNER,
+ t1.CONSTRAINT_NAME,
+ t1.CONSTRAINT_TYPE,
+ t1.TABLE_NAME,
+ t1.SEARCH_CONDITION,
+ t1.R_OWNER,
+ t1.R_CONSTRAINT_NAME,
+ t1.DELETE_RULE,
+ t1.STATUS,
+ t1.DEFERRABLE,
+ t1.DEFERRED,
+ t1.VALIDATED,
+ t2.TABLE_NAME as R_TABLE_NAME,
+ t2.COLUMN_NAME as R_COLUMN_NAME,
+ t3.position as POSITION,
+ t3.COLUMN_NAME as COLUMN_NAME
+ FROM
+ SYS.ALL_CONSTRAINTS t1
+ JOIN SYS.ALL_CONS_COLUMNS t3 on t1.CONSTRAINT_NAME = t3.CONSTRAINT_NAME and t1.OWNER = t3.OWNER
+ LEFT JOIN SYS.ALL_CONS_COLUMNS t2 on t2.CONSTRAINT_NAME = t1.R_CONSTRAINT_NAME
+ AND t2.OWNER = t1.R_OWNER
+ WHERE
+ t1.OWNER = ? and t1.TABLE_NAME = ?
+ ORDER BY
+ t1.CONSTRAINT_NAME,
+ t2.position ASC
+ get-partition-option: |-
+ SELECT
+ PARTITIONING_TYPE
+ FROM
+ SYS.ALL_PART_TABLES
+ WHERE
+ OWNER = ?
+ AND TABLE_NAME = ?
+ list-partition-definitions: |-
+ SELECT
+ PARTITION_NAME,
+ PARTITION_POSITION,
+ HIGH_VALUE
+ FROM
+ SYS.ALL_TAB_PARTITIONS
+ WHERE
+ TABLE_OWNER = ?
+ AND TABLE_NAME = ?
+ ORDER BY
+ PARTITION_POSITION ASC
+ list-database: |-
+ SELECT
+ USERNAME,
+ USER_ID
+ from
+ SYS.ALL_USERS
+ get-database: |-
+ SELECT
+ USERNAME,
+ USER_ID
+ from
+ SYS.ALL_USERS
+ WHERE
+ USERNAME = ?
\ No newline at end of file
diff --git a/libs/db-browser/src/test/java/com/oceanbase/tools/dbbrowser/env/BaseTestEnv.java b/libs/db-browser/src/test/java/com/oceanbase/tools/dbbrowser/env/BaseTestEnv.java
index 58575058aa..4e60689242 100644
--- a/libs/db-browser/src/test/java/com/oceanbase/tools/dbbrowser/env/BaseTestEnv.java
+++ b/libs/db-browser/src/test/java/com/oceanbase/tools/dbbrowser/env/BaseTestEnv.java
@@ -22,6 +22,8 @@
import java.sql.Statement;
import java.util.HashMap;
import java.util.Map;
+import java.util.Objects;
+import java.util.Properties;
import javax.sql.DataSource;
@@ -46,14 +48,22 @@ public abstract class BaseTestEnv extends BasePropertiesEnv {
private static final String OB_MYSQL_COMMANDLINE_KEY = "odc.ob.default.mysql.commandline";
private static final String OB_ORACLE_COMMANDLINE_KEY = "odc.ob.default.oracle.commandline";
private static final String MYSQL_COMMANDLINE_KEY = "odc.mysql.default.commandline";
+ private static final String ORACLE_HOST_KEY = "odc.oracle.default.host";
+ private static final String ORACLE_PORT_KEY = "odc.oracle.default.port";
+ private static final String ORACLE_USERNAME_KEY = "odc.oracle.default.username";
+ private static final String ORACLE_PASSWORD_KEY = "odc.oracle.default.password";
+ private static final String ORACLE_SID_KEY = "odc.oracle.default.sid";
+ private static final String ORACLE_ROLE_KEY = "odc.oracle.default.role";
private static final Map DATASOURCE_MAP = new HashMap<>();
private static final int MAX_HOST_NAME_LENGTH = 16;
private static final String OB_MYSQL_DS_KEY = "OB_MYSQL_DATA_SOURCE";
private static final String OB_ORACLE_DS_KEY = "OB_ORACLE_DATA_SOURCE";
private static final String MYSQL_DS_KEY = "MYSQL_DATA_SOURCE";
+ private static final String ORACLE_DS_KEY = "ORACLE_DATA_SOURCE";
private static final String TEST_OB_MYSQL_DATABASE_NAME = generate().toLowerCase();
private static final String TEST_OB_ORACLE_DATABASE_NAME = generate().toUpperCase();
private static final String TEST_MYSQL_DATABASE_NAME = generate().toLowerCase();
+ private static final String TEST_ORACLE_DATABASE_NAME = generate().toUpperCase();
static {
String obMysqlCommandLine = get(OB_MYSQL_COMMANDLINE_KEY);
@@ -68,13 +78,18 @@ public abstract class BaseTestEnv extends BasePropertiesEnv {
ConnectionParseResult mysqlParseResult = MySQLClientArgsParser.parse(mysqlCommandLine);
initDataSource(mysqlParseResult, MYSQL_DS_KEY);
+ OracleConnectionConfig oracleConfig = buildOracleConnectionConfig();
+ initOracleDataSource(oracleConfig);
+
Thread shutdownHookThread = new Thread(() -> {
clear(obMysqlParseResult, OB_MYSQL_DS_KEY);
log.info("Clear OB MySQL database succeed, database={}", TEST_OB_MYSQL_DATABASE_NAME);
clear(obOracleParseResult, OB_ORACLE_DS_KEY);
log.info("Clear OB Oracle user succeed, user={}", TEST_OB_ORACLE_DATABASE_NAME);
clear(mysqlParseResult, MYSQL_DS_KEY);
- log.info("Clear MySQL user succeed, user={}", TEST_MYSQL_DATABASE_NAME);
+ log.info("Clear MySQL database succeed, database={}", TEST_MYSQL_DATABASE_NAME);
+ clear(oracleConfig);
+ log.info("Clear Oracle user succeed, user={}", TEST_ORACLE_DATABASE_NAME);
DATASOURCE_MAP.values().forEach(SingleConnectionDataSource::destroy);
log.info("Clear datasource succeed");
});
@@ -95,6 +110,10 @@ protected static DataSource getMySQLDataSource() {
return DATASOURCE_MAP.get(MYSQL_DS_KEY);
}
+ protected static DataSource getOracleDataSource() {
+ return DATASOURCE_MAP.get(ORACLE_DS_KEY);
+ }
+
protected static String getOBMySQLDataBaseName() {
return TEST_OB_MYSQL_DATABASE_NAME;
}
@@ -107,6 +126,10 @@ protected static String getMySQLDataBaseName() {
return TEST_MYSQL_DATABASE_NAME;
}
+ protected static String getOracleSchema() {
+ return TEST_ORACLE_DATABASE_NAME;
+ }
+
/**
* 生成用于不同环境UT执行相互隔离的名称
*
@@ -133,7 +156,7 @@ private static String generate() {
}
log.info("hostName={}, removeSpecial={}, HOST_NAME={}", hostName, removeSpecial, hostName);
long currentMillis = System.currentTimeMillis() % 1000000;
- return "dbbrowser_" + hostName + "_" + currentMillis;
+ return "db_" + hostName + "_" + currentMillis;
}
private static void initDataSource(ConnectionParseResult parseResult, String dataSourceKey) {
@@ -186,6 +209,42 @@ private static void initDataSource(ConnectionParseResult parseResult, String dat
parseResult.setDefaultDBName(origin);
}
+ private static void initOracleDataSource(OracleConnectionConfig config) {
+ clear(config);
+ String jdbcUrl = buildOracleJdbcUrl(config);
+ Properties props = new Properties();
+ props.setProperty("user", config.getUsername());
+ props.setProperty("password", config.getPassword());
+ if (Objects.nonNull(config.getRole())) {
+ props.put("internal_logon", config.getRole());
+ }
+ try (Connection connection = DriverManager.getConnection(jdbcUrl, props)) {
+ try (Statement statement = connection.createStatement()) {
+ String sql = "CREATE USER " + TEST_ORACLE_DATABASE_NAME;
+ if (StringUtils.isNotEmpty(config.getPassword())) {
+ sql += " IDENTIFIED BY \"" + config.getPassword() + "\"";
+ }
+ statement.executeUpdate(sql);
+ sql = "GRANT ALL PRIVILEGES TO " + TEST_ORACLE_DATABASE_NAME;
+ statement.executeUpdate(sql);
+ }
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+ DATASOURCE_MAP.put(ORACLE_DS_KEY, buildDataSource(config));
+ }
+
+ private static OracleConnectionConfig buildOracleConnectionConfig() {
+ OracleConnectionConfig config = new OracleConnectionConfig();
+ config.setHost(get(ORACLE_HOST_KEY));
+ config.setPort(get(ORACLE_PORT_KEY));
+ config.setSid(get(ORACLE_SID_KEY));
+ config.setUsername(get(ORACLE_USERNAME_KEY));
+ config.setPassword(get(ORACLE_PASSWORD_KEY));
+ config.setRole(get(ORACLE_ROLE_KEY));
+ return config;
+ }
+
private static void clear(ConnectionParseResult parseResult, String dataSourceKey) {
String jdbcUrl = buildOBJdbcUrl(parseResult);
String username = buildUser(parseResult);
@@ -222,6 +281,24 @@ private static void clear(ConnectionParseResult parseResult, String dataSourceKe
}
}
+ private static void clear(OracleConnectionConfig config) {
+ String jdbcUrl = buildOracleJdbcUrl(config);
+ Properties props = new Properties();
+ props.setProperty("user", config.getUsername());
+ props.setProperty("password", config.getPassword());
+ if (Objects.nonNull(config.getRole())) {
+ props.put("internal_logon", config.getRole());
+ }
+ try (Connection connection = DriverManager.getConnection(jdbcUrl, props)) {
+ try (Statement statement = connection.createStatement()) {
+ String sql = String.format("DROP USER %s CASCADE", TEST_ORACLE_DATABASE_NAME);
+ statement.executeUpdate(sql);
+ }
+ } catch (Exception e) {
+ log.warn("Failed to drop oracle user, errMsg={}", e.getMessage());
+ }
+ }
+
private static String buildOBJdbcUrl(ConnectionParseResult parseResult) {
StringBuilder builder =
new StringBuilder(
@@ -243,6 +320,18 @@ private static String buildMySQLJdbcUrl(ConnectionParseResult parseResult) {
return builder.toString();
}
+ private static String buildOracleJdbcUrl(OracleConnectionConfig config) {
+ StringBuilder builder = new StringBuilder();
+ if (Objects.nonNull(config.getSid())) {
+ builder.append(
+ String.format("jdbc:oracle:thin:@%s:%s:%s", config.getHost(), config.getPort(), config.getSid()));
+ } else {
+ builder.append(String.format("jdbc:oracle:thin:@//%s:%s/%s", config.getHost(), config.getPort(),
+ config.getServiceName()));
+ }
+ return builder.toString();
+ }
+
private static String buildUser(ConnectionParseResult parseResult) {
StringBuilder builder = new StringBuilder(parseResult.getUsername());
if (StringUtils.isNotBlank(parseResult.getTenant())) {
@@ -267,10 +356,24 @@ private static SingleConnectionDataSource buildDataSource(ConnectionParseResult
return dataSource;
}
+ private static SingleConnectionDataSource buildDataSource(OracleConnectionConfig config) {
+ SingleConnectionDataSource dataSource = new SingleConnectionDataSource();
+ dataSource.setUrl(buildOracleJdbcUrl(config));
+ Properties props = new Properties();
+ props.setProperty("user", config.getUsername());
+ props.setProperty("password", config.getPassword());
+ if (Objects.nonNull(config.getRole())) {
+ props.put("internal_logon", config.getRole());
+ }
+ dataSource.setConnectionProperties(props);
+ return dataSource;
+ }
+
private enum ConnectType {
OB_MYSQL,
OB_ORACLE,
MYSQL,
+ ORACLE,
}
}
diff --git a/libs/db-browser/src/test/java/com/oceanbase/tools/dbbrowser/env/OracleConnectionConfig.java b/libs/db-browser/src/test/java/com/oceanbase/tools/dbbrowser/env/OracleConnectionConfig.java
new file mode 100644
index 0000000000..b48bdf152b
--- /dev/null
+++ b/libs/db-browser/src/test/java/com/oceanbase/tools/dbbrowser/env/OracleConnectionConfig.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2023 OceanBase.
+ *
+ * Licensed 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 com.oceanbase.tools.dbbrowser.env;
+
+import lombok.Data;
+
+/**
+ * @author jingtian
+ * @date 2023/10/9
+ */
+@Data
+public class OracleConnectionConfig {
+ private String host;
+ private String port;
+ private String username;
+ private String password;
+ private String serviceName;
+ private String sid;
+ private String role;
+}
diff --git a/libs/db-browser/src/test/java/com/oceanbase/tools/dbbrowser/schema/DBSchemaAccessors.java b/libs/db-browser/src/test/java/com/oceanbase/tools/dbbrowser/schema/DBSchemaAccessors.java
index a6fd8f0e27..4dd45fa75f 100644
--- a/libs/db-browser/src/test/java/com/oceanbase/tools/dbbrowser/schema/DBSchemaAccessors.java
+++ b/libs/db-browser/src/test/java/com/oceanbase/tools/dbbrowser/schema/DBSchemaAccessors.java
@@ -30,6 +30,7 @@
import com.oceanbase.tools.dbbrowser.schema.oracle.OBOracleLessThan2270SchemaAccessor;
import com.oceanbase.tools.dbbrowser.schema.oracle.OBOracleLessThan400SchemaAccessor;
import com.oceanbase.tools.dbbrowser.schema.oracle.OBOracleSchemaAccessor;
+import com.oceanbase.tools.dbbrowser.schema.oracle.OracleSchemaAccessor;
import com.oceanbase.tools.dbbrowser.util.ALLDataDictTableNames;
import lombok.extern.slf4j.Slf4j;
@@ -103,6 +104,10 @@ public DBSchemaAccessor createOBOracle() {
}
}
+ public DBSchemaAccessor createOracle() {
+ return new OracleSchemaAccessor(this.jdbcTemplate, new ALLDataDictTableNames());
+ }
+
public DBSchemaAccessor createMysql() {
return new MySQLNoGreaterThan5740SchemaAccessor(this.jdbcTemplate);
}
diff --git a/libs/db-browser/src/test/java/com/oceanbase/tools/dbbrowser/schema/OBOracleSchemaAccessorTest.java b/libs/db-browser/src/test/java/com/oceanbase/tools/dbbrowser/schema/OBOracleSchemaAccessorTest.java
index b6ebd7f745..f61d00d9a6 100644
--- a/libs/db-browser/src/test/java/com/oceanbase/tools/dbbrowser/schema/OBOracleSchemaAccessorTest.java
+++ b/libs/db-browser/src/test/java/com/oceanbase/tools/dbbrowser/schema/OBOracleSchemaAccessorTest.java
@@ -65,7 +65,7 @@
* @author jingtian
*/
public class OBOracleSchemaAccessorTest extends BaseTestEnv {
- private static final String BASE_PATH = "src/test/resources/table/oracle/";
+ private static final String BASE_PATH = "src/test/resources/table/oboracle/";
private static String ddl;
private static String dropTables;
private static String testFunctionDDL;
@@ -307,6 +307,12 @@ public void showViews_Success() {
Assert.assertTrue(views != null && views.size() == 2);
}
+ @Test
+ public void listAllViews_Success() {
+ List views = accessor.listAllViews("ALL");
+ Assert.assertTrue(views.size() > 0);
+ }
+
@Test
public void getView_Success() {
DBView view = accessor.getView(getOBOracleSchema(), "VIEW_TEST1");
diff --git a/libs/db-browser/src/test/java/com/oceanbase/tools/dbbrowser/schema/OracleSchemaAccessorTest.java b/libs/db-browser/src/test/java/com/oceanbase/tools/dbbrowser/schema/OracleSchemaAccessorTest.java
new file mode 100644
index 0000000000..3de905bbe7
--- /dev/null
+++ b/libs/db-browser/src/test/java/com/oceanbase/tools/dbbrowser/schema/OracleSchemaAccessorTest.java
@@ -0,0 +1,506 @@
+/*
+ * Copyright (c) 2023 OceanBase.
+ *
+ * Licensed 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 com.oceanbase.tools.dbbrowser.schema;
+
+import static com.oceanbase.tools.dbbrowser.editor.DBObjectUtilsTest.loadAsString;
+
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.springframework.jdbc.core.JdbcTemplate;
+
+import com.oceanbase.tools.dbbrowser.env.BaseTestEnv;
+import com.oceanbase.tools.dbbrowser.model.DBConstraintType;
+import com.oceanbase.tools.dbbrowser.model.DBDatabase;
+import com.oceanbase.tools.dbbrowser.model.DBFunction;
+import com.oceanbase.tools.dbbrowser.model.DBIndexType;
+import com.oceanbase.tools.dbbrowser.model.DBObjectIdentity;
+import com.oceanbase.tools.dbbrowser.model.DBObjectType;
+import com.oceanbase.tools.dbbrowser.model.DBPLObjectIdentity;
+import com.oceanbase.tools.dbbrowser.model.DBPackage;
+import com.oceanbase.tools.dbbrowser.model.DBProcedure;
+import com.oceanbase.tools.dbbrowser.model.DBSequence;
+import com.oceanbase.tools.dbbrowser.model.DBSynonym;
+import com.oceanbase.tools.dbbrowser.model.DBSynonymType;
+import com.oceanbase.tools.dbbrowser.model.DBTable.DBTableOptions;
+import com.oceanbase.tools.dbbrowser.model.DBTableColumn;
+import com.oceanbase.tools.dbbrowser.model.DBTableConstraint;
+import com.oceanbase.tools.dbbrowser.model.DBTableIndex;
+import com.oceanbase.tools.dbbrowser.model.DBTablePartition;
+import com.oceanbase.tools.dbbrowser.model.DBTablePartitionType;
+import com.oceanbase.tools.dbbrowser.model.DBTrigger;
+import com.oceanbase.tools.dbbrowser.model.DBType;
+import com.oceanbase.tools.dbbrowser.model.DBTypeCode;
+import com.oceanbase.tools.dbbrowser.model.DBVariable;
+import com.oceanbase.tools.dbbrowser.model.DBView;
+import com.oceanbase.tools.dbbrowser.util.StringUtils;
+
+/**
+ * @author jingtian
+ * @date 2023/10/9
+ * @since ODC_release_4.2.4
+ */
+public class OracleSchemaAccessorTest extends BaseTestEnv {
+ private static final String BASE_PATH = "src/test/resources/table/oracle/";
+ private static String testTableDDL;
+ private static String drop;
+ private static String testFunctionDDL;
+ private static String testPackageDDL;
+ private static String testProcedureDDL;
+ private static String testTypeDDL;
+ private static String testSequenceDDL;
+ private static String testSynonymDDL;
+ private static String testTriggerDDL;
+ private static JdbcTemplate jdbcTemplate = new JdbcTemplate(getOracleDataSource());
+ private static DBSchemaAccessor accessor = new DBSchemaAccessors(getOracleDataSource()).createOracle();
+
+ @BeforeClass
+ public static void before() throws Exception {
+ jdbcTemplate.execute("alter session set current_schema=\"" + getOracleSchema() + "\"");
+ drop = loadAsString(BASE_PATH + "drop.sql");
+ batchExcuteSql(drop);
+ testFunctionDDL = loadAsString(BASE_PATH + "testFunctionDDL.sql");
+ batchExcuteSql(testFunctionDDL);
+ testProcedureDDL = loadAsString(BASE_PATH + "testProcedureDDL.sql");
+ batchExcuteSql(testProcedureDDL);
+ testPackageDDL = loadAsString(BASE_PATH + "testPackageDDL.sql");
+ batchExcuteSql(testPackageDDL);
+ testTriggerDDL = loadAsString(BASE_PATH + "testTriggerDDL.sql");
+ batchExcuteSql(testTriggerDDL);
+ testTypeDDL = loadAsString(BASE_PATH + "testTypeDDL.sql");
+ batchExcuteSql(testTypeDDL);
+ testSequenceDDL = loadAsString(BASE_PATH + "testSequenceDDL.sql");
+ batchExcuteSql(testSequenceDDL);
+ testSynonymDDL = loadAsString(BASE_PATH + "testSynonymDDL.sql");
+ batchExcuteSql(testSynonymDDL);
+ testTableDDL = loadAsString(BASE_PATH + "testTableColumnDDL.sql", BASE_PATH + "testTableConstraintDDL.sql",
+ BASE_PATH + "testTableIndexDDL.sql", BASE_PATH + "testViewDDL.sql",
+ BASE_PATH + "testTablePartitionDDL.sql");
+ batchExcuteSql(testTableDDL);
+ }
+
+ @AfterClass
+ public static void after() throws Exception {
+ batchExcuteSql(drop);
+ }
+
+ private static void batchExcuteSql(String str) {
+ for (String ddl : str.split("/")) {
+ try {
+ jdbcTemplate.execute(ddl);
+ } catch (Exception e) {
+ System.out.println(e);
+ }
+ }
+ }
+
+ @Test
+ public void listTableColumns_TestGetAllColumnInSchema_Success() {
+ Map> table2Columns = accessor.listTableColumns(getOracleSchema());
+ Assert.assertTrue(table2Columns.size() > 0);
+ }
+
+ @Test
+ public void listTableColumns_Success() {
+ List columns =
+ accessor.listTableColumns(getOracleSchema(), "TEST_COL_DATA_TYPE");
+ Assert.assertEquals(13, columns.size());
+ }
+
+ @Test
+ public void listTableConstraint_TestPrimaryKey_Success() {
+ List constraintListList =
+ accessor.listTableConstraints(getOracleSchema(), "TEST_FK_PARENT");
+ Assert.assertEquals(1, constraintListList.size());
+ Assert.assertEquals(DBConstraintType.PRIMARY_KEY, constraintListList.get(0).getType());
+ Assert.assertEquals(2, constraintListList.get(0).getColumnNames().size());
+ Assert.assertEquals("TEST_FK_PARENT", constraintListList.get(0).getTableName());
+ Assert.assertEquals(getOracleSchema(), constraintListList.get(0).getSchemaName());
+ }
+
+ @Test
+ public void listTableConstraint_TestForeignKey_Success() {
+ List constraintListList =
+ accessor.listTableConstraints(getOracleSchema(), "TEST_FK_CHILD");
+ Assert.assertEquals(1, constraintListList.size());
+ Assert.assertEquals(DBConstraintType.FOREIGN_KEY, constraintListList.get(0).getType());
+ Assert.assertEquals("TEST_FK_PARENT", constraintListList.get(0).getReferenceTableName());
+ Assert.assertEquals("TEST_FK_CHILD", constraintListList.get(0).getTableName());
+ Assert.assertEquals(getOracleSchema(), constraintListList.get(0).getSchemaName());
+ }
+
+ @Test
+ public void listTableIndexes_TestPrimaryKeyIndex_Success() {
+ List indexes =
+ accessor.listTableIndexes(getOracleSchema(), "TEST_PK_INDEX");
+ Assert.assertEquals(1, indexes.size());
+ Assert.assertEquals(DBIndexType.UNIQUE, indexes.get(0).getType());
+ }
+
+ @Test
+ public void listTableIndex_TestIndexType_Success() {
+ List indexList = accessor.listTableIndexes(getOracleSchema(), "TEST_INDEX_TYPE");
+ Assert.assertEquals(2, indexList.size());
+ Assert.assertEquals(DBIndexType.UNIQUE, indexList.get(1).getType());
+ Assert.assertEquals(DBIndexType.NORMAL, indexList.get(0).getType());
+ }
+
+ @Test
+ public void listTableIndex_TestIndexRange_Success() {
+ List indexList = accessor.listTableIndexes(getOracleSchema(), "TEST_INDEX_RANGE");
+ Assert.assertEquals(3, indexList.size());
+ indexList.stream().forEach(idx -> {
+ if ("test_global_idx".equalsIgnoreCase(idx.getName())) {
+ Assert.assertTrue(idx.getGlobal());
+ } else {
+ Assert.assertFalse(idx.getGlobal());
+ }
+ });
+ }
+
+ @Test
+ public void getPartition_Hash_Success() {
+ DBTablePartition partition =
+ accessor.getPartition(getOracleSchema(), "PART_HASH_TEST");
+ Assert.assertEquals(5L, partition.getPartitionOption().getPartitionsNum().longValue());
+ Assert.assertEquals(DBTablePartitionType.HASH, partition.getPartitionOption().getType());
+ }
+
+ @Test
+ public void getView_Success() {
+ DBView view = accessor.getView(getOracleSchema(), "VIEW_TEST");
+ Assert.assertTrue(view != null && view.getColumns().size() == 2);
+ }
+
+ @Test
+ public void getDatabase_Success() {
+ DBDatabase database = accessor.getDatabase(getOracleSchema());
+ Assert.assertNotNull(database);
+ Assert.assertNotNull(database.getId());
+ Assert.assertNotNull(database.getCharset());
+ Assert.assertNotNull(database.getCollation());
+ Assert.assertEquals(getOracleSchema(), database.getName());
+ }
+
+ @Test
+ public void listDatabases_Success() {
+ List databases = accessor.listDatabases();
+ Assert.assertTrue(databases.size() > 0);
+ }
+
+ @Test
+ public void switchDatabase_Success() {
+ accessor.switchDatabase("SYS");
+ Assert.assertEquals("SYS", jdbcTemplate.queryForObject(
+ "SELECT SYS_CONTEXT('USERENV', 'CURRENT_SCHEMA') AS CURRENT_SCHEMA FROM DUAL", String.class));
+ accessor.switchDatabase(getOracleSchema());
+ Assert.assertEquals(getOracleSchema(), jdbcTemplate.queryForObject(
+ "SELECT SYS_CONTEXT('USERENV', 'CURRENT_SCHEMA') AS CURRENT_SCHEMA FROM DUAL", String.class));
+ }
+
+ @Test
+ public void listUsers_Success() {
+ List dbUsers = accessor.listUsers();
+ Assert.assertFalse(dbUsers.isEmpty());
+ Assert.assertSame(DBObjectType.USER, dbUsers.get(0).getType());
+ Assert.assertNotNull(dbUsers.get(0).getName());
+ }
+
+ @Test
+ public void showTablesLike_Success() {
+ List tables = accessor.showTablesLike(getOracleSchema(), "");
+ Assert.assertTrue(tables.size() > 0);
+ }
+
+ @Test
+ public void listTables_Success() {
+ List tables =
+ accessor.listTables(getOracleSchema(), null);
+ Assert.assertTrue(tables.size() > 0);
+ }
+
+ @Test
+ public void listViews_Success() {
+ List views = accessor.listViews("SYS");
+ Assert.assertTrue(views.size() > 0);
+ }
+
+ @Test
+ public void listAllViews_Success() {
+ List views = accessor.listAllViews("ALL");
+ Assert.assertTrue(views.size() > 0);
+ }
+
+ @Test
+ public void listAllUserViews_Success() {
+ List views = accessor.listAllUserViews();
+ Assert.assertTrue(views.size() > 0);
+ }
+
+ @Test
+ public void listSystemViews_databaseNotSYS_empty() {
+ List viewNames = accessor.showSystemViews("notsys");
+ Assert.assertTrue(viewNames.isEmpty());
+ }
+
+ @Test
+ public void listSystemViews_databaseSYS_notEmpty() {
+ List viewNames = accessor.showSystemViews("SYS");
+ Assert.assertTrue(!viewNames.isEmpty());
+ }
+
+ @Test
+ public void showVariables_Success() {
+ List variables = accessor.showVariables();
+ List sessionVariables = accessor.showSessionVariables();
+ List globalVariables = accessor.showGlobalVariables();
+ Assert.assertTrue(variables != null && variables.size() > 0);
+ Assert.assertTrue(sessionVariables != null && sessionVariables.size() > 0);
+ Assert.assertTrue(globalVariables != null && globalVariables.size() > 0);
+ }
+
+ @Test
+ public void showCharset_Success() {
+ List charset = accessor.showCharset();
+ Assert.assertTrue(charset != null && charset.size() > 0);
+ }
+
+ @Test
+ public void showCollation_Success() {
+ List collation = accessor.showCollation();
+ Assert.assertTrue(collation != null && collation.size() > 0);
+ }
+
+ @Test
+ public void listFunctions_Success() {
+ List functions = accessor.listFunctions(getOracleSchema());
+ Assert.assertTrue(functions != null && functions.size() == 4);
+ }
+
+ @Test
+ public void listFunctions_invalidFunctionList() {
+ List functions = accessor.listFunctions(getOracleSchema());
+ functions = functions.stream().filter(function -> {
+ if (StringUtils.equals(function.getName(), "FUNC_INVALIDE_ACCESSOR")) {
+ return true;
+ }
+ return false;
+ }).collect(Collectors.toList());
+ boolean flag = false;
+ if (StringUtils.containsIgnoreCase(functions.get(0).getErrorMessage(), "ORA")) {
+ flag = true;
+ }
+ Assert.assertTrue(flag);
+ }
+
+ @Test
+ public void getFunction_Success() {
+ DBFunction function = accessor.getFunction(getOracleSchema(), "FUNC_DETAIL_ACCESSOR");
+ Assert.assertTrue(function != null
+ && function.getParams().size() == 3
+ && function.getVariables().size() == 1
+ && function.getTypes() != null
+ && function.getReturnType() != null);
+ function = accessor.getFunction(getOracleSchema(), "FUNC_NO_PARAM_ACCESSOR");
+ Assert.assertTrue(function != null
+ && function.getParams().size() == 0
+ && function.getVariables().size() == 1
+ && function.getReturnType() != null);
+ }
+
+ @Test
+ public void listProcedures_Success() {
+ List procedures = accessor.listProcedures(getOracleSchema());
+ Assert.assertTrue(procedures.size() > 0);
+ }
+
+ @Test
+ public void listProcedures_invalidProcedureList() {
+ List procedures = accessor.listProcedures(getOracleSchema());
+ procedures = procedures.stream().filter(procedure -> {
+ if (StringUtils.equals(procedure.getName(), "PROC_INVALID_ACCESSOR")) {
+ return true;
+ }
+ return false;
+ }).collect(Collectors.toList());
+ boolean flag = false;
+ if (StringUtils.containsIgnoreCase(procedures.get(0).getErrorMessage(), "ORA")) {
+ flag = true;
+ }
+ Assert.assertTrue(flag);
+ }
+
+ @Test
+ public void getProcedure_Success() {
+ DBProcedure procedure = accessor.getProcedure(getOracleSchema(), "PROC_PARAMS_ACCESSOR");
+ Assert.assertTrue(procedure != null
+ && procedure.getParams().size() == 4
+ && procedure.getVariables().size() == 1);
+ procedure = accessor.getProcedure(getOracleSchema(), "PROC_INVALID_ACCESSOR");
+ Assert.assertTrue(procedure != null
+ && procedure.getParams().size() == 0
+ && procedure.getVariables().size() == 0);
+ }
+
+ @Test
+ public void listPackages_Success() {
+ List packages = accessor.listPackages(getOracleSchema());
+ Assert.assertTrue(packages != null && !packages.isEmpty());
+ }
+
+ @Test
+ public void listPackages_invalidPackageList() {
+ List packages = accessor.listPackages(getOracleSchema());
+ boolean flag = false;
+ for (DBPLObjectIdentity dbPackage : packages) {
+ if (StringUtils.containsIgnoreCase(dbPackage.getErrorMessage(), "ORA")) {
+ flag = true;
+ }
+ }
+ Assert.assertTrue(flag);
+ }
+
+ @Test
+ public void getPackage_Success() {
+ DBPackage dbPackage = accessor.getPackage(getOracleSchema(), "PAC_ACCESSOR");
+ Assert.assertTrue(dbPackage != null
+ && dbPackage.getPackageHead().getVariables().size() == 1
+ && dbPackage.getPackageHead().getTypes().size() == 1
+ && dbPackage.getPackageHead().getFunctions().size() == 2
+ && dbPackage.getPackageHead().getProcedures().size() == 1);
+
+ Assert.assertTrue(dbPackage.getPackageBody().getVariables().size() == 3
+ && dbPackage.getPackageBody().getFunctions().size() == 2
+ && dbPackage.getPackageBody().getProcedures().size() == 1);
+ }
+
+ @Test
+ public void lisTriggers_Success() {
+ List triggers = accessor.listTriggers(getOracleSchema());
+ Assert.assertNotEquals(null, triggers);
+ boolean flag = false;
+ for (DBPLObjectIdentity trigger : triggers) {
+ if ("TRIGGER_ACCESSOR".equals(trigger.getName())) {
+ flag = true;
+ }
+ }
+ Assert.assertTrue(flag);
+ }
+
+ @Test
+ public void listTriggers_test_invalid_trigger() {
+ List triggers = accessor.listTriggers(getOracleSchema());
+ boolean flag = false;
+ for (DBPLObjectIdentity trigger : triggers) {
+ if (StringUtils.containsIgnoreCase(trigger.getErrorMessage(), "ORA")) {
+ flag = true;
+ }
+ }
+ Assert.assertTrue(flag);
+ }
+
+ @Test
+ public void getTrigger_Success() {
+ DBTrigger trigger = accessor.getTrigger(getOracleSchema(), "TRIGGER_ACCESSOR");
+ Assert.assertNotNull(trigger);
+ Assert.assertEquals("TRIGGER_ACCESSOR", trigger.getTriggerName());
+ }
+
+ @Test
+ public void listTypes_Success() {
+ List types = accessor.listTypes(getOracleSchema());
+ Assert.assertNotNull(types);
+ Assert.assertEquals(2, types.size());
+ }
+
+ @Test
+ public void getType_Success() {
+ DBType type = accessor.getType(getOracleSchema(), "TYPE_ACCESSOR2");
+ Assert.assertNotNull(type);
+ Assert.assertEquals("TYPE_ACCESSOR2", type.getTypeName());
+ Assert.assertEquals(DBTypeCode.OBJECT.name(), type.getType());
+ Assert.assertEquals(4, type.getTypeDetail().getVariables().size());
+ Assert.assertEquals(1, type.getTypeDetail().getFunctions().size());
+ }
+
+ @Test
+ public void listSequences_Success() {
+ List sequences = accessor.listSequences(getOracleSchema());
+ Assert.assertTrue(sequences != null && !sequences.isEmpty());
+ }
+
+ @Test
+ public void getSequence_Success() {
+ DBSequence sequence = accessor.getSequence(getOracleSchema(), "SEQ_TEST");
+ Assert.assertTrue(sequence != null && sequence.getName().equalsIgnoreCase("SEQ_TEST"));
+ Assert.assertNotNull(sequence.getDdl());
+ }
+
+ @Test
+ public void listSynonyms_Success() {
+ List synonyms = accessor.listSynonyms(getOracleSchema(), DBSynonymType.COMMON);
+ Assert.assertNotEquals(0, synonyms.size());
+ boolean flag = false;
+ for (DBObjectIdentity synonym : synonyms) {
+ if ("COMMON_SYNONYM_ACCESSOR".equals(synonym.getName())) {
+ flag = true;
+ }
+ }
+ Assert.assertTrue(flag);
+
+ synonyms = accessor.listSynonyms(getOracleSchema(), DBSynonymType.PUBLIC);
+ Assert.assertNotEquals(0, synonyms.size());
+ flag = false;
+ for (DBObjectIdentity synonym : synonyms) {
+ if ("PUBLIC_SYNONYM_ACCESSOR".equals(synonym.getName())) {
+ flag = true;
+ }
+ }
+ Assert.assertTrue(flag);
+ }
+
+ @Test
+ public void getSynonym_testPublicSynonymInfoForOracle() {
+ DBSynonym synonym = accessor.getSynonym(getOracleSchema(), "PUBLIC_SYNONYM_ACCESSOR", DBSynonymType.PUBLIC);
+ Assert.assertNotNull(synonym);
+ Assert.assertEquals(DBSynonymType.PUBLIC, synonym.getSynonymType());
+ Assert.assertEquals("PUBLIC_SYNONYM_ACCESSOR", synonym.getSynonymName());
+ }
+
+ @Test
+ public void getSynonym_testCommonSynonymInfoForOracle() {
+ DBSynonym synonym = accessor.getSynonym(getOracleSchema(), "COMMON_SYNONYM_ACCESSOR", DBSynonymType.COMMON);
+ Assert.assertNotNull(synonym);
+ Assert.assertEquals(DBSynonymType.COMMON, synonym.getSynonymType());
+ Assert.assertEquals("COMMON_SYNONYM_ACCESSOR", synonym.getSynonymName());
+ }
+
+ @Test
+ public void getTableOptions_Success() {
+ DBTableOptions options =
+ accessor.getTableOptions(getOracleSchema(), "PART_HASH_TEST");
+ Assert.assertEquals("this is a comment", options.getComment());
+ Assert.assertNotNull(options.getCharsetName());
+ Assert.assertNotNull(options.getCollationName());
+ Assert.assertNotNull(options.getUpdateTime());
+ }
+}
diff --git a/libs/db-browser/src/test/java/com/oceanbase/tools/dbbrowser/stats/OracleStatsAccessorTest.java b/libs/db-browser/src/test/java/com/oceanbase/tools/dbbrowser/stats/OracleStatsAccessorTest.java
new file mode 100644
index 0000000000..571e734475
--- /dev/null
+++ b/libs/db-browser/src/test/java/com/oceanbase/tools/dbbrowser/stats/OracleStatsAccessorTest.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2023 OceanBase.
+ *
+ * Licensed 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 com.oceanbase.tools.dbbrowser.stats;
+
+import java.util.List;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.springframework.jdbc.core.JdbcTemplate;
+
+import com.oceanbase.tools.dbbrowser.env.BaseTestEnv;
+import com.oceanbase.tools.dbbrowser.model.DBSession;
+import com.oceanbase.tools.dbbrowser.model.DBTableStats;
+import com.oceanbase.tools.dbbrowser.stats.oracle.OracleStatsAccessor;
+
+/**
+ * @author jingtian
+ * @date 2023/11/24
+ * @since ODC_release_4.2.4
+ */
+public class OracleStatsAccessorTest extends BaseTestEnv {
+ private final DBStatsAccessor accessor = new OracleStatsAccessor(new JdbcTemplate(getOracleDataSource()));
+ private static JdbcTemplate jdbcTemplate = new JdbcTemplate(getOracleDataSource());
+
+ @Test
+ public void listAllSessions() {
+ List session = accessor.listAllSessions();
+ Assert.assertTrue(session.size() > 0);
+ }
+
+ @Test
+ public void currentSession() {
+ DBSession session = accessor.currentSession();
+ Assert.assertNotNull(session);
+ Assert.assertNotNull(session.getId());
+ }
+
+ @Test
+ public void getTableStats() {
+ jdbcTemplate.execute("alter session set current_schema = \"" + getOracleSchema() + "\"");
+ jdbcTemplate.execute("create table TABLE_STATS_TEST (ID NUMBER, NAME VARCHAR(20))");
+ jdbcTemplate.execute("insert into TABLE_STATS_TEST values (1, 'test1')");
+ DBTableStats tableStats = accessor.getTableStats(getOracleSchema(), "TABLE_STATS_TEST");
+ Assert.assertNotNull(tableStats);
+ jdbcTemplate.execute("drop table TABLE_STATS_TEST");
+ }
+}
diff --git a/libs/db-browser/src/test/resources/table/oboracle/drop.sql b/libs/db-browser/src/test/resources/table/oboracle/drop.sql
new file mode 100644
index 0000000000..cb9d3c9c68
--- /dev/null
+++ b/libs/db-browser/src/test/resources/table/oboracle/drop.sql
@@ -0,0 +1,138 @@
+CREATE OR REPLACE PROCEDURE DROPIFEXISTS_TABLE(new_table IN varchar2)
+ IS
+ v_count number(10);
+BEGIN
+ SELECT count(*)
+ INTO v_count
+ FROM user_tables
+ WHERE table_name = upper(new_table);
+ IF v_count > 0
+ THEN
+ EXECUTE IMMEDIATE 'drop table ' || new_table || ' cascade constraints purge';
+ END IF;
+END;
+/
+
+CREATE OR REPLACE PROCEDURE DROPIFEXISTS_VIEW(new_view IN varchar2)
+ IS
+ v_count number(10);
+BEGIN
+ SELECT count(*)
+ INTO v_count
+ FROM USER_VIEWS
+ WHERE VIEW_NAME = upper(new_view);
+ IF v_count > 0
+ THEN
+ EXECUTE IMMEDIATE 'drop view ' || new_view ;
+ END IF;
+END;
+/
+
+CREATE OR REPLACE PROCEDURE DROPIFEXISTS_FUNC(new_func IN varchar2)
+ IS
+ v_count number(10);
+BEGIN
+ SELECT count(*)
+ INTO v_count
+ FROM USER_OBJECTS
+ WHERE object_name = upper(new_func) and object_type = 'FUNCTION' ;
+ IF v_count > 0
+ THEN
+ EXECUTE IMMEDIATE 'drop function ' || new_func ;
+ END IF;
+END;
+/
+
+CREATE OR REPLACE PROCEDURE DROPIFEXISTS_SEQUENCE(new_sequence IN varchar2)
+ IS
+ v_count number(10);
+BEGIN
+ SELECT count(*)
+ INTO v_count
+ FROM USER_SEQUENCES
+ WHERE sequence_name = upper(new_sequence);
+ IF v_count > 0
+ THEN
+ EXECUTE IMMEDIATE 'drop sequence ' || new_sequence ;
+ END IF;
+END;
+/
+
+CREATE OR REPLACE PROCEDURE DROPIFEXISTS_PACKAGE(new_package IN varchar2)
+ IS
+ v_count number(10);
+BEGIN
+ SELECT count(*)
+ INTO v_count
+ FROM USER_OBJECTS
+ WHERE object_name = upper(new_package) AND (object_type = 'PACKAGE' or object_type = 'PACKAGE BODY');
+ IF v_count > 0
+ THEN
+ EXECUTE IMMEDIATE 'drop package ' || new_package ;
+ END IF;
+END;
+/
+
+CREATE OR REPLACE PROCEDURE DROPIFEXISTS_TRIGGER(new_trigger IN varchar2)
+ IS
+ v_count number(10);
+BEGIN
+ SELECT count(*)
+ INTO v_count
+ FROM USER_TRIGGERS
+ WHERE TRIGGER_NAME = upper(new_trigger);
+ IF v_count > 0
+ THEN
+ EXECUTE IMMEDIATE 'drop trigger ' || new_trigger ;
+ END IF;
+END;
+/
+
+CREATE OR REPLACE PROCEDURE DROPIFEXISTS_SYNONYM(new_synonym IN varchar2)
+ IS
+ v_count number(10);
+BEGIN
+ SELECT count(*)
+ INTO v_count
+ FROM USER_SYNONYMS
+ WHERE SYNONYM_NAME = upper(new_synonym);
+ IF v_count > 0
+ THEN
+ EXECUTE IMMEDIATE 'drop synonym ' || new_synonym ;
+ END IF;
+END;
+/
+
+
+call DROPIFEXISTS_TABLE('TEST_DATA_TYPE');
+call DROPIFEXISTS_TABLE('TEST_OTHER_THAN_DATA_TYPE');
+call DROPIFEXISTS_TABLE('TEST_INDEX_TYPE');
+call DROPIFEXISTS_TABLE('TEST_INDEX_RANGE');
+call DROPIFEXISTS_TABLE('TEST_FK_PARENT');
+call DROPIFEXISTS_TABLE('TEST_FK_CHILD');
+call DROPIFEXISTS_TABLE('part_hash');
+call DROPIFEXISTS_TABLE('TEST_PK_INDEX');
+call DROPIFEXISTS_TABLE('TEST_DEFAULT_NULL');
+
+call DROPIFEXISTS_VIEW('VIEW_TEST1');
+call DROPIFEXISTS_VIEW('VIEW_TEST2');
+call DROPIFEXISTS_TABLE('TEST_VIEW_TABLE');
+
+call DROPIFEXISTS_FUNC('FUNC_TEST');
+call DROPIFEXISTS_FUNC('INVALIDE_FUNC');
+call DROPIFEXISTS_FUNC('FUNC_DETAIL_TEST');
+
+call DROPIFEXISTS_PACKAGE('T_PACKAGE');
+call DROPIFEXISTS_PACKAGE('INVALID_PKG');
+
+call DROPIFEXISTS_TRIGGER('TRIGGER_TEST');
+call DROPIFEXISTS_TRIGGER('INVALID_TRIGGER');
+call DROPIFEXISTS_TABLE('TRIGGER_TABLE');
+
+call DROPIFEXISTS_SEQUENCE('SEQ_TEST');
+
+call DROPIFEXISTS_TABLE('SYNONYM_TEST_TABLE');
+call DROPIFEXISTS_SYNONYM('COMMON_SYNONYM_TEST');
+call DROPIFEXISTS_SYNONYM('PUBLIC_SYNONYM_TEST');
+
+
diff --git a/libs/db-browser/src/test/resources/table/oboracle/testFunctionDDL.sql b/libs/db-browser/src/test/resources/table/oboracle/testFunctionDDL.sql
new file mode 100644
index 0000000000..2df02afaa6
--- /dev/null
+++ b/libs/db-browser/src/test/resources/table/oboracle/testFunctionDDL.sql
@@ -0,0 +1,29 @@
+CREATE OR REPLACE FUNCTION FUNC_TEST(
+p1 in NUMBER,
+p2 in NUMBER)
+return NUMBER as
+v1 int;
+begin
+return p1+p2;
+end;
+/
+
+CREATE OR REPLACE FUNCTION INVALIDE_FUNC(
+p1 in NUMBER,
+p2 in NUMBER)
+return NUMBER as
+v1 int;
+begin
+select 1+1 into v_result from dual11;
+return v_result;
+end;
+/
+
+CREATE OR REPLACE FUNCTION FUNC_DETAIL_TEST(
+v_input number)
+RETURN NUMBER IS
+v1 number; v2 varchar2(100);
+type cur_emp is ref cursor;
+BEGIN
+RETURN v1;
+END;
\ No newline at end of file
diff --git a/libs/db-browser/src/test/resources/table/oboracle/testPackageDDL.sql b/libs/db-browser/src/test/resources/table/oboracle/testPackageDDL.sql
new file mode 100644
index 0000000000..9f8ddb5e2a
--- /dev/null
+++ b/libs/db-browser/src/test/resources/table/oboracle/testPackageDDL.sql
@@ -0,0 +1,77 @@
+create or replace package t_package is
+ v1 number;
+ type cur_emp is ref cursor;
+ procedure append_proc(p1 in out varchar2, p2 number);
+ function append_fun(p2 out varchar2) return varchar2;
+end;
+/
+
+create or replace package body t_package is
+ v_t varchar2(30);
+ function private_fun(p1 IN OUT NOCOPY varchar2) return varchar2 is
+ begin
+ return v_t;
+ end;
+ procedure append_proc(p2 number) is
+ begin
+ return v_t;
+ end;
+end;
+/
+
+create or replace package INVALID_PKG is
+ v1 number;
+ type cur_emp is ref cursor;
+ procedure append_proc(p1 in out varchar2, p2 number);
+ function append_fun(p2 out varchar2) return varchar2;
+end;
+/
+
+create or replace package body INVALID_PKG is
+ v_t varchar2(30);
+ function private_fun(p1 IN OUT NOCOPY varchar2) return varchar2 is
+ begin
+ return v_t;
+ end;
+ procedure append_proc(p2 number) is
+ begin
+ return v_t;
+ end;
+end;
+/
+
+CREATE OR REPLACE PACKAGE PAC_ACCESSOR
+IS
+ v1 number;
+ type cur_emp is ref cursor;
+ PROCEDURE PROC_PARAMS_ACCESSOR (p_in IN NUMBER DEFAULT 100, p_in_out IN OUT VARCHAR2, p_out OUT DATE, p_result OUT BOOLEAN);
+ FUNCTION FUNC_DETAIL_ACCESSOR (p_in IN NUMBER, p_in_out IN OUT VARCHAR2, p_out OUT DATE) RETURN NUMBER;
+ FUNCTION FUNC_IN_PRO RETURN NUMBER;
+END PAC_ACCESSOR;
+/
+
+CREATE OR REPLACE PACKAGE BODY PAC_ACCESSOR
+AS
+PROCEDURE PROC_PARAMS_ACCESSOR (p_in IN NUMBER DEFAULT 100, p_in_out IN OUT VARCHAR2, p_out OUT DATE, p_result OUT BOOLEAN)
+IS
+ total NUMBER;
+BEGIN
+ DBMS_OUTPUT.PUT_LINE('db-browser test');
+END;
+
+FUNCTION FUNC_DETAIL_ACCESSOR (p_in IN NUMBER, p_in_out IN OUT VARCHAR2, p_out OUT DATE)
+RETURN NUMBER
+IS
+ total NUMBER;
+BEGIN
+ RETURN total;
+END;
+
+FUNCTION FUNC_IN_PRO
+RETURN NUMBER
+IS
+ total NUMBER;
+BEGIN
+ RETURN total;
+END;
+END PAC_ACCESSOR;
diff --git a/libs/db-browser/src/test/resources/table/oracle/testPartitionDDL.sql b/libs/db-browser/src/test/resources/table/oboracle/testPartitionDDL.sql
similarity index 100%
rename from libs/db-browser/src/test/resources/table/oracle/testPartitionDDL.sql
rename to libs/db-browser/src/test/resources/table/oboracle/testPartitionDDL.sql
diff --git a/libs/db-browser/src/test/resources/table/oboracle/testProcedureDDL.sql b/libs/db-browser/src/test/resources/table/oboracle/testProcedureDDL.sql
new file mode 100644
index 0000000000..3dcb7e28f2
--- /dev/null
+++ b/libs/db-browser/src/test/resources/table/oboracle/testProcedureDDL.sql
@@ -0,0 +1,17 @@
+create or replace procedure PROCEDURE_TEST(p1 in VARCHAR) is
+begin
+null;
+end PROCEDURE_TEST;
+/
+
+create or replace procedure INVALID_PROCEDURE_TEST(
+val in varchar2 ) is
+begin
+select 1, val from invalid_dual;
+end INVALID_PROCEDURE_TEST;
+/
+
+create or replace procedure PROCEDURE_DETAIL_TEST(p1 in int, p2 in varchar2) IS v1 number;
+begin
+return;
+end;
\ No newline at end of file
diff --git a/libs/db-browser/src/test/resources/table/oboracle/testSequenceDDL.sql b/libs/db-browser/src/test/resources/table/oboracle/testSequenceDDL.sql
new file mode 100644
index 0000000000..9f59194c9c
--- /dev/null
+++ b/libs/db-browser/src/test/resources/table/oboracle/testSequenceDDL.sql
@@ -0,0 +1 @@
+CREATE SEQUENCE SEQ_TEST MINVALUE 1 MAXVALUE 10 START WITH 1 INCREMENT BY 2 CACHE 5 ORDER CYCLE;
\ No newline at end of file
diff --git a/libs/db-browser/src/test/resources/table/oboracle/testSynonymDDL.sql b/libs/db-browser/src/test/resources/table/oboracle/testSynonymDDL.sql
new file mode 100644
index 0000000000..5fc8e1fba1
--- /dev/null
+++ b/libs/db-browser/src/test/resources/table/oboracle/testSynonymDDL.sql
@@ -0,0 +1,5 @@
+create table SYNONYM_TEST_TABLE (col varchar(20));
+
+create or replace synonym COMMON_SYNONYM_TEST for SYNONYM_TEST_TABLE;
+
+create or replace public synonym PUBLIC_SYNONYM_TEST for SYNONYM_TEST_TABLE;
\ No newline at end of file
diff --git a/libs/db-browser/src/test/resources/table/oboracle/testTableColumnDDL.sql b/libs/db-browser/src/test/resources/table/oboracle/testTableColumnDDL.sql
new file mode 100644
index 0000000000..d7f876d998
--- /dev/null
+++ b/libs/db-browser/src/test/resources/table/oboracle/testTableColumnDDL.sql
@@ -0,0 +1,30 @@
+create table TEST_DATA_TYPE(
+ col1 int,
+ col2 number(22),
+ col3 char(10),
+ col4 varchar2(10),
+ col5 blob,
+ col6 clob,
+ col7 date,
+ col8 timestamp,
+ col9 timestamp with time zone,
+ col10 timestamp with local time zone,
+ col11 raw(100),
+ col12 interval year to month,
+ col13 interval day to second,
+ col14 number
+);
+
+create table TEST_OTHER_THAN_DATA_TYPE(
+ col1 int NOT NULL,
+ col2 int,
+ col3 GENERATED ALWAYS AS (col1 + col2) VIRTUAL
+);
+comment on column TEST_OTHER_THAN_DATA_TYPE.col1 is 'col1_comments';
+
+CREATE TABLE TEST_DEFAULT_NULL (
+ COL1 NUMBER(*,0) DEFAULT NULL,
+ COL2 NUMBER(22) DEFAULT null,
+ COL3 CHAR(10) DEFAULT (null),
+ COL4 VARCHAR2(10) DEFAULT 'null'
+);
\ No newline at end of file
diff --git a/libs/db-browser/src/test/resources/table/oboracle/testTableConstraintDDL.sql b/libs/db-browser/src/test/resources/table/oboracle/testTableConstraintDDL.sql
new file mode 100644
index 0000000000..cebc7d4e0e
--- /dev/null
+++ b/libs/db-browser/src/test/resources/table/oboracle/testTableConstraintDDL.sql
@@ -0,0 +1,16 @@
+create table TEST_FK_PARENT(
+ col1 int,
+ col2 int,
+ CONSTRAINT pk_parent_col1_col2 PRIMARY KEY (col1, col2)
+);
+
+CREATE TABLE TEST_FK_CHILD(
+ col1 int,
+ col2 int,
+ CONSTRAINT fk_child_col1_col2 FOREIGN KEY (col1, col2) REFERENCES TEST_FK_PARENT(col1, col2)
+);
+
+CREATE TABLE TEST_PK_INDEX (
+"A" INTEGER NOT NULL,
+CONSTRAINT "PK_TEST" PRIMARY KEY ("A")
+);
diff --git a/libs/db-browser/src/test/resources/table/oboracle/testTableIndexDDL.sql b/libs/db-browser/src/test/resources/table/oboracle/testTableIndexDDL.sql
new file mode 100644
index 0000000000..894f45b84c
--- /dev/null
+++ b/libs/db-browser/src/test/resources/table/oboracle/testTableIndexDDL.sql
@@ -0,0 +1,15 @@
+-- test index type
+create table TEST_INDEX_TYPE(
+ col1 int,
+ col2 int
+);
+CREATE UNIQUE INDEX test_normal_idx on TEST_INDEX_TYPE(col1);
+CREATE UNIQUE INDEX test_btree_idx using btree on TEST_INDEX_TYPE(col2);
+
+-- test index range
+create table TEST_INDEX_RANGE(
+ col1 int,
+ col2 int
+);
+CREATE INDEX test_global_idx on TEST_INDEX_RANGE(col1) GLOBAL;
+CREATE INDEX test_local_idx on TEST_INDEX_RANGE(col2) LOCAL;
\ No newline at end of file
diff --git a/libs/db-browser/src/test/resources/table/oboracle/testTriggerDDL.sql b/libs/db-browser/src/test/resources/table/oboracle/testTriggerDDL.sql
new file mode 100644
index 0000000000..39a31c06f3
--- /dev/null
+++ b/libs/db-browser/src/test/resources/table/oboracle/testTriggerDDL.sql
@@ -0,0 +1,7 @@
+create table TRIGGER_TABLE (col varchar2(20));
+/
+
+create or replace trigger TRIGGER_TEST before insert on TRIGGER_TABLE for each row begin select 1+1 from dual;end;
+/
+
+create or replace trigger INVALID_TRIGGER before insert on TRIGGER_TABLE for each row begin select 1+1 from invalid_dual;end;
diff --git a/libs/db-browser/src/test/resources/table/oboracle/testViewDDL.sql b/libs/db-browser/src/test/resources/table/oboracle/testViewDDL.sql
new file mode 100644
index 0000000000..8c79207105
--- /dev/null
+++ b/libs/db-browser/src/test/resources/table/oboracle/testViewDDL.sql
@@ -0,0 +1,7 @@
+create table TEST_VIEW_TABLE(
+ c1 int,
+ c2 varchar(100)
+);
+
+create view VIEW_TEST1 as select c1, c2 from TEST_VIEW_TABLE;
+create view VIEW_TEST2 as select c1 from TEST_VIEW_TABLE;
diff --git a/libs/db-browser/src/test/resources/table/oracle/drop.sql b/libs/db-browser/src/test/resources/table/oracle/drop.sql
index cb9d3c9c68..a492143ad2 100644
--- a/libs/db-browser/src/test/resources/table/oracle/drop.sql
+++ b/libs/db-browser/src/test/resources/table/oracle/drop.sql
@@ -13,126 +13,19 @@ BEGIN
END;
/
-CREATE OR REPLACE PROCEDURE DROPIFEXISTS_VIEW(new_view IN varchar2)
- IS
- v_count number(10);
-BEGIN
- SELECT count(*)
- INTO v_count
- FROM USER_VIEWS
- WHERE VIEW_NAME = upper(new_view);
- IF v_count > 0
- THEN
- EXECUTE IMMEDIATE 'drop view ' || new_view ;
- END IF;
-END;
+call DROPIFEXISTS_TABLE('TEST_COL_DATA_TYPE')
/
-
-CREATE OR REPLACE PROCEDURE DROPIFEXISTS_FUNC(new_func IN varchar2)
- IS
- v_count number(10);
-BEGIN
- SELECT count(*)
- INTO v_count
- FROM USER_OBJECTS
- WHERE object_name = upper(new_func) and object_type = 'FUNCTION' ;
- IF v_count > 0
- THEN
- EXECUTE IMMEDIATE 'drop function ' || new_func ;
- END IF;
-END;
+call DROPIFEXISTS_TABLE('TEST_FK_PARENT')
/
-
-CREATE OR REPLACE PROCEDURE DROPIFEXISTS_SEQUENCE(new_sequence IN varchar2)
- IS
- v_count number(10);
-BEGIN
- SELECT count(*)
- INTO v_count
- FROM USER_SEQUENCES
- WHERE sequence_name = upper(new_sequence);
- IF v_count > 0
- THEN
- EXECUTE IMMEDIATE 'drop sequence ' || new_sequence ;
- END IF;
-END;
+call DROPIFEXISTS_TABLE('TEST_FK_CHILD')
/
-
-CREATE OR REPLACE PROCEDURE DROPIFEXISTS_PACKAGE(new_package IN varchar2)
- IS
- v_count number(10);
-BEGIN
- SELECT count(*)
- INTO v_count
- FROM USER_OBJECTS
- WHERE object_name = upper(new_package) AND (object_type = 'PACKAGE' or object_type = 'PACKAGE BODY');
- IF v_count > 0
- THEN
- EXECUTE IMMEDIATE 'drop package ' || new_package ;
- END IF;
-END;
+call DROPIFEXISTS_TABLE('TEST_PK_INDEX')
/
-
-CREATE OR REPLACE PROCEDURE DROPIFEXISTS_TRIGGER(new_trigger IN varchar2)
- IS
- v_count number(10);
-BEGIN
- SELECT count(*)
- INTO v_count
- FROM USER_TRIGGERS
- WHERE TRIGGER_NAME = upper(new_trigger);
- IF v_count > 0
- THEN
- EXECUTE IMMEDIATE 'drop trigger ' || new_trigger ;
- END IF;
-END;
+call DROPIFEXISTS_TABLE('TEST_INDEX_TYPE')
/
-
-CREATE OR REPLACE PROCEDURE DROPIFEXISTS_SYNONYM(new_synonym IN varchar2)
- IS
- v_count number(10);
-BEGIN
- SELECT count(*)
- INTO v_count
- FROM USER_SYNONYMS
- WHERE SYNONYM_NAME = upper(new_synonym);
- IF v_count > 0
- THEN
- EXECUTE IMMEDIATE 'drop synonym ' || new_synonym ;
- END IF;
-END;
+call DROPIFEXISTS_TABLE('TEST_VIEW_TABLE')
/
+call DROPIFEXISTS_TABLE('PART_HASH_TEST')
-call DROPIFEXISTS_TABLE('TEST_DATA_TYPE');
-call DROPIFEXISTS_TABLE('TEST_OTHER_THAN_DATA_TYPE');
-call DROPIFEXISTS_TABLE('TEST_INDEX_TYPE');
-call DROPIFEXISTS_TABLE('TEST_INDEX_RANGE');
-call DROPIFEXISTS_TABLE('TEST_FK_PARENT');
-call DROPIFEXISTS_TABLE('TEST_FK_CHILD');
-call DROPIFEXISTS_TABLE('part_hash');
-call DROPIFEXISTS_TABLE('TEST_PK_INDEX');
-call DROPIFEXISTS_TABLE('TEST_DEFAULT_NULL');
-
-call DROPIFEXISTS_VIEW('VIEW_TEST1');
-call DROPIFEXISTS_VIEW('VIEW_TEST2');
-call DROPIFEXISTS_TABLE('TEST_VIEW_TABLE');
-
-call DROPIFEXISTS_FUNC('FUNC_TEST');
-call DROPIFEXISTS_FUNC('INVALIDE_FUNC');
-call DROPIFEXISTS_FUNC('FUNC_DETAIL_TEST');
-
-call DROPIFEXISTS_PACKAGE('T_PACKAGE');
-call DROPIFEXISTS_PACKAGE('INVALID_PKG');
-
-call DROPIFEXISTS_TRIGGER('TRIGGER_TEST');
-call DROPIFEXISTS_TRIGGER('INVALID_TRIGGER');
-call DROPIFEXISTS_TABLE('TRIGGER_TABLE');
-
-call DROPIFEXISTS_SEQUENCE('SEQ_TEST');
-
-call DROPIFEXISTS_TABLE('SYNONYM_TEST_TABLE');
-call DROPIFEXISTS_SYNONYM('COMMON_SYNONYM_TEST');
-call DROPIFEXISTS_SYNONYM('PUBLIC_SYNONYM_TEST');
-
diff --git a/libs/db-browser/src/test/resources/table/oracle/testFunctionDDL.sql b/libs/db-browser/src/test/resources/table/oracle/testFunctionDDL.sql
index 2df02afaa6..4a6e098210 100644
--- a/libs/db-browser/src/test/resources/table/oracle/testFunctionDDL.sql
+++ b/libs/db-browser/src/test/resources/table/oracle/testFunctionDDL.sql
@@ -1,6 +1,6 @@
-CREATE OR REPLACE FUNCTION FUNC_TEST(
-p1 in NUMBER,
-p2 in NUMBER)
+CREATE OR REPLACE FUNCTION FUNC_ACCESSOR(
+ p1 in NUMBER,
+ p2 in NUMBER)
return NUMBER as
v1 int;
begin
@@ -8,7 +8,7 @@ return p1+p2;
end;
/
-CREATE OR REPLACE FUNCTION INVALIDE_FUNC(
+CREATE OR REPLACE FUNCTION FUNC_INVALIDE_ACCESSOR(
p1 in NUMBER,
p2 in NUMBER)
return NUMBER as
@@ -19,11 +19,28 @@ return v_result;
end;
/
-CREATE OR REPLACE FUNCTION FUNC_DETAIL_TEST(
-v_input number)
-RETURN NUMBER IS
-v1 number; v2 varchar2(100);
-type cur_emp is ref cursor;
+CREATE OR REPLACE FUNCTION FUNC_DETAIL_ACCESSOR (
+ p_in IN NUMBER,
+ p_in_out IN OUT VARCHAR2,
+ p_out OUT DATE
+)
+RETURN BOOLEAN
+IS
+ v_temp VARCHAR2(100);
+ type cur_emp is ref cursor;
+BEGIN
+ v_temp := 'Hello ' || p_in_out;
+ p_in_out := v_temp;
+ p_out := SYSDATE;
+ RETURN TRUE;
+END;
+/
+
+CREATE OR REPLACE FUNCTION FUNC_NO_PARAM_ACCESSOR
+RETURN VARCHAR2
+IS
+ result VARCHAR2(100);
BEGIN
-RETURN v1;
+ result := 'Hello';
+ RETURN result;
END;
\ No newline at end of file
diff --git a/libs/db-browser/src/test/resources/table/oracle/testPackageDDL.sql b/libs/db-browser/src/test/resources/table/oracle/testPackageDDL.sql
index f497c2dc41..4705cb3a4e 100644
--- a/libs/db-browser/src/test/resources/table/oracle/testPackageDDL.sql
+++ b/libs/db-browser/src/test/resources/table/oracle/testPackageDDL.sql
@@ -1,40 +1,51 @@
-create or replace package t_package is
+CREATE OR REPLACE PACKAGE PAC_ACCESSOR IS
v1 number;
type cur_emp is ref cursor;
- procedure append_proc(p1 in out varchar2, p2 number);
- function append_fun(p2 out varchar2) return varchar2;
-end;
+ PROCEDURE PROC_PARAMS_ACCESSOR (p_in IN NUMBER DEFAULT 100, p_in_out IN OUT VARCHAR2, p_out OUT DATE, p_result OUT BOOLEAN);
+ FUNCTION FUNC_DETAIL_ACCESSOR (p_in IN NUMBER, p_in_out IN OUT VARCHAR2, p_out OUT DATE) RETURN NUMBER;
+ FUNCTION FUNC_IN_PRO RETURN NUMBER;
+END PAC_ACCESSOR;
/
-create or replace package body t_package is
- v_t varchar2(30);
- function private_fun(p1 IN OUT NOCOPY varchar2) return varchar2 is
- begin
- return v_t;
- end;
- procedure append_proc(p2 number) is
- begin
- return v_t;
- end;
-end;
+CREATE OR REPLACE PACKAGE BODY PAC_ACCESSOR AS
+ PROCEDURE PROC_PARAMS_ACCESSOR (p_in IN NUMBER DEFAULT 100, p_in_out IN OUT VARCHAR2, p_out OUT DATE, p_result OUT BOOLEAN) IS
+ total NUMBER;
+ BEGIN
+ DBMS_OUTPUT.PUT_LINE('db-browser test');
+ END;
+
+ FUNCTION FUNC_DETAIL_ACCESSOR (p_in IN NUMBER, p_in_out IN OUT VARCHAR2, p_out OUT DATE)
+ RETURN NUMBER IS
+ total NUMBER;
+ BEGIN
+ RETURN total;
+ END;
+
+ FUNCTION FUNC_IN_PRO
+ RETURN NUMBER IS
+ total NUMBER;
+ BEGIN
+ RETURN total;
+ END;
+END PAC_ACCESSOR;
/
-create or replace package INVALID_PKG is
- v1 number;
- type cur_emp is ref cursor;
- procedure append_proc(p1 in out varchar2, p2 number);
- function append_fun(p2 out varchar2) return varchar2;
-end;
+CREATE OR REPLACE PACKAGE PAC_INVALID_ACCESSOR IS
+ PROCEDURE my_procedure;
+ FUNCTION my_function RETURN NUMBER;
+END PAC_INVALID_ACCESSOR;
/
-create or replace package body INVALID_PKG is
- v_t varchar2(30);
- function private_fun(p1 IN OUT NOCOPY varchar2) return varchar2 is
- begin
- return v_t;
- end;
- procedure append_proc(p2 number) is
- begin
- return v_t;
- end;
-end;
\ No newline at end of file
+CREATE OR REPLACE PACKAGE BODY PAC_INVALID_ACCESSOR IS
+ PROCEDURE my_procedure IS
+ BEGIN
+ -- 无效的语句
+ SELECT * FROM non_existent_table;
+ END my_procedure;
+
+ FUNCTION my_function RETURN NUMBER IS
+ BEGIN
+ -- 无效的语句
+ SELECT * FROM non_existent_table;
+ END my_function;
+END PAC_INVALID_ACCESSOR;
\ No newline at end of file
diff --git a/libs/db-browser/src/test/resources/table/oracle/testProcedureDDL.sql b/libs/db-browser/src/test/resources/table/oracle/testProcedureDDL.sql
index 1a3035ae5f..bd3f274b09 100644
--- a/libs/db-browser/src/test/resources/table/oracle/testProcedureDDL.sql
+++ b/libs/db-browser/src/test/resources/table/oracle/testProcedureDDL.sql
@@ -1,18 +1,22 @@
-create or replace procedure PROCEDURE_TEST(
-p1 in VARCHAR) is
-begin
-null;
-end PROCEDURE_TEST;
+CREATE OR REPLACE PROCEDURE PROC_PARAMS_ACCESSOR (
+ p_in IN NUMBER DEFAULT 100,
+ p_in_out IN OUT VARCHAR2,
+ p_out OUT DATE,
+ p_result OUT BOOLEAN
+)
+IS
+ v_temp VARCHAR2(100);
+BEGIN
+ v_temp := 'Hello ' || p_in_out;
+ p_in_out := v_temp;
+ p_out := SYSDATE;
+ p_result := TRUE;
+END;
/
-create or replace procedure INVALID_PROCEDURE_TEST(
-val in varchar2 ) is
-begin
-select 1, val from invalid_dual;
-end INVALID_PROCEDURE_TEST;
-/
-create or replace procedure PROCEDURE_DETAIL_TEST(p1 in int, p2 in varchar2) IS v1 number;
-begin
-return;
-end;
\ No newline at end of file
+CREATE OR REPLACE PROCEDURE PROC_INVALID_ACCESSOR
+IS
+BEGIN
+ SELECT * FROM non_existent_table;
+END;
diff --git a/libs/db-browser/src/test/resources/table/oracle/testSequenceDDL.sql b/libs/db-browser/src/test/resources/table/oracle/testSequenceDDL.sql
index 9f59194c9c..62957081f6 100644
--- a/libs/db-browser/src/test/resources/table/oracle/testSequenceDDL.sql
+++ b/libs/db-browser/src/test/resources/table/oracle/testSequenceDDL.sql
@@ -1 +1 @@
-CREATE SEQUENCE SEQ_TEST MINVALUE 1 MAXVALUE 10 START WITH 1 INCREMENT BY 2 CACHE 5 ORDER CYCLE;
\ No newline at end of file
+CREATE SEQUENCE SEQ_TEST MINVALUE 1 MAXVALUE 10 START WITH 1 INCREMENT BY 2 CACHE 5 ORDER CYCLE
\ No newline at end of file
diff --git a/libs/db-browser/src/test/resources/table/oracle/testSynonymDDL.sql b/libs/db-browser/src/test/resources/table/oracle/testSynonymDDL.sql
index 5fc8e1fba1..c1c53812e2 100644
--- a/libs/db-browser/src/test/resources/table/oracle/testSynonymDDL.sql
+++ b/libs/db-browser/src/test/resources/table/oracle/testSynonymDDL.sql
@@ -1,5 +1,7 @@
-create table SYNONYM_TEST_TABLE (col varchar(20));
+create table SYNONYM_TEST_TABLE (col varchar(20))
+/
-create or replace synonym COMMON_SYNONYM_TEST for SYNONYM_TEST_TABLE;
+create or replace synonym COMMON_SYNONYM_ACCESSOR for SYNONYM_TEST_TABLE
+/
-create or replace public synonym PUBLIC_SYNONYM_TEST for SYNONYM_TEST_TABLE;
\ No newline at end of file
+create or replace public synonym PUBLIC_SYNONYM_ACCESSOR for SYNONYM_TEST_TABLE
\ No newline at end of file
diff --git a/libs/db-browser/src/test/resources/table/oracle/testTableColumnDDL.sql b/libs/db-browser/src/test/resources/table/oracle/testTableColumnDDL.sql
index d7f876d998..228f8c78b9 100644
--- a/libs/db-browser/src/test/resources/table/oracle/testTableColumnDDL.sql
+++ b/libs/db-browser/src/test/resources/table/oracle/testTableColumnDDL.sql
@@ -1,4 +1,4 @@
-create table TEST_DATA_TYPE(
+create table TEST_COL_DATA_TYPE(
col1 int,
col2 number(22),
col3 char(10),
@@ -11,20 +11,6 @@ create table TEST_DATA_TYPE(
col10 timestamp with local time zone,
col11 raw(100),
col12 interval year to month,
- col13 interval day to second,
- col14 number
-);
-
-create table TEST_OTHER_THAN_DATA_TYPE(
- col1 int NOT NULL,
- col2 int,
- col3 GENERATED ALWAYS AS (col1 + col2) VIRTUAL
-);
-comment on column TEST_OTHER_THAN_DATA_TYPE.col1 is 'col1_comments';
-
-CREATE TABLE TEST_DEFAULT_NULL (
- COL1 NUMBER(*,0) DEFAULT NULL,
- COL2 NUMBER(22) DEFAULT null,
- COL3 CHAR(10) DEFAULT (null),
- COL4 VARCHAR2(10) DEFAULT 'null'
-);
\ No newline at end of file
+ col13 interval day to second
+)
+/
\ No newline at end of file
diff --git a/libs/db-browser/src/test/resources/table/oracle/testTableConstraintDDL.sql b/libs/db-browser/src/test/resources/table/oracle/testTableConstraintDDL.sql
index cebc7d4e0e..0684a76f40 100644
--- a/libs/db-browser/src/test/resources/table/oracle/testTableConstraintDDL.sql
+++ b/libs/db-browser/src/test/resources/table/oracle/testTableConstraintDDL.sql
@@ -2,15 +2,18 @@ create table TEST_FK_PARENT(
col1 int,
col2 int,
CONSTRAINT pk_parent_col1_col2 PRIMARY KEY (col1, col2)
-);
+)
+/
CREATE TABLE TEST_FK_CHILD(
col1 int,
col2 int,
CONSTRAINT fk_child_col1_col2 FOREIGN KEY (col1, col2) REFERENCES TEST_FK_PARENT(col1, col2)
-);
+)
+/
CREATE TABLE TEST_PK_INDEX (
"A" INTEGER NOT NULL,
CONSTRAINT "PK_TEST" PRIMARY KEY ("A")
-);
+)
+/
\ No newline at end of file
diff --git a/libs/db-browser/src/test/resources/table/oracle/testTableIndexDDL.sql b/libs/db-browser/src/test/resources/table/oracle/testTableIndexDDL.sql
index 894f45b84c..13fd252479 100644
--- a/libs/db-browser/src/test/resources/table/oracle/testTableIndexDDL.sql
+++ b/libs/db-browser/src/test/resources/table/oracle/testTableIndexDDL.sql
@@ -1,15 +1,22 @@
--- test index type
+CREATE TABLE TEST_INDEX_RANGE (
+C1 NUMBER,
+C2 NUMBER,
+C3 NUMBER
+) PARTITION BY HASH(C2)
+PARTITIONS 5
+/
+CREATE INDEX test_global_idx on TEST_INDEX_RANGE(C1) GLOBAL
+/
+CREATE INDEX test_local_idx on TEST_INDEX_RANGE(C2) LOCAL
+/
+CREATE INDEX test_local_idx2 on TEST_INDEX_RANGE(C3) LOCAL
+/
create table TEST_INDEX_TYPE(
col1 int,
col2 int
-);
-CREATE UNIQUE INDEX test_normal_idx on TEST_INDEX_TYPE(col1);
-CREATE UNIQUE INDEX test_btree_idx using btree on TEST_INDEX_TYPE(col2);
-
--- test index range
-create table TEST_INDEX_RANGE(
- col1 int,
- col2 int
-);
-CREATE INDEX test_global_idx on TEST_INDEX_RANGE(col1) GLOBAL;
-CREATE INDEX test_local_idx on TEST_INDEX_RANGE(col2) LOCAL;
\ No newline at end of file
+)
+/
+CREATE INDEX test_normal_idx on TEST_INDEX_TYPE(col1)
+/
+CREATE UNIQUE INDEX test_unique_idx on TEST_INDEX_TYPE(col2)
+/
diff --git a/libs/db-browser/src/test/resources/table/oracle/testTablePartitionDDL.sql b/libs/db-browser/src/test/resources/table/oracle/testTablePartitionDDL.sql
new file mode 100644
index 0000000000..0b30e8cbde
--- /dev/null
+++ b/libs/db-browser/src/test/resources/table/oracle/testTablePartitionDDL.sql
@@ -0,0 +1,7 @@
+CREATE TABLE PART_HASH_TEST (
+C1 INTEGER NOT NULL
+) PARTITION BY HASH(C1)
+PARTITIONS 5
+/
+COMMENT ON TABLE PART_HASH_TEST IS 'this is a comment'
+/
\ No newline at end of file
diff --git a/libs/db-browser/src/test/resources/table/oracle/testTriggerDDL.sql b/libs/db-browser/src/test/resources/table/oracle/testTriggerDDL.sql
index 39a31c06f3..3b21c9af95 100644
--- a/libs/db-browser/src/test/resources/table/oracle/testTriggerDDL.sql
+++ b/libs/db-browser/src/test/resources/table/oracle/testTriggerDDL.sql
@@ -1,7 +1,17 @@
-create table TRIGGER_TABLE (col varchar2(20));
+CREATE TABLE TRIGGER_TABLE (col varchar2(20))
/
-create or replace trigger TRIGGER_TEST before insert on TRIGGER_TABLE for each row begin select 1+1 from dual;end;
+CREATE OR REPLACE TRIGGER TRIGGER_ACCESSOR
+ BEFORE INSERT OR DELETE OR UPDATE ON TRIGGER_TABLE
+ FOR EACH ROW
+ BEGIN
+ DBMS_OUTPUT.PUT_LINE('db-browser test');
+ END;
/
-create or replace trigger INVALID_TRIGGER before insert on TRIGGER_TABLE for each row begin select 1+1 from invalid_dual;end;
+CREATE OR REPLACE TRIGGER TRIGGER_INVALID_ACCESSOR
+ BEFORE INSERT ON TRIGGER_TABLE
+ FOR EACH ROW
+ BEGIN
+ select 1+1 from invalid_dual;
+ END;
\ No newline at end of file
diff --git a/libs/db-browser/src/test/resources/table/oracle/testTypeDDL.sql b/libs/db-browser/src/test/resources/table/oracle/testTypeDDL.sql
new file mode 100644
index 0000000000..a5e765b1fb
--- /dev/null
+++ b/libs/db-browser/src/test/resources/table/oracle/testTypeDDL.sql
@@ -0,0 +1,23 @@
+CREATE OR REPLACE TYPE TYPE_ACCESSOR AS OBJECT (
+ street VARCHAR2(30),
+ city VARCHAR2(20),
+ state CHAR(2),
+ postal_code VARCHAR2(6)
+);
+/
+
+CREATE OR REPLACE TYPE TYPE_ACCESSOR2 AS OBJECT (
+ first_name VARCHAR2(50),
+ last_name VARCHAR2(50),
+ gender VARCHAR2(10),
+ birth_date DATE,
+ MEMBER FUNCTION get_full_name RETURN VARCHAR2
+);
+/
+
+CREATE OR REPLACE TYPE BODY TYPE_ACCESSOR2 AS
+ MEMBER FUNCTION get_full_name RETURN VARCHAR2 IS
+ BEGIN
+ RETURN first_name || ' ' || last_name;
+ END;
+END;
\ No newline at end of file
diff --git a/libs/db-browser/src/test/resources/table/oracle/testViewDDL.sql b/libs/db-browser/src/test/resources/table/oracle/testViewDDL.sql
index 8c79207105..2664b45386 100644
--- a/libs/db-browser/src/test/resources/table/oracle/testViewDDL.sql
+++ b/libs/db-browser/src/test/resources/table/oracle/testViewDDL.sql
@@ -1,7 +1,8 @@
create table TEST_VIEW_TABLE(
c1 int,
c2 varchar(100)
-);
+)
+/
-create view VIEW_TEST1 as select c1, c2 from TEST_VIEW_TABLE;
-create view VIEW_TEST2 as select c1 from TEST_VIEW_TABLE;
+create view VIEW_TEST as select c1, c2 from TEST_VIEW_TABLE
+/
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 85fab35000..b2524c3588 100644
--- a/pom.xml
+++ b/pom.xml
@@ -93,7 +93,7 @@
4.20.19.ALL
4.10.0
2.10.0
- 1.0.5
+ 1.1.0
1.2.0
3.10.0
1.64