/*
* Copyright (c) 2013, OpenCloudDB/MyCAT and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software;Designed and Developed mainly by many Chinese
* opensource volunteers. you can redistribute it and/or modify it under the
* terms of the GNU General Public License version 2 only, as published by the
* Free Software Foundation.
*
* This code 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 General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Any questions about this component can be directed to it's project Web address
* https://code.google.com/p/opencloudb/.
*
*/
package com.akiban.sql.parser;
import com.akiban.sql.StandardException;
import com.akiban.sql.types.AliasInfo;
import com.akiban.sql.types.DataTypeDescriptor;
import com.akiban.sql.types.RoutineAliasInfo;
import com.akiban.sql.types.SynonymAliasInfo;
import com.akiban.sql.types.UDTAliasInfo;
import java.util.List;
/**
* A CreateAliasNode represents a CREATE ALIAS statement.
*
*/
public class CreateAliasNode extends DDLStatementNode
{
// indexes into routineElements
public static final int PARAMETER_ARRAY = 0;
public static final int TABLE_NAME = PARAMETER_ARRAY + 1;
public static final int DYNAMIC_RESULT_SET_COUNT = TABLE_NAME + 1;
public static final int LANGUAGE = DYNAMIC_RESULT_SET_COUNT + 1;
public static final int EXTERNAL_NAME = LANGUAGE + 1;
public static final int PARAMETER_STYLE = EXTERNAL_NAME + 1;
public static final int SQL_CONTROL = PARAMETER_STYLE + 1;
public static final int DETERMINISTIC = SQL_CONTROL + 1;
public static final int NULL_ON_NULL_INPUT = DETERMINISTIC + 1;
public static final int RETURN_TYPE = NULL_ON_NULL_INPUT + 1;
public static final int ROUTINE_SECURITY_DEFINER = RETURN_TYPE + 1;
public static final int INLINE_DEFINITION = ROUTINE_SECURITY_DEFINER + 1;
// Keep ROUTINE_ELEMENT_COUNT last (determines set cardinality).
// Note: Remember to also update the map ROUTINE_CLAUSE_NAMES in
// SQLGrammar.jj when elements are added.
public static final int ROUTINE_ELEMENT_COUNT = INLINE_DEFINITION + 1;
private String javaClassName;
private String methodName;
private boolean createOrReplace;
private AliasInfo.Type aliasType;
private AliasInfo aliasInfo;
private String definition;
/**
* Initializer for a CreateAliasNode
*
* @param aliasName The name of the alias
* @param targetObject Target name
* @param methodName The method name
* @param aliasType The alias type
*
* @exception StandardException Thrown on error
*/
public void init(Object aliasName,
Object targetObject,
Object methodName,
Object aliasSpecificInfo,
Object aliasType,
Object createOrReplace)
throws StandardException {
TableName qn = (TableName)aliasName;
this.aliasType = (AliasInfo.Type)aliasType;
this.createOrReplace = (Boolean)createOrReplace;
initAndCheck(qn);
switch (this.aliasType) {
case UDT:
this.javaClassName = (String)targetObject;
aliasInfo = new UDTAliasInfo();
implicitCreateSchema = true;
break;
case PROCEDURE:
case FUNCTION:
{
//routineElements contains the description of the procedure.
//
// 0 - Object[] 3 element array for parameters
// 1 - TableName - specific name
// 2 - Integer - dynamic result set count
// 3 - String language
// 4 - String external name (also passed directly to create alias node - ignore
// 5 - ParameterStyle parameter style
// 6 - SQLAllowed - SQL control
// 7 - Boolean - CALLED ON NULL INPUT (always TRUE for procedures)
// 8 - DataTypeDescriptor - return type (always NULL for procedures)
// 9 - Boolean - definers rights
// 10 - String - inline definition
Object[] routineElements = (Object[])aliasSpecificInfo;
Object[] parameters = (Object[])routineElements[PARAMETER_ARRAY];
int paramCount = ((List)parameters[0]).size();
String[] names = null;
DataTypeDescriptor[] types = null;
int[] modes = null;
if (paramCount != 0) {
names = new String[paramCount];
((List<String>)parameters[0]).toArray(names);
types = new DataTypeDescriptor[paramCount];
((List<DataTypeDescriptor>)parameters[1]).toArray(types);
modes = new int[paramCount];
for (int i = 0; i < paramCount; i++) {
int currentMode = ((List<Integer>)parameters[2]).get(i).intValue();
modes[i] = currentMode;
}
if (paramCount > 1) {
String[] dupNameCheck = new String[paramCount];
System.arraycopy(names, 0, dupNameCheck, 0, paramCount);
java.util.Arrays.sort(dupNameCheck);
for (int dnc = 1; dnc < dupNameCheck.length; dnc++) {
if (! dupNameCheck[dnc].equals("") && dupNameCheck[dnc].equals(dupNameCheck[dnc - 1]))
throw new StandardException("Duplicate parameter name");
}
}
}
Integer drso = (Integer)routineElements[DYNAMIC_RESULT_SET_COUNT];
int drs = drso == null ? 0 : drso.intValue();
RoutineAliasInfo.SQLAllowed sqlAllowed = (RoutineAliasInfo.SQLAllowed)routineElements[SQL_CONTROL];
Boolean isDeterministicO = (Boolean)routineElements[DETERMINISTIC];
boolean isDeterministic = (isDeterministicO == null) ? false : isDeterministicO.booleanValue();
Boolean definersRightsO = (Boolean)routineElements[ROUTINE_SECURITY_DEFINER];
boolean definersRights = (definersRightsO == null) ? false : definersRightsO.booleanValue();
Boolean calledOnNullInputO = (Boolean)routineElements[NULL_ON_NULL_INPUT];
boolean calledOnNullInput = (calledOnNullInputO == null) ? false : calledOnNullInputO.booleanValue();
DataTypeDescriptor returnType = (DataTypeDescriptor)routineElements[RETURN_TYPE];
String language = (String)routineElements[LANGUAGE];
String pstyle = (String)routineElements[PARAMETER_STYLE];
this.definition = (String)routineElements[INLINE_DEFINITION];
this.javaClassName = (String)targetObject;
this.methodName = (String)methodName;
aliasInfo = new RoutineAliasInfo(this.methodName,
paramCount,
names,
types,
modes,
drs,
language,
pstyle,
sqlAllowed,
isDeterministic,
definersRights,
calledOnNullInput,
returnType);
implicitCreateSchema = true;
}
break;
case SYNONYM:
String targetSchema = null;
implicitCreateSchema = true;
TableName t = (TableName)targetObject;
if (t.getSchemaName() != null)
targetSchema = t.getSchemaName();
aliasInfo = new SynonymAliasInfo(targetSchema, t.getTableName());
break;
default:
assert false : "Unexpected value for aliasType " + aliasType;
}
}
public String getJavaClassName() {
return javaClassName;
}
public String getMethodName() {
return methodName;
}
public String getExternalName() {
if (javaClassName == null)
return methodName;
else if (methodName == null)
return javaClassName;
else
return javaClassName + "." + methodName;
}
public boolean isCreateOrReplace() {
return createOrReplace;
}
public AliasInfo.Type getAliasType() {
return aliasType;
}
public AliasInfo getAliasInfo() {
return aliasInfo;
}
public String getDefinition() {
return definition;
}
/**
* Convert this object to a String. See comments in QueryTreeNode.java
* for how this should be done for tree printing.
*
* @return This object as a String
*/
public String toString() {
return "aliasType: " + aliasType + "\n" +
"aliasInfo: " + aliasInfo + "\n" +
"createOrReplace: " + createOrReplace + "\n" +
((definition != null) ?
("definition: " + definition + "\n") :
("javaClassName: " + javaClassName + "\n" +
"methodName: " + methodName + "\n")) +
super.toString();
}
/**
* Fill this node with a deep copy of the given node.
*/
public void copyFrom(QueryTreeNode node) throws StandardException {
super.copyFrom(node);
CreateAliasNode other = (CreateAliasNode)node;
this.javaClassName = other.javaClassName;
this.methodName = other.methodName;
this.definition = other.definition;
this.aliasType = other.aliasType;
this.aliasInfo = other.aliasInfo; // TODO: Clone?
}
public String statementToString() {
switch (this.aliasType) {
case UDT:
return "CREATE TYPE";
case PROCEDURE:
return "CREATE PROCEDURE";
case SYNONYM:
return "CREATE SYNONYM";
default:
return "CREATE FUNCTION";
}
}
}