提交 6673ec5f 编写于 作者: S Serge Rider 提交者: GitHub

Merge pull request #2811 from dbeaver/2556-debug-events

2556 debug events

Former-commit-id: 31b55ea7
......@@ -21,3 +21,5 @@ Bundle-Name = DBeaver Debug Core
databaseBreakpoint.name=Database Breakpoint
databaseLineBreakpoint.name=Database Line Breakpoint
procedureSourceLocator.name = Procedure Source Locator
\ No newline at end of file
......@@ -30,5 +30,29 @@
name="%databaseLineBreakpoint.name">
</breakpoint>
</extension>
<extension
point="org.eclipse.debug.core.sourceLocators">
<sourceLocator
class="org.jkiss.dbeaver.debug.sourcelookup.ProcedureSourceLookupDirector"
id="org.jkiss.dbeaver.debug.core.procedureSourceLocator"
name="%procedureSourceLocator.name">
</sourceLocator>
</extension>
<extension
point="org.eclipse.debug.core.sourcePathComputers">
<sourcePathComputer
class="org.jkiss.dbeaver.debug.sourcelookup.ProcedureSourcePathComputer"
id="org.jkiss.dbeaver.debug.core.procedureSourcePathComputer">
</sourcePathComputer>
</extension>
<extension
point="org.eclipse.debug.core.sourceContainerTypes">
<sourceContainerType
class="org.jkiss.dbeaver.debug.sourcelookup.DatasourceSourceContainerTypeDelegate"
description="A collection of databases"
id="org.jkiss.dbeaver.debug.core.datasourceSourceContainerType"
name="Databases">
</sourceContainerType>
</extension>
</plugin>
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2017 Serge Rider (serge@jkiss.org)
* Copyright (C) 2017 Alexander Fedorov (alexander.fedorov@jkiss.org)
* Copyright (C) 2010-2018 Serge Rider (serge@jkiss.org)
* Copyright (C) 2017-2018 Andrew Khitrin (ahitrin@gmail.com)
* Copyright (C) 2017-2018 Alexander Fedorov (alexander.fedorov@jkiss.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -23,14 +24,26 @@ import java.util.HashMap;
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.ListenerList;
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.core.DebugCore;
import org.jkiss.dbeaver.debug.internal.DebugMessages;
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.runtime.DBRProgressMonitor;
import org.jkiss.dbeaver.model.runtime.VoidProgressMonitor;
public abstract class DBGBaseController implements DBGController {
......@@ -41,6 +54,8 @@ public abstract class DBGBaseController implements DBGController {
private final Map<String, Object> configuration = new HashMap<String, Object>();
private final Map<Object, DBGSession> sessions = new HashMap<Object, DBGSession>(1);
private ListenerList<DBGEventHandler> eventHandlers = new ListenerList<>();
private DBCExecutionContext executionContext;
public DBGBaseController(DBPDataSourceContainer dataSourceContainer) {
......@@ -112,6 +127,10 @@ public abstract class DBGBaseController implements DBGController {
for (DBGSession session : values) {
session.close();
}
Object[] listeners = eventHandlers.getListeners();
for (Object listener : listeners) {
unregisterEventHandler((DBGEventHandler) listener);
}
}
@Override
......@@ -180,4 +199,46 @@ public abstract class DBGBaseController implements DBGController {
//throw DBGException?
}
@Override
public void registerEventHandler(DBGEventHandler eventHandler) {
eventHandlers.add(eventHandler);
}
@Override
public void unregisterEventHandler(DBGEventHandler eventHandler) {
eventHandlers.remove(eventHandler);
}
public void fireEvent(DBGEvent event) {
for (DBGEventHandler eventHandler : eventHandlers) {
eventHandler.handleDebugEvent(event);
}
}
protected void executeProcedure(DBPDataSource dataSource, Map<String, Object> configuration, DBRProgressMonitor monitor) throws DBException {
String procedureName = String.valueOf(configuration.get(PROCEDURE_NAME));
String call = String.valueOf(configuration.get(PROCEDURE_CALL));
String taskName = NLS.bind("Execute procedure {0}", procedureName);
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();
}
}
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2018 Serge Rider (serge@jkiss.org)
* Copyright (C) 2017-2018 Andrew Khitrin (ahitrin@gmail.com)
* Copyright (C) 2017-2018 Alexander Fedorov (alexander.fedorov@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.debug;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.model.impl.jdbc.JDBCExecutionContext;
import org.jkiss.dbeaver.model.runtime.VoidProgressMonitor;
public abstract class DBGBaseSession implements DBGSession {
private static final Log log = Log.getLog(DBGBaseSession.class);
protected final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true);
private final DBGBaseController controller;
private FutureTask<DBGEvent> task;
private Thread workerThread = null;
private JDBCExecutionContext connection = null;
private final List<DBGBreakpointDescriptor> breakpoints = new ArrayList<>(1);
public DBGBaseSession(DBGBaseController controller) {
this.controller = controller;
}
/**
* Return connection used in debug session
*
* @return java.sql.Connection
* @throws DBGException
*/
// FIXME: rework to DBC API
protected Connection getConnection() throws DBGException {
try {
return ((JDBCExecutionContext) connection).getConnection(new VoidProgressMonitor());
} catch (SQLException e) {
throw new DBGException("SQL error", e);
}
}
// FIXME: should be known during construction
protected void setConnection(JDBCExecutionContext connection) {
this.connection = connection;
}
public DBGBaseController getController() {
return controller;
}
/**
* Return true if debug session up and running on server
*
* @return boolean
*/
public boolean isAttached() {
return connection != null;
}
/**
* Return true if session up and running debug thread
*
* @return boolean
*/
public boolean isWaiting() {
return (task == null ? false : !task.isDone()) && (workerThread == null ? false : workerThread.isAlive());
}
/**
* Return true if session waiting target connection (on breakpoint, after
* step or continue) in debug thread
*
* @return boolean
*/
public boolean isDone() {
if (task == null) {
return true;
}
if (task.isDone()) {
try {
DBGEvent dbgEvent = task.get();
getController().fireEvent(dbgEvent);
} catch (InterruptedException e) {
log.error("DEBUG INTERRUPT ERROR ", e);
return false;
} catch (ExecutionException e) {
log.error("DEBUG WARNING ", e);
return false;
}
return true;
}
return false;
}
/**
* Start thread for SQL command
*
* @param commandSQL
* @param name
* @throws DBGException
*/
protected void runAsync(String commandSQL, String name, DBGEvent event) throws DBGException {
Connection connection = getConnection();
try (Statement stmt = connection.createStatement()) {
connection.setAutoCommit(false);
DBGWorker worker = new DBGWorker(connection, commandSQL, event);
task = new FutureTask<DBGEvent>(worker);
workerThread = new Thread(task);
workerThread.setName(name);
workerThread.start();
} catch (SQLException e) {
throw new DBGException("SQL error", e);
}
}
public void close() {
lock.writeLock().lock();
try {
if (!isDone()) {
task.cancel(true);
}
connection.close();
} finally {
lock.writeLock().unlock();
}
}
@Override
public void abort() throws DBGException {
acquireReadLock();
try (Statement stmt = getConnection().createStatement()) {
String sqlCommand = composeAbortCommand();
stmt.execute(sqlCommand);
// FIXME: move to finally?
task = null;
} catch (SQLException e) {
throw new DBGException("SQL error", e);
} finally {
lock.readLock().unlock();
}
}
protected abstract String composeAbortCommand();
@Override
public List<? extends DBGBreakpointDescriptor> getBreakpoints() {
return new ArrayList<DBGBreakpointDescriptor>(breakpoints);
}
@Override
public void addBreakpoint(DBGBreakpointDescriptor descriptor) throws DBGException {
acquireReadLock();
try {
try (Statement stmt = getConnection().createStatement()) {
String sqlQuery = composeAddBreakpointCommand(descriptor);
stmt.executeQuery(sqlQuery);
} catch (SQLException e) {
throw new DBGException("SQL error", e);
}
breakpoints.add(descriptor);
} finally {
lock.readLock().unlock();
}
}
protected abstract String composeAddBreakpointCommand(DBGBreakpointDescriptor descriptor);
@Override
public void removeBreakpoint(DBGBreakpointDescriptor bp) throws DBGException {
acquireReadLock();
try {
try (Statement stmt = getConnection().createStatement()) {
String sqlCommand = composeRemoveBreakpointCommand(bp);
stmt.executeQuery(sqlCommand);
} catch (SQLException e) {
throw new DBGException("SQL error", e);
}
breakpoints.remove(bp);
} finally {
lock.readLock().unlock();
}
}
protected abstract String composeRemoveBreakpointCommand(DBGBreakpointDescriptor descriptor);
/**
* Try to acquire shared lock
*
* @throws DBGException
*/
protected void acquireReadLock() throws DBGException {
try {
lock.readLock().lockInterruptibly();
} catch (InterruptedException e1) {
throw new DBGException(e1.getMessage());
}
if (!isAttached()) {
lock.readLock().unlock();
throw new DBGException("Debug session not attached");
}
if (isWaiting()) {
lock.readLock().unlock();
throw new DBGException("Debug session in waiting state");
}
if (!isDone()) {
lock.readLock().unlock();
throw new DBGException("Debug session in incorrect state");
}
}
/**
* Try to acquire exclusive lock
*
* @throws DBGException
*/
protected void acquireWriteLock() throws DBGException {
try {
lock.writeLock().lockInterruptibly();
} catch (InterruptedException e1) {
throw new DBGException(e1.getMessage());
}
if (!isAttached()) {
lock.writeLock().unlock();
throw new DBGException("Debug session not attached");
}
if (isWaiting()) {
lock.writeLock().unlock();
throw new DBGException("Debug session in waiting state");
}
if (!isDone()) {
lock.writeLock().unlock();
throw new DBGException("Debug session in incorrect state");
}
}
}
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2017 Serge Rider (serge@jkiss.org)
* Copyright (C) 2017 Andrew Khitrin (ahitrin@gmail.com)
* Copyright (C) 2010-2018 Serge Rider (serge@jkiss.org)
* Copyright (C) 2017-2018 Andrew Khitrin (ahitrin@gmail.com)
* Copyright (C) 2017-2018 Alexander Fedorov (alexander.fedorov@jkiss.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2017 Andrew Khitrin (ahitrin@gmail.com)
* Copyright (C) 2010-2018 Serge Rider (serge@jkiss.org)
* Copyright (C) 2017-2018 Andrew Khitrin (ahitrin@gmail.com)
* Copyright (C) 2017-2018 Alexander Fedorov (alexander.fedorov@jkiss.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2017 Serge Rider (serge@jkiss.org)
* Copyright (C) 2017 Alexander Fedorov (alexander.fedorov@jkiss.org)
* Copyright (C) 2010-2018 Serge Rider (serge@jkiss.org)
* Copyright (C) 2017-2018 Andrew Khitrin (ahitrin@gmail.com)
* Copyright (C) 2017-2018 Alexander Fedorov (alexander.fedorov@jkiss.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -29,8 +30,11 @@ import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
public interface DBGController {
public static final String DATABASE_NAME = "databaseName"; //$NON-NLS-1$
public static final String SCHEMA_NAME = "schemaName"; //$NON-NLS-1$
public static final String PROCEDURE_OID = "procedureOID"; //$NON-NLS-1$
public static final String PROCESS_ID = "processID"; //$NON-NLS-1$
public static final String PROCEDURE_NAME = "procedureName"; //$NON-NLS-1$
public static final String PROCEDURE_CALL = "procedureCall"; //$NON-NLS-1$
/*
* General lifecycle
......@@ -86,5 +90,12 @@ public interface DBGController {
void stepInto(Object sessionKey) throws DBGException;
void stepOver(Object sessionKey) throws DBGException;
void stepReturn(Object sessionKey) throws DBGException;
/*
* Events
*/
void registerEventHandler(DBGEventHandler eventHandler);
void unregisterEventHandler(DBGEventHandler eventHandler);
}
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2018 Serge Rider (serge@jkiss.org)
* Copyright (C) 2017-2018 Andrew Khitrin (ahitrin@gmail.com)
* Copyright (C) 2017-2018 Alexander Fedorov (alexander.fedorov@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.debug;
import java.util.EventObject;
......@@ -6,9 +24,37 @@ public class DBGEvent extends EventObject {
private static final long serialVersionUID = 1L;
public DBGEvent(Object source) {
super(source);
public static final int ATTACH = 0x0001;
public static final int SUSPEND = 0x0002;
public static final int RESUME = 0x0004;
public static final int DETACH = 0x0008;
public static final int UNSPECIFIED = 0;
public static final int STEP_INTO = 0x0001;
public static final int STEP_OVER = 0x0002;
public static final int STEP_RETURN = 0x0004;
public static final int STEP_END = 0x0008;
private int kind;
private int details;
public DBGEvent(Object source, int kind) {
this(source, kind, UNSPECIFIED);
}
public DBGEvent(Object source, int kind, int details) {
super(source);
this.kind = kind;
this.details = details;
}
public int getKind() {
return kind;
}
public int getDetails() {
return details;
}
}
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2018 Serge Rider (serge@jkiss.org)
* Copyright (C) 2017-2018 Andrew Khitrin (ahitrin@gmail.com)
* Copyright (C) 2017-2018 Alexander Fedorov (alexander.fedorov@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.debug;
public interface DBGEventHandler {
void handleDebugEvent(DBGEvent event);
}
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2017 Serge Rider (serge@jkiss.org)
* Copyright (C) 2017 Andrew Khitrin (ahitrin@gmail.com)
* Copyright (C) 2010-2018 Serge Rider (serge@jkiss.org)
* Copyright (C) 2017-2018 Andrew Khitrin (ahitrin@gmail.com)
* Copyright (C) 2017-2018 Alexander Fedorov (alexander.fedorov@jkiss.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2017 Serge Rider (serge@jkiss.org)
* Copyright (C) 2017 Andrew Khitrin (ahitrin@gmail.com)
* Copyright (C) 2010-2018 Serge Rider (serge@jkiss.org)
* Copyright (C) 2017-2018 Andrew Khitrin (ahitrin@gmail.com)
* Copyright (C) 2017-2018 Alexander Fedorov (alexander.fedorov@jkiss.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2017 Serge Rider (serge@jkiss.org)
* Copyright (C) 2017 Andrew Khitrin (ahitrin@gmail.com)
* Copyright (C) 2010-2018 Serge Rider (serge@jkiss.org)
* Copyright (C) 2017-2018 Andrew Khitrin (ahitrin@gmail.com)
* Copyright (C) 2017-2018 Alexander Fedorov (alexander.fedorov@jkiss.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -26,9 +27,9 @@ public interface DBGSession {
List<? extends DBGBreakpointDescriptor> getBreakpoints();
void addBreakpoint(DBGObjectDescriptor object, DBGBreakpointProperties properties) throws DBGException;
void addBreakpoint(DBGBreakpointDescriptor descriptor) throws DBGException;
void removeBreakpoint(DBGBreakpointDescriptor bp) throws DBGException;
void removeBreakpoint(DBGBreakpointDescriptor descriptor) throws DBGException;
void execContinue() throws DBGException;
......
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2017 Serge Rider (serge@jkiss.org)
* Copyright (C) 2017 Andrew Khitrin (ahitrin@gmail.com)
* Copyright (C) 2010-2018 Serge Rider (serge@jkiss.org)
* Copyright (C) 2017-2018 Andrew Khitrin (ahitrin@gmail.com)
* Copyright (C) 2017-2018 Alexander Fedorov (alexander.fedorov@jkiss.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2017 Serge Rider (serge@jkiss.org)
* Copyright (C) 2017 Andrew Khitrin (ahitrin@gmail.com)
* Copyright (C) 2010-2018 Serge Rider (serge@jkiss.org)
* Copyright (C) 2017-2018 Andrew Khitrin (ahitrin@gmail.com)
* Copyright (C) 2017-2018 Alexander Fedorov (alexander.fedorov@jkiss.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2017 Serge Rider (serge@jkiss.org)
* Copyright (C) 2017 Andrew Khitrin (ahitrin@gmail.com)
* Copyright (C) 2010-2018 Serge Rider (serge@jkiss.org)
* Copyright (C) 2017-2018 Andrew Khitrin (ahitrin@gmail.com)
* Copyright (C) 2017-2018 Alexander Fedorov (alexander.fedorov@jkiss.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2017 Serge Rider (serge@jkiss.org)
* Copyright (C) 2017 Andrew Khitrin (ahitrin@gmail.com)
* Copyright (C) 2010-2018 Serge Rider (serge@jkiss.org)
* Copyright (C) 2017-2018 Andrew Khitrin (ahitrin@gmail.com)
* Copyright (C) 2017-2018 Alexander Fedorov (alexander.fedorov@jkiss.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2017 Serge Rider (serge@jkiss.org)
* Copyright (C) 2017 Andrew Khitrin (ahitrin@gmail.com)
* Copyright (C) 2010-2018 Serge Rider (serge@jkiss.org)
* Copyright (C) 2017-2018 Andrew Khitrin (ahitrin@gmail.com)
* Copyright (C) 2017-2018 Alexander Fedorov (alexander.fedorov@jkiss.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -16,31 +17,33 @@
* limitations under the License.
*/
package org.jkiss.dbeaver.ext.postgresql.debug.internal.impl;
package org.jkiss.dbeaver.debug;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.concurrent.Callable;
public class PostgreDebugSessionWorker implements Callable<Void> {
public class DBGWorker implements Callable<DBGEvent> {
private final Connection conn;
private final String sql;
private final DBGEvent event;
public PostgreDebugSessionWorker(Connection conn, String sqlCommand)
public DBGWorker(Connection conn, String sqlCommand, DBGEvent event)
{
this.conn = conn;
this.sql = sqlCommand;
this.event = event;
}
@Override
public Void call() throws Exception
public DBGEvent call() throws Exception
{
try (Statement stmt = conn.createStatement()) {
stmt.executeQuery(sql);
return null;
return event;
} catch (SQLException e) {
String message = String.format("Failed to execute %s", sql);
throw new Exception(message, e);
......
......@@ -59,17 +59,16 @@ public abstract class DatabaseLaunchDelegate extends LaunchConfigurationDelegate
protected Map<String, Object> extractAttributes(ILaunchConfiguration configuration) throws CoreException {
Map<String, Object> 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);
attributes.put(DBGController.DATABASE_NAME, DebugCore.extractDatabaseName(configuration));
attributes.put(DBGController.SCHEMA_NAME, DebugCore.extractSchemaName(configuration));
attributes.put(DBGController.PROCEDURE_OID, DebugCore.extractProcedureOid(configuration));
attributes.put(DBGController.PROCEDURE_NAME, DebugCore.extractProcedureName(configuration));
attributes.put(DBGController.PROCEDURE_CALL, DebugCore.extractProcedureCall(configuration));
//FIXME:AF:extract from launch configuration
//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;
}
......
......@@ -18,20 +18,31 @@
package org.jkiss.dbeaver.debug.core;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.runtime.Adapters;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationType;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.osgi.util.NLS;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.debug.DBGController;
import org.jkiss.dbeaver.debug.DBGException;
import org.jkiss.dbeaver.debug.internal.core.DebugCoreMessages;
import org.jkiss.dbeaver.model.DBPDataSourceContainer;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
import org.jkiss.dbeaver.model.runtime.VoidProgressMonitor;
import org.jkiss.dbeaver.model.struct.DBSObject;
import org.jkiss.dbeaver.model.struct.rdb.DBSProcedure;
import org.jkiss.dbeaver.model.struct.rdb.DBSProcedureParameter;
public class DebugCore {
......@@ -44,17 +55,31 @@ public class DebugCore {
public static final String BREAKPOINT_DATABASE = BUNDLE_SYMBOLIC_NAME + '.' + "databaseBreakpointMarker"; //$NON-NLS-1$
public static final String BREAKPOINT_DATABASE_LINE = BUNDLE_SYMBOLIC_NAME + '.' + "databaseLineBreakpointMarker"; //$NON-NLS-1$
public static final String ATTR_DRIVER = BUNDLE_SYMBOLIC_NAME + '.' + "ATTR_DRIVER"; //$NON-NLS-1$
public static final String ATTR_DRIVER_DEFAULT = ""; //$NON-NLS-1$
public static final String SOURCE_CONTAINER_TYPE_DATASOURCE = BUNDLE_SYMBOLIC_NAME + '.' + "datasourceSourceContainerType"; //$NON-NLS-1$
public static final String ATTR_DATASOURCE = BUNDLE_SYMBOLIC_NAME + '.' + "ATTR_DATASOURCE"; //$NON-NLS-1$
public static final String ATTR_DATASOURCE_DEFAULT = ""; //$NON-NLS-1$
public static final String ATTR_DRIVER_ID = BUNDLE_SYMBOLIC_NAME + '.' + "ATTR_DRIVER_ID"; //$NON-NLS-1$
public static final String ATTR_DRIVER_ID_DEFAULT = ""; //$NON-NLS-1$
public static final String ATTR_DATABASE = BUNDLE_SYMBOLIC_NAME + '.' + "ATTR_DATABASE"; //$NON-NLS-1$
public static final String ATTR_DATABASE_DEFAULT = ""; //$NON-NLS-1$
public static final String ATTR_DATASOURCE_ID = BUNDLE_SYMBOLIC_NAME + '.' + "ATTR_DATASOURCE_ID"; //$NON-NLS-1$
public static final String ATTR_DATASOURCE_ID_DEFAULT = ""; //$NON-NLS-1$
public static final String ATTR_OID = BUNDLE_SYMBOLIC_NAME + '.' + "ATTR_OID"; //$NON-NLS-1$
public static final String ATTR_OID_DEFAULT = ""; //$NON-NLS-1$
public static final String ATTR_DATABASE_NAME = BUNDLE_SYMBOLIC_NAME + '.' + "ATTR_DATABASE_NAME"; //$NON-NLS-1$
public static final String ATTR_DATABASE_NAME_DEFAULT = ""; //$NON-NLS-1$
public static final String ATTR_SCHEMA_NAME = BUNDLE_SYMBOLIC_NAME + '.' + "ATTR_SCHEMA_NAME"; //$NON-NLS-1$
public static final String ATTR_SCHEMA_NAME_DEFAULT = ""; //$NON-NLS-1$
public static final String ATTR_PROCEDURE_OID = BUNDLE_SYMBOLIC_NAME + '.' + "ATTR_PROCEDURE_OID"; //$NON-NLS-1$
public static final String ATTR_PROCEDURE_OID_DEFAULT = ""; //$NON-NLS-1$
public static final String ATTR_PROCEDURE_NAME = BUNDLE_SYMBOLIC_NAME + '.' + "ATTR_PROCEDURE_NAME"; //$NON-NLS-1$
public static final String ATTR_PROCEDURE_NAME_DEFAULT = ""; //$NON-NLS-1$
public static final String ATTR_PROCEDURE_CALL = BUNDLE_SYMBOLIC_NAME + '.' + "ATTR_PROCEDURE_CALL"; //$NON-NLS-1$
public static final String ATTR_PROCEDURE_CALL_DEFAULT = ""; //$NON-NLS-1$
public static final String ATTR_NODE_PATH = BUNDLE_SYMBOLIC_NAME + '.' + "ATTR_NODE_PATH"; //$NON-NLS-1$
public static final String ATTR_NODE_PATH_DEFAULT = ""; //$NON-NLS-1$
private static Log log = Log.getLog(DebugCore.class);
......@@ -70,6 +95,43 @@ public class DebugCore {
return abort(message, null);
}
public static String composeProcedureCall(DBSProcedure procedure, DBRProgressMonitor monitor) throws DBException {
StringBuilder sb = new StringBuilder();
sb.append("select").append(' ').append(procedure.getName());
sb.append('(');
Collection<? extends DBSProcedureParameter> parameters = procedure.getParameters(monitor);
int size = parameters.size();
if (size > 0) {
for (int i = 0; i < size; i++) {
Object value = '?';
sb.append(value);
sb.append(',');
}
sb.deleteCharAt(sb.length()-1);
}
sb.append(')');
String call = sb.toString();
return call;
}
public static String composeProcedureCall(DBSProcedure procedure) {
try {
return composeProcedureCall(procedure, new VoidProgressMonitor());
} catch (DBException e) {
String message = NLS.bind("Failed to compose call for {0}", procedure);
log.error(message , e);
return ATTR_PROCEDURE_CALL_DEFAULT;
}
}
public static ILaunchConfigurationWorkingCopy createConfiguration(IContainer container, String typeName, String name)
throws CoreException {
ILaunchManager manager = DebugPlugin.getDefault().getLaunchManager();
ILaunchConfigurationType type = manager.getLaunchConfigurationType(typeName);
ILaunchConfigurationWorkingCopy workingCopy = type.newInstance(container, name);
return workingCopy;
}
public static boolean canLaunch(ILaunchConfiguration configuration, String mode) {
if (configuration == null || !configuration.exists()) {
return false;
......@@ -99,15 +161,35 @@ public class DebugCore {
}
public static String extractDriverId(ILaunchConfiguration configuration) {
return extractStringAttribute(configuration, ATTR_DRIVER, ATTR_DRIVER_DEFAULT);
return extractStringAttribute(configuration, ATTR_DRIVER_ID, ATTR_DRIVER_ID_DEFAULT);
}
public static String extractDatasourceId(ILaunchConfiguration configuration) {
return extractStringAttribute(configuration, ATTR_DATASOURCE, ATTR_DATASOURCE_DEFAULT);
return extractStringAttribute(configuration, ATTR_DATASOURCE_ID, ATTR_DATASOURCE_ID_DEFAULT);
}
public static String extractDatabaseName(ILaunchConfiguration configuration) {
return extractStringAttribute(configuration, ATTR_DATABASE, ATTR_DATABASE_DEFAULT);
return extractStringAttribute(configuration, ATTR_DATABASE_NAME, ATTR_DATABASE_NAME_DEFAULT);
}
public static String extractSchemaName(ILaunchConfiguration configuration) {
return extractStringAttribute(configuration, ATTR_SCHEMA_NAME, ATTR_SCHEMA_NAME_DEFAULT);
}
public static String extractProcedureOid(ILaunchConfiguration configuration) {
return extractStringAttribute(configuration, ATTR_PROCEDURE_OID, ATTR_PROCEDURE_OID_DEFAULT);
}
public static String extractProcedureName(ILaunchConfiguration configuration) {
return extractStringAttribute(configuration, ATTR_PROCEDURE_NAME, ATTR_PROCEDURE_NAME_DEFAULT);
}
public static String extractProcedureCall(ILaunchConfiguration configuration) {
return extractStringAttribute(configuration, ATTR_PROCEDURE_CALL, ATTR_PROCEDURE_CALL_DEFAULT);
}
public static String extractNodePath(ILaunchConfiguration configuration) {
return extractStringAttribute(configuration, ATTR_NODE_PATH, ATTR_NODE_PATH_DEFAULT);
}
public static String extractStringAttribute(ILaunchConfiguration configuration, String attributeName,
......
......@@ -36,12 +36,14 @@ import org.eclipse.debug.core.model.IThread;
import org.eclipse.osgi.util.NLS;
import org.jkiss.dbeaver.debug.DBGController;
import org.jkiss.dbeaver.debug.DBGEvent;
import org.jkiss.dbeaver.debug.DBGEventHandler;
import org.jkiss.dbeaver.debug.DBGException;
import org.jkiss.dbeaver.debug.core.DebugCore;
import org.jkiss.dbeaver.debug.core.DebugEvents;
import org.jkiss.dbeaver.model.runtime.DefaultProgressMonitor;
import org.jkiss.dbeaver.model.runtime.VoidProgressMonitor;
public abstract class DatabaseDebugTarget extends DatabaseDebugElement implements IDatabaseDebugTarget {
public abstract class DatabaseDebugTarget extends DatabaseDebugElement implements IDatabaseDebugTarget, DBGEventHandler {
private final String modelIdentifier;
......@@ -64,6 +66,7 @@ public abstract class DatabaseDebugTarget extends DatabaseDebugElement implement
this.launch = launch;
this.process = process;
this.controller = controller;
this.controller.registerEventHandler(this);
this.threads = new ArrayList<IThread>();
}
......@@ -174,6 +177,7 @@ public abstract class DatabaseDebugTarget extends DatabaseDebugElement implement
suspended = false;
try {
controller.detach(sessionKey, getProgressMonitor());
controller.unregisterEventHandler(this);
} catch (DBGException e) {
String message = NLS.bind("Error terminating {0}", getName());
IStatus status = DebugCore.newErrorStatus(message, e);
......@@ -285,7 +289,7 @@ public abstract class DatabaseDebugTarget extends DatabaseDebugElement implement
@Override
public DebugEvent toDebugEvent(DBGEvent event) {
return new DebugEvent(event.getSource(), DebugEvent.MODEL_SPECIFIC);
return new DebugEvent(event.getSource(), event.getKind(), event.getDetails());
}
@Override
......@@ -297,5 +301,12 @@ public abstract class DatabaseDebugTarget extends DatabaseDebugElement implement
public IMemoryBlock getMemoryBlock(long startAddress, long length) throws DebugException {
return null;
}
@Override
public void handleDebugEvent(DBGEvent event) {
DebugEvent debugEvent = toDebugEvent(event);
DebugEvents.fireEvent(debugEvent);
// DebugEvents.fireEvent(new DebugEvent(this, DebugEvent.SUSPEND, DebugEvent.BREAKPOINT));
}
}
......@@ -8,6 +8,7 @@ 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.eclipse.osgi.util.NLS;
import org.jkiss.dbeaver.debug.DBGException;
import org.jkiss.dbeaver.debug.DBGSession;
import org.jkiss.dbeaver.debug.DBGStackFrame;
......@@ -141,19 +142,21 @@ public class DatabaseStackFrame extends DatabaseDebugElement implements IStackFr
@Override
public int getCharStart() throws DebugException {
// TODO Auto-generated method stub
return 0;
// unknown
return -1;
}
@Override
public int getCharEnd() throws DebugException {
// TODO Auto-generated method stub
return 0;
// unknown
return -1;
}
@Override
public String getName() throws DebugException {
return dbgStackFrame.toString();
String pattern = "{0} line: {1}";
String name = NLS.bind(pattern, dbgStackFrame.getName(), dbgStackFrame.getLine());
return name;
}
@Override
......
......@@ -52,7 +52,7 @@ public class DatabaseVariable extends DatabaseDebugElement implements IVariable
@Override
public String getName() throws DebugException {
return dbgVariable.toString();
return dbgVariable.getName();
}
@Override
......
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2018 Serge Rider (serge@jkiss.org)
* Copyright (C) 2017-2018 Alexander Fedorov (alexander.fedorov@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.debug.sourcelookup;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.debug.core.sourcelookup.ISourceContainer;
import org.eclipse.debug.core.sourcelookup.ISourceContainerType;
import org.eclipse.debug.core.sourcelookup.containers.CompositeSourceContainer;
import org.jkiss.dbeaver.debug.core.DebugCore;
import org.jkiss.dbeaver.model.DBPDataSourceContainer;
import org.jkiss.dbeaver.model.navigator.DBNNode;
import org.jkiss.dbeaver.registry.DataSourceDescriptor;
public class DatasourceSourceContainer extends CompositeSourceContainer {
private final DBPDataSourceContainer datasource;
private final DBNNode startNode;
public DatasourceSourceContainer(DataSourceDescriptor descriptor, DBNNode node) {
this.datasource = descriptor;
this.startNode = node;
}
@Override
public String getName() {
return datasource.getName();
}
@Override
protected Object[] findSourceElements(String name, ISourceContainer[] containers) throws CoreException {
if (startNode != null) {
return new Object[] {startNode};
}
return super.findSourceElements(name, containers);
}
@Override
public ISourceContainerType getType() {
return getSourceContainerType(DebugCore.SOURCE_CONTAINER_TYPE_DATASOURCE);
}
@Override
protected ISourceContainer[] createSourceContainers() throws CoreException {
// TODO Auto-generated method stub
return new ISourceContainer[0];
}
}
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2018 Serge Rider (serge@jkiss.org)
* Copyright (C) 2017-2018 Alexander Fedorov (alexander.fedorov@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.debug.sourcelookup;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.debug.core.sourcelookup.ISourceContainer;
import org.eclipse.debug.core.sourcelookup.containers.AbstractSourceContainerTypeDelegate;
public class DatasourceSourceContainerTypeDelegate extends AbstractSourceContainerTypeDelegate {
@Override
public ISourceContainer createSourceContainer(String memento) throws CoreException {
// TODO Auto-generated method stub
return null;
}
@Override
public String getMemento(ISourceContainer container) throws CoreException {
// TODO Auto-generated method stub
return null;
}
}
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2018 Serge Rider (serge@jkiss.org)
* Copyright (C) 2017-2018 Alexander Fedorov (alexander.fedorov@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.debug.sourcelookup;
import org.eclipse.debug.core.sourcelookup.AbstractSourceLookupDirector;
import org.eclipse.debug.core.sourcelookup.ISourceLookupParticipant;
public class ProcedureSourceLookupDirector extends AbstractSourceLookupDirector {
@Override
public void initializeParticipants() {
addParticipants(new ISourceLookupParticipant[] {new ProcedureSourceLookupParticipant()});
}
}
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2018 Serge Rider (serge@jkiss.org)
* Copyright (C) 2017-2018 Alexander Fedorov (alexander.fedorov@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.debug.sourcelookup;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.debug.core.sourcelookup.AbstractSourceLookupParticipant;
import org.jkiss.dbeaver.debug.core.model.DatabaseStackFrame;
public class ProcedureSourceLookupParticipant extends AbstractSourceLookupParticipant {
@Override
public String getSourceName(Object object) throws CoreException {
if (object instanceof DatabaseStackFrame) {
DatabaseStackFrame stackFrame = (DatabaseStackFrame) object;
return stackFrame.getName();
}
return String.valueOf(object);
}
}
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2018 Serge Rider (serge@jkiss.org)
* Copyright (C) 2017-2018 Alexander Fedorov (alexander.fedorov@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.debug.sourcelookup;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.sourcelookup.ISourceContainer;
import org.eclipse.debug.core.sourcelookup.ISourcePathComputerDelegate;
import org.eclipse.osgi.util.NLS;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.core.DBeaverCore;
import org.jkiss.dbeaver.debug.core.DebugCore;
import org.jkiss.dbeaver.model.navigator.DBNModel;
import org.jkiss.dbeaver.model.navigator.DBNNode;
import org.jkiss.dbeaver.model.runtime.DefaultProgressMonitor;
import org.jkiss.dbeaver.registry.DataSourceDescriptor;
import org.jkiss.dbeaver.registry.DataSourceRegistry;
public class ProcedureSourcePathComputer implements ISourcePathComputerDelegate {
@Override
public ISourceContainer[] computeSourceContainers(ILaunchConfiguration configuration, IProgressMonitor monitor)
throws CoreException {
String datasourceId = DebugCore.extractDatasourceId(configuration);
String nodePath = DebugCore.extractNodePath(configuration);
DataSourceDescriptor descriptor = DataSourceRegistry.findDataSource(datasourceId);
final DBNModel navigatorModel = DBeaverCore.getInstance().getNavigatorModel();
IProject project = descriptor.getRegistry().getProject();
DBNNode node;
try {
node = navigatorModel.getNodeByPath(new DefaultProgressMonitor(monitor), project, nodePath);
} catch (DBException e) {
String message = NLS.bind("Unable to extract node {0}", nodePath);
throw new CoreException(DebugCore.newErrorStatus(message, e));
}
DatasourceSourceContainer container = new DatasourceSourceContainer(descriptor, node);
return new ISourceContainer[] {container};
}
}
......@@ -57,6 +57,23 @@
<detailFactories
class="org.jkiss.dbeaver.debug.ui.details.DatabaseDetailPaneFactory"
id="org.jkiss.dbeaver.debug.ui.detailPaneFactories.detailFactories.database">
<enablement>
<with
variable="selection">
<count
value="1">
</count>
<iterate
operator="or">
<instanceof
value="org.jkiss.dbeaver.debug.core.breakpoints.IDatabaseBreakpoint">
</instanceof>
</iterate>
<iterate
operator="or">
</iterate>
</with>
</enablement>
</detailFactories>
</extension>
......
......@@ -28,12 +28,18 @@ public class DebugUIMessages extends NLS {
public static String DatabaseTab_driver_group_text;
public static String DatabaseTab_driver_label_text;
public static String DatabaseTab_database_group_text;
public static String DatabaseTab_database_label_text;
public static String DatabaseTab_datasource_group_text;
public static String DatabaseTab_datasource_label_text;
public static String DatabaseTab_database_group_text;
public static String DatabaseTab_database_label_text;
public static String DatabaseTab_schema_group_text;
public static String DatabaseTab_schema_label_text;
public static String DatabaseTab_oid_group_text;
public static String DatabaseTab_oid_label_text;
public static String DatabaseTab_name_group_text;
public static String DatabaseTab_name_label_text;
public static String DatabaseTab_call_group_text;
public static String DatabaseTab_call_label_text;
public static String DatabaseTab_name;
......
......@@ -19,12 +19,18 @@ DatabaseStandardBreakpointPane_description=Breakpoint settings
DatabaseTab_driver_group_text=Driver
DatabaseTab_driver_label_text=Driver
DatabaseTab_database_group_text=Database
DatabaseTab_database_label_text=Database
DatabaseTab_datasource_group_text=Connection
DatabaseTab_datasource_label_text=Connection
DatabaseTab_database_group_text=Database
DatabaseTab_database_label_text=Database
DatabaseTab_schema_group_text=Schema
DatabaseTab_schema_label_text=Schema
DatabaseTab_oid_group_text=OID
DatabaseTab_oid_label_text=OID
DatabaseTab_name_group_text=Name
DatabaseTab_name_label_text=Name
DatabaseTab_call_group_text=Call
DatabaseTab_call_label_text=Call
DatabaseTab_name=&Main
......
......@@ -17,32 +17,48 @@
*/
package org.jkiss.dbeaver.debug.internal.ui;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.model.IValue;
import org.eclipse.debug.ui.IValueDetailListener;
import org.eclipse.osgi.util.NLS;
import org.eclipse.ui.IEditorInput;
import org.jkiss.dbeaver.debug.core.DebugCore;
import org.jkiss.dbeaver.debug.ui.DatabaseDebugModelPresentation;
import org.jkiss.dbeaver.model.navigator.DBNDatabaseNode;
import org.jkiss.dbeaver.ui.editors.entity.EntityEditorInput;
public class ProcedureDebugModelPresentation extends DatabaseDebugModelPresentation {
@Override
public IEditorInput getEditorInput(Object element)
{
// TODO Auto-generated method stub
if (element instanceof DBNDatabaseNode) {
DBNDatabaseNode dbnNode = (DBNDatabaseNode) element;
return new EntityEditorInput(dbnNode);
}
return null;
}
@Override
public String getEditorId(IEditorInput input, Object element)
{
// TODO Auto-generated method stub
return null;
//FIXME:AF: is there a constant anywhere?
return "org.jkiss.dbeaver.ui.editors.entity.EntityEditor";
}
@Override
public void computeDetail(IValue value, IValueDetailListener listener)
{
// TODO Auto-generated method stub
try {
String valueString = value.getValueString();
listener.detailComputed(value, valueString);
} catch (DebugException e) {
String message = NLS.bind("Unable to compute valie for {0}", value);
IStatus status = DebugCore.newErrorStatus(message, e);
DebugCore.log(status);
listener.detailComputed(value, e.getMessage());
}
}
}
......@@ -17,7 +17,6 @@
*/
package org.jkiss.dbeaver.debug.ui;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.debug.ui.AbstractLaunchConfigurationTab;
......@@ -45,7 +44,10 @@ public class DatabaseTab extends AbstractLaunchConfigurationTab {
private Text driverText;
private Text datasourceText;
private Text databaseText;
private Text schemaText;
private Text oidText;
private Text nameText;
private Text callText;
/**
* Modify listener that simply updates the owning launch configuration
......@@ -76,7 +78,10 @@ public class DatabaseTab extends AbstractLaunchConfigurationTab {
createDriverComponent(comp);
createDatasourceComponent(comp);
createDatabaseComponent(comp);
createSchemaComponent(comp);
createOidComponent(comp);
createNameComponent(comp);
createCallComponent(comp);
}
protected void createDriverComponent(Composite comp)
......@@ -84,7 +89,7 @@ public class DatabaseTab extends AbstractLaunchConfigurationTab {
Group driverGroup = UIUtils.createControlGroup(comp, DebugUIMessages.DatabaseTab_driver_group_text, 2, GridData.FILL_HORIZONTAL,
SWT.DEFAULT);
driverText = UIUtils.createLabelText(driverGroup, DebugUIMessages.DatabaseTab_driver_label_text, DebugCore.ATTR_DRIVER_DEFAULT);
driverText = UIUtils.createLabelText(driverGroup, DebugUIMessages.DatabaseTab_driver_label_text, DebugCore.ATTR_DRIVER_ID_DEFAULT);
driverText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
driverText.addModifyListener(modifyListener);
driverText.setEditable(false);
......@@ -95,7 +100,7 @@ public class DatabaseTab extends AbstractLaunchConfigurationTab {
Group datasourceGroup = UIUtils.createControlGroup(comp, DebugUIMessages.DatabaseTab_datasource_group_text, 2, GridData.FILL_HORIZONTAL,
SWT.DEFAULT);
datasourceText = UIUtils.createLabelText(datasourceGroup, DebugUIMessages.DatabaseTab_datasource_label_text, DebugCore.ATTR_DATASOURCE_DEFAULT);
datasourceText = UIUtils.createLabelText(datasourceGroup, DebugUIMessages.DatabaseTab_datasource_label_text, DebugCore.ATTR_DATASOURCE_ID_DEFAULT);
datasourceText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
datasourceText.addModifyListener(modifyListener);
datasourceText.setEditable(false);
......@@ -105,27 +110,57 @@ public class DatabaseTab extends AbstractLaunchConfigurationTab {
{
Group databaseGroup = UIUtils.createControlGroup(comp, DebugUIMessages.DatabaseTab_database_group_text, 2, GridData.FILL_HORIZONTAL, SWT.DEFAULT);
databaseText = UIUtils.createLabelText(databaseGroup, DebugUIMessages.DatabaseTab_database_label_text, DebugCore.ATTR_DATABASE_DEFAULT);
databaseText = UIUtils.createLabelText(databaseGroup, DebugUIMessages.DatabaseTab_database_label_text, DebugCore.ATTR_DATABASE_NAME_DEFAULT);
databaseText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
databaseText.addModifyListener(modifyListener);
}
protected void createSchemaComponent(Composite comp)
{
Group databaseGroup = UIUtils.createControlGroup(comp, DebugUIMessages.DatabaseTab_schema_group_text, 2, GridData.FILL_HORIZONTAL, SWT.DEFAULT);
schemaText = UIUtils.createLabelText(databaseGroup, DebugUIMessages.DatabaseTab_schema_label_text, DebugCore.ATTR_SCHEMA_NAME_DEFAULT);
schemaText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
schemaText.addModifyListener(modifyListener);
}
protected void createOidComponent(Composite comp)
{
Group datasourceGroup = UIUtils.createControlGroup(comp, DebugUIMessages.DatabaseTab_oid_group_text, 2, GridData.FILL_HORIZONTAL, SWT.DEFAULT);
Group oidGroup = UIUtils.createControlGroup(comp, DebugUIMessages.DatabaseTab_oid_group_text, 2, GridData.FILL_HORIZONTAL, SWT.DEFAULT);
oidText = UIUtils.createLabelText(datasourceGroup, DebugUIMessages.DatabaseTab_oid_label_text, DebugCore.ATTR_OID_DEFAULT);
oidText = UIUtils.createLabelText(oidGroup, DebugUIMessages.DatabaseTab_oid_label_text, DebugCore.ATTR_PROCEDURE_OID_DEFAULT);
oidText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
oidText.addModifyListener(modifyListener);
}
protected void createNameComponent(Composite comp)
{
Group oidGroup = UIUtils.createControlGroup(comp, DebugUIMessages.DatabaseTab_name_group_text, 2, GridData.FILL_HORIZONTAL, SWT.DEFAULT);
nameText = UIUtils.createLabelText(oidGroup, DebugUIMessages.DatabaseTab_name_label_text, DebugCore.ATTR_PROCEDURE_NAME_DEFAULT);
nameText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
nameText.addModifyListener(modifyListener);
}
protected void createCallComponent(Composite comp)
{
Group callGroup = UIUtils.createControlGroup(comp, DebugUIMessages.DatabaseTab_call_group_text, 2, GridData.FILL_HORIZONTAL, SWT.DEFAULT);
callText = UIUtils.createLabelText(callGroup, DebugUIMessages.DatabaseTab_call_label_text, DebugCore.ATTR_PROCEDURE_CALL_DEFAULT);
callText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
callText.addModifyListener(modifyListener);
}
@Override
public void setDefaults(ILaunchConfigurationWorkingCopy configuration)
{
configuration.setAttribute(DebugCore.ATTR_DRIVER, DebugCore.ATTR_DRIVER);
configuration.setAttribute(DebugCore.ATTR_DATASOURCE, DebugCore.ATTR_DATASOURCE_DEFAULT);
configuration.setAttribute(DebugCore.ATTR_DATABASE, DebugCore.ATTR_DATABASE_DEFAULT);
configuration.setAttribute(DebugCore.ATTR_OID, DebugCore.ATTR_OID_DEFAULT);
configuration.setAttribute(DebugCore.ATTR_DRIVER_ID, DebugCore.ATTR_DRIVER_ID);
configuration.setAttribute(DebugCore.ATTR_DATASOURCE_ID, DebugCore.ATTR_DATASOURCE_ID_DEFAULT);
configuration.setAttribute(DebugCore.ATTR_DATABASE_NAME, DebugCore.ATTR_DATABASE_NAME_DEFAULT);
configuration.setAttribute(DebugCore.ATTR_SCHEMA_NAME, DebugCore.ATTR_SCHEMA_NAME_DEFAULT);
configuration.setAttribute(DebugCore.ATTR_PROCEDURE_OID, DebugCore.ATTR_PROCEDURE_OID_DEFAULT);
configuration.setAttribute(DebugCore.ATTR_PROCEDURE_NAME, DebugCore.ATTR_PROCEDURE_NAME_DEFAULT);
configuration.setAttribute(DebugCore.ATTR_PROCEDURE_CALL, DebugCore.ATTR_PROCEDURE_CALL_DEFAULT);
}
@Override
......@@ -134,7 +169,10 @@ public class DatabaseTab extends AbstractLaunchConfigurationTab {
initializeDriver(configuration);
initializeDatasource(configuration);
initializeDatabase(configuration);
initializeSchema(configuration);
initializeOid(configuration);
initializeName(configuration);
initializeCall(configuration);
}
protected void initializeDriver(ILaunchConfiguration configuration)
......@@ -155,17 +193,28 @@ public class DatabaseTab extends AbstractLaunchConfigurationTab {
databaseText.setText(extracted);
}
protected void initializeSchema(ILaunchConfiguration configuration)
{
String extracted = DebugCore.extractSchemaName(configuration);
schemaText.setText(extracted);
}
protected void initializeOid(ILaunchConfiguration configuration)
{
String oid = null;
try {
oid = configuration.getAttribute(DebugCore.ATTR_OID, (String)null);
} catch (CoreException e) {
}
if (oid == null) {
oid = DebugCore.ATTR_OID_DEFAULT;
}
oidText.setText(oid);
String extracted = DebugCore.extractProcedureOid(configuration);
oidText.setText(extracted);
}
protected void initializeName(ILaunchConfiguration configuration)
{
String extracted = DebugCore.extractProcedureName(configuration);
nameText.setText(extracted);
}
protected void initializeCall(ILaunchConfiguration configuration)
{
String extracted = DebugCore.extractProcedureCall(configuration);
callText.setText(extracted);
}
@Override
......@@ -192,10 +241,13 @@ public class DatabaseTab extends AbstractLaunchConfigurationTab {
@Override
public void performApply(ILaunchConfigurationWorkingCopy configuration)
{
configuration.setAttribute(DebugCore.ATTR_DRIVER, driverText.getText());
configuration.setAttribute(DebugCore.ATTR_DATASOURCE, datasourceText.getText());
configuration.setAttribute(DebugCore.ATTR_DATABASE, databaseText.getText());
configuration.setAttribute(DebugCore.ATTR_OID, oidText.getText());
configuration.setAttribute(DebugCore.ATTR_DRIVER_ID, driverText.getText());
configuration.setAttribute(DebugCore.ATTR_DATASOURCE_ID, datasourceText.getText());
configuration.setAttribute(DebugCore.ATTR_DATABASE_NAME, databaseText.getText());
configuration.setAttribute(DebugCore.ATTR_SCHEMA_NAME, schemaText.getText());
configuration.setAttribute(DebugCore.ATTR_PROCEDURE_OID, oidText.getText());
configuration.setAttribute(DebugCore.ATTR_PROCEDURE_NAME, nameText.getText());
configuration.setAttribute(DebugCore.ATTR_PROCEDURE_CALL, callText.getText());
}
@Override
......
......@@ -27,7 +27,9 @@
delegateName="%launchConfigurationTypes.launchConfigurationType.pgSQL.delegateName"
id="org.jkiss.dbeaver.ext.postgresql.debug.core.pgSQL"
modes="debug"
name="%launchConfigurationTypes.launchConfigurationType.pgSQL.name">
name="%launchConfigurationTypes.launchConfigurationType.pgSQL.name"
sourceLocatorId="org.jkiss.dbeaver.debug.core.procedureSourceLocator"
sourcePathComputerId="org.jkiss.dbeaver.debug.core.procedureSourcePathComputer">
</launchConfigurationType>
</extension>
......
......@@ -19,11 +19,9 @@ package org.jkiss.dbeaver.ext.postgresql.debug.core;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunchConfigurationType;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.osgi.util.NLS;
import org.jkiss.dbeaver.core.DBeaverCore;
import org.jkiss.dbeaver.debug.core.DebugCore;
import org.jkiss.dbeaver.ext.postgresql.debug.internal.PostgreDebugCoreMessages;
import org.jkiss.dbeaver.ext.postgresql.model.PostgreDataSource;
......@@ -31,6 +29,9 @@ 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.DBPDataSourceContainer;
import org.jkiss.dbeaver.model.navigator.DBNDatabaseNode;
import org.jkiss.dbeaver.model.navigator.DBNModel;
import org.jkiss.dbeaver.model.navigator.DBNNode;
import org.jkiss.dbeaver.model.struct.DBSObject;
public class PostgreSqlDebugCore {
......@@ -52,24 +53,23 @@ public class PostgreSqlDebugCore {
PostgreSchema schema = procedure.getContainer();
String databaseName = database.getName();
Object[] bindings = new Object[] {dataSourceContainer.getName(), databaseName,
procedure.getName(), schema.getName()};
String schemaName = schema.getName();
String procedureName = procedure.getName();
Object[] bindings = new Object[] { dataSourceContainer.getName(), databaseName, procedureName, schemaName };
String name = NLS.bind(PostgreDebugCoreMessages.PostgreSqlDebugCore_launch_configuration_name, bindings);
//Let's use metadata area for storage
IContainer container = null;
ILaunchConfigurationWorkingCopy workingCopy = createConfiguration(container, name);
workingCopy.setAttribute(DebugCore.ATTR_DRIVER, dataSourceContainer.getDriver().getId());
workingCopy.setAttribute(DebugCore.ATTR_DATASOURCE, dataSourceContainer.getId());
workingCopy.setAttribute(DebugCore.ATTR_DATABASE, databaseName);
workingCopy.setAttribute(DebugCore.ATTR_OID, String.valueOf(procedure.getObjectId()));
return workingCopy;
}
public static ILaunchConfigurationWorkingCopy createConfiguration(IContainer container, String name)
throws CoreException {
ILaunchManager manager = DebugPlugin.getDefault().getLaunchManager();
ILaunchConfigurationType type = manager.getLaunchConfigurationType(CONFIGURATION_TYPE);
ILaunchConfigurationWorkingCopy workingCopy = type.newInstance(container, name);
ILaunchConfigurationWorkingCopy workingCopy = DebugCore.createConfiguration(container, CONFIGURATION_TYPE, name);
workingCopy.setAttribute(DebugCore.ATTR_DRIVER_ID, dataSourceContainer.getDriver().getId());
workingCopy.setAttribute(DebugCore.ATTR_DATASOURCE_ID, dataSourceContainer.getId());
workingCopy.setAttribute(DebugCore.ATTR_DATABASE_NAME, databaseName);
workingCopy.setAttribute(DebugCore.ATTR_SCHEMA_NAME, schemaName);
workingCopy.setAttribute(DebugCore.ATTR_PROCEDURE_OID, String.valueOf(procedure.getObjectId()));
workingCopy.setAttribute(DebugCore.ATTR_PROCEDURE_NAME, procedureName);
workingCopy.setAttribute(DebugCore.ATTR_PROCEDURE_CALL, DebugCore.composeProcedureCall(procedure));
final DBNModel navigatorModel = DBeaverCore.getInstance().getNavigatorModel();
DBNDatabaseNode node = navigatorModel.getNodeByObject(procedure);
workingCopy.setAttribute(DebugCore.ATTR_NODE_PATH, node.getNodeItemPath());
return workingCopy;
}
}
......@@ -24,7 +24,6 @@ import java.util.List;
import java.util.Scanner;
import org.jkiss.dbeaver.debug.DBGBreakpointDescriptor;
import org.jkiss.dbeaver.debug.DBGBreakpointProperties;
import org.jkiss.dbeaver.debug.DBGController;
import org.jkiss.dbeaver.debug.DBGException;
import org.jkiss.dbeaver.debug.DBGObjectDescriptor;
......@@ -32,8 +31,10 @@ import org.jkiss.dbeaver.debug.DBGSession;
import org.jkiss.dbeaver.debug.DBGSessionInfo;
import org.jkiss.dbeaver.debug.DBGStackFrame;
import org.jkiss.dbeaver.debug.DBGVariable;
import org.jkiss.dbeaver.ext.postgresql.debug.internal.impl.PostgreDebugBreakpointDescriptor;
import org.jkiss.dbeaver.ext.postgresql.debug.internal.impl.PostgreDebugBreakpointProperties;
import org.jkiss.dbeaver.ext.postgresql.debug.internal.impl.PostgreDebugController;
import org.jkiss.dbeaver.ext.postgresql.debug.internal.impl.PostgreDebugObjectDescriptor;
import org.jkiss.dbeaver.model.DBPDataSourceContainer;
import org.jkiss.dbeaver.model.exec.DBCExecutionContext;
import org.jkiss.dbeaver.model.runtime.VoidProgressMonitor;
......@@ -543,14 +544,16 @@ public class Debugger {
break;
}
DBGBreakpointProperties bp = lineNo > 0 ? new PostgreDebugBreakpointProperties(lineNo, true)
PostgreDebugBreakpointProperties breakpointProperties = lineNo > 0
? new PostgreDebugBreakpointProperties(lineNo, true)
: new PostgreDebugBreakpointProperties(true);
debugSession.addBreakpoint(debugObject, bp);
PostgreDebugBreakpointDescriptor descriptor = new PostgreDebugBreakpointDescriptor((PostgreDebugObjectDescriptor)debugObject, breakpointProperties);
debugSession.addBreakpoint(descriptor);
System.out.println("Breakpoint added");
System.out.println(bp.toString());
System.out.println(breakpointProperties.toString());
break;
......
......@@ -26,13 +26,9 @@ public class PostgreDebugBreakpointDescriptor implements DBGBreakpointDescriptor
private final PostgreDebugObjectDescriptor obj;
private final PostgreDebugSession session;
private final PostgreDebugBreakpointProperties properties;
public PostgreDebugBreakpointDescriptor(PostgreDebugSession session, PostgreDebugObjectDescriptor obj,
PostgreDebugBreakpointProperties properties) throws DBGException {
this.session = session;
public PostgreDebugBreakpointDescriptor(PostgreDebugObjectDescriptor obj, PostgreDebugBreakpointProperties properties) throws DBGException {
this.obj = obj;
this.properties = properties;
......@@ -50,8 +46,7 @@ public class PostgreDebugBreakpointDescriptor implements DBGBreakpointDescriptor
@Override
public String toString() {
return "PostgreDebugBreakpointDescriptor [obj=" + obj + ", session id =" + session.getSessionId() + ", properties="
+ properties + "]";
return "PostgreDebugBreakpointDescriptor [obj=" + obj + ", properties=" + properties + "]";
}
}
......@@ -22,46 +22,23 @@ 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$
private static final String SQL_OBJECT = "select p.oid,p.proname,u.usename as owner,n.nspname, l.lanname as lang " //$NON-NLS-1$
......@@ -94,7 +71,7 @@ public class PostgreDebugController extends DBGBaseController {
throw new DBGException("Error getting session");
} catch (SQLException e) {
throw new DBGException("SQ Lerror", e);
throw new DBGException("SQL error", e);
}
}
......@@ -155,7 +132,7 @@ public class PostgreDebugController extends DBGBaseController {
@Override
public PostgreDebugSession createSession(DBGSessionInfo targetInfo, DBCExecutionContext sessionContext) throws DBGException {
PostgreDebugSessionInfo sessionInfo = getSessionDescriptor(sessionContext);
PostgreDebugSession debugSession = new PostgreDebugSession(sessionInfo, targetInfo.getID());
PostgreDebugSession debugSession = new PostgreDebugSession(this, sessionInfo, targetInfo.getID());
return debugSession;
......@@ -169,79 +146,9 @@ public class PostgreDebugController extends DBGBaseController {
//FIXME -1 - target PID (-1 for ANY 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<String, Object> 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<String, Object> configuration,
DBRProgressMonitor monitor) throws DBException {
StringBuilder sb = new StringBuilder();
sb.append("select").append(' ').append(procedure.getName());
sb.append('(');
Collection<? extends DBSProcedureParameter> 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;
executeProcedure(dataSource, configuration, monitor);
}
}
......@@ -18,29 +18,22 @@
package org.jkiss.dbeaver.ext.postgresql.debug.internal.impl;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.debug.DBGBaseController;
import org.jkiss.dbeaver.debug.DBGBaseSession;
import org.jkiss.dbeaver.debug.DBGBreakpointDescriptor;
import org.jkiss.dbeaver.debug.DBGBreakpointProperties;
import org.jkiss.dbeaver.debug.DBGEvent;
import org.jkiss.dbeaver.debug.DBGException;
import org.jkiss.dbeaver.debug.DBGObjectDescriptor;
import org.jkiss.dbeaver.debug.DBGSession;
import org.jkiss.dbeaver.debug.DBGSessionInfo;
import org.jkiss.dbeaver.debug.DBGStackFrame;
import org.jkiss.dbeaver.debug.DBGVariable;
import org.jkiss.dbeaver.model.exec.DBCExecutionContext;
import org.jkiss.dbeaver.model.impl.jdbc.JDBCExecutionContext;
import org.jkiss.dbeaver.model.runtime.VoidProgressMonitor;
/**
* Typical scenario for debug session <br/>
......@@ -57,15 +50,11 @@ import org.jkiss.dbeaver.model.runtime.VoidProgressMonitor;
* procedure will be reached <br/>
*
*/
public class PostgreDebugSession implements DBGSession {
public class PostgreDebugSession extends DBGBaseSession {
private static final Log log = Log.getLog(PostgreDebugSession.class);
private final DBGSessionInfo sessionInfo;
private final Object targetId;
private JDBCExecutionContext connection = null;
private int sessionId = -1;
private static final String SQL_ATTACH = "select pldbg_wait_for_target(?sessionid)";
......@@ -92,14 +81,6 @@ public class PostgreDebugSession implements DBGSession {
private static final String SQL_DROP_BREAKPOINT = "select pldbg_drop_breakpoint(?sessionid, ?obj, ?line)";
private static final String SQL_ATTACH_BREAKPOINT = "select pldbg_wait_for_breakpoint(?sessionid)";
private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true);
private List<PostgreDebugBreakpointDescriptor> breakpoints = new ArrayList<PostgreDebugBreakpointDescriptor>(1);
private FutureTask<Void> task;
private Thread workerThread = null;
/**
* Create session with two description
* after creation session need to be attached to postgres procedure by attach method
......@@ -108,7 +89,8 @@ public class PostgreDebugSession implements DBGSession {
* @param sessionDebugInfo - session (debugger client connection) description
* @throws DBGException
*/
public PostgreDebugSession(PostgreDebugSessionInfo sessionInfo, Object targetId) throws DBGException {
public PostgreDebugSession(DBGBaseController controller, PostgreDebugSessionInfo sessionInfo, Object targetId) throws DBGException {
super(controller);
this.sessionInfo = sessionInfo;
this.targetId = targetId;
}
......@@ -128,14 +110,14 @@ public class PostgreDebugSession implements DBGSession {
try {
this.connection = connection;
setConnection(connection);
try (Statement stmt = getConnection(connection).createStatement();
try (Statement stmt = getConnection().createStatement();
ResultSet rs = stmt.executeQuery(SQL_LISTEN)) {
if (rs.next()) {
sessionId = rs.getInt("sessionid");
getConnection(connection).setClientInfo("ApplicationName", "Debug Mode : " + String.valueOf(sessionId));
getConnection().setClientInfo("ApplicationName", "Debug Mode : " + String.valueOf(sessionId));
} else {
throw new DBGException("Unable to create debug instance");
}
......@@ -146,10 +128,12 @@ public class PostgreDebugSession implements DBGSession {
PostgreDebugBreakpointProperties properties = new PostgreDebugBreakpointProperties(true);
PostgreDebugObjectDescriptor obj = new PostgreDebugObjectDescriptor(OID,"ENTRY","SESSION","THIS","PG");
addBreakpoint(obj, properties);
PostgreDebugBreakpointDescriptor bp = new PostgreDebugBreakpointDescriptor(obj, properties);
addBreakpoint(bp);
runAsync(SQL_ATTACH.replaceAll("\\?sessionid", String.valueOf(sessionId)),
String.valueOf(sessionId) + " global attached to " + String.valueOf(targetId));
String sessionParam = String.valueOf(getSessionId());
String taskName = sessionParam + " global attached to " + String.valueOf(targetId);
runAsync(SQL_ATTACH.replaceAll("\\?sessionid", sessionParam), taskName, new DBGEvent(this, DBGEvent.ATTACH));
/*if (breakpoint) {
runAsync(SQL_ATTACH_BREAKPOINT.replaceAll("\\?sessionid", String.valueOf(sessionId)),
......@@ -167,98 +151,46 @@ public class PostgreDebugSession implements DBGSession {
}
/**
* @param connectionTarget - DBCExecutionContext of debug client (will be used in debug process)
* @return Connection - java.sql.Connection
* @throws SQLException
*/
private static Connection getConnection(DBCExecutionContext connectionTarget) throws SQLException {
return ((JDBCExecutionContext) connectionTarget).getConnection(new VoidProgressMonitor());
}
@Override
public DBGSessionInfo getSessionInfo() {
return sessionInfo;
}
@Override
public List<PostgreDebugBreakpointDescriptor> getBreakpoints() {
return breakpoints;
protected String composeAddBreakpointCommand(DBGBreakpointDescriptor descriptor) {
PostgreDebugBreakpointDescriptor bp = (PostgreDebugBreakpointDescriptor) descriptor;
PostgreDebugBreakpointProperties bpd = (PostgreDebugBreakpointProperties) bp.getProperties();
String sqlPattern = bpd.isGlobal() ? SQL_SET_GLOBAL_BREAKPOINT : SQL_SET_BREAKPOINT;
String sqlCommand = sqlPattern.replaceAll("\\?sessionid", String.valueOf(getSessionId()))
.replaceAll("\\?obj", String.valueOf(descriptor.getObjectDescriptor().getID()))
.replaceAll("\\?line", bpd.isOnStart() ? "-1" : String.valueOf(bpd.getLineNo()))
.replaceAll("\\?target", bpd.isAll() ? "null"
: String.valueOf(bpd.getTargetId()));
return sqlCommand;
}
@Override
public void addBreakpoint(DBGObjectDescriptor object, DBGBreakpointProperties properties) throws DBGException {
acquireReadLock();
PostgreDebugBreakpointDescriptor bp = null;
try {
PostgreDebugBreakpointProperties bpd = (PostgreDebugBreakpointProperties) properties;
bp = new PostgreDebugBreakpointDescriptor(this, (PostgreDebugObjectDescriptor)object, bpd);
try (Statement stmt = getConnection().createStatement()) {
String sqlCommand = bpd.isGlobal() ? SQL_SET_GLOBAL_BREAKPOINT : SQL_SET_BREAKPOINT;
stmt.executeQuery(sqlCommand.replaceAll("\\?sessionid", String.valueOf(getSessionId()))
.replaceAll("\\?obj", String.valueOf(object.getID()))
.replaceAll("\\?line", bpd.isOnStart() ? "-1" : String.valueOf(bpd.getLineNo()))
.replaceAll("\\?target", bpd.isAll() ? "null"
: String.valueOf(bpd.getTargetId())));
} catch (SQLException e) {
throw new DBGException("SQL error", e);
}
breakpoints.add(bp);
} finally {
lock.readLock().unlock();
}
}
@Override
public void removeBreakpoint(DBGBreakpointDescriptor bp) throws DBGException {
acquireReadLock();
try {
try (Statement stmt = getConnection().createStatement()) {
PostgreDebugBreakpointProperties properties = (PostgreDebugBreakpointProperties) bp.getProperties();
stmt.executeQuery(SQL_DROP_BREAKPOINT.replaceAll("\\?sessionid", String.valueOf(getSessionId()))
.replaceAll("\\?obj", String.valueOf(bp.getObjectDescriptor().getID()))
.replaceAll("\\?line", properties.isOnStart() ? "-1" : String.valueOf(properties.getLineNo())));
} catch (SQLException e) {
throw new DBGException("SQL error", e);
}
breakpoints.remove(bp);
} finally {
lock.readLock().unlock();
}
protected String composeRemoveBreakpointCommand(DBGBreakpointDescriptor bp) {
PostgreDebugBreakpointProperties properties = (PostgreDebugBreakpointProperties) bp.getProperties();
String sqlCommand = SQL_DROP_BREAKPOINT.replaceAll("\\?sessionid", String.valueOf(getSessionId()))
.replaceAll("\\?obj", String.valueOf(bp.getObjectDescriptor().getID()))
.replaceAll("\\?line", properties.isOnStart() ? "-1" : String.valueOf(properties.getLineNo()));
return sqlCommand;
}
@Override
public void execContinue() throws DBGException {
execStep(SQL_CONTINUE, " continue for ");
execStep(SQL_CONTINUE, " continue for ", DBGEvent.RESUME);
}
@Override
public void execStepInto() throws DBGException {
execStep(SQL_STEP_INTO, " step into for ");
execStep(SQL_STEP_INTO, " step into for ", DBGEvent.STEP_INTO);
}
@Override
public void execStepOver() throws DBGException {
execStep(SQL_STEP_OVER, " step over for ");
execStep(SQL_STEP_OVER, " step over for ", DBGEvent.STEP_OVER);
}
......@@ -270,14 +202,15 @@ public class PostgreDebugSession implements DBGSession {
* @param name - session 'name' part
* @throws DBGException
*/
public void execStep(String commandSQL, String name) throws DBGException {
public void execStep(String commandSQL, String name, int eventDetail) throws DBGException {
acquireWriteLock();
try {
DBGEvent event = new DBGEvent(this, DBGEvent.RESUME, eventDetail);
runAsync(commandSQL.replaceAll("\\?sessionid", String.valueOf(sessionId)),
String.valueOf(sessionId) + name + String.valueOf(targetId));
String.valueOf(sessionId) + name + String.valueOf(targetId), event);
} finally {
lock.writeLock().unlock();
......@@ -285,41 +218,8 @@ public class PostgreDebugSession implements DBGSession {
}
@Override
public void abort() throws DBGException {
acquireReadLock();
try (Statement stmt = getConnection(connection).createStatement()) {
stmt.execute(SQL_ABORT.replaceAll("\\?sessionid", String.valueOf(sessionId)));
task = null;
} catch (SQLException e) {
throw new DBGException("SQL error", e);
} finally {
lock.readLock().unlock();
}
}
public void close() {
lock.writeLock().lock();
try {
if (!isDone()) {
task.cancel(true);
}
connection.close();
} finally {
lock.writeLock().unlock();
}
protected String composeAbortCommand() {
return SQL_ABORT.replaceAll("\\?sessionid", String.valueOf(sessionId));
}
@Override
......@@ -330,7 +230,7 @@ public class PostgreDebugSession implements DBGSession {
List<DBGVariable<?>> vars = new ArrayList<>();
String sql = SQL_GET_VARS.replaceAll("\\?sessionid", String.valueOf(sessionId));
try (Statement stmt = getConnection(connection).createStatement(); ResultSet rs = stmt.executeQuery(sql)) {
try (Statement stmt = getConnection().createStatement(); ResultSet rs = stmt.executeQuery(sql)) {
while (rs.next()) {
String name = rs.getString("name");
......@@ -361,7 +261,7 @@ public class PostgreDebugSession implements DBGSession {
acquireReadLock();
try (PreparedStatement stmt = getConnection(connection).prepareStatement(SQL_SET_VAR)) {
try (PreparedStatement stmt = getConnection().prepareStatement(SQL_SET_VAR)) {
if (variable instanceof PostgreDebugVariable){
......@@ -401,8 +301,8 @@ public class PostgreDebugSession implements DBGSession {
List<DBGStackFrame> stack = new ArrayList<DBGStackFrame>(1);
String sql = SQL_GET_STACK.replaceAll("\\?sessionid", String.valueOf(sessionId));
try (Statement stmt = getConnection(connection).createStatement(); ResultSet rs = stmt.executeQuery(sql)) {
String sql = SQL_GET_STACK.replaceAll("\\?sessionid", String.valueOf(getSessionId()));
try (Statement stmt = getConnection().createStatement(); ResultSet rs = stmt.executeQuery(sql)) {
while (rs.next()) {
int level = rs.getInt("level");
String targetname = rs.getString("targetname");
......@@ -421,23 +321,9 @@ public class PostgreDebugSession implements DBGSession {
return stack;
}
/**
* Return connection used in debug session
*
* @return java.sql.Connection
* @throws DBGException
*/
private Connection getConnection() throws DBGException {
try {
return getConnection(connection);
} catch (SQLException e) {
throw new DBGException("SQL error", e);
}
}
@Override
public String toString() {
return "PostgreDebugSession " + (isWaiting() ? "WAITING" : "READY") + " [connection=" + connection + ", sessionId=" + sessionId + ", breakpoints=" + breakpoints + "targetId=("
return "PostgreDebugSession " + (isWaiting() ? "WAITING" : "READY") + " [sessionId=" + sessionId + ", breakpoints=" + getBreakpoints() + "targetId=("
+ targetId + ") Session=(" + sessionInfo.toString() + ") " + "]";
}
......@@ -446,146 +332,13 @@ public class PostgreDebugSession implements DBGSession {
return sessionId;
}
/**
* Return true if session up and running debug thread
*
* @return boolean
*/
public boolean isWaiting() {
return (task == null ? false : !task.isDone()) && (workerThread == null ? false : workerThread.isAlive());
}
/**
* Return true if session waiting target connection (on breakpoint, after step or continue) in debug thread
*
* @return boolean
*/
public boolean isDone(){
if (task == null)
return true;
if (task.isDone()) {
try {
task.get();
} catch (InterruptedException e) {
log.error("DEBUG INTERRUPT ERROR ",e);
return false;
} catch (ExecutionException e) {
log.error("DEBUG WARNING ",e);
return false;
}
return true;
}
return false;
}
/**
* Return true if debug session up and running on server
*
* @return boolean
*/
public boolean isAttached() {
return (connection != null && sessionId > 0);
}
/**
* Start thread for SQL command
*
* @param commandSQL
* @param name
* @throws DBGException
*/
private void runAsync(String commandSQL, String name) throws DBGException {
Connection connection = getConnection();
try (Statement stmt = connection.createStatement()) {
connection.setAutoCommit(false);
PostgreDebugSessionWorker worker = new PostgreDebugSessionWorker(connection, commandSQL);
task = new FutureTask<Void>(worker);
workerThread = new Thread(task);
workerThread.setName(name);
workerThread.start();
} catch (SQLException e) {
throw new DBGException("SQL error", e);
}
}
/**
* Try to acquire shared lock
*
* @throws DBGException
*/
private void acquireReadLock() throws DBGException {
try {
lock.readLock().lockInterruptibly();
} catch (InterruptedException e1) {
throw new DBGException(e1.getMessage());
}
if (!isAttached()) {
lock.readLock().unlock();
throw new DBGException("Debug session not attached");
}
if (isWaiting()) {
lock.readLock().unlock();
throw new DBGException("Debug session in waiting state");
}
if (!isDone()) {
lock.readLock().unlock();
throw new DBGException("Debug session in incorrect state");
}
}
/**
* Try to acquire exclusive lock
*
* @throws DBGException
*/
private void acquireWriteLock() throws DBGException {
try {
lock.writeLock().lockInterruptibly();
} catch (InterruptedException e1) {
throw new DBGException(e1.getMessage());
}
if (!isAttached()) {
lock.writeLock().unlock();
throw new DBGException("Debug session not attached");
}
if (isWaiting()) {
lock.writeLock().unlock();
throw new DBGException("Debug session in waiting state");
}
if (!isDone()) {
lock.writeLock().unlock();
throw new DBGException("Debug session in incorrect state");
}
return super.isAttached() && (sessionId > 0);
}
}
......@@ -77,13 +77,19 @@ public class PgSqlLaunchShortcut extends LaunchShortcut {
}
String database = DebugCore.extractDatabaseName(config);
String databaseName = launchable.getDataSource().getName();
String databaseName = procedure.getDatabase().getName();
if (!database.equals(databaseName)) {
return false;
}
String schema = DebugCore.extractSchemaName(config);
String schemaName = procedure.getContainer().getName();
if (!schema.equals(schemaName)) {
return false;
}
try {
String oid = config.getAttribute(DebugCore.ATTR_OID, String.valueOf(0));
String oid = config.getAttribute(DebugCore.ATTR_PROCEDURE_OID, String.valueOf(0));
long objectId = procedure.getObjectId();
if (!(Long.parseLong(oid)==objectId)) {
return false;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册