Beispiel #1
0
  private boolean executeSingleQuery(
      @NotNull DBCSession session, @NotNull SQLQuery sqlQuery, boolean fireEvents) {
    lastError = null;

    final String originalQueryText = sqlQuery.getQuery();
    DBCExecutionContext executionContext = getExecutionContext();
    SQLQueryResult curResult = new SQLQueryResult(sqlQuery);
    if (rsOffset > 0) {
      curResult.setRowOffset(rsOffset);
    }
    SQLQuery originalQuery = sqlQuery;
    long startTime = System.currentTimeMillis();

    if (fireEvents && listener != null) {
      // Notify query start
      listener.onStartQuery(sqlQuery);
    }

    try {
      // Prepare statement
      closeStatement();

      // Check and invalidate connection
      DBPDataSource dataSource = executionContext.getDataSource();
      if (!connectionInvalidated
          && dataSource
              .getContainer()
              .getPreferenceStore()
              .getBoolean(DBeaverPreferences.STATEMENT_INVALIDATE_BEFORE_EXECUTE)) {
        executionContext.invalidateContext(session.getProgressMonitor());
        connectionInvalidated = true;
      }

      try {
        // Modify query (filters + parameters)
        if (dataFilter != null && dataFilter.hasFilters() && dataSource instanceof SQLDataSource) {
          String filteredQueryText =
              ((SQLDataSource) dataSource)
                  .getSQLDialect()
                  .addFiltersToQuery(dataSource, originalQueryText, dataFilter);
          sqlQuery = new SQLQuery(filteredQueryText, sqlQuery.getOffset(), sqlQuery.getLength());
        }
      } catch (DBException e) {
        throw new DBCException("Can't apply query filter", e);
      }

      Boolean hasParameters = prepareStatementParameters(sqlQuery);
      if (hasParameters == null) {
        return false;
      }

      statistics.setQueryText(originalQueryText);

      startTime = System.currentTimeMillis();
      DBCExecutionSource source =
          new AbstractExecutionSource(
              dataContainer, executionContext, partSite.getPart(), sqlQuery);
      curStatement =
          DBUtils.prepareStatement(
              source,
              session,
              hasParameters ? DBCStatementType.QUERY : DBCStatementType.SCRIPT,
              sqlQuery,
              rsOffset,
              rsMaxRows);

      if (hasParameters) {
        bindStatementParameters(session, sqlQuery);
      }

      // Execute statement
      try {
        boolean hasResultSet = curStatement.executeStatement();
        curResult.setHasResultSet(hasResultSet);
        statistics.addExecuteTime(System.currentTimeMillis() - startTime);
        statistics.addStatementsCount();

        long updateCount = -1;
        while (hasResultSet || resultSetNumber == 0 || updateCount >= 0) {
          // Fetch data only if we have to fetch all results or if it is rs requested
          if (fetchResultSetNumber < 0 || fetchResultSetNumber == resultSetNumber) {
            if (hasResultSet && fetchResultSets) {
              DBDDataReceiver dataReceiver =
                  resultsConsumer.getDataReceiver(sqlQuery, resultSetNumber);
              if (dataReceiver != null) {
                hasResultSet =
                    fetchQueryData(
                        session, curStatement.openResultSet(), curResult, dataReceiver, true);
              }
            }
          }
          if (!hasResultSet) {
            try {
              updateCount = curStatement.getUpdateRowCount();
              if (updateCount >= 0) {
                curResult.setUpdateCount(updateCount);
                statistics.addRowsUpdated(updateCount);
              }
            } catch (DBCException e) {
              // In some cases we can't read update count
              // This is bad but we can live with it
              // Just print a warning
              log.warn("Can't obtain update count", e);
            }
          }
          if (hasResultSet && fetchResultSets) {
            resultSetNumber++;
            fetchResultSetNumber = resultSetNumber;
          }
          if (!hasResultSet && updateCount < 0) {
            // Nothing else to fetch
            break;
          }

          if (dataSource.getInfo().supportsMultipleResults()) {
            hasResultSet = curStatement.nextResults();
            updateCount = hasResultSet ? -1 : 0;
          } else {
            break;
          }
        }

        try {
          curResult.setWarnings(curStatement.getStatementWarnings());
        } catch (Throwable e) {
          log.warn("Can't read execution warnings", e);
        }
      } finally {
        // monitor.subTask("Close query");
        if (!keepStatementOpen()) {
          closeStatement();
        }

        // Release parameters
        releaseStatementParameters(sqlQuery);
      }
    } catch (Throwable ex) {
      if (!(ex instanceof DBException)) {
        log.error("Unexpected error while processing SQL", ex);
      }
      curResult.setError(ex);
      lastError = ex;
    } finally {
      curResult.setQueryTime(System.currentTimeMillis() - startTime);

      if (fireEvents && listener != null) {
        // Notify query end
        listener.onEndQuery(curResult);
      }
    }

    if (curResult.getError() != null && errorHandling != SQLScriptErrorHandling.IGNORE) {
      return false;
    }
    // Success
    lastGoodQuery = originalQuery;
    return true;
  }
