use of org.teiid.query.metadata.StoredProcedureInfo in project teiid by teiid.
the class ExecResolver method findCommandMetadata.
/**
* @see org.teiid.query.resolver.CommandResolver#findCommandMetadata(org.teiid.query.sql.lang.Command,
* org.teiid.query.metadata.QueryMetadataInterface)
*/
private void findCommandMetadata(Command command, TempMetadataStore discoveredMetadata, QueryMetadataInterface metadata) throws QueryMetadataException, QueryResolverException, TeiidComponentException {
StoredProcedure storedProcedureCommand = (StoredProcedure) command;
StoredProcedureInfo storedProcedureInfo = null;
try {
storedProcedureInfo = metadata.getStoredProcedureInfoForProcedure(storedProcedureCommand.getProcedureName());
} catch (QueryMetadataException e) {
// $NON-NLS-1$
String[] parts = storedProcedureCommand.getProcedureName().split("\\.", 2);
if (parts.length > 1 && parts[0].equalsIgnoreCase(metadata.getVirtualDatabaseName())) {
try {
storedProcedureInfo = metadata.getStoredProcedureInfoForProcedure(parts[1]);
storedProcedureCommand.setProcedureName(parts[1]);
} catch (QueryMetadataException e1) {
}
}
if (storedProcedureInfo == null) {
throw e;
}
}
storedProcedureCommand.setUpdateCount(storedProcedureInfo.getUpdateCount());
storedProcedureCommand.setModelID(storedProcedureInfo.getModelID());
storedProcedureCommand.setProcedureID(storedProcedureInfo.getProcedureID());
storedProcedureCommand.setProcedureCallableName(storedProcedureInfo.getProcedureCallableName());
// Get old parameters as they may have expressions set on them - collect
// those expressions to copy later into the resolved parameters
Collection<SPParameter> oldParams = storedProcedureCommand.getParameters();
boolean namedParameters = storedProcedureCommand.displayNamedParameters();
// of relying on all default values of all optional parameters.
if (oldParams.size() == 0 || (oldParams.size() == 1 && storedProcedureCommand.isCalledWithReturn())) {
storedProcedureCommand.setDisplayNamedParameters(true);
namedParameters = true;
}
// Cache original input parameter expressions. Depending on whether
// the procedure was parsed with named or unnamed parameters, the keys
// for this map will either be the String names of the parameters or
// the Integer indices, as entered in the user query
Map<Integer, Expression> positionalExpressions = new TreeMap<Integer, Expression>();
Map<String, Expression> namedExpressions = new TreeMap<String, Expression>(String.CASE_INSENSITIVE_ORDER);
int adjustIndex = 0;
for (SPParameter param : oldParams) {
if (param.getExpression() == null) {
if (param.getParameterType() == SPParameter.RESULT_SET) {
// If this was already resolved, just pretend the result set param doesn't exist
adjustIndex--;
}
continue;
}
if (namedParameters && param.getParameterType() != SPParameter.RETURN_VALUE) {
if (namedExpressions.put(param.getParameterSymbol().getShortName(), param.getExpression()) != null) {
throw new QueryResolverException(QueryPlugin.Event.TEIID30138, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30138, param.getName()));
}
} else {
positionalExpressions.put(param.getIndex() + adjustIndex, param.getExpression());
}
}
storedProcedureCommand.clearParameters();
int origInputs = positionalExpressions.size() + namedExpressions.size();
/*
* Take the values set from the stored procedure implementation, and match up with the
* types of parameter it is from the metadata and then reset the newly joined parameters
* into the stored procedure command. If it is a result set get those columns and place
* them into the stored procedure command as well.
*/
List<SPParameter> metadataParams = storedProcedureInfo.getParameters();
List<SPParameter> clonedMetadataParams = new ArrayList<SPParameter>(metadataParams.size());
int inputParams = 0;
int optionalParams = 0;
int outParams = 0;
boolean hasReturnValue = false;
boolean optional = false;
boolean varargs = false;
for (int i = 0; i < metadataParams.size(); i++) {
SPParameter metadataParameter = metadataParams.get(i);
if ((metadataParameter.getParameterType() == ParameterInfo.IN) || (metadataParameter.getParameterType() == ParameterInfo.INOUT)) {
if (ResolverUtil.hasDefault(metadataParameter.getMetadataID(), metadata) || metadataParameter.isVarArg()) {
optional = true;
optionalParams++;
} else {
inputParams++;
if (optional) {
optional = false;
inputParams += optionalParams;
optionalParams = 0;
}
}
if (metadataParameter.isVarArg()) {
varargs = true;
}
} else if (metadataParameter.getParameterType() == ParameterInfo.OUT) {
outParams++;
/*
* TODO: it would consistent to do the following, but it is a breaking change for procedures that have intermixed out params with in.
* we may need to revisit this later
*/
// optional = true;
// optionalParams++;
} else if (metadataParameter.getParameterType() == ParameterInfo.RETURN_VALUE) {
hasReturnValue = true;
}
SPParameter clonedParam = (SPParameter) metadataParameter.clone();
clonedMetadataParams.add(clonedParam);
storedProcedureCommand.setParameter(clonedParam);
}
if (storedProcedureCommand.isCalledWithReturn() && !hasReturnValue) {
throw new QueryResolverException(QueryPlugin.Event.TEIID30139, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30139, storedProcedureCommand.getGroup()));
}
if (!namedParameters && (inputParams > positionalExpressions.size())) {
// $NON-NLS-1$ //$NON-NLS-2$
throw new QueryResolverException(QueryPlugin.Event.TEIID30140, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30140, inputParams, inputParams + optionalParams + (varargs ? "+" : ""), origInputs, storedProcedureCommand.getGroup()));
}
// Walk through the resolved parameters and set the expressions from the
// input parameters
int exprIndex = 1;
HashSet<String> expected = new HashSet<String>();
if (storedProcedureCommand.isCalledWithReturn() && hasReturnValue) {
for (SPParameter param : clonedMetadataParams) {
if (param.getParameterType() == SPParameter.RETURN_VALUE) {
Expression expr = positionalExpressions.remove(exprIndex++);
param.setExpression(expr);
break;
}
}
}
for (SPParameter param : clonedMetadataParams) {
if (param.getParameterType() == SPParameter.RESULT_SET || param.getParameterType() == SPParameter.RETURN_VALUE) {
continue;
}
if (namedParameters) {
String nameKey = param.getParameterSymbol().getShortName();
Expression expr = namedExpressions.remove(nameKey);
// With named parameters, have to check on optional params and default values
if (expr == null) {
if (param.getParameterType() != ParameterInfo.OUT) {
param.setUsingDefault(true);
expected.add(nameKey);
if (!param.isVarArg()) {
expr = ResolverUtil.getDefault(param.getParameterSymbol(), metadata);
} else {
// zero length array
List<Expression> exprs = new ArrayList<Expression>(0);
Array array = new Array(exprs);
array.setImplicit(true);
array.setType(param.getClassType());
expr = array;
}
}
}
param.setExpression(expr);
} else {
Expression expr = positionalExpressions.remove(exprIndex++);
if (param.getParameterType() == SPParameter.OUT) {
if (expr != null) {
boolean isRef = expr instanceof Reference;
if (!isRef || exprIndex <= inputParams + 1) {
// for backwards compatibility, this should be treated instead as an input
exprIndex--;
positionalExpressions.put(exprIndex, expr);
} else if (isRef) {
// mimics the hack that was in PreparedStatementRequest.
Reference ref = (Reference) expr;
// may be an out
ref.setOptional(true);
/*
* Note that there is a corner case here with out parameters intermixed with optional parameters
* there's not a good way around this.
*/
}
}
continue;
}
if (expr == null) {
if (!param.isVarArg()) {
expr = ResolverUtil.getDefault(param.getParameterSymbol(), metadata);
}
param.setUsingDefault(true);
}
if (param.isVarArg()) {
List<Expression> exprs = new ArrayList<Expression>(positionalExpressions.size() + 1);
if (expr != null) {
exprs.add(expr);
}
exprs.addAll(positionalExpressions.values());
positionalExpressions.clear();
Array array = new Array(exprs);
array.setImplicit(true);
array.setType(param.getClassType());
expr = array;
}
param.setExpression(expr);
}
}
// Check for leftovers, i.e. params entered by user w/ wrong/unknown names
if (!namedExpressions.isEmpty()) {
throw new QueryResolverException(QueryPlugin.Event.TEIID30141, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30141, namedExpressions.keySet(), expected));
}
if (!positionalExpressions.isEmpty()) {
throw new QueryResolverException(QueryPlugin.Event.TEIID31113, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID31113, positionalExpressions.size(), origInputs, storedProcedureCommand.getGroup().toString()));
}
// Create temporary metadata that defines a group based on either the stored proc
// name or the stored query name - this will be used later during planning
String procName = storedProcedureCommand.getProcedureName();
List tempElements = storedProcedureCommand.getProjectedSymbols();
boolean isVirtual = storedProcedureInfo.getQueryPlan() != null;
discoveredMetadata.addTempGroup(procName, tempElements, isVirtual);
// Resolve tempElements against new metadata
GroupSymbol procGroup = new GroupSymbol(storedProcedureInfo.getProcedureCallableName());
procGroup.setProcedure(true);
TempMetadataID tid = discoveredMetadata.getTempGroupID(procName);
tid.setOriginalMetadataID(storedProcedureCommand.getProcedureID());
procGroup.setMetadataID(tid);
storedProcedureCommand.setGroup(procGroup);
}
use of org.teiid.query.metadata.StoredProcedureInfo in project teiid by teiid.
the class ExecResolver method getPlan.
/**
* @throws QueryResolverException
* @see org.teiid.query.resolver.ProcedureContainerResolver#getPlan(org.teiid.query.metadata.QueryMetadataInterface, org.teiid.query.sql.symbol.GroupSymbol)
*/
protected String getPlan(QueryMetadataInterface metadata, GroupSymbol group) throws TeiidComponentException, QueryMetadataException, QueryResolverException {
StoredProcedureInfo storedProcedureInfo = metadata.getStoredProcedureInfoForProcedure(group.getName());
// if there is a query plan associated with the procedure, get it.
QueryNode plan = storedProcedureInfo.getQueryPlan();
if (plan.getQuery() == null) {
throw new QueryResolverException(QueryPlugin.Event.TEIID30146, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30146, group));
}
return plan.getQuery();
}
use of org.teiid.query.metadata.StoredProcedureInfo in project teiid by teiid.
the class ResolverUtil method resolveGroup.
public static void resolveGroup(GroupSymbol symbol, QueryMetadataInterface metadata) throws TeiidComponentException, QueryResolverException {
if (symbol.getMetadataID() != null) {
return;
}
// determine the "metadataID" part of the symbol to look up
String potentialID = symbol.getNonCorrelationName();
String name = symbol.getName();
String definition = symbol.getDefinition();
Object groupID = null;
try {
// get valid GroupID for possibleID - this may throw exceptions if group is invalid
groupID = metadata.getGroupID(potentialID);
} catch (QueryMetadataException e) {
// didn't find this group ID
}
// If that didn't work, try to strip a vdb name from potentialID
if (groupID == null) {
// $NON-NLS-1$
String[] parts = potentialID.split("\\.", 2);
if (parts.length > 1 && parts[0].equalsIgnoreCase(metadata.getVirtualDatabaseName())) {
try {
groupID = metadata.getGroupID(parts[1]);
} catch (QueryMetadataException e) {
// ignore - just didn't find it
}
if (groupID != null) {
potentialID = parts[1];
}
}
}
// and there is only one group that matches the given partial name
if (groupID == null) {
Collection groupNames = null;
try {
groupNames = metadata.getGroupsForPartialName(potentialID);
} catch (QueryMetadataException e) {
// ignore - just didn't find it
}
if (groupNames != null) {
int matches = groupNames.size();
if (matches == 1) {
potentialID = (String) groupNames.iterator().next();
try {
// get valid GroupID for possibleID - this may throw exceptions if group is invalid
groupID = metadata.getGroupID(potentialID);
} catch (QueryMetadataException e) {
// didn't find this group ID
}
} else if (matches > 1) {
// $NON-NLS-1$
throw handleUnresolvedGroup(symbol, QueryPlugin.Util.getString("ERR.015.008.0055"));
}
}
}
if (groupID == null || metadata.isProcedure(groupID)) {
// try procedure relational resolving
try {
StoredProcedureInfo storedProcedureInfo = metadata.getStoredProcedureInfoForProcedure(potentialID);
symbol.setProcedure(true);
groupID = storedProcedureInfo.getProcedureID();
} catch (QueryMetadataException e) {
// just ignore
}
}
if (groupID == null) {
// $NON-NLS-1$
throw handleUnresolvedGroup(symbol, QueryPlugin.Util.getString("ERR.015.008.0056"));
}
// set real metadata ID in the symbol
symbol.setMetadataID(groupID);
potentialID = metadata.getFullName(groupID);
if (symbol.getDefinition() == null) {
symbol.setName(potentialID);
} else {
symbol.setDefinition(potentialID);
}
try {
if (!symbol.isProcedure()) {
symbol.setIsTempTable(metadata.isTemporaryTable(groupID));
}
} catch (QueryMetadataException e) {
// should not come here
}
if (metadata.useOutputName()) {
symbol.setOutputDefinition(definition);
symbol.setOutputName(name);
}
}
use of org.teiid.query.metadata.StoredProcedureInfo in project teiid by teiid.
the class ProcedureContainerResolver method findChildCommandMetadata.
/**
* Set the appropriate "external" metadata for the given command
* @param inferProcedureResultSetColumns
* @throws QueryResolverException
*/
public static void findChildCommandMetadata(Command currentCommand, GroupSymbol container, int type, QueryMetadataInterface metadata, boolean inferProcedureResultSetColumns) throws QueryMetadataException, TeiidComponentException, QueryResolverException {
// find the childMetadata using a clean metadata store
TempMetadataStore childMetadata = new TempMetadataStore();
TempMetadataAdapter tma = new TempMetadataAdapter(metadata, childMetadata);
GroupContext externalGroups = new GroupContext();
if (currentCommand instanceof TriggerAction) {
TriggerAction ta = (TriggerAction) currentCommand;
ta.setView(container);
// TODO: it seems easier to just inline the handling here rather than have each of the resolvers check for trigger actions
List<ElementSymbol> viewElements = ResolverUtil.resolveElementsInGroup(ta.getView(), metadata);
if (type == Command.TYPE_UPDATE || type == Command.TYPE_INSERT) {
ProcedureContainerResolver.addChanging(tma.getMetadataStore(), externalGroups, viewElements);
ProcedureContainerResolver.addScalarGroup(SQLConstants.Reserved.NEW, tma.getMetadataStore(), externalGroups, viewElements, false);
if (type == Command.TYPE_INSERT) {
List<ElementSymbol> key = InsertResolver.getAutoIncrementKey(ta.getView().getMetadataID(), viewElements, metadata);
if (key != null) {
ProcedureContainerResolver.addScalarGroup(SQLConstants.NonReserved.KEY, tma.getMetadataStore(), externalGroups, key, true);
}
}
}
if (type == Command.TYPE_UPDATE || type == Command.TYPE_DELETE) {
ProcedureContainerResolver.addScalarGroup(SQLConstants.Reserved.OLD, tma.getMetadataStore(), externalGroups, viewElements, false);
}
} else if (currentCommand instanceof CreateProcedureCommand) {
CreateProcedureCommand cupc = (CreateProcedureCommand) currentCommand;
cupc.setVirtualGroup(container);
if (type == Command.TYPE_STORED_PROCEDURE) {
StoredProcedureInfo info = metadata.getStoredProcedureInfoForProcedure(container.getName());
// Create temporary metadata that defines a group based on either the stored proc
// name or the stored query name - this will be used later during planning
String procName = info.getProcedureCallableName();
// Look through parameters to find input elements - these become child metadata
List<ElementSymbol> tempElements = new ArrayList<ElementSymbol>(info.getParameters().size());
boolean[] updatable = new boolean[info.getParameters().size()];
int i = 0;
List<ElementSymbol> rsColumns = Collections.emptyList();
for (SPParameter param : info.getParameters()) {
if (param.getParameterType() != ParameterInfo.RESULT_SET) {
ElementSymbol symbol = param.getParameterSymbol();
tempElements.add(symbol);
updatable[i++] = param.getParameterType() != ParameterInfo.IN;
if (param.getParameterType() == ParameterInfo.RETURN_VALUE) {
cupc.setReturnVariable(symbol);
}
} else {
rsColumns = param.getResultSetColumns();
}
}
if (inferProcedureResultSetColumns) {
rsColumns = null;
}
GroupSymbol gs = ProcedureContainerResolver.addScalarGroup(procName, childMetadata, externalGroups, tempElements, updatable);
if (cupc.getReturnVariable() != null) {
ResolverVisitor.resolveLanguageObject(cupc.getReturnVariable(), Arrays.asList(gs), metadata);
}
cupc.setResultSetColumns(rsColumns);
// the relational planner will override this with the appropriate value
cupc.setProjectedSymbols(rsColumns);
} else {
cupc.setUpdateType(type);
}
}
QueryResolver.setChildMetadata(currentCommand, childMetadata, externalGroups);
}
use of org.teiid.query.metadata.StoredProcedureInfo in project teiid by teiid.
the class ValidationVisitor method visit.
@Override
public void visit(AlterProcedure obj) {
GroupSymbol gs = obj.getTarget();
validateAlterTarget(obj);
try {
if (!gs.isProcedure() || !getMetadata().isVirtualModel(getMetadata().getModelID(gs.getMetadataID()))) {
// $NON-NLS-1$
handleValidationError(QueryPlugin.Util.getString("ValidationVisitor.not_a_procedure", gs), gs);
return;
}
Validator.validate(obj.getDefinition(), getMetadata(), this);
StoredProcedureInfo info = getMetadata().getStoredProcedureInfoForProcedure(gs.getName());
for (SPParameter param : info.getParameters()) {
if (param.getParameterType() == SPParameter.RESULT_SET) {
QueryResolver.validateProjectedSymbols(gs, param.getResultSetColumns(), obj.getDefinition().getProjectedSymbols());
break;
}
}
} catch (QueryValidatorException e) {
handleValidationError(e.getMessage(), obj.getDefinition().getBlock());
} catch (TeiidComponentException e) {
handleException(e);
}
}
Aggregations