提交 5dca3c37 编写于 作者: S Serge Rider

Merge remote-tracking branch 'origin/devel' into devel

......@@ -17,10 +17,12 @@
package org.jkiss.dbeaver.ext.hana.model;
import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.ext.generic.model.GenericSQLDialect;
import org.jkiss.dbeaver.model.DBPDataKind;
import org.jkiss.dbeaver.model.DBPDataSource;
import org.jkiss.dbeaver.model.DBPDataSourceContainer;
import org.jkiss.dbeaver.model.data.DBDBinaryFormatter;
import org.jkiss.dbeaver.model.exec.DBCException;
import org.jkiss.dbeaver.model.exec.jdbc.JDBCDatabaseMetaData;
......@@ -29,13 +31,17 @@ import org.jkiss.dbeaver.model.impl.data.formatters.BinaryFormatterHexString;
import org.jkiss.dbeaver.model.impl.jdbc.JDBCDataSource;
import org.jkiss.dbeaver.model.runtime.VoidProgressMonitor;
import org.jkiss.dbeaver.model.sql.SQLConstants;
import org.jkiss.dbeaver.model.sql.parser.rules.SQLVariableRule;
import org.jkiss.dbeaver.model.struct.DBSTypedObject;
import org.jkiss.dbeaver.model.text.parser.TPRule;
import org.jkiss.dbeaver.model.text.parser.TPRuleProvider;
import org.jkiss.utils.CommonUtils;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
public class HANASQLDialect extends GenericSQLDialect {
public class HANASQLDialect extends GenericSQLDialect implements TPRuleProvider {
private static final Log log = Log.getLog(HANASQLDialect.class);
......@@ -108,4 +114,11 @@ public class HANASQLDialect extends GenericSQLDialect {
// https://github.com/dbeaver/dbeaver/issues/9998#issuecomment-805710837
return "\\";
}
@Override
public void extendRules(@Nullable DBPDataSourceContainer dataSource, @NotNull List<TPRule> rules, @NotNull RulePosition position) {
if (position == RulePosition.INITIAL) {
rules.add(new SQLVariableRule());
}
}
}
......@@ -28,6 +28,7 @@ import org.jkiss.dbeaver.model.exec.jdbc.JDBCSession;
import org.jkiss.dbeaver.model.impl.jdbc.JDBCDataSource;
import org.jkiss.dbeaver.model.impl.jdbc.JDBCSQLDialect;
import org.jkiss.dbeaver.model.sql.SQLConstants;
import org.jkiss.dbeaver.model.sql.parser.rules.SQLVariableRule;
import org.jkiss.dbeaver.model.sql.parser.rules.SQLMultiWordRule;
import org.jkiss.dbeaver.model.sql.parser.tokens.SQLTokenType;
import org.jkiss.dbeaver.model.struct.DBSTypedObject;
......@@ -304,6 +305,9 @@ public class SQLServerDialect extends JDBCSQLDialect implements TPRuleProvider {
@Override
public void extendRules(@Nullable DBPDataSourceContainer dataSource, @NotNull List<TPRule> rules, @NotNull RulePosition position) {
if (position == RulePosition.INITIAL) {
rules.add(new SQLVariableRule());
}
if (position == RulePosition.KEYWORDS) {
final TPTokenDefault keywordToken = new TPTokenDefault(SQLTokenType.T_KEYWORD);
// https://docs.microsoft.com/en-us/sql/t-sql/language-elements/transactions-transact-sql
......
......@@ -130,7 +130,7 @@ public class SQLRuleManager {
{
if (!minimalRules && syntaxManager.isVariablesEnabled()) {
// Variable rule
rules.add(new SQLVariableRule(parameterToken));
rules.add(new ScriptVariableRule(parameterToken));
}
}
......@@ -240,7 +240,7 @@ public class SQLRuleManager {
// Parameter rule
for (String npPrefix : syntaxManager.getNamedParameterPrefixes()) {
rules.add(new SQLParameterRule(syntaxManager, parameterToken, npPrefix));
rules.add(new ScriptParameterRule(syntaxManager, parameterToken, npPrefix));
}
}
......
......@@ -16,64 +16,57 @@
*/
package org.jkiss.dbeaver.model.sql.parser.rules;
import org.jkiss.dbeaver.model.sql.SQLQueryParameter;
import org.jkiss.dbeaver.model.sql.parser.tokens.SQLVariableToken;
import org.jkiss.dbeaver.model.text.parser.TPCharacterScanner;
import org.jkiss.dbeaver.model.text.parser.TPRule;
import org.jkiss.dbeaver.model.text.parser.TPPredicateRule;
import org.jkiss.dbeaver.model.text.parser.TPToken;
import org.jkiss.dbeaver.model.text.parser.TPTokenAbstract;
/**
* SQL variable rule.
* ${varName}
*/
public class SQLVariableRule implements TPRule {
* Rule that matches {@code @variableName} supported by some dialects.
*/
public class SQLVariableRule implements TPPredicateRule {
private final TPToken parameterToken;
private final TPToken token = new SQLVariableToken();
public SQLVariableRule(TPToken parameterToken) {
this.parameterToken = parameterToken;
@Override
public TPToken getSuccessToken() {
return token;
}
@Override
public TPToken evaluate(TPCharacterScanner scanner)
{
int c = scanner.read();
if (c == '$') {
int prefixLength = 0;
c = scanner.read();
if (SQLQueryParameter.supportsJasperSyntax()) {
if (c == 'P') {
c = scanner.read();
prefixLength++;
if (c == '!') {
c = scanner.read();
prefixLength++;
}
}
}
if (c == '{') {
int varLength = 0;
for (;;) {
c = scanner.read();
if (c == '}' || Character.isWhitespace(c) || c == TPCharacterScanner.EOF) {
break;
}
varLength++;
}
if (varLength > 0 && c == '}') {
return parameterToken;
}
scanner.unread();
public TPToken evaluate(TPCharacterScanner scanner, boolean resume) {
scanner.unread();
int ch = scanner.read();
int read = 0;
for (int i = varLength - 1 + prefixLength; i >= 0; i--) {
if (!Character.isJavaIdentifierPart(ch)) {
ch = scanner.read();
read++;
if (ch == '@') {
do {
ch = scanner.read();
read++;
} while (Character.isJavaIdentifierPart(ch));
if (read > 2) {
scanner.unread();
return token;
}
}
}
while (read-- > 0) {
scanner.unread();
}
scanner.unread();
return TPTokenAbstract.UNDEFINED;
}
@Override
public TPToken evaluate(TPCharacterScanner scanner) {
return evaluate(scanner, false);
}
}
......@@ -26,14 +26,14 @@ import org.jkiss.dbeaver.model.text.parser.TPTokenAbstract;
/**
* SQL parameter rule
*/
public class SQLParameterRule implements TPRule {
public class ScriptParameterRule implements TPRule {
private final SQLSyntaxManager syntaxManager;
private final SQLParameterToken parameterToken;
private final StringBuilder buffer;
private final char anonymousParameterMark;
private final String namedParameterPrefix;
public SQLParameterRule(SQLSyntaxManager syntaxManager, SQLParameterToken parameterToken, String prefix) {
public ScriptParameterRule(SQLSyntaxManager syntaxManager, SQLParameterToken parameterToken, String prefix) {
this.syntaxManager = syntaxManager;
this.parameterToken = parameterToken;
this.buffer = new StringBuilder();
......
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2021 DBeaver Corp and others
*
* 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.model.sql.parser.rules;
import org.jkiss.dbeaver.model.sql.SQLQueryParameter;
import org.jkiss.dbeaver.model.text.parser.TPCharacterScanner;
import org.jkiss.dbeaver.model.text.parser.TPRule;
import org.jkiss.dbeaver.model.text.parser.TPToken;
import org.jkiss.dbeaver.model.text.parser.TPTokenAbstract;
/**
* SQL variable rule.
* ${varName}
*/
public class ScriptVariableRule implements TPRule {
private final TPToken parameterToken;
public ScriptVariableRule(TPToken parameterToken) {
this.parameterToken = parameterToken;
}
@Override
public TPToken evaluate(TPCharacterScanner scanner)
{
int c = scanner.read();
if (c == '$') {
int prefixLength = 0;
c = scanner.read();
if (SQLQueryParameter.supportsJasperSyntax()) {
if (c == 'P') {
c = scanner.read();
prefixLength++;
if (c == '!') {
c = scanner.read();
prefixLength++;
}
}
}
if (c == '{') {
int varLength = 0;
for (;;) {
c = scanner.read();
if (c == '}' || Character.isWhitespace(c) || c == TPCharacterScanner.EOF) {
break;
}
varLength++;
}
if (varLength > 0 && c == '}') {
return parameterToken;
}
scanner.unread();
for (int i = varLength - 1 + prefixLength; i >= 0; i--) {
scanner.unread();
}
}
scanner.unread();
}
scanner.unread();
return TPTokenAbstract.UNDEFINED;
}
}
......@@ -37,7 +37,6 @@ import org.jkiss.dbeaver.model.struct.DBSObjectContainer;
import org.jkiss.dbeaver.model.struct.rdb.DBSProcedure;
import org.jkiss.dbeaver.model.struct.rdb.DBSProcedureContainer;
import org.jkiss.dbeaver.model.struct.rdb.DBSProcedureParameter;
import org.jkiss.dbeaver.model.struct.rdb.DBSProcedureParameterKind;
import org.jkiss.utils.CommonUtils;
import java.io.InputStream;
......@@ -45,9 +44,8 @@ import java.io.Reader;
import java.math.BigDecimal;
import java.net.URL;
import java.sql.*;
import java.util.Calendar;
import java.util.Collection;
import java.util.Map;
import java.sql.Date;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
......@@ -105,44 +103,55 @@ public class JDBCCallableStatementImpl extends JDBCPreparedStatementImpl impleme
}
}
if (procedure != null) {
try {
Collection<? extends DBSProcedureParameter> params = procedure.getParameters(getConnection().getProgressMonitor());
if (!CommonUtils.isEmpty(params)) {
for (DBSProcedureParameter param : params) {
if (param.getParameterKind() == DBSProcedureParameterKind.OUT ||
param.getParameterKind() == DBSProcedureParameterKind.INOUT ||
param.getParameterKind() == DBSProcedureParameterKind.RETURN)
{
procResults.addColumn(param.getName(), param.getParameterType());
}
}
ParameterMetaData paramsMeta = null;
try {
paramsMeta = original.getParameterMetaData();
} catch (Throwable e) {
log.debug("Error extracting parameters meta data", e);
}
final List<DBSProcedureParameter> metaOutputParameters = getOutputParametersFromMeta();
final List<Integer> jdbcOutputParameters = getOutputParametersFromJDBC(paramsMeta);
if (metaOutputParameters == null && jdbcOutputParameters == null) {
log.debug("Can't obtain procedure metadata nor jdbc metadata");
return;
}
final JDBCDataSource dataSource = connection.getDataSource();
if (metaOutputParameters != null && jdbcOutputParameters != null && metaOutputParameters.size() == jdbcOutputParameters.size()) {
for (int index = 0, localIndex = 0; index < metaOutputParameters.size(); index++) {
final DBSProcedureParameter param = metaOutputParameters.get(index);
if (isParameterCursor(dataSource, paramsMeta, jdbcOutputParameters.get(index))) {
continue;
}
} catch (DBException e) {
log.debug("Error extracting callable results", e);
procResults.addColumn(param.getName(), param.getParameterType(), localIndex++, jdbcOutputParameters.get(index));
}
} else if (metaOutputParameters != null) {
for (int index = 0; index < metaOutputParameters.size(); index++) {
final DBSProcedureParameter param = metaOutputParameters.get(index);
procResults.addColumn(param.getName(), param.getParameterType(), index, index + 1);
}
} else {
// Try to make columns from parameters meta
try {
JDBCDataSource dataSource = connection.getDataSource();
ParameterMetaData paramsMeta = original.getParameterMetaData();
int parameterCount = paramsMeta.getParameterCount();
if (parameterCount > 0) {
for (int index = 0; index < parameterCount; index++) {
int parameterMode = paramsMeta.getParameterMode(index + 1);
if (parameterMode == ParameterMetaData.parameterModeOut || parameterMode == ParameterMetaData.parameterModeInOut) {
DBSDataType dataType = dataSource.getLocalDataType(paramsMeta.getParameterTypeName(index + 1));
if (dataType == null) {
DBPDataKind dataKind = JDBCUtils.resolveDataKind(dataSource, paramsMeta.getParameterTypeName(index + 1), paramsMeta.getParameterType(index + 1));
procResults.addColumn(String.valueOf(index + 1), dataKind);
} else {
procResults.addColumn(String.valueOf(index + 1), dataType);
}
}
int localIndex = 0;
for (int index : jdbcOutputParameters) {
if (isParameterCursor(dataSource, paramsMeta, index)) {
continue;
}
final DBSDataType dataType = dataSource.getLocalDataType(paramsMeta.getParameterTypeName(index));
if (dataType == null) {
final DBPDataKind dataKind = JDBCUtils.resolveDataKind(dataSource, paramsMeta.getParameterTypeName(index), paramsMeta.getParameterType(index));
procResults.addColumn(String.valueOf(index), dataKind, localIndex++, index);
} else {
procResults.addColumn(String.valueOf(index), dataType, localIndex++, index);
}
}
} catch (Throwable e) {
log.debug("Error extracting parameters meta data: " + e.getMessage());
log.debug("Error extracting parameters meta data", e);
}
}
procResults.addRow();
......@@ -241,7 +250,7 @@ public class JDBCCallableStatementImpl extends JDBCPreparedStatementImpl impleme
Collection<? extends DBSProcedureParameter> params = procedure.getParameters(getConnection().getProgressMonitor());
if (!CommonUtils.isEmpty(params)) {
for (DBSProcedureParameter param : params) {
if (param.getParameterKind() == DBSProcedureParameterKind.OUT || param.getParameterKind() == DBSProcedureParameterKind.INOUT) {
if (param.getParameterKind().isOutput()) {
return true;
}
}
......@@ -258,7 +267,7 @@ public class JDBCCallableStatementImpl extends JDBCPreparedStatementImpl impleme
if (!CommonUtils.isEmpty(params)) {
int index = 0;
for (DBSProcedureParameter param : params) {
if (param.getParameterKind() == DBSProcedureParameterKind.OUT || param.getParameterKind() == DBSProcedureParameterKind.INOUT) {
if (param.getParameterKind().isOutput()) {
index++;
registerOutParameter(index, param.getParameterType().getTypeID());
}
......@@ -269,25 +278,77 @@ public class JDBCCallableStatementImpl extends JDBCPreparedStatementImpl impleme
}
}
@Nullable
private List<DBSProcedureParameter> getOutputParametersFromMeta() {
if (procedure == null) {
return null;
}
try {
final Collection<? extends DBSProcedureParameter> params = procedure.getParameters(getConnection().getProgressMonitor());
if (params.isEmpty()) {
return Collections.emptyList();
}
final List<DBSProcedureParameter> outputParams = new ArrayList<>();
for (DBSProcedureParameter param : params) {
if (param.getParameterKind().isOutput()) {
outputParams.add(param);
}
}
return outputParams;
} catch (DBException e) {
log.debug("Error obtaining output parameters from procedure: " + e.getMessage());
return null;
}
}
@Nullable
private List<Integer> getOutputParametersFromJDBC(@Nullable ParameterMetaData paramsMeta) {
if (paramsMeta == null) {
return null;
}
try {
final int count = paramsMeta.getParameterCount();
if (count == 0) {
return Collections.emptyList();
}
final List<Integer> outputParams = new ArrayList<>();
for (int index = 1; index <= count; index++) {
final int mode = paramsMeta.getParameterMode(index);
if (mode == ParameterMetaData.parameterModeOut || mode == ParameterMetaData.parameterModeInOut) {
outputParams.add(index);
}
}
return outputParams;
} catch (SQLException e) {
log.debug("Error obtaining output parameters from metadata: " + e.getMessage());
return null;
}
}
private static boolean isParameterCursor(@NotNull DBPDataSource dataSource, @Nullable ParameterMetaData parameterMetaData, int parameterIndex) {
try {
// If database supports multiple results and parameter is cursor, then it will be in a separate result set
return dataSource.getInfo().supportsMultipleResults() && parameterMetaData != null && parameterMetaData.getParameterType(parameterIndex) == Types.REF_CURSOR;
} catch (Throwable ignored) {
return false;
}
}
@Override
public boolean executeStatement() throws DBCException {
boolean hasResults = super.executeStatement();
if (!hasResults && procResults.getColumnCount() > 0) {
return true;
}
return hasResults;
return super.executeStatement() || procResults.getColumnCount() > 0;
}
@Override
public boolean nextResults() throws DBCException {
return super.nextResults() || procResults.getColumnCount() > 0;
}
@Nullable
@Override
public JDBCResultSet getResultSet()
throws SQLException
{
JDBCResultSet resultSet = makeResultSet(getOriginal().getResultSet());
if (resultSet == null && procResults != null) {
return procResults;
}
return resultSet;
public JDBCResultSet getResultSet() throws SQLException {
final JDBCResultSet resultSet = makeResultSet(getOriginal().getResultSet());
return resultSet != null ? resultSet : procResults;
}
......
......@@ -16,12 +16,18 @@
*/
package org.jkiss.dbeaver.model.impl.jdbc.exec;
import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.model.DBPDataKind;
import org.jkiss.dbeaver.model.exec.DBCAttributeMetaData;
import org.jkiss.dbeaver.model.exec.DBCException;
import org.jkiss.dbeaver.model.exec.DBCResultSet;
import org.jkiss.dbeaver.model.exec.jdbc.JDBCCallableStatement;
import org.jkiss.dbeaver.model.exec.jdbc.JDBCResultSet;
import org.jkiss.dbeaver.model.exec.jdbc.JDBCSession;
import org.jkiss.dbeaver.model.impl.local.LocalResultSet;
import org.jkiss.dbeaver.model.impl.local.LocalResultSetColumn;
import org.jkiss.dbeaver.model.struct.DBSTypedObject;
import java.io.InputStream;
import java.io.Reader;
......@@ -59,7 +65,7 @@ public class JDBCResultSetCallable extends LocalResultSet<JDBCCallableStatement>
@Override
public Object getAttributeValue(int index) throws DBCException {
try {
return this.getObject(index + 1);
return this.getObject(getColumnOriginalIndex(index));
} catch (SQLException e) {
throw new DBCException(e, session.getExecutionContext());
}
......@@ -69,7 +75,7 @@ public class JDBCResultSetCallable extends LocalResultSet<JDBCCallableStatement>
@Override
public Object getAttributeValue(String name) throws DBCException {
try {
return this.getObject(name + 1);
return this.getObject(name);
} catch (SQLException e) {
throw new DBCException(e, session.getExecutionContext());
}
......@@ -91,55 +97,55 @@ public class JDBCResultSetCallable extends LocalResultSet<JDBCCallableStatement>
}
public String getString(int parameterIndex) throws SQLException {
return statement.getString(parameterIndex);
return statement.getString(getColumnOriginalIndex(parameterIndex));
}
public boolean getBoolean(int parameterIndex) throws SQLException {
return statement.getBoolean(parameterIndex);
return statement.getBoolean(getColumnOriginalIndex(parameterIndex));
}
public byte getByte(int parameterIndex) throws SQLException {
return statement.getByte(parameterIndex);
return statement.getByte(getColumnOriginalIndex(parameterIndex));
}
public short getShort(int parameterIndex) throws SQLException {
return statement.getShort(parameterIndex);
return statement.getShort(getColumnOriginalIndex(parameterIndex));
}
public int getInt(int parameterIndex) throws SQLException {
return statement.getInt(parameterIndex);
return statement.getInt(getColumnOriginalIndex(parameterIndex));
}
public long getLong(int parameterIndex) throws SQLException {
return statement.getLong(parameterIndex);
return statement.getLong(getColumnOriginalIndex(parameterIndex));
}
public float getFloat(int parameterIndex) throws SQLException {
return statement.getFloat(parameterIndex);
return statement.getFloat(getColumnOriginalIndex(parameterIndex));
}
public double getDouble(int parameterIndex) throws SQLException {
return statement.getDouble(parameterIndex);
return statement.getDouble(getColumnOriginalIndex(parameterIndex));
}
public BigDecimal getBigDecimal(int parameterIndex, int scale) throws SQLException {
return statement.getBigDecimal(parameterIndex, scale);
return statement.getBigDecimal(getColumnOriginalIndex(parameterIndex), scale);
}
public byte[] getBytes(int parameterIndex) throws SQLException {
return statement.getBytes(parameterIndex);
return statement.getBytes(getColumnOriginalIndex(parameterIndex));
}
public Date getDate(int parameterIndex) throws SQLException {
return statement.getDate(parameterIndex);
return statement.getDate(getColumnOriginalIndex(parameterIndex));
}
public Time getTime(int parameterIndex) throws SQLException {
return statement.getTime(parameterIndex);
return statement.getTime(getColumnOriginalIndex(parameterIndex));
}
public Timestamp getTimestamp(int parameterIndex) throws SQLException {
return statement.getTimestamp(parameterIndex);
return statement.getTimestamp(getColumnOriginalIndex(parameterIndex));
}
@Override
......@@ -158,7 +164,7 @@ public class JDBCResultSetCallable extends LocalResultSet<JDBCCallableStatement>
}
public URL getURL(int parameterIndex) throws SQLException {
return statement.getURL(parameterIndex);
return statement.getURL(getColumnOriginalIndex(parameterIndex));
}
public String getString(String parameterName) throws SQLException {
......@@ -264,7 +270,7 @@ public class JDBCResultSetCallable extends LocalResultSet<JDBCCallableStatement>
@Override
public Date getDate(int columnIndex, Calendar cal) throws SQLException {
return statement.getDate(columnIndex);
return statement.getDate(getColumnOriginalIndex(columnIndex));
}
public Date getDate(String parameterName, Calendar cal) throws SQLException {
......@@ -273,7 +279,7 @@ public class JDBCResultSetCallable extends LocalResultSet<JDBCCallableStatement>
@Override
public Time getTime(int columnIndex, Calendar cal) throws SQLException {
return statement.getTime(columnIndex);
return statement.getTime(getColumnOriginalIndex(columnIndex));
}
public Time getTime(String parameterName, Calendar cal) throws SQLException {
......@@ -282,7 +288,7 @@ public class JDBCResultSetCallable extends LocalResultSet<JDBCCallableStatement>
@Override
public Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException {
return statement.getTimestamp(columnIndex);
return statement.getTimestamp(getColumnOriginalIndex(columnIndex));
}
public Timestamp getTimestamp(String parameterName, Calendar cal) throws SQLException {
......@@ -295,27 +301,27 @@ public class JDBCResultSetCallable extends LocalResultSet<JDBCCallableStatement>
@Override
public Object getObject(int columnIndex, Map<String, Class<?>> map) throws SQLException {
return statement.getObject(columnIndex);
return statement.getObject(getColumnOriginalIndex(columnIndex));
}
@Override
public Ref getRef(int columnIndex) throws SQLException {
return statement.getRef(columnIndex);
return statement.getRef(getColumnOriginalIndex(columnIndex));
}
@Override
public Blob getBlob(int columnIndex) throws SQLException {
return statement.getBlob(columnIndex);
return statement.getBlob(getColumnOriginalIndex(columnIndex));
}
@Override
public Clob getClob(int columnIndex) throws SQLException {
return statement.getClob(columnIndex);
return statement.getClob(getColumnOriginalIndex(columnIndex));
}
@Override
public Array getArray(int columnIndex) throws SQLException {
return statement.getArray(columnIndex);
return statement.getArray(getColumnOriginalIndex(columnIndex));
}
@Override
......@@ -340,7 +346,7 @@ public class JDBCResultSetCallable extends LocalResultSet<JDBCCallableStatement>
@Override
public Object getObject(int columnIndex) throws SQLException {
return statement.getObject(columnIndex);
return statement.getObject(getColumnOriginalIndex(columnIndex));
}
@Override
......@@ -720,7 +726,7 @@ public class JDBCResultSetCallable extends LocalResultSet<JDBCCallableStatement>
@Override
public RowId getRowId(int columnIndex) throws SQLException {
return statement.getRowId(columnIndex);
return statement.getRowId(getColumnOriginalIndex(columnIndex));
}
@Override
......@@ -729,7 +735,7 @@ public class JDBCResultSetCallable extends LocalResultSet<JDBCCallableStatement>
}
public NClob getNClob(int parameterIndex) throws SQLException {
return statement.getNClob(parameterIndex);
return statement.getNClob(getColumnOriginalIndex(parameterIndex));
}
public NClob getNClob(String parameterName) throws SQLException {
......@@ -737,7 +743,7 @@ public class JDBCResultSetCallable extends LocalResultSet<JDBCCallableStatement>
}
public SQLXML getSQLXML(int parameterIndex) throws SQLException {
return statement.getSQLXML(parameterIndex);
return statement.getSQLXML(getColumnOriginalIndex(parameterIndex));
}
public SQLXML getSQLXML(String parameterName) throws SQLException {
......@@ -745,7 +751,7 @@ public class JDBCResultSetCallable extends LocalResultSet<JDBCCallableStatement>
}
public String getNString(int parameterIndex) throws SQLException {
return statement.getNString(parameterIndex);
return statement.getNString(getColumnOriginalIndex(parameterIndex));
}
public String getNString(String parameterName) throws SQLException {
......@@ -753,7 +759,7 @@ public class JDBCResultSetCallable extends LocalResultSet<JDBCCallableStatement>
}
public Reader getNCharacterStream(int parameterIndex) throws SQLException {
return statement.getNCharacterStream(parameterIndex);
return statement.getNCharacterStream(getColumnOriginalIndex(parameterIndex));
}
public Reader getNCharacterStream(String parameterName) throws SQLException {
......@@ -761,7 +767,7 @@ public class JDBCResultSetCallable extends LocalResultSet<JDBCCallableStatement>
}
public Reader getCharacterStream(int parameterIndex) throws SQLException {
return statement.getCharacterStream(parameterIndex);
return statement.getCharacterStream(getColumnOriginalIndex(parameterIndex));
}
public Reader getCharacterStream(String parameterName) throws SQLException {
......@@ -770,7 +776,7 @@ public class JDBCResultSetCallable extends LocalResultSet<JDBCCallableStatement>
@Override
public BigDecimal getBigDecimal(int columnIndex) throws SQLException {
return statement.getBigDecimal(columnIndex);
return statement.getBigDecimal(getColumnOriginalIndex(columnIndex));
}
@Override
......@@ -965,7 +971,7 @@ public class JDBCResultSetCallable extends LocalResultSet<JDBCCallableStatement>
@Override
public <T> T getObject(int columnIndex, Class<T> type) throws SQLException {
return statement.getObject(columnIndex, type);
return statement.getObject(getColumnOriginalIndex(columnIndex), type);
}
@Override
......@@ -983,4 +989,71 @@ public class JDBCResultSetCallable extends LocalResultSet<JDBCCallableStatement>
return false;
}
/** @deprecated Use {@link JDBCResultSetCallable#addColumn(String, DBPDataKind, int, int)} instead */
@Override
public DBCAttributeMetaData addColumn(String label, DBPDataKind dataKind) {
return addColumn(label, dataKind, getColumnCount(), getColumnCount());
}
/** @deprecated Use {@link JDBCResultSetCallable#addColumn(String, DBSTypedObject, int, int)} instead */
@Override
public DBCAttributeMetaData addColumn(String label, DBSTypedObject typedObject) {
return addColumn(label, typedObject, getColumnCount(), getColumnCount());
}
DBCAttributeMetaData addColumn(@NotNull String label, @NotNull DBSTypedObject typedObject, int localIndex, int originalIndex) {
final MappedLocalResultSetColumn column = new MappedLocalResultSetColumn(this, label, typedObject, localIndex, originalIndex);
addColumn(column);
return column;
}
DBCAttributeMetaData addColumn(@NotNull String label, @NotNull DBPDataKind dataKind, int localIndex, int originalIndex) {
final MappedLocalResultSetColumn column = new MappedLocalResultSetColumn(this, label, dataKind, localIndex, originalIndex);
addColumn(column);
return column;
}
private int getColumnOriginalIndex(int localIndex) throws SQLException {
final DBCAttributeMetaData metaColumn = getMetaColumn(localIndex - 1);
if (!(metaColumn instanceof MappedLocalResultSetColumn)) {
// Should **never** reach here
throw new SQLException("Can't get original index from local index: " + localIndex);
}
return ((MappedLocalResultSetColumn) metaColumn).getOriginalIndex();
}
/**
* Column containing is local result set index along with original result set index.
* <p>
* It is useful when not every parameter of a procedure produce scalar values
* but also cursors which we remove from local result set and instead process
* in a new tab, making holes in the local result set.
* <p>
* Consider following example:
* <pre>
* CREATE PROCEDURE test(OUT tab1 Table, OUT val1 INT, OUT tab2 Table, OUT val2 INT) AS
* BEGIN
* ...
* END
* </pre>
* After removing cursors (tab1, tab2), our local result set may look like: (val1, val2) which have zero-based
* indexes (0, 1), but their real indexes are (1, 3).
*/
private static class MappedLocalResultSetColumn extends LocalResultSetColumn {
private final int originalIndex;
private MappedLocalResultSetColumn(DBCResultSet resultSet, String label, DBPDataKind dataKind, int index, int originalIndex) {
super(resultSet, index, label, dataKind);
this.originalIndex = originalIndex;
}
private MappedLocalResultSetColumn(DBCResultSet resultSet, String label, DBSTypedObject typedObject, int index, int originalIndex) {
super(resultSet, index, label, typedObject);
this.originalIndex = originalIndex;
}
private int getOriginalIndex() {
return originalIndex;
}
}
}
......@@ -115,6 +115,15 @@ public class LocalResultSet<SOURCE_STMT extends DBCStatement> extends AbstractRe
return column;
}
protected void addColumn(@NotNull LocalResultSetColumn column) {
metaColumns.add(column);
}
@NotNull
protected DBCAttributeMetaData getMetaColumn(int index) {
return metaColumns.get(index);
}
public void addRow(Object... values) {
rows.add(values);
}
......
......@@ -22,21 +22,23 @@ package org.jkiss.dbeaver.model.struct.rdb;
*/
public enum DBSProcedureParameterKind
{
UNKNOWN("Unknown", false),
IN("IN", true),
OUT("OUT", false),
INOUT("IN/OUT", true),
RETURN("Return", false),
RESULTSET("ResultSet", false),
TABLE("Table", false),
UNKNOWN("Unknown", false, false),
IN("IN", true, false),
OUT("OUT", false, true),
INOUT("IN/OUT", true, true),
RETURN("Return", false, true),
RESULTSET("ResultSet", false, true),
TABLE("Table", false, true),
;
private final String title;
private final boolean isInput;
private final boolean isOutput;
DBSProcedureParameterKind(String title, boolean isInput) {
DBSProcedureParameterKind(String title, boolean isInput, boolean isOutput) {
this.title = title;
this.isInput = isInput;
this.isOutput = isOutput;
}
public String getTitle() {
......@@ -46,4 +48,8 @@ public enum DBSProcedureParameterKind
public boolean isInput() {
return isInput;
}
public boolean isOutput() {
return isOutput;
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册