提交 59cb7951 编写于 作者: S serge-rider

Vertica UDFs


Former-commit-id: 9d643776
上级 41aa6ac0
......@@ -25,11 +25,11 @@ tree.index_columns.node.name=Index columns
tree.references.node.name=References
tree.reference.node.name=Reference
tree.reference_columns.node.name=Reference columns
tree.procedures.node.name=Procedures
tree.procedure.node.name=Procedure
tree.procedure_columns.node.name=Procedure Columns
tree.packages.node.name=Packages
tree.package.node.name=Package
tree.functions.node.name=Functions
tree.functions.node.description=Functions/UDFs
tree.function.node.name=Function
tree.function_columns.node.name=Function arguments
tree.function_column.node.name=Argument
tree.sequences.node.name=Sequences
tree.sequence.node.name=Sequence
tree.triggers.node.name=Triggers
......
......@@ -80,22 +80,14 @@
</items>
</folder>
<folder type="org.jkiss.dbeaver.ext.generic.model.GenericScriptObject" label="%tree.procedures.node.name" icon="#procedures" description="Procedures">
<items label="%tree.package.node.name" path="package" property="packages" icon="#package">
<items label="%tree.procedures.node.name" itemLabel="%tree.procedure.node.name" path="procedure" property="procedures" icon="#procedure">
<items label="%tree.procedure_columns.node.name" itemLabel="%tree.column.node.name" path="column" property="parameters" navigable="false" inline="true"/>
</items>
</items>
<items label="%tree.procedures.node.name" itemLabel="%tree.procedure.node.name" path="procedure" property="procedures" icon="#procedure">
<items label="%tree.procedure_columns.node.name" itemLabel="%tree.column.node.name" path="column" property="parameters" navigable="false"/>
<folder type="org.jkiss.dbeaver.ext.generic.model.GenericScriptObject" label="%tree.functions.node.name" icon="#procedures" description="Functions/UDFs">
<items label="%tree.functions.node.name" itemLabel="%tree.function.node.name" path="procedure" property="procedures" icon="#function">
<items label="%tree.function_columns.node.name" itemLabel="%tree.function_column.node.name" path="column" property="parameters" navigable="false"/>
</items>
</folder>
<folder type="org.jkiss.dbeaver.ext.generic.model.GenericSequence" label="%tree.sequences.node.name" icon="#sequences" description="Sequences" >
<items label="%tree.sequence.node.name" path="sequence" property="sequences" icon="#sequence"/>
</folder>
<!--<folder type="org.jkiss.dbeaver.ext.generic.model.GenericTrigger" label="%tree.triggers.node.name" icon="#triggers" description="Global triggers" visibleIf="object.dataSource.metaModel.supportsDatabaseTriggers(object.dataSource)">
<items label="%tree.trigger.node.name" path="trigger" property="triggers" icon="#trigger"/>
</folder>-->
</items>
</folder>
<folder label="%tree.admin.node.name" icon="#folder_admin" description="%tree.admin.node.description">
......
......@@ -30,6 +30,7 @@ import org.jkiss.dbeaver.model.exec.jdbc.JDBCPreparedStatement;
import org.jkiss.dbeaver.model.exec.jdbc.JDBCResultSet;
import org.jkiss.dbeaver.model.exec.jdbc.JDBCSession;
import org.jkiss.dbeaver.model.exec.jdbc.JDBCStatement;
import org.jkiss.dbeaver.model.impl.jdbc.cache.JDBCObjectLookupCache;
import org.jkiss.dbeaver.model.impl.jdbc.cache.JDBCStructLookupCache;
import org.jkiss.dbeaver.model.meta.Association;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
......@@ -55,6 +56,7 @@ public class VerticaSchema extends GenericSchema implements DBPSystemObject
};
final ProjectionCache projectionCache = new ProjectionCache();
final UDFCache udfCache = new UDFCache();
public VerticaSchema(GenericDataSource dataSource, GenericCatalog catalog, String schemaName) {
super(dataSource, catalog, schemaName);
......@@ -80,6 +82,11 @@ public class VerticaSchema extends GenericSchema implements DBPSystemObject
return projectionCache.getAllObjects(monitor, this);
}
@Association
public Collection<VerticaUDF> getUserDefinedFunctions(DBRProgressMonitor monitor) throws DBException {
return udfCache.getAllObjects(monitor, this);
}
@Override
public boolean isSystem() {
return ArrayUtils.contains(SYSTEM_SCHEMAS, getName());
......@@ -135,4 +142,33 @@ public class VerticaSchema extends GenericSchema implements DBPSystemObject
}
public class UDFCache extends JDBCObjectLookupCache<VerticaSchema, VerticaUDF> {
UDFCache()
{
super();
setListOrderComparator(DBUtils.nameComparator());
}
@NotNull
@Override
public JDBCStatement prepareLookupStatement(@NotNull JDBCSession session, @NotNull VerticaSchema schema, @Nullable VerticaUDF object, @Nullable String objectName) throws SQLException {
final JDBCPreparedStatement dbStat = session.prepareStatement(
"SELECT * FROM v_catalog.user_functions WHERE schema_schema=?" +
(object == null && objectName == null ? "" : " AND function_name=?")
);
dbStat.setString(1, schema.getName());
if (object != null || objectName != null) dbStat.setString(2, object != null ? object.getName() : objectName);
return dbStat;
}
@Override
protected VerticaUDF fetchObject(@NotNull JDBCSession session, @NotNull VerticaSchema owner, @NotNull JDBCResultSet dbResult)
throws SQLException, DBException
{
return new VerticaUDF(VerticaSchema.this, dbResult);
}
}
}
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2017 Serge Rider (serge@jkiss.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jkiss.dbeaver.ext.vertica.model;
import org.jkiss.code.NotNull;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.ext.generic.GenericConstants;
import org.jkiss.dbeaver.ext.generic.model.*;
import org.jkiss.dbeaver.ext.generic.model.meta.GenericMetaObject;
import org.jkiss.dbeaver.model.DBPEvaluationContext;
import org.jkiss.dbeaver.model.DBPRefreshableObject;
import org.jkiss.dbeaver.model.DBPUniqueObject;
import org.jkiss.dbeaver.model.DBUtils;
import org.jkiss.dbeaver.model.exec.jdbc.JDBCResultSet;
import org.jkiss.dbeaver.model.exec.jdbc.JDBCSession;
import org.jkiss.dbeaver.model.impl.jdbc.JDBCConstants;
import org.jkiss.dbeaver.model.impl.jdbc.JDBCUtils;
import org.jkiss.dbeaver.model.impl.struct.AbstractProcedure;
import org.jkiss.dbeaver.model.meta.Property;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
import org.jkiss.dbeaver.model.struct.DBSObject;
import org.jkiss.dbeaver.model.struct.rdb.DBSProcedureParameterKind;
import org.jkiss.dbeaver.model.struct.rdb.DBSProcedureType;
import org.jkiss.utils.CommonUtils;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* GenericProcedure
*/
public class VerticaUDF extends AbstractProcedure<GenericDataSource, GenericStructContainer> implements GenericScriptObject, DBPUniqueObject, DBPRefreshableObject
{
private static final Pattern PATTERN_COL_NAME_NUMERIC = Pattern.compile("\\$?([0-9]+)");
private String type;
private String returnType;
private String argumentType;
private String definition;
private String volatility;
private boolean isStrict;
private boolean isFenced;
//private List<GenericProcedureParameter> columns;
public VerticaUDF(
VerticaSchema container,
JDBCResultSet dbResult)
{
super(container, true, JDBCUtils.safeGetString(dbResult, "function_name"), null);
this.type = JDBCUtils.safeGetString(dbResult, "procedure_type");
this.returnType = JDBCUtils.safeGetString(dbResult, "function_return_type");
this.argumentType = JDBCUtils.safeGetString(dbResult, "function_argument_type");
this.definition = JDBCUtils.safeGetString(dbResult, "function_definition");
this.volatility = JDBCUtils.safeGetString(dbResult, "volatility");
this.isStrict = JDBCUtils.safeGetBoolean(dbResult, "is_strict");
this.isFenced = JDBCUtils.safeGetBoolean(dbResult, "is_fenced");
setDescription(JDBCUtils.safeGetString(dbResult, "comment"));
}
@Property(viewable = true, order = 3)
public GenericCatalog getCatalog()
{
return getContainer().getCatalog();
}
@Override
public DBSProcedureType getProcedureType()
{
return DBSProcedureType.FUNCTION;
}
@Override
public Collection<GenericProcedureParameter> getParameters(DBRProgressMonitor monitor)
throws DBException
{
return null;
/*
if (columns == null) {
loadProcedureColumns(monitor);
}
return columns;
*/
}
/*
private void loadProcedureColumns(DBRProgressMonitor monitor) throws DBException
{
Collection<? extends VerticaUDF> procedures = getContainer().getProcedures(monitor, getName());
if (procedures == null || !procedures.contains(this)) {
throw new DBException("Internal error - cannot read columns for procedure '" + getName() + "' because its not found in container");
}
Iterator<? extends VerticaUDF> procIter = procedures.iterator();
VerticaUDF procedure = null;
final GenericMetaObject pcObject = getDataSource().getMetaObject(GenericConstants.OBJECT_PROCEDURE_COLUMN);
try (JDBCSession session = DBUtils.openMetaSession(monitor, getDataSource(), "Load procedure columns")) {
final JDBCResultSet dbResult;
if (functionResultType == null) {
dbResult = session.getMetaData().getProcedureColumns(
getCatalog() == null ?
this.getPackage() == null || !this.getPackage().isNameFromCatalog() ?
null :
this.getPackage().getName() :
getCatalog().getName(),
getSchema() == null ? null : getSchema().getName(),
getName(),
getDataSource().getAllObjectsPattern()
);
} else {
dbResult = session.getMetaData().getFunctionColumns(
getCatalog() == null ? null : getCatalog().getName(),
getSchema() == null ? null : getSchema().getName(),
getName(),
getDataSource().getAllObjectsPattern()
);
}
try {
int previousPosition = -1;
while (dbResult.next()) {
String columnName = GenericUtils.safeGetString(pcObject, dbResult, JDBCConstants.COLUMN_NAME);
int columnTypeNum = GenericUtils.safeGetInt(pcObject, dbResult, JDBCConstants.COLUMN_TYPE);
int valueType = GenericUtils.safeGetInt(pcObject, dbResult, JDBCConstants.DATA_TYPE);
String typeName = GenericUtils.safeGetString(pcObject, dbResult, JDBCConstants.TYPE_NAME);
int columnSize = GenericUtils.safeGetInt(pcObject, dbResult, JDBCConstants.LENGTH);
boolean notNull = GenericUtils.safeGetInt(pcObject, dbResult, JDBCConstants.NULLABLE) == DatabaseMetaData.procedureNoNulls;
int scale = GenericUtils.safeGetInt(pcObject, dbResult, JDBCConstants.SCALE);
int precision = GenericUtils.safeGetInt(pcObject, dbResult, JDBCConstants.PRECISION);
//int radix = GenericUtils.safeGetInt(dbResult, JDBCConstants.RADIX);
String remarks = GenericUtils.safeGetString(pcObject, dbResult, JDBCConstants.REMARKS);
int position = GenericUtils.safeGetInt(pcObject, dbResult, JDBCConstants.ORDINAL_POSITION);
DBSProcedureParameterKind parameterType;
if (functionResultType == null) {
switch (columnTypeNum) {
case DatabaseMetaData.procedureColumnIn:
parameterType = DBSProcedureParameterKind.IN;
break;
case DatabaseMetaData.procedureColumnInOut:
parameterType = DBSProcedureParameterKind.INOUT;
break;
case DatabaseMetaData.procedureColumnOut:
parameterType = DBSProcedureParameterKind.OUT;
break;
case DatabaseMetaData.procedureColumnReturn:
parameterType = DBSProcedureParameterKind.RETURN;
break;
case DatabaseMetaData.procedureColumnResult:
parameterType = DBSProcedureParameterKind.RESULTSET;
break;
default:
parameterType = DBSProcedureParameterKind.UNKNOWN;
break;
}
} else {
switch (columnTypeNum) {
case DatabaseMetaData.functionColumnIn:
parameterType = DBSProcedureParameterKind.IN;
break;
case DatabaseMetaData.functionColumnInOut:
parameterType = DBSProcedureParameterKind.INOUT;
break;
case DatabaseMetaData.functionColumnOut:
parameterType = DBSProcedureParameterKind.OUT;
break;
case DatabaseMetaData.functionReturn:
parameterType = DBSProcedureParameterKind.RETURN;
break;
case DatabaseMetaData.functionColumnResult:
parameterType = DBSProcedureParameterKind.RESULTSET;
break;
default:
parameterType = DBSProcedureParameterKind.UNKNOWN;
break;
}
}
if (CommonUtils.isEmpty(columnName) && parameterType == DBSProcedureParameterKind.RETURN) {
columnName = "RETURN";
}
if (position == 0) {
// Some drivers do not return ordinal position (PostgreSQL) but
// position is contained in column name
Matcher numberMatcher = PATTERN_COL_NAME_NUMERIC.matcher(columnName);
if (numberMatcher.matches()) {
position = Integer.parseInt(numberMatcher.group(1));
}
}
if (procedure == null || (previousPosition >= 0 && position <= previousPosition && procIter.hasNext())) {
procedure = procIter.next();
}
GenericProcedureParameter column = new GenericProcedureParameter(
procedure,
columnName,
typeName,
valueType,
position,
columnSize,
scale, precision, notNull,
remarks,
parameterType);
procedure.addColumn(column);
previousPosition = position;
}
} finally {
dbResult.close();
}
} catch (SQLException e) {
throw new DBException(e, getDataSource());
}
}
private void addColumn(GenericProcedureParameter column)
{
if (this.columns == null) {
this.columns = new ArrayList<>();
}
this.columns.add(column);
}
*/
@NotNull
@Override
public String getFullyQualifiedName(DBPEvaluationContext context)
{
return DBUtils.getFullQualifiedName(getDataSource(),
getContainer(),
this);
}
@NotNull
@Override
public String getUniqueName()
{
return getName();
}
@Override
public String getObjectDefinitionText(DBRProgressMonitor monitor, Map<String, Object> options) throws DBException {
return definition;
}
@Override
public DBSObject refreshObject(@NotNull DBRProgressMonitor monitor) throws DBException {
return this;
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册