/**
* Copyright (C) 2009-2013 FoundationDB, LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.foundationdb.ais.model;
import com.foundationdb.ais.model.validation.AISInvariants;
import com.foundationdb.server.error.InvalidRoutineException;
import java.util.*;
public class Routine
{
public static enum CallingConvention {
JAVA, LOADABLE_PLAN, SQL_ROW, SCRIPT_FUNCTION_JAVA, SCRIPT_BINDINGS,
SCRIPT_FUNCTION_JSON, SCRIPT_BINDINGS_JSON, SCRIPT_LIBRARY
}
public static enum SQLAllowed {
MODIFIES_SQL_DATA, READS_SQL_DATA, CONTAINS_SQL, NO_SQL
}
public static Routine create(AkibanInformationSchema ais,
String schemaName, String name,
String language, CallingConvention callingConvention) {
Routine routine = new Routine(ais, schemaName, name, language, callingConvention);
ais.addRoutine(routine);
return routine;
}
protected Routine(AkibanInformationSchema ais,
String schemaName, String name,
String language, CallingConvention callingConvention) {
ais.checkMutability();
AISInvariants.checkNullName(schemaName, "Routine", "schema name");
AISInvariants.checkNullName(name, "Routine", "table name");
AISInvariants.checkDuplicateRoutine(ais, schemaName, name);
this.ais = ais;
this.name = new TableName(schemaName, name);
this.language = language;
this.callingConvention = callingConvention;
}
public TableName getName() {
return name;
}
public List<Parameter> getParameters() {
return parameters;
}
public Parameter getNamedParameter(String name) {
for (Parameter parameter : parameters) {
if (name.equals(parameter.getName())) {
return parameter;
}
}
return null;
}
public boolean isProcedure() {
return (returnValue == null);
}
public Parameter getReturnValue() {
return returnValue;
}
public String getLanguage() {
return language;
}
public CallingConvention getCallingConvention() {
return callingConvention;
}
public SQLJJar getSQLJJar() {
return sqljJar;
}
public String getClassName() {
return className;
}
public String getMethodName() {
return methodName;
}
public String getExternalName() {
if (methodName == null)
return className;
else if (className == null)
return methodName;
else
return className + "." + methodName;
}
public String getDefinition() {
return definition;
}
public SQLAllowed getSQLAllowed() {
return sqlAllowed;
}
public int getDynamicResultSets() {
return dynamicResultSets;
}
public boolean isDeterministic() {
return deterministic;
}
public boolean isCalledOnNullInput() {
return calledOnNullInput;
}
protected void checkMutability() {
ais.checkMutability();
}
public boolean isSystemRoutine() {
if (name.getSchemaName().equalsIgnoreCase("sys") ||
name.getSchemaName().equalsIgnoreCase("security_schema") ||
name.getSchemaName().equalsIgnoreCase("sqlj")) {
return true;
}
return false;
}
protected void addParameter(Parameter parameter)
{
checkMutability();
switch (parameter.getDirection()) {
case RETURN:
returnValue = parameter;
break;
default:
parameters.add(parameter);
}
}
public void setExternalName(SQLJJar sqljJar, String className, String methodName) {
checkMutability();
switch (callingConvention) {
case JAVA:
AISInvariants.checkNullName(className, "Routine", "class name");
AISInvariants.checkNullName(methodName, "Routine", "method name");
break;
case LOADABLE_PLAN:
AISInvariants.checkNullName(className, "Routine", "class name");
break;
case SCRIPT_FUNCTION_JAVA:
case SCRIPT_FUNCTION_JSON:
AISInvariants.checkNullName(methodName, "Routine", "function name");
break;
default:
throw new InvalidRoutineException(name.getSchemaName(), name.getTableName(),
"EXTERNAL NAME not allowed for " + callingConvention);
}
this.sqljJar = sqljJar;
if (sqljJar != null)
sqljJar.addRoutine(this);
this.className = className;
this.methodName = methodName;
}
public void setDefinition(String definition) {
checkMutability();
switch (callingConvention) {
case JAVA:
case LOADABLE_PLAN:
throw new InvalidRoutineException(name.getSchemaName(), name.getTableName(),
"AS not allowed for " + callingConvention);
}
this.definition = definition;
}
public void setSQLAllowed(SQLAllowed sqlAllowed) {
checkMutability();
this.sqlAllowed = sqlAllowed;
}
public void setDynamicResultSets(int dynamicResultSets) {
checkMutability();
this.dynamicResultSets = dynamicResultSets;
}
public void setDeterministic(boolean deterministic) {
checkMutability();
this.deterministic = deterministic;
}
public void setCalledOnNullInput(boolean calledOnNullInput) {
checkMutability();
this.calledOnNullInput = calledOnNullInput;
}
public long getVersion() {
return version;
}
public void setVersion(long version) {
this.version = version;
}
// State
protected final AkibanInformationSchema ais;
protected final TableName name;
protected final List<Parameter> parameters = new ArrayList<>();
protected Parameter returnValue = null;
protected String language;
protected CallingConvention callingConvention;
protected SQLJJar sqljJar;
protected String className, methodName;
protected String definition;
protected SQLAllowed sqlAllowed;
protected int dynamicResultSets = 0;
protected boolean deterministic, calledOnNullInput;
protected long version;
}