提交 1a9c1c51 编写于 作者: L liuyizhuo

Add procedure/function to OB-MySQL mode

上级 25244231
......@@ -16,7 +16,7 @@
icon="icons/ob_icon.png"
label="OceanBase data source"
path="oceanbase">
<folder type="org.jkiss.dbeaver.ext.mysql.model.MySQLCatalog" label="%tree.databases.node.name" icon="#folder_schema" description="%tree.databases.node.tip">
<folder type="org.jkiss.dbeaver.ext.oceanbase.mysql.model.OceanbaseMySQLCatalog" label="%tree.databases.node.name" icon="#folder_schema" description="%tree.databases.node.tip">
<items label="%tree.database.node.name" path="database" property="catalogs" icon="#database">
<folder type="org.jkiss.dbeaver.ext.mysql.model.MySQLTable" label="%tree.tables.node.name" icon="#folder_table" description="%tree.tables.node.tip">
<items label="%tree.table.node.name" path="table" property="tables" icon="#table">
......@@ -68,6 +68,12 @@
</items>
</items>
</folder>
<folder type="org.jkiss.dbeaver.ext.oceanbase.mysql.model.OceanbaseMySQLProcedure" label="%tree.procedures.node.name" icon="#procedures" description="%tree.procedures.node.tip">
<items label="%tree.procedure.node.name" path="procedure" property="procedures" icon="#procedure">
<items label="Parameters" itemLabel="%tree.column.node.name" path="column" property="parameters" navigable="false" inline="true">
</items>
</items>
</folder>
</items>
</folder>
<folder type="org.jkiss.dbeaver.ext.mysql.model.MySQLUser" label="%tree.users.node.name" icon="#folder_user" description="%tree.users.node.tip">
......@@ -152,7 +158,10 @@
</editor>
</extension>
<extension point="org.jkiss.dbeaver.dataSourceProvider">
<editorContribution editorId="org.jkiss.dbeaver.ext.mysql.ui.editors.MySQLSessionEditor" category="connectionEditor" label="%editor.session_manager.name" icon="platform:/plugin/org.jkiss.dbeaver.model/icons/tree/sessions.png">
<editorContribution
editorId="org.jkiss.dbeaver.ext.mysql.ui.editors.MySQLSessionEditor"
category="connectionEditor" label="%editor.session_manager.name"
icon="platform:/plugin/org.jkiss.dbeaver.model/icons/tree/sessions.png">
<supports dataSource="oceanbase"/>
</editorContribution>
</extension>
......@@ -193,4 +202,8 @@
uiClass="org.jkiss.dbeaver.ui.dialogs.connection.DatabaseNativeAuthModelConfigurator"/>
</extension>
<extension point="org.jkiss.dbeaver.objectManager">
<manager class="org.jkiss.dbeaver.ext.oceanbase.mysql.model.OceanbaseMySQLDatabaseManager" objectType="org.jkiss.dbeaver.ext.oceanbase.mysql.model.OceanbaseMySQLCatalog" label="%manager.catalog.name"/>
</extension>
</plugin>
package org.jkiss.dbeaver.ext.oceanbase.mysql.model;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.jkiss.code.NotNull;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.ext.mysql.MySQLConstants;
import org.jkiss.dbeaver.ext.mysql.model.MySQLCatalog;
import org.jkiss.dbeaver.ext.mysql.model.MySQLDataSource;
import org.jkiss.dbeaver.ext.mysql.model.MySQLProcedure;
import org.jkiss.dbeaver.ext.mysql.model.MySQLProcedureParameter;
import org.jkiss.dbeaver.model.exec.jdbc.JDBCPreparedStatement;
import org.jkiss.dbeaver.model.exec.jdbc.JDBCResultSet;
import org.jkiss.dbeaver.model.exec.jdbc.JDBCSession;
import org.jkiss.dbeaver.model.exec.jdbc.JDBCStatement;
import org.jkiss.dbeaver.model.impl.jdbc.JDBCConstants;
import org.jkiss.dbeaver.model.impl.jdbc.JDBCUtils;
import org.jkiss.dbeaver.model.impl.jdbc.cache.JDBCStructLookupCache;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
import org.jkiss.dbeaver.model.struct.DBSObject;
import org.jkiss.dbeaver.model.struct.rdb.DBSProcedureParameterKind;
import org.jkiss.dbeaver.model.struct.rdb.DBSProcedureType;
import org.jkiss.utils.CommonUtils;
public class OceanbaseMySQLCatalog extends MySQLCatalog{
private final OceanbaseMySQLDataSource dataSource;
final OceanbaseProceduresCache oceanbaseProceduresCache = new OceanbaseProceduresCache();
static class OceanbaseProceduresCache extends JDBCStructLookupCache<OceanbaseMySQLCatalog, OceanbaseMySQLProcedure, MySQLProcedureParameter> {
public OceanbaseProceduresCache() {
super(JDBCConstants.PROCEDURE_NAME);
}
@Override
public JDBCStatement prepareLookupStatement(JDBCSession session, OceanbaseMySQLCatalog owner, OceanbaseMySQLProcedure object,
String objectName) throws SQLException {
JDBCPreparedStatement dbStat = session.prepareStatement(
"SELECT * FROM " + MySQLConstants.META_TABLE_ROUTINES +
"\nWHERE " + MySQLConstants.COL_ROUTINE_SCHEMA + "=?" +
(object == null && objectName == null ? "" : " AND " + MySQLConstants.COL_ROUTINE_NAME + "=?") +
" AND ROUTINE_TYPE" + (object == null ? " IN ('PROCEDURE','FUNCTION')" : "=?") +
"\nORDER BY " + MySQLConstants.COL_ROUTINE_NAME
);
dbStat.setString(1, owner.getName());
if (object != null || objectName != null) {
dbStat.setString(2, object != null ? object.getName() : objectName);
if (object != null) {
dbStat.setString(3, String.valueOf(object.getProcedureType()));
}
}
return dbStat;
}
@Override
protected JDBCStatement prepareChildrenStatement(JDBCSession session, OceanbaseMySQLCatalog owner,
OceanbaseMySQLProcedure procedure) throws SQLException {
if(procedure.getProcedureType().equals(DBSProcedureType.PROCEDURE)) {
return session.getMetaData().getProcedureColumns(
owner.getName(),
null,
procedure == null ? null : JDBCUtils.escapeWildCards(session, procedure.getName()),
"%").getSourceStatement();
}
else {
String queryFunctionString = "select * from mysql.proc where db='%s' and type='FUNCTION' and name='%s'";
return session.prepareStatement(String.format(queryFunctionString, owner.getName(), procedure.getName()));
}
}
@Override
protected MySQLProcedureParameter fetchChild(JDBCSession session, OceanbaseMySQLCatalog owner, OceanbaseMySQLProcedure parent,
JDBCResultSet dbResult) throws SQLException, DBException {
if(parent.getProcedureType().equals(DBSProcedureType.PROCEDURE)) {
String columnName = JDBCUtils.safeGetString(dbResult, JDBCConstants.COLUMN_NAME);
int columnTypeNum = JDBCUtils.safeGetInt(dbResult, JDBCConstants.COLUMN_TYPE);
int valueType = JDBCUtils.safeGetInt(dbResult, JDBCConstants.DATA_TYPE);
String typeName = JDBCUtils.safeGetString(dbResult, JDBCConstants.TYPE_NAME);
int position = JDBCUtils.safeGetInt(dbResult, JDBCConstants.ORDINAL_POSITION);
long columnSize = JDBCUtils.safeGetLong(dbResult, JDBCConstants.LENGTH);
boolean notNull = JDBCUtils.safeGetInt(dbResult, JDBCConstants.NULLABLE) == DatabaseMetaData.procedureNoNulls;
int scale = JDBCUtils.safeGetInt(dbResult, JDBCConstants.SCALE);
int precision = JDBCUtils.safeGetInt(dbResult, JDBCConstants.PRECISION);
DBSProcedureParameterKind parameterType;
switch (columnTypeNum) {
case DatabaseMetaData.procedureColumnIn: parameterType = DBSProcedureParameterKind.IN; break;
case DatabaseMetaData.procedureColumnInOut: parameterType = DBSProcedureParameterKind.INOUT; break;
case DatabaseMetaData.procedureColumnOut: parameterType = DBSProcedureParameterKind.OUT; break;
case DatabaseMetaData.procedureColumnReturn: parameterType = DBSProcedureParameterKind.RETURN; break;
case DatabaseMetaData.procedureColumnResult: parameterType = DBSProcedureParameterKind.RESULTSET; break;
default: parameterType = DBSProcedureParameterKind.UNKNOWN; break;
}
if (CommonUtils.isEmpty(columnName) && parameterType == DBSProcedureParameterKind.RETURN) {
columnName = "RETURN";
}
return new MySQLProcedureParameter(
parent,
columnName,
typeName,
valueType,
position,
columnSize,
scale, precision, notNull,
parameterType);
} else {
String[] paramList = JDBCUtils.safeGetString(dbResult, "returns").split("\\(");
int columnSize = Integer.parseInt(paramList[1].split("\\)")[0]);
return new MySQLProcedureParameter(
parent,
"RETURN",
paramList[0],
STRUCT_ATTRIBUTES,
0,
columnSize,
null,
null,
true,
null);
}
}
@Override
protected OceanbaseMySQLProcedure fetchObject(JDBCSession session, OceanbaseMySQLCatalog owner, JDBCResultSet resultSet)
throws SQLException, DBException {
return new OceanbaseMySQLProcedure(owner, resultSet);
}
}
public OceanbaseMySQLCatalog(OceanbaseMySQLDataSource dataSource, ResultSet dbResult) {
super(dataSource, dbResult);
this.dataSource = dataSource;
}
public OceanbaseProceduresCache getOceanbaseProceduresCache() {
return this.oceanbaseProceduresCache;
}
@Override
public Collection<MySQLProcedure> getProcedures(DBRProgressMonitor monitor) throws DBException {
if(!getDataSource().supportsInformationSchema()) {
return Collections.emptyList();
}
List<MySQLProcedure> objects = new ArrayList<>();
for(OceanbaseMySQLProcedure oceanbaseMySQLProcedure : oceanbaseProceduresCache.getAllObjects(monitor, this)) {
objects.add(oceanbaseMySQLProcedure);
}
return objects;
}
@Override
public MySQLProcedure getProcedure(DBRProgressMonitor monitor, String procName)
throws DBException
{
return oceanbaseProceduresCache.getObject(monitor, this, procName);
}
@Override
public synchronized DBSObject refreshObject(@NotNull DBRProgressMonitor monitor)
throws DBException
{
super.refreshObject(monitor);
oceanbaseProceduresCache.clearCache();
return this;
}
@NotNull
@Override
public MySQLDataSource getDataSource()
{
return (OceanbaseMySQLDataSource)dataSource;
}
}
......@@ -16,32 +16,50 @@
*/
package org.jkiss.dbeaver.ext.oceanbase.mysql.model;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.ext.mysql.MySQLConstants;
import org.jkiss.dbeaver.ext.mysql.model.MySQLCatalog;
import org.jkiss.dbeaver.ext.mysql.model.MySQLDataSource;
import org.jkiss.dbeaver.ext.mysql.model.MySQLEngine;
import org.jkiss.dbeaver.ext.mysql.model.MySQLPrivilege;
import org.jkiss.dbeaver.ext.mysql.model.MySQLTable;
import org.jkiss.dbeaver.ext.oceanbase.model.plan.OceanbasePlanAnalyzer;
import org.jkiss.dbeaver.model.DBPDataSourceContainer;
import org.jkiss.dbeaver.model.DBUtils;
import org.jkiss.dbeaver.model.data.DBDValueHandlerProvider;
import org.jkiss.dbeaver.model.exec.jdbc.JDBCPreparedStatement;
import org.jkiss.dbeaver.model.exec.jdbc.JDBCResultSet;
import org.jkiss.dbeaver.model.exec.jdbc.JDBCSession;
import org.jkiss.dbeaver.model.exec.jdbc.JDBCStatement;
import org.jkiss.dbeaver.model.exec.plan.DBCQueryPlanner;
import org.jkiss.dbeaver.model.impl.jdbc.JDBCUtils;
import org.jkiss.dbeaver.model.impl.jdbc.cache.JDBCBasicDataTypeCache;
import org.jkiss.dbeaver.model.impl.jdbc.cache.JDBCObjectCache;
import org.jkiss.dbeaver.model.impl.jdbc.data.handlers.JDBCStandardValueHandlerProvider;
import org.jkiss.dbeaver.model.impl.jdbc.struct.JDBCDataType;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
import org.jkiss.dbeaver.model.struct.DBSDataType;
import org.jkiss.dbeaver.model.struct.DBSObjectFilter;
import org.jkiss.utils.CommonUtils;
public class OceanbaseMySQLDataSource extends MySQLDataSource {
private final JDBCBasicDataTypeCache<MySQLDataSource, JDBCDataType> dataTypeCache;
private final String tenantType;
private final OceanbaseCatalogCache oceanbaseCatalogCache = new OceanbaseCatalogCache();
public OceanbaseMySQLDataSource(DBRProgressMonitor monitor, DBPDataSourceContainer container)
throws DBException
{
super(monitor, container);
dataTypeCache = new JDBCBasicDataTypeCache<>(this);
tenantType = container.getConnectionConfiguration().getProviderProperty("tenantType");
}
@Override
......@@ -49,6 +67,8 @@ public class OceanbaseMySQLDataSource extends MySQLDataSource {
throws DBException {
super.initialize(monitor);
dataTypeCache.getAllObjects(monitor, this);
// Read catalogs
oceanbaseCatalogCache.getAllObjects(monitor, this);
}
@Override
......@@ -97,4 +117,85 @@ public class OceanbaseMySQLDataSource extends MySQLDataSource {
public DBSDataType getLocalDataType(int typeID) {
return dataTypeCache.getCachedObject(typeID);
}
public boolean isMySQLMode () {
return tenantType.equals("MySQL");
}
MySQLTable findTable(DBRProgressMonitor monitor, String catalogName, String tableName)throws DBException {
if (CommonUtils.isEmpty(catalogName)) {
return null;
}
OceanbaseMySQLCatalog catalog = (OceanbaseMySQLCatalog)getCatalog(catalogName);
if (catalog == null) {
return null;
}
return catalog.getTable(monitor, tableName);
}
@Override
public Collection<? extends MySQLCatalog> getChildren(@NotNull DBRProgressMonitor monitor)
throws DBException {
return getCatalogs();
}
@Override
public MySQLCatalog getChild(@NotNull DBRProgressMonitor monitor, @NotNull String childName)
throws DBException {
return getCatalog(childName);
}
@NotNull
@Override
public Class<? extends MySQLCatalog> getPrimaryChildType(@Nullable DBRProgressMonitor monitor)
throws DBException {
return OceanbaseMySQLCatalog.class;
}
public OceanbaseCatalogCache getOceanbaseCatalogCache() {
return oceanbaseCatalogCache;
}
@Override
public MySQLCatalog getCatalog(String name) {
return oceanbaseCatalogCache.getCachedObject(name);
}
@Override
public Collection<MySQLCatalog> getCatalogs() {
List<MySQLCatalog> catalogs = new ArrayList<>();
for (OceanbaseMySQLCatalog oceanbaseMySQLCatalog : oceanbaseCatalogCache.getCachedObjects()) {
catalogs.add(oceanbaseMySQLCatalog);
}
return catalogs;
}
static class OceanbaseCatalogCache extends JDBCObjectCache<OceanbaseMySQLDataSource, OceanbaseMySQLCatalog> {
@NotNull
@Override
protected JDBCStatement prepareObjectsStatement(@NotNull JDBCSession session, @NotNull OceanbaseMySQLDataSource owner) throws SQLException {
StringBuilder catalogQuery = new StringBuilder("show databases");
DBSObjectFilter catalogFilters = owner.getContainer().getObjectFilter(MySQLCatalog.class, null, false);
if (catalogFilters != null) {
JDBCUtils.appendFilterClause(catalogQuery, catalogFilters, MySQLConstants.COL_DATABASE_NAME, true);
}
JDBCPreparedStatement dbStat = session.prepareStatement(catalogQuery.toString());
if (catalogFilters != null) {
JDBCUtils.setFilterParameters(dbStat, 1, catalogFilters);
}
return dbStat;
}
@Override
protected OceanbaseMySQLCatalog fetchObject(@NotNull JDBCSession session, @NotNull OceanbaseMySQLDataSource owner, @NotNull JDBCResultSet resultSet) throws SQLException, DBException {
return new OceanbaseMySQLCatalog(owner, resultSet);
}
}
@Override
public boolean supportsInformationSchema() {
return true;
}
}
package org.jkiss.dbeaver.ext.oceanbase.mysql.model;
import java.util.List;
import java.util.Map;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.model.DBPDataSource;
import org.jkiss.dbeaver.model.edit.DBECommandContext;
import org.jkiss.dbeaver.model.edit.DBEObjectRenamer;
import org.jkiss.dbeaver.model.edit.DBEPersistAction;
import org.jkiss.dbeaver.model.exec.DBCExecutionContext;
import org.jkiss.dbeaver.model.impl.edit.SQLDatabasePersistAction;
import org.jkiss.dbeaver.model.impl.sql.edit.SQLObjectEditor;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
import org.jkiss.dbeaver.model.struct.DBSObject;
import org.jkiss.dbeaver.model.struct.cache.DBSObjectCache;
public class OceanbaseMySQLDatabaseManager extends SQLObjectEditor<OceanbaseMySQLCatalog, OceanbaseMySQLDataSource> implements DBEObjectRenamer<OceanbaseMySQLCatalog>{
@Override
public long getMakerOptions(DBPDataSource dataSource) {
return FEATURE_SAVE_IMMEDIATELY;
}
@Override
public DBSObjectCache<? extends DBSObject, OceanbaseMySQLCatalog> getObjectsCache(OceanbaseMySQLCatalog object) {
return ((OceanbaseMySQLDataSource)object.getDataSource()).getOceanbaseCatalogCache();
}
@Override
public void renameObject(DBECommandContext commandContext, OceanbaseMySQLCatalog object,
Map<String, Object> options, String newName) throws DBException {
throw new DBException("Direct database rename is not yet implemented in MySQL. You should use export/import functions for that.");
}
@Override
protected OceanbaseMySQLCatalog createDatabaseObject(DBRProgressMonitor monitor, DBECommandContext context,
Object container, Object copyFrom, Map<String, Object> options) throws DBException {
System.out.println("11111");
return new OceanbaseMySQLCatalog((OceanbaseMySQLDataSource) container, null);
}
@Override
protected void addObjectCreateActions(DBRProgressMonitor monitor, DBCExecutionContext executionContext,
List<DBEPersistAction> actions,
SQLObjectEditor<OceanbaseMySQLCatalog, OceanbaseMySQLDataSource>.ObjectCreateCommand command,
Map<String, Object> options) throws DBException {
final OceanbaseMySQLCatalog catalog = command.getObject();
final StringBuilder script = new StringBuilder("CREATE SCHEMA `" + catalog.getName() + "`");
appendDatabaseModifiers(catalog, script);
actions.add(
new SQLDatabasePersistAction("Create schema", script.toString()) //$NON-NLS-2$
);
}
@Override
protected void addObjectDeleteActions(DBRProgressMonitor monitor, DBCExecutionContext executionContext,
List<DBEPersistAction> actions,
SQLObjectEditor<OceanbaseMySQLCatalog, OceanbaseMySQLDataSource>.ObjectDeleteCommand command,
Map<String, Object> options) throws DBException {
actions.add(new SQLDatabasePersistAction("Drop schema", "DROP SCHEMA `" + command.getObject().getName() + "`"));
}
private void appendDatabaseModifiers(OceanbaseMySQLCatalog catalog, StringBuilder script) {
if (catalog.getAdditionalInfo().getDefaultCharset() != null) {
script.append("\nDEFAULT CHARACTER SET ").append(catalog.getAdditionalInfo().getDefaultCharset().getName());
}
if (catalog.getAdditionalInfo().getDefaultCollation() != null) {
script.append("\nDEFAULT COLLATE ").append(catalog.getAdditionalInfo().getDefaultCollation().getName());
}
}
}
package org.jkiss.dbeaver.ext.oceanbase.mysql.model;
import java.sql.ResultSet;
import java.util.Collection;
import org.jkiss.code.NotNull;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.ext.mysql.model.MySQLCatalog;
import org.jkiss.dbeaver.ext.mysql.model.MySQLProcedure;
import org.jkiss.dbeaver.ext.mysql.model.MySQLProcedureParameter;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
import org.jkiss.dbeaver.model.struct.DBSObject;
public class OceanbaseMySQLProcedure extends MySQLProcedure{
private OceanbaseMySQLCatalog container = (OceanbaseMySQLCatalog)getContainer();
public OceanbaseMySQLProcedure(MySQLCatalog catalog) {
super(catalog);
}
public OceanbaseMySQLProcedure(MySQLCatalog catalog, ResultSet dbResult) {
super(catalog, dbResult);
}
@Override
public Collection<MySQLProcedureParameter> getParameters(DBRProgressMonitor monitor)
throws DBException
{
return container.oceanbaseProceduresCache.getChildren(monitor, container, this);
}
@Override
public DBSObject refreshObject(@NotNull DBRProgressMonitor monitor) throws DBException {
return container.oceanbaseProceduresCache.refreshObject(monitor, container, this);
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册