diff --git a/plugins/org.jkiss.dbeaver.ext.mysql/OSGI-INF/l10n/bundle.properties b/plugins/org.jkiss.dbeaver.ext.mysql/OSGI-INF/l10n/bundle.properties index 9cccc183a69207887290c9308900a2486e9e4d87..b6a35361e9e7f0ad376c39bb894fa819ce1ae40f 100644 --- a/plugins/org.jkiss.dbeaver.ext.mysql/OSGI-INF/l10n/bundle.properties +++ b/plugins/org.jkiss.dbeaver.ext.mysql/OSGI-INF/l10n/bundle.properties @@ -48,6 +48,9 @@ tree.charset.node.name=Charset tree.collation.node.name=Collation tree.events.node.name=Events tree.event.node.name=Event +tree.packages.node.name=Packages +tree.packages.node.description=MariaDB Packages (Oracle mode) +tree.package.node.name=Package manager.catalog.name=Catalog manager @@ -55,6 +58,9 @@ editor.general.name=General editor.schema_privileges.name=Schema Privileges editor.session_manager.name=Session Manager editor.source.name=Source +editor.package.body.name=Body source +editor.package.body.description=Package body source + meta.org.jkiss.dbeaver.ext.mysql.model.MySQLCatalog.name.name=Schema Name meta.org.jkiss.dbeaver.ext.mysql.model.MySQLCatalog.defaultCharset.name=Default Charset meta.org.jkiss.dbeaver.ext.mysql.model.MySQLCatalog.defaultCollation.name=Default Collation @@ -194,6 +200,10 @@ meta.org.jkiss.dbeaver.ext.mysql.model.session.MySQLSession.state.name=State meta.org.jkiss.dbeaver.ext.mysql.model.session.MySQLSession.state.description=State meta.org.jkiss.dbeaver.ext.mysql.model.session.MySQLSession.activeQuery.name=Active Query meta.org.jkiss.dbeaver.ext.mysql.model.session.MySQLSession.activeQuery.description=Currently executing SQL query +meta.org.jkiss.dbeaver.ext.mysql.model.MySQLPackage.name.name=Name +meta.org.jkiss.dbeaver.ext.mysql.model.MySQLPackage.description.name=Name +meta.org.jkiss.dbeaver.ext.mysql.model.MySQLPackage.objectDefinitionText.name=Package Declaration +meta.org.jkiss.dbeaver.ext.mysql.model.MySQLPackage.extendedDefinitionText.name=Package Body meta.org.jkiss.dbeaver.ext.mysql.model.MySQLEvent.name.name=Event Name meta.org.jkiss.dbeaver.ext.mysql.model.MySQLEvent.definer.name=Definer diff --git a/plugins/org.jkiss.dbeaver.ext.mysql/plugin.xml b/plugins/org.jkiss.dbeaver.ext.mysql/plugin.xml index 311d6eb1ac1a7ac064564377cfe0f3bb3bc27fb5..1a1693c78b65858f6c2aac4f80e4bedabccade64 100644 --- a/plugins/org.jkiss.dbeaver.ext.mysql/plugin.xml +++ b/plugins/org.jkiss.dbeaver.ext.mysql/plugin.xml @@ -92,6 +92,10 @@ + + + + @@ -223,6 +227,12 @@ + + + + { + + public MySQLPackageBodyEditor() + { + } + + @Override + protected boolean isReadOnly() + { + return false; + } + + @Override + protected String getSourceText(DBRProgressMonitor monitor) throws DBException { + return ((DBPScriptObjectExt)getSourceObject()).getExtendedDefinitionText(monitor); + } + + @Override + protected void setSourceText(DBRProgressMonitor monitor, String sourceText) { + getEditorInput().getPropertySource().setPropertyValue( + monitor, + "extendedDefinitionText", + sourceText); + } + +} \ No newline at end of file diff --git a/plugins/org.jkiss.dbeaver.ext.mysql/src/org/jkiss/dbeaver/ext/mysql/model/MySQLCatalog.java b/plugins/org.jkiss.dbeaver.ext.mysql/src/org/jkiss/dbeaver/ext/mysql/model/MySQLCatalog.java index 834df2c6520d4d9cce922caaa6c7f53cdb4476e0..ae08d281772cb5b6b53b8229f4e9af6005e523ca 100644 --- a/plugins/org.jkiss.dbeaver.ext.mysql/src/org/jkiss/dbeaver/ext/mysql/model/MySQLCatalog.java +++ b/plugins/org.jkiss.dbeaver.ext.mysql/src/org/jkiss/dbeaver/ext/mysql/model/MySQLCatalog.java @@ -61,6 +61,7 @@ public class MySQLCatalog implements DBSCatalog, DBPSaveableObject, DBPRefreshab final TableCache tableCache = new TableCache(); final ProceduresCache proceduresCache = new ProceduresCache(); + final PackageCache packageCache = new PackageCache(); final TriggerCache triggerCache = new TriggerCache(); final ConstraintCache constraintCache = new ConstraintCache(tableCache); final IndexCache indexCache = new IndexCache(tableCache); @@ -184,7 +185,7 @@ public class MySQLCatalog implements DBSCatalog, DBPSaveableObject, DBPRefreshab if (dbResult.next()) { databaseSize = dbResult.getLong(1); } else { - databaseSize = 0l; + databaseSize = 0L; } } } @@ -264,6 +265,13 @@ public class MySQLCatalog implements DBSCatalog, DBPSaveableObject, DBPRefreshab return proceduresCache.getObject(monitor, this, procName); } + @Association + public Collection getPackages(DBRProgressMonitor monitor) + throws DBException + { + return packageCache.getAllObjects(monitor, this); + } + @Association public Collection getTriggers(DBRProgressMonitor monitor) throws DBException @@ -685,6 +693,30 @@ public class MySQLCatalog implements DBSCatalog, DBPSaveableObject, DBPRefreshab } } + static class PackageCache extends JDBCObjectLookupCache { + + @Override + protected MySQLPackage fetchObject(@NotNull JDBCSession session, @NotNull MySQLCatalog owner, @NotNull JDBCResultSet dbResult) + throws SQLException, DBException + { + return new MySQLPackage(owner, dbResult); + } + + @Override + public JDBCStatement prepareLookupStatement(JDBCSession session, MySQLCatalog owner, MySQLPackage object, String objectName) throws SQLException { + JDBCPreparedStatement dbStat = session.prepareStatement( + "SELECT name,comment FROM mysql.proc\n" + + "WHERE db = ? AND type = 'PACKAGE'" + + (object == null && objectName == null ? "" : " \nAND name = ?") + ); + dbStat.setString(1, owner.getName()); + if (object != null || objectName != null) { + dbStat.setString(2, object != null ? object.getName() : objectName); + } + return dbStat; + } + } + static class TriggerCache extends JDBCObjectLookupCache { @Override diff --git a/plugins/org.jkiss.dbeaver.ext.mysql/src/org/jkiss/dbeaver/ext/mysql/model/MySQLPackage.java b/plugins/org.jkiss.dbeaver.ext.mysql/src/org/jkiss/dbeaver/ext/mysql/model/MySQLPackage.java new file mode 100644 index 0000000000000000000000000000000000000000..477cee0210920b6a91d4fcdf5e3a5c622c2bd21a --- /dev/null +++ b/plugins/org.jkiss.dbeaver.ext.mysql/src/org/jkiss/dbeaver/ext/mysql/model/MySQLPackage.java @@ -0,0 +1,225 @@ +/* + * DBeaver - Universal Database Manager + * Copyright (C) 2010-2018 Serge Rider (serge@jkiss.org) + * + * 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 org.jkiss.dbeaver.ext.mysql.model; + +import org.jkiss.code.NotNull; +import org.jkiss.dbeaver.DBException; +import org.jkiss.dbeaver.model.*; +import org.jkiss.dbeaver.model.exec.DBCException; +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.JDBCUtils; +import org.jkiss.dbeaver.model.impl.jdbc.cache.JDBCObjectCache; +import org.jkiss.dbeaver.model.meta.Association; +import org.jkiss.dbeaver.model.meta.Property; +import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor; +import org.jkiss.dbeaver.model.struct.DBSObject; +import org.jkiss.dbeaver.model.struct.DBSObjectContainer; +import org.jkiss.dbeaver.model.struct.rdb.DBSProcedureContainer; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Collection; +import java.util.Map; + +/** + * GenericProcedure + */ +public class MySQLPackage + implements DBPScriptObject, DBPScriptObjectExt, DBSObjectContainer, DBPRefreshableObject, DBSProcedureContainer, DBPQualifiedObject +{ + private MySQLCatalog catalog; + private String name; + private String description; + private boolean persisted; + private final ProceduresCache proceduresCache = new ProceduresCache(); + private String sourceDeclaration; + private String sourceDefinition; + + public MySQLPackage( + MySQLCatalog catalog, + ResultSet dbResult) + { + this.catalog = catalog; + this.name = JDBCUtils.safeGetString(dbResult, "name"); + this.description = JDBCUtils.safeGetString(dbResult, "comment"); + this.persisted = true; + } + + public MySQLPackage(MySQLCatalog catalog, String name) + { + this.catalog = catalog; + this.name = name; + this.persisted = false; + } + + @Override + public DBPDataSource getDataSource() { + return catalog.getDataSource(); + } + + @Override + public DBSObject getParentObject() { + return catalog; + } + + @Override + public boolean isPersisted() { + return persisted; + } + + @Property(viewable = true, order = 1) + @Override + public String getName() { + return name; + } + + @Override + public String getFullyQualifiedName(DBPEvaluationContext context) { + return DBUtils.getFullQualifiedName(getDataSource(), + getCatalog(), + this); + } + + @Property(viewable = true, order = 100) + @Override + public String getDescription() { + return description; + } + + public MySQLCatalog getCatalog() { + return catalog; + } + + @Override + @Property(hidden = true, editable = true, updatable = true, order = -1) + public String getObjectDefinitionText(DBRProgressMonitor monitor, Map options) throws DBCException + { + if (sourceDeclaration == null && monitor != null) { + sourceDeclaration = readSource(monitor, false); + } + return sourceDeclaration; + } + + public void setObjectDefinitionText(String sourceDeclaration) + { + this.sourceDeclaration = sourceDeclaration; + } + + @Override + @Property(hidden = true, editable = true, updatable = true, order = -1) + public String getExtendedDefinitionText(DBRProgressMonitor monitor) throws DBException + { + if (sourceDefinition == null && monitor != null) { + sourceDefinition = readSource(monitor, true); + } + return sourceDefinition; + } + + public void setExtendedDefinitionText(String source) + { + this.sourceDefinition = source; + } + + @Association + public Collection getProcedures(DBRProgressMonitor monitor) throws DBException + { + return proceduresCache.getAllObjects(monitor, this); + } + + @Override + public MySQLProcedure getProcedure(DBRProgressMonitor monitor, String uniqueName) throws DBException { + return proceduresCache.getObject(monitor, this, uniqueName); + } + + @Override + public Collection getChildren(@NotNull DBRProgressMonitor monitor) throws DBException + { + return proceduresCache.getAllObjects(monitor, this); + } + + @Override + public DBSObject getChild(@NotNull DBRProgressMonitor monitor, @NotNull String childName) throws DBException + { + return proceduresCache.getObject(monitor, this, childName); + } + + @Override + public Class getChildType(@NotNull DBRProgressMonitor monitor) throws DBException + { + return MySQLProcedure.class; + } + + @Override + public void cacheStructure(@NotNull DBRProgressMonitor monitor, int scope) throws DBException + { + proceduresCache.getAllObjects(monitor, this); + } + + @Override + public DBSObject refreshObject(@NotNull DBRProgressMonitor monitor) throws DBException + { + this.proceduresCache.clearCache(); + this.sourceDeclaration = null; + this.sourceDefinition = null; + return this; + } + + private String readSource(DBRProgressMonitor monitor, boolean isBody) throws DBCException { + try (JDBCSession session = DBUtils.openMetaSession(monitor, getDataSource(), "Read package declaration")) { + try (JDBCPreparedStatement dbStat = session.prepareStatement("SHOW CREATE PACKAGE" + (isBody ? " BODY" : "") + " " + getFullyQualifiedName(DBPEvaluationContext.DML))) { + try (JDBCResultSet dbResult = dbStat.executeQuery()) { + if (dbResult.next()) { + return JDBCUtils.safeGetString(dbResult, (isBody ? "Create Package Body" : "Create Package")); + } else { + throw new DBCException("Package '" + getName() + "' not found"); + } + } + } + } catch (SQLException e) { + throw new DBCException(e, getDataSource()); + } + } + + static class ProceduresCache extends JDBCObjectCache { + + @Override + protected JDBCStatement prepareObjectsStatement(@NotNull JDBCSession session, @NotNull MySQLPackage owner) + throws SQLException + { + JDBCPreparedStatement dbStat = session.prepareStatement( + "SELECT P.*,CASE WHEN A.DATA_TYPE IS NULL THEN 'PROCEDURE' ELSE 'FUNCTION' END as PROCEDURE_TYPE FROM ALL_PROCEDURES P\n" + + "LEFT OUTER JOIN ALL_ARGUMENTS A ON A.OWNER=P.OWNER AND A.PACKAGE_NAME=P.OBJECT_NAME AND A.OBJECT_NAME=P.PROCEDURE_NAME AND A.ARGUMENT_NAME IS NULL AND A.DATA_LEVEL=0\n" + + "WHERE P.OWNER=? AND P.OBJECT_NAME=?\n" + + "ORDER BY P.PROCEDURE_NAME"); + dbStat.setString(1, owner.getCatalog().getName()); + dbStat.setString(2, owner.getName()); + return dbStat; + } + + @Override + protected MySQLProcedure fetchObject(@NotNull JDBCSession session, @NotNull MySQLPackage owner, @NotNull JDBCResultSet dbResult) + throws SQLException, DBException + { + return new MySQLProcedure(owner.getCatalog(), dbResult); + } + + } + +}