From 3d0acb066fde4741cc4c292c5476afa5fb630669 Mon Sep 17 00:00:00 2001 From: Alexander Fedorov Date: Fri, 12 Jan 2018 14:31:38 +0300 Subject: [PATCH] #2556 show stackframe --- .../dbeaver/debug/DBGBaseController.java | 10 +- .../jkiss/dbeaver/debug/DBGController.java | 2 +- .../debug/core/DatabaseLaunchDelegate.java | 10 +- .../core/model/DatabaseDebugElement.java | 4 +- .../debug/core/model/DatabaseDebugTarget.java | 5 +- .../debug/core/model/DatabaseStackFrame.java | 162 ++++++++++++++++++ .../debug/core/model/DatabaseThread.java | 7 +- .../ui/DatabaseDebugModelPresentation.java | 5 + .../internal/impl/PostgreDebugController.java | 108 +++++++++++- .../internal/impl/PostgreDebugSession.java | 2 +- 10 files changed, 297 insertions(+), 18 deletions(-) create mode 100644 plugins/org.jkiss.dbeaver.debug.core/src/org/jkiss/dbeaver/debug/core/model/DatabaseStackFrame.java diff --git a/plugins/org.jkiss.dbeaver.debug.core/src/org/jkiss/dbeaver/debug/DBGBaseController.java b/plugins/org.jkiss.dbeaver.debug.core/src/org/jkiss/dbeaver/debug/DBGBaseController.java index 2439dc32cc..49a15cf636 100644 --- a/plugins/org.jkiss.dbeaver.debug.core/src/org/jkiss/dbeaver/debug/DBGBaseController.java +++ b/plugins/org.jkiss.dbeaver.debug.core/src/org/jkiss/dbeaver/debug/DBGBaseController.java @@ -18,6 +18,7 @@ package org.jkiss.dbeaver.debug; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -72,7 +73,7 @@ public abstract class DBGBaseController implements DBGController { DBGSession debugSession = createDebugSession(targetInfo, sessionContext); Object id = targetInfo.getID(); sessions.put(id, debugSession); - attachSession(debugSession, sessionContext, configuration); + attachSession(debugSession, sessionContext, configuration, monitor); return id; } catch (DBException e) { String message = NLS.bind(DebugMessages.DatabaseDebugController_e_opening_debug_context, @@ -82,7 +83,7 @@ public abstract class DBGBaseController implements DBGController { } } - public abstract void attachSession(DBGSession session, DBCExecutionContext sessionContext, Map configuataion) throws DBGException; + public abstract void attachSession(DBGSession session, DBCExecutionContext sessionContext, Map configuataion, DBRProgressMonitor monitor) throws DBGException, DBException; @Override public void resume(DBRProgressMonitor monitor) throws DBGException { @@ -107,7 +108,10 @@ public abstract class DBGBaseController implements DBGController { @Override public void dispose() { executionContext.close(); - //FIXME: AF: perform cleanup for everything cached + Collection values = sessions.values(); + for (DBGSession session : values) { + session.close(); + } } @Override diff --git a/plugins/org.jkiss.dbeaver.debug.core/src/org/jkiss/dbeaver/debug/DBGController.java b/plugins/org.jkiss.dbeaver.debug.core/src/org/jkiss/dbeaver/debug/DBGController.java index 28f2936a2f..5857650a9a 100644 --- a/plugins/org.jkiss.dbeaver.debug.core/src/org/jkiss/dbeaver/debug/DBGController.java +++ b/plugins/org.jkiss.dbeaver.debug.core/src/org/jkiss/dbeaver/debug/DBGController.java @@ -62,7 +62,7 @@ public interface DBGController { */ void detach(Object key, DBRProgressMonitor monitor) throws DBGException; - void dispose() throws DBGException; + void dispose(); List getStack(Object id) throws DBGException; diff --git a/plugins/org.jkiss.dbeaver.debug.core/src/org/jkiss/dbeaver/debug/core/DatabaseLaunchDelegate.java b/plugins/org.jkiss.dbeaver.debug.core/src/org/jkiss/dbeaver/debug/core/DatabaseLaunchDelegate.java index 596627b33d..7cefb2b2f6 100644 --- a/plugins/org.jkiss.dbeaver.debug.core/src/org/jkiss/dbeaver/debug/core/DatabaseLaunchDelegate.java +++ b/plugins/org.jkiss.dbeaver.debug.core/src/org/jkiss/dbeaver/debug/core/DatabaseLaunchDelegate.java @@ -57,15 +57,19 @@ public abstract class DatabaseLaunchDelegate extends LaunchConfigurationDelegate launch.addDebugTarget(target); } - protected Map extractAttributes(ILaunchConfiguration configuration) { + protected Map extractAttributes(ILaunchConfiguration configuration) throws CoreException { Map attributes = new HashMap<>(); String databaseName = DebugCore.extractDatabaseName(configuration); attributes.put(DBGController.DATABASE_NAME, databaseName); + String oid = DebugCore.extractStringAttribute(configuration, DebugCore.ATTR_OID, DebugCore.ATTR_OID_DEFAULT); + attributes.put(DBGController.PROCEDURE_OID, oid); //FIXME:AF:extract from launch configuration - //FIXME 16749 - OID for debug proc - attributes.put(DBGController.PROCEDURE_OID, 16749); //FIXME -1 - target PID (-1 for ANY PID) attributes.put(DBGController.PROCESS_ID, -1); + //Well, put it all for now + attributes.putAll(configuration.getAttributes()); + //FIXME:AF:and little hack until we implemented the parameter storage during launch config creation + attributes.put("tabname", "pg_class"); return attributes; } diff --git a/plugins/org.jkiss.dbeaver.debug.core/src/org/jkiss/dbeaver/debug/core/model/DatabaseDebugElement.java b/plugins/org.jkiss.dbeaver.debug.core/src/org/jkiss/dbeaver/debug/core/model/DatabaseDebugElement.java index 5dcb2d0379..27e187f26d 100644 --- a/plugins/org.jkiss.dbeaver.debug.core/src/org/jkiss/dbeaver/debug/core/model/DatabaseDebugElement.java +++ b/plugins/org.jkiss.dbeaver.debug.core/src/org/jkiss/dbeaver/debug/core/model/DatabaseDebugElement.java @@ -26,12 +26,12 @@ public class DatabaseDebugElement extends DebugElement { super(target); } - public IDatabaseDebugTarget geDatabaseDebugTarget() { + public IDatabaseDebugTarget getDatabaseDebugTarget() { return (IDatabaseDebugTarget) getDebugTarget(); } public DBGController getController() { - return geDatabaseDebugTarget().getController(); + return getDatabaseDebugTarget().getController(); } @Override diff --git a/plugins/org.jkiss.dbeaver.debug.core/src/org/jkiss/dbeaver/debug/core/model/DatabaseDebugTarget.java b/plugins/org.jkiss.dbeaver.debug.core/src/org/jkiss/dbeaver/debug/core/model/DatabaseDebugTarget.java index d05ff4fcab..f8c7e3c30b 100644 --- a/plugins/org.jkiss.dbeaver.debug.core/src/org/jkiss/dbeaver/debug/core/model/DatabaseDebugTarget.java +++ b/plugins/org.jkiss.dbeaver.debug.core/src/org/jkiss/dbeaver/debug/core/model/DatabaseDebugTarget.java @@ -145,8 +145,9 @@ public abstract class DatabaseDebugTarget extends DatabaseDebugElement implement this.thread = newThread(controller, sessionKey); threads.add(thread); } catch (DBGException e) { - String message = NLS.bind("Failed to connect {0) to the target", getName()); + String message = NLS.bind("Failed to connect {0} to the target", getName()); IStatus error = DebugCore.newErrorStatus(message, e); + process.terminate(); throw new CoreException(error); } } @@ -176,6 +177,8 @@ public abstract class DatabaseDebugTarget extends DatabaseDebugElement implement String message = NLS.bind("Error terminating {0}", getName()); IStatus status = DebugCore.newErrorStatus(message, e); throw new DebugException(status); + } finally { + controller.dispose(); } } } diff --git a/plugins/org.jkiss.dbeaver.debug.core/src/org/jkiss/dbeaver/debug/core/model/DatabaseStackFrame.java b/plugins/org.jkiss.dbeaver.debug.core/src/org/jkiss/dbeaver/debug/core/model/DatabaseStackFrame.java new file mode 100644 index 0000000000..5f5b01a0ab --- /dev/null +++ b/plugins/org.jkiss.dbeaver.debug.core/src/org/jkiss/dbeaver/debug/core/model/DatabaseStackFrame.java @@ -0,0 +1,162 @@ +package org.jkiss.dbeaver.debug.core.model; + +import org.eclipse.debug.core.DebugException; +import org.eclipse.debug.core.model.IRegisterGroup; +import org.eclipse.debug.core.model.IStackFrame; +import org.eclipse.debug.core.model.IThread; +import org.eclipse.debug.core.model.IVariable; +import org.jkiss.dbeaver.debug.DBGStackFrame; + +public class DatabaseStackFrame extends DatabaseDebugElement implements IStackFrame { + + private final DBGStackFrame dbgStackFrame; + private final DatabaseThread thread; + + public DatabaseStackFrame(DatabaseThread thread, DBGStackFrame dbgStackFrame) { + super(thread.getDatabaseDebugTarget()); + this.thread = thread; + this.dbgStackFrame = dbgStackFrame; + } + + @Override + public boolean canStepInto() { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean canStepOver() { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean canStepReturn() { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean isStepping() { + // TODO Auto-generated method stub + return false; + } + + @Override + public void stepInto() throws DebugException { + // TODO Auto-generated method stub + + } + + @Override + public void stepOver() throws DebugException { + // TODO Auto-generated method stub + + } + + @Override + public void stepReturn() throws DebugException { + // TODO Auto-generated method stub + + } + + @Override + public boolean canResume() { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean canSuspend() { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean isSuspended() { + // TODO Auto-generated method stub + return false; + } + + @Override + public void resume() throws DebugException { + // TODO Auto-generated method stub + + } + + @Override + public void suspend() throws DebugException { + // TODO Auto-generated method stub + + } + + @Override + public boolean canTerminate() { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean isTerminated() { + // TODO Auto-generated method stub + return false; + } + + @Override + public void terminate() throws DebugException { + // TODO Auto-generated method stub + + } + + @Override + public IThread getThread() { + return thread; + } + + @Override + public IVariable[] getVariables() throws DebugException { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean hasVariables() throws DebugException { + // TODO Auto-generated method stub + return false; + } + + @Override + public int getLineNumber() throws DebugException { + return dbgStackFrame.getLine(); + } + + @Override + public int getCharStart() throws DebugException { + // TODO Auto-generated method stub + return 0; + } + + @Override + public int getCharEnd() throws DebugException { + // TODO Auto-generated method stub + return 0; + } + + @Override + public String getName() throws DebugException { + return dbgStackFrame.toString(); + } + + @Override + public IRegisterGroup[] getRegisterGroups() throws DebugException { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean hasRegisterGroups() throws DebugException { + // TODO Auto-generated method stub + return false; + } + +} diff --git a/plugins/org.jkiss.dbeaver.debug.core/src/org/jkiss/dbeaver/debug/core/model/DatabaseThread.java b/plugins/org.jkiss.dbeaver.debug.core/src/org/jkiss/dbeaver/debug/core/model/DatabaseThread.java index cc657e1f6c..1d9306fe53 100644 --- a/plugins/org.jkiss.dbeaver.debug.core/src/org/jkiss/dbeaver/debug/core/model/DatabaseThread.java +++ b/plugins/org.jkiss.dbeaver.debug.core/src/org/jkiss/dbeaver/debug/core/model/DatabaseThread.java @@ -128,11 +128,14 @@ public abstract class DatabaseThread extends DatabaseDebugElement implements ITh @Override public IStackFrame[] getStackFrames() throws DebugException { - List frames = new ArrayList(); + List frames = new ArrayList(); DBGController controller = getController(); try { List stack = controller.getStack(sessionKey); - stack.size(); + for (DBGStackFrame dbgStackFrame : stack) { + DatabaseStackFrame frame = new DatabaseStackFrame(this, dbgStackFrame); + frames.add(frame); + } } catch (DBGException e) { // TODO Auto-generated catch block e.printStackTrace(); diff --git a/plugins/org.jkiss.dbeaver.debug.ui/src/org/jkiss/dbeaver/debug/ui/DatabaseDebugModelPresentation.java b/plugins/org.jkiss.dbeaver.debug.ui/src/org/jkiss/dbeaver/debug/ui/DatabaseDebugModelPresentation.java index 0dcb132037..aa58ff2f08 100644 --- a/plugins/org.jkiss.dbeaver.debug.ui/src/org/jkiss/dbeaver/debug/ui/DatabaseDebugModelPresentation.java +++ b/plugins/org.jkiss.dbeaver.debug.ui/src/org/jkiss/dbeaver/debug/ui/DatabaseDebugModelPresentation.java @@ -30,6 +30,7 @@ import org.eclipse.swt.graphics.Image; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.model.WorkbenchLabelProvider; import org.jkiss.dbeaver.debug.core.model.DatabaseProcess; +import org.jkiss.dbeaver.debug.core.model.DatabaseStackFrame; import org.jkiss.dbeaver.debug.core.model.DatabaseThread; import org.jkiss.dbeaver.debug.core.model.IDatabaseDebugTarget; @@ -71,6 +72,10 @@ public class DatabaseDebugModelPresentation extends LabelProvider implements IDe { // FIXME:AF: register adapters try { + if (element instanceof DatabaseStackFrame) { + DatabaseStackFrame stackFrame = (DatabaseStackFrame) element; + return stackFrame.getName(); + } if (element instanceof DatabaseThread) { DatabaseThread thread = (DatabaseThread) element; return thread.getName(); diff --git a/plugins/org.jkiss.dbeaver.ext.postgresql.debug.core/src/org/jkiss/dbeaver/ext/postgresql/debug/internal/impl/PostgreDebugController.java b/plugins/org.jkiss.dbeaver.ext.postgresql.debug.core/src/org/jkiss/dbeaver/ext/postgresql/debug/internal/impl/PostgreDebugController.java index 5cfc2e041f..c39c16ab1d 100644 --- a/plugins/org.jkiss.dbeaver.ext.postgresql.debug.core/src/org/jkiss/dbeaver/ext/postgresql/debug/internal/impl/PostgreDebugController.java +++ b/plugins/org.jkiss.dbeaver.ext.postgresql.debug.core/src/org/jkiss/dbeaver/ext/postgresql/debug/internal/impl/PostgreDebugController.java @@ -22,19 +22,45 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; +import java.util.Collection; import java.util.List; import java.util.Map; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.osgi.util.NLS; +import org.jkiss.dbeaver.DBException; +import org.jkiss.dbeaver.Log; import org.jkiss.dbeaver.debug.DBGBaseController; import org.jkiss.dbeaver.debug.DBGException; import org.jkiss.dbeaver.debug.DBGSession; import org.jkiss.dbeaver.debug.DBGSessionInfo; +import org.jkiss.dbeaver.debug.core.DebugCore; +import org.jkiss.dbeaver.ext.postgresql.model.PostgreDataSource; +import org.jkiss.dbeaver.ext.postgresql.model.PostgreDatabase; +import org.jkiss.dbeaver.ext.postgresql.model.PostgreProcedure; +import org.jkiss.dbeaver.ext.postgresql.model.PostgreSchema; +import org.jkiss.dbeaver.model.DBPDataKind; +import org.jkiss.dbeaver.model.DBPDataSource; import org.jkiss.dbeaver.model.DBPDataSourceContainer; +import org.jkiss.dbeaver.model.DBUtils; +import org.jkiss.dbeaver.model.exec.DBCException; import org.jkiss.dbeaver.model.exec.DBCExecutionContext; +import org.jkiss.dbeaver.model.exec.DBCSession; +import org.jkiss.dbeaver.model.exec.DBCStatement; +import org.jkiss.dbeaver.model.exec.DBCStatementType; import org.jkiss.dbeaver.model.impl.jdbc.JDBCExecutionContext; +import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor; import org.jkiss.dbeaver.model.runtime.VoidProgressMonitor; +import org.jkiss.dbeaver.model.struct.DBSTypedObject; +import org.jkiss.dbeaver.model.struct.rdb.DBSProcedure; +import org.jkiss.dbeaver.model.struct.rdb.DBSProcedureParameter; public class PostgreDebugController extends DBGBaseController { + + private static Log log = Log.getLog(PostgreDebugController.class); private static final String SQL_SESSION = "select pid,usename,application_name,state,query from pg_stat_activity"; //$NON-NLS-1$ @@ -136,14 +162,86 @@ public class PostgreDebugController extends DBGBaseController { } @Override - public void attachSession(DBGSession session, DBCExecutionContext sessionContext, Map configuration) throws DBGException { + public void attachSession(DBGSession session, DBCExecutionContext sessionContext, Map configuration, DBRProgressMonitor monitor) throws DBException { PostgreDebugSession pgSession = (PostgreDebugSession) session; - JDBCExecutionContext jdbcContext = (JDBCExecutionContext) sessionContext; + JDBCExecutionContext sessionJdbc = (JDBCExecutionContext) sessionContext; //FIXME 16749 - OID for debug proc //FIXME -1 - target PID (-1 for ANY PID) - Integer oid = (Integer) configuration.get(PROCEDURE_OID); - Integer pid = (Integer) configuration.get(PROCESS_ID); - pgSession.attach(jdbcContext, oid, pid); + int oid = Integer.parseInt(String.valueOf(configuration.get(PROCEDURE_OID))); + int pid = Integer.parseInt(String.valueOf(configuration.get(PROCESS_ID))); + String databaseName = String.valueOf(configuration.get(DATABASE_NAME)); + pgSession.attach(sessionJdbc, oid, pid); + DBPDataSource dataSource = sessionContext.getDataSource(); + executeProcedure(configuration, monitor, oid, databaseName, dataSource); + } + + private void executeProcedure(Map configuration, DBRProgressMonitor monitor, int oid, + String databaseName, DBPDataSource dataSource) throws DBException { + if (dataSource instanceof PostgreDataSource) { + PostgreDataSource pgDS = (PostgreDataSource) dataSource; + PostgreDatabase database = pgDS.getDatabase(databaseName); + PostgreSchema schema = database.getSchema(monitor, "public"); + PostgreProcedure procedure = schema.getProcedure(monitor, oid); + String call = composeProcedureCall(procedure, configuration, monitor); + String taskName = NLS.bind("Execute procedure {0}", procedure.getName()); + Job job = new Job(taskName) { + + @Override + protected IStatus run(IProgressMonitor monitor) { + try { + try (final DBCSession execSession = DBUtils.openUtilSession(new VoidProgressMonitor(), dataSource, taskName)) { + try (final DBCStatement dbStat = execSession.prepareStatement(DBCStatementType.EXEC, call, true, false, + false)) { + dbStat.executeStatement(); + } + } + } catch (DBCException e) { + log.error(taskName, e); + return DebugCore.newErrorStatus(taskName, e); + + } + return Status.OK_STATUS; + } + }; + job.schedule(); + } } + private String composeProcedureCall(DBSProcedure procedure, Map configuration, + DBRProgressMonitor monitor) throws DBException { + StringBuilder sb = new StringBuilder(); + sb.append("select").append(' ').append(procedure.getName()); + sb.append('('); + Collection parameters = procedure.getParameters(monitor); + if (parameters.size() > 0) { + for (DBSProcedureParameter parameter : parameters) { + String name = parameter.getName(); + Object value = configuration.get(name); + if (value == null) { + value = '?'; + sb.append(value); + } else { + DBSTypedObject parameterType = parameter.getParameterType(); + DBPDataKind dataKind = parameterType.getDataKind(); + switch (dataKind) { + case STRING: + sb.append('\''); + sb.append(value); + sb.append('\''); + break; + + default: + sb.append(value); + break; + } + } + sb.append(','); + } + sb.deleteCharAt(sb.length()-1); + } + sb.append(')'); + String call = sb.toString(); + return call; + } + } diff --git a/plugins/org.jkiss.dbeaver.ext.postgresql.debug.core/src/org/jkiss/dbeaver/ext/postgresql/debug/internal/impl/PostgreDebugSession.java b/plugins/org.jkiss.dbeaver.ext.postgresql.debug.core/src/org/jkiss/dbeaver/ext/postgresql/debug/internal/impl/PostgreDebugSession.java index f66d26a2ac..dbc2c21dd5 100644 --- a/plugins/org.jkiss.dbeaver.ext.postgresql.debug.core/src/org/jkiss/dbeaver/ext/postgresql/debug/internal/impl/PostgreDebugSession.java +++ b/plugins/org.jkiss.dbeaver.ext.postgresql.debug.core/src/org/jkiss/dbeaver/ext/postgresql/debug/internal/impl/PostgreDebugSession.java @@ -132,8 +132,8 @@ public class PostgreDebugSession implements DBGSession { ResultSet rs = stmt.executeQuery(SQL_LISTEN)) { if (rs.next()) { - getConnection(connection).setClientInfo("ApplicationName", "Debug Mode : " + String.valueOf(sessionId)); sessionId = rs.getInt("sessionid"); + getConnection(connection).setClientInfo("ApplicationName", "Debug Mode : " + String.valueOf(sessionId)); } else { throw new DBGException("Unable to create debug instance"); } -- GitLab