[ 
https://issues.apache.org/jira/browse/PHOENIX-514?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14278328#comment-14278328
 ] 

ASF GitHub Bot commented on PHOENIX-514:
----------------------------------------

Github user JamesRTaylor commented on a diff in the pull request:

    https://github.com/apache/phoenix/pull/34#discussion_r22992799
  
    --- Diff: 
phoenix-core/src/main/java/org/apache/phoenix/compile/IndexColumnExpressionCompiler.java
 ---
    @@ -0,0 +1,302 @@
    +/*
    + * 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.apache.phoenix.compile;
    +
    +import java.sql.SQLException;
    +import java.util.Collections;
    +import java.util.List;
    +
    +import org.apache.hadoop.hbase.client.Scan;
    +import org.apache.phoenix.compile.GroupByCompiler.GroupBy;
    +import org.apache.phoenix.expression.ColumnExpression;
    +import org.apache.phoenix.expression.Expression;
    +import org.apache.phoenix.jdbc.PhoenixConnection;
    +import org.apache.phoenix.parse.AddParseNode;
    +import org.apache.phoenix.parse.AndParseNode;
    +import org.apache.phoenix.parse.ArrayAllComparisonNode;
    +import org.apache.phoenix.parse.ArrayAnyComparisonNode;
    +import org.apache.phoenix.parse.ArrayElemRefNode;
    +import org.apache.phoenix.parse.CaseParseNode;
    +import org.apache.phoenix.parse.CastParseNode;
    +import org.apache.phoenix.parse.ColumnDef;
    +import org.apache.phoenix.parse.ColumnParseNode;
    +import org.apache.phoenix.parse.ComparisonParseNode;
    +import org.apache.phoenix.parse.DivideParseNode;
    +import org.apache.phoenix.parse.FunctionParseNode;
    +import org.apache.phoenix.parse.ModulusParseNode;
    +import org.apache.phoenix.parse.MultiplyParseNode;
    +import org.apache.phoenix.parse.NamedTableNode;
    +import org.apache.phoenix.parse.NotParseNode;
    +import org.apache.phoenix.parse.OrParseNode;
    +import org.apache.phoenix.parse.ParseNode;
    +import org.apache.phoenix.parse.RowValueConstructorParseNode;
    +import org.apache.phoenix.parse.SQLParser;
    +import org.apache.phoenix.parse.StringConcatParseNode;
    +import org.apache.phoenix.parse.SubtractParseNode;
    +import org.apache.phoenix.parse.TableName;
    +import org.apache.phoenix.schema.PColumn;
    +import org.apache.phoenix.schema.PTable;
    +import org.apache.phoenix.schema.PTableType;
    +import org.apache.phoenix.util.IndexUtil;
    +
    +/**
    + * Visitor that checks if nodes other than ColumnParseNode are present as 
    + * an expression in an index. If the expression is present, then the node 
is
    + * not visited but processed as a ColumnParseNode.
    + */
    +public class IndexColumnExpressionCompiler extends ExpressionCompiler {
    +   
    +   IndexColumnExpressionCompiler(StatementContext context) {
    +        super(context);
    +    }
    +
    +   IndexColumnExpressionCompiler(StatementContext context, boolean 
resolveViewConstants) {
    +        super(context, resolveViewConstants);
    +    }
    +
    +   IndexColumnExpressionCompiler(StatementContext context, GroupBy 
groupBy) {
    +           super(context, groupBy);
    +    }
    +
    +   IndexColumnExpressionCompiler(StatementContext context, GroupBy 
groupBy, boolean resolveViewConstants) {
    +           super(context, groupBy, resolveViewConstants);
    +    }
    +   
    +    /**
    +     * Returns the compiled expression
    +     * 
    +     * @param node
    +     *            data table parse node
    +     */
    +   private Expression getExpression(ParseNode node) throws SQLException {
    +           PhoenixConnection connection = this.context.getConnection();
    +        PTable indexTable = this.context.getCurrentTable().getTable();
    +        NamedTableNode dataTableNode = NamedTableNode.create(null, 
TableName.create(indexTable.getParentSchemaName().getString(), 
    +                   indexTable.getParentTableName().getString()), 
Collections.<ColumnDef>emptyList());
    +        ColumnResolver resolver = FromCompiler.getResolver(dataTableNode, 
connection);
    +           StatementContext context = new 
StatementContext(this.context.getStatement(), resolver, new Scan(), new 
SequenceManager(this.context.getStatement()));        
    +        ExpressionCompiler expressionCompiler = new 
ExpressionCompiler(context);
    +        return node.accept(expressionCompiler);            
    +   }
    +
    +   /**
    +    * @return true if current table is an index and there is an expression 
that matches the given node
    +    */
    +   private boolean matchesIndexedExpression(ParseNode node) throws 
SQLException {   
    +           if 
(context.getCurrentTable().getTable().getType()!=PTableType.INDEX) {
    +                   return false;
    +           }
    +           DataTableNodeRewriter statementRewriter = new 
DataTableNodeRewriter();
    +        ParseNode dataTableParseNode = node.accept(statementRewriter);
    +           Expression dataTableExpression = 
getExpression(dataTableParseNode);
    +           // if the node matches a column expression
    +           if 
(ColumnExpression.class.isAssignableFrom(dataTableExpression.getClass())) {
    +                   return false;
    +           }
    +       for ( PColumn column : 
this.context.getCurrentTable().getTable().getColumns()) {
    +           if (column.getExpressionStr()!=null) {
    +               ParseNode parseNode = 
SQLParser.parseCondition(column.getExpressionStr());
    +               Expression expression = getExpression(parseNode);
    +               if (expression.equals(dataTableExpression))
    +                   return true;
    +           }
    +       }
    +           return false;
    +    }
    +    
    +    private Expression convertAndVisitParseNode(ParseNode node) throws 
SQLException {
    +        DataTableNodeRewriter statementRewriter = new 
DataTableNodeRewriter();
    +        ParseNode dataTableParseNode = node.accept(statementRewriter);
    +           Expression expression = getExpression(dataTableParseNode);
    +           ColumnParseNode columnParseNode = new ColumnParseNode(null, 
IndexUtil.getIndexColumnName(null,String.valueOf(expression.hashCode())), null);
    +           return visit(columnParseNode);
    +    }
    +
    +   @Override
    +    public boolean visitEnter(ComparisonParseNode node) throws 
SQLException {
    +           // do not visit this node if it matches an expression that is 
indexed,  it will be converted to a ColumnParseNode and processed in visitLeave
    +           return matchesIndexedExpression(node) ? false : 
super.visitEnter(node);
    +    }
    +
    +    @Override
    +    public Expression visitLeave(ComparisonParseNode node, 
List<Expression> children) throws SQLException {
    --- End diff --
    
    Having to specialize every visitorLeave is a bit painful. One possibility 
would be to make the wrapGroupByExpression method protected, override it, and 
do a super.wrapGroupByExpression() call (and perhaps rename it). I believe that 
method is called from every visitorLeave method.


> Support functional indexes
> --------------------------
>
>                 Key: PHOENIX-514
>                 URL: https://issues.apache.org/jira/browse/PHOENIX-514
>             Project: Phoenix
>          Issue Type: Task
>            Reporter: James Taylor
>            Assignee: Thomas D'Silva
>              Labels: enhancement
>
> Instead of only defining the set of columns from the data table that make up 
> an index, you should be able to use expressions.  For example:
>       CREATE INDEX upper_last_name_idx ON person (UPPER(last_name))
> Then in queries that use UPPER(last_name), we can replace them with column 
> references to the index table.



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

Reply via email to