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