/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to you 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.eigenbase.sql; import java.util.*; import org.eigenbase.reltype.*; import org.eigenbase.resource.Resources; import org.eigenbase.sql.fun.*; import org.eigenbase.sql.validate.*; import org.eigenbase.util.*; import static org.eigenbase.util.Static.RESOURCE; /** * <code>SqlCallBinding</code> implements {@link SqlOperatorBinding} by * analyzing to the operands of a {@link SqlCall} with a {@link SqlValidator}. */ public class SqlCallBinding extends SqlOperatorBinding { //~ Instance fields -------------------------------------------------------- private final SqlValidator validator; private final SqlValidatorScope scope; private final SqlCall call; //~ Constructors ----------------------------------------------------------- /** * Creates a call binding. * * @param validator Validator * @param scope Scope of call * @param call Call node */ public SqlCallBinding( SqlValidator validator, SqlValidatorScope scope, SqlCall call) { super( validator.getTypeFactory(), call.getOperator()); this.validator = validator; this.scope = scope; this.call = call; } //~ Methods ---------------------------------------------------------------- @Override public int getGroupCount() { final SelectScope selectScope = SqlValidatorUtil.getEnclosingSelectScope(scope); if (selectScope == null) { // Probably "VALUES expr". Treat same as "SELECT expr GROUP BY ()" return 0; } final SqlSelect select = selectScope.getNode(); if (select.getGroup() != null) { return select.getGroup().size(); } return validator.isAggregate(select) ? 0 : -1; } /** * Returns the validator. */ public SqlValidator getValidator() { return validator; } /** * Returns the scope of the call. */ public SqlValidatorScope getScope() { return scope; } /** * Returns the call node. */ public SqlCall getCall() { return call; } // implement SqlOperatorBinding public String getStringLiteralOperand(int ordinal) { SqlNode node = call.operand(ordinal); return SqlLiteral.stringValue(node); } // implement SqlOperatorBinding public int getIntLiteralOperand(int ordinal) { // todo: move this to SqlTypeUtil SqlNode node = call.operand(ordinal); if (node instanceof SqlLiteral) { SqlLiteral sqlLiteral = (SqlLiteral) node; return sqlLiteral.intValue(true); } else if (node instanceof SqlCall) { final SqlCall c = (SqlCall) node; if (c.getKind() == SqlKind.MINUS_PREFIX) { SqlNode child = c.operand(0); if (child instanceof SqlLiteral) { return -((SqlLiteral) child).intValue(true); } } } throw Util.newInternal("should never come here"); } // implement SqlOperatorBinding public boolean isOperandNull(int ordinal, boolean allowCast) { return SqlUtil.isNullLiteral(call.operand(ordinal), allowCast); } // implement SqlOperatorBinding public int getOperandCount() { return call.getOperandList().size(); } // implement SqlOperatorBinding public RelDataType getOperandType(int ordinal) { final SqlNode operand = call.operand(ordinal); final RelDataType type = validator.deriveType(scope, operand); final SqlValidatorNamespace namespace = validator.getNamespace(operand); if (namespace != null) { return namespace.getType(); } return type; } public RelDataType getCursorOperand(int ordinal) { final SqlNode operand = call.operand(ordinal); if (!SqlUtil.isCallTo(operand, SqlStdOperatorTable.CURSOR)) { return null; } final SqlCall cursorCall = (SqlCall) operand; final SqlNode query = cursorCall.operand(0); return validator.deriveType(scope, query); } // implement SqlOperatorBinding public String getColumnListParamInfo( int ordinal, String paramName, List<String> columnList) { final SqlNode operand = call.operand(ordinal); if (!SqlUtil.isCallTo(operand, SqlStdOperatorTable.ROW)) { return null; } for (SqlNode id : ((SqlCall) operand).getOperandList()) { columnList.add(((SqlIdentifier) id).getSimple()); } return validator.getParentCursor(paramName); } public EigenbaseException newError( Resources.ExInst<SqlValidatorException> e) { return validator.newValidationError(call, e); } /** * Constructs a new validation signature error for the call. * * @return signature exception */ public EigenbaseException newValidationSignatureError() { return validator.newValidationError(call, RESOURCE.canNotApplyOp2Type(getOperator().getName(), call.getCallSignature(validator, scope), getOperator().getAllowedSignatures())); } /** * Constructs a new validation error for the call. (Do not use this to * construct a validation error for other nodes such as an operands.) * * @param ex underlying exception * @return wrapped exception */ public EigenbaseException newValidationError( Resources.ExInst<SqlValidatorException> ex) { return validator.newValidationError(call, ex); } } // End SqlCallBinding.java