/* * 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.rex; import java.util.*; import org.eigenbase.sql.*; import org.eigenbase.sql.fun.*; import org.eigenbase.sql.parser.*; import org.eigenbase.sql.type.*; /** * Standard implementation of {@link RexSqlConvertletTable}. */ public class RexSqlStandardConvertletTable extends RexSqlReflectiveConvertletTable { //~ Constructors ----------------------------------------------------------- public RexSqlStandardConvertletTable() { super(); // Register convertlets registerEquivOp(SqlStdOperatorTable.GREATER_THAN_OR_EQUAL); registerEquivOp(SqlStdOperatorTable.GREATER_THAN); registerEquivOp(SqlStdOperatorTable.LESS_THAN_OR_EQUAL); registerEquivOp(SqlStdOperatorTable.LESS_THAN); registerEquivOp(SqlStdOperatorTable.EQUALS); registerEquivOp(SqlStdOperatorTable.NOT_EQUALS); registerEquivOp(SqlStdOperatorTable.AND); registerEquivOp(SqlStdOperatorTable.OR); registerEquivOp(SqlStdOperatorTable.NOT_IN); registerEquivOp(SqlStdOperatorTable.IN); registerEquivOp(SqlStdOperatorTable.LIKE); registerEquivOp(SqlStdOperatorTable.NOT_LIKE); registerEquivOp(SqlStdOperatorTable.SIMILAR_TO); registerEquivOp(SqlStdOperatorTable.NOT_SIMILAR_TO); registerEquivOp(SqlStdOperatorTable.PLUS); registerEquivOp(SqlStdOperatorTable.MINUS); registerEquivOp(SqlStdOperatorTable.MULTIPLY); registerEquivOp(SqlStdOperatorTable.DIVIDE); registerEquivOp(SqlStdOperatorTable.NOT); registerEquivOp(SqlStdOperatorTable.IS_NOT_NULL); registerEquivOp(SqlStdOperatorTable.IS_NULL); registerEquivOp(SqlStdOperatorTable.IS_NOT_TRUE); registerEquivOp(SqlStdOperatorTable.IS_TRUE); registerEquivOp(SqlStdOperatorTable.IS_NOT_FALSE); registerEquivOp(SqlStdOperatorTable.IS_FALSE); registerEquivOp(SqlStdOperatorTable.IS_NOT_UNKNOWN); registerEquivOp(SqlStdOperatorTable.IS_UNKNOWN); registerEquivOp(SqlStdOperatorTable.UNARY_MINUS); registerEquivOp(SqlStdOperatorTable.UNARY_PLUS); registerCaseOp(SqlStdOperatorTable.CASE); registerEquivOp(SqlStdOperatorTable.CONCAT); registerEquivOp(SqlStdOperatorTable.BETWEEN); registerEquivOp(SqlStdOperatorTable.SYMMETRIC_BETWEEN); registerEquivOp(SqlStdOperatorTable.NOT_BETWEEN); registerEquivOp(SqlStdOperatorTable.SYMMETRIC_NOT_BETWEEN); registerEquivOp(SqlStdOperatorTable.IS_NOT_DISTINCT_FROM); registerEquivOp(SqlStdOperatorTable.IS_DISTINCT_FROM); registerEquivOp(SqlStdOperatorTable.MINUS_DATE); registerEquivOp(SqlStdOperatorTable.EXTRACT); registerEquivOp(SqlStdOperatorTable.SUBSTRING); registerEquivOp(SqlStdOperatorTable.CONVERT); registerEquivOp(SqlStdOperatorTable.TRANSLATE); registerEquivOp(SqlStdOperatorTable.OVERLAY); registerEquivOp(SqlStdOperatorTable.TRIM); registerEquivOp(SqlStdOperatorTable.POSITION); registerEquivOp(SqlStdOperatorTable.CHAR_LENGTH); registerEquivOp(SqlStdOperatorTable.CHARACTER_LENGTH); registerEquivOp(SqlStdOperatorTable.UPPER); registerEquivOp(SqlStdOperatorTable.LOWER); registerEquivOp(SqlStdOperatorTable.INITCAP); registerEquivOp(SqlStdOperatorTable.POWER); registerEquivOp(SqlStdOperatorTable.SQRT); registerEquivOp(SqlStdOperatorTable.MOD); registerEquivOp(SqlStdOperatorTable.LN); registerEquivOp(SqlStdOperatorTable.LOG10); registerEquivOp(SqlStdOperatorTable.ABS); registerEquivOp(SqlStdOperatorTable.EXP); registerEquivOp(SqlStdOperatorTable.FLOOR); registerEquivOp(SqlStdOperatorTable.CEIL); registerEquivOp(SqlStdOperatorTable.NULLIF); registerEquivOp(SqlStdOperatorTable.COALESCE); registerTypeAppendOp(SqlStdOperatorTable.CAST); } //~ Methods ---------------------------------------------------------------- /** * Converts a call to an operator into a {@link SqlCall} to the same * operator. * * <p>Called automatically via reflection. * * @param converter Converter * @param call Call * @return Sql call */ public SqlNode convertCall( RexToSqlNodeConverter converter, RexCall call) { if (get(call) == null) { return null; } final SqlOperator op = call.getOperator(); final List<RexNode> operands = call.getOperands(); final SqlNode[] exprs = convertExpressionList(converter, operands); if (exprs == null) { return null; } return new SqlBasicCall( op, exprs, SqlParserPos.ZERO); } private SqlNode[] convertExpressionList( RexToSqlNodeConverter converter, List<RexNode> nodes) { final SqlNode[] exprs = new SqlNode[nodes.size()]; for (int i = 0; i < nodes.size(); i++) { RexNode node = nodes.get(i); exprs[i] = converter.convertNode(node); if (exprs[i] == null) { return null; } } return exprs; } /** * Creates and registers a convertlet for an operator in which * the SQL and Rex representations are structurally equivalent. * * @param op operator instance */ protected void registerEquivOp(final SqlOperator op) { registerOp( op, new RexSqlConvertlet() { public SqlNode convertCall( RexToSqlNodeConverter converter, RexCall call) { SqlNode[] operands = convertExpressionList(converter, call.operands); if (operands == null) { return null; } return new SqlBasicCall( op, operands, SqlParserPos.ZERO); } }); } /** * Creates and registers a convertlet for an operator in which * the SQL representation needs the result type appended * as an extra argument (e.g. CAST). * * @param op operator instance */ private void registerTypeAppendOp(final SqlOperator op) { registerOp( op, new RexSqlConvertlet() { public SqlNode convertCall( RexToSqlNodeConverter converter, RexCall call) { SqlNode[] operands = convertExpressionList(converter, call.operands); if (operands == null) { return null; } List<SqlNode> operandList = new ArrayList<SqlNode>(Arrays.asList(operands)); SqlDataTypeSpec typeSpec = SqlTypeUtil.convertTypeToSpec(call.getType()); operandList.add(typeSpec); return new SqlBasicCall( op, operandList.toArray(new SqlNode[operandList.size()]), SqlParserPos.ZERO); } }); } /** * Creates and registers a convertlet for the CASE operator, * which takes different forms for SQL vs Rex. * * @param op instance of CASE operator */ private void registerCaseOp(final SqlOperator op) { registerOp( op, new RexSqlConvertlet() { public SqlNode convertCall( RexToSqlNodeConverter converter, RexCall call) { assert op instanceof SqlCaseOperator; SqlNode[] operands = convertExpressionList(converter, call.operands); if (operands == null) { return null; } SqlNodeList whenList = new SqlNodeList(SqlParserPos.ZERO); SqlNodeList thenList = new SqlNodeList(SqlParserPos.ZERO); int i = 0; while (i < operands.length - 1) { whenList.add(operands[i]); ++i; thenList.add(operands[i]); ++i; } SqlNode elseExpr = operands[i]; SqlNode[] newOperands = new SqlNode[3]; newOperands[0] = whenList; newOperands[1] = thenList; newOperands[2] = elseExpr; return op.createCall(null, SqlParserPos.ZERO, newOperands); } }); } } // End RexSqlStandardConvertletTable.java