Beispiel #2
0
  @Override
  protected IStatus run(DBRProgressMonitor monitor) {
    RuntimeUtils.setThreadName("SQL script execution");
    statistics = new DBCStatistics();
    try {
      DBCExecutionContext context = getExecutionContext();
      DBCTransactionManager txnManager = DBUtils.getTransactionManager(context);
      DBCExecutionPurpose purpose =
          queries.size() > 1 ? DBCExecutionPurpose.USER_SCRIPT : DBCExecutionPurpose.USER;
      try (DBCSession session = context.openSession(monitor, purpose, "SQL Query")) {
        // Set transaction settings (only if autocommit is off)
        QMUtils.getDefaultHandler().handleScriptBegin(session);

        boolean oldAutoCommit = txnManager == null || txnManager.isAutoCommit();
        boolean newAutoCommit = (commitType == SQLScriptCommitType.AUTOCOMMIT);
        if (txnManager != null && !oldAutoCommit && newAutoCommit) {
          txnManager.setAutoCommit(monitor, true);
        }

        monitor.beginTask(this.getName(), queries.size());

        // Notify job start
        if (listener != null) {
          listener.onStartScript();
        }

        resultSetNumber = 0;
        for (int queryNum = 0; queryNum < queries.size(); ) {
          // Execute query
          SQLQuery query = queries.get(queryNum);

          fetchResultSetNumber = resultSetNumber;
          boolean runNext = executeSingleQuery(session, query, true);
          if (!runNext) {
            // Ask to continue
            if (lastError != null) {
              log.error(lastError);
            }
            boolean isQueue = queryNum < queries.size() - 1;
            ExecutionQueueErrorResponse response =
                ExecutionQueueErrorJob.showError(
                    isQueue ? "SQL script execution" : "SQL query execution", lastError, isQueue);

            boolean stopScript = false;
            switch (response) {
              case STOP:
                // just stop execution
                stopScript = true;
                break;
              case RETRY:
                // just make it again
                continue;
              case IGNORE:
                // Just do nothing
                break;
              case IGNORE_ALL:
                errorHandling = SQLScriptErrorHandling.IGNORE;
                break;
            }

            if (stopScript) {
              break;
            }
          }

          // Check monitor
          if (monitor.isCanceled()) {
            break;
          }
          monitor.worked(1);
          queryNum++;
        }
        showExecutionResult(session);
        monitor.done();

        // Commit data
        if (txnManager != null && !oldAutoCommit && commitType != SQLScriptCommitType.AUTOCOMMIT) {
          if (lastError == null || errorHandling == SQLScriptErrorHandling.STOP_COMMIT) {
            if (commitType != SQLScriptCommitType.NO_COMMIT) {
              monitor.beginTask("Commit data", 1);
              txnManager.commit(session);
              monitor.done();
            }
          } else {
            monitor.beginTask("Rollback data", 1);
            txnManager.rollback(session, null);
            monitor.done();
          }
        }

        // Restore transactions settings
        if (txnManager != null && !oldAutoCommit && newAutoCommit) {
          txnManager.setAutoCommit(monitor, false);
        }

        QMUtils.getDefaultHandler().handleScriptEnd(session);

        // Return success
        return new Status(Status.OK, DBeaverCore.getCorePluginID(), "SQL job completed");
      }
    } catch (Throwable ex) {
      return new Status(
          Status.ERROR,
          DBeaverCore.getCorePluginID(),
          "Error during SQL job execution: " + ex.getMessage());
    } finally {
      // Notify job end
      if (listener != null) {
        listener.onEndScript(statistics, lastError != null);
      }
    }
  }