Package com.odiago.flumebase.lang

Source Code of com.odiago.flumebase.lang.JoinKeyVisitor

/**
* Licensed to Odiago, Inc. under one or more contributor license
* agreements.  See the NOTICE.txt file distributed with this work for
* additional information regarding copyright ownership.  Odiago, Inc.
* 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 com.odiago.flumebase.lang;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.odiago.flumebase.exec.AssignedSymbol;
import com.odiago.flumebase.exec.Symbol;
import com.odiago.flumebase.exec.SymbolTable;

import com.odiago.flumebase.parser.BinExpr;
import com.odiago.flumebase.parser.BinOp;
import com.odiago.flumebase.parser.Expr;
import com.odiago.flumebase.parser.IdentifierExpr;
import com.odiago.flumebase.parser.JoinedSource;

import com.odiago.flumebase.util.StringUtils;

/**
* Identifies the "key" columns in an equijoin which should be performed by a
* HashJoin.
*/
public class JoinKeyVisitor extends TreeWalkVisitor {
  private static final Logger LOG = LoggerFactory.getLogger(
      JoinKeyVisitor.class.getName());

  private void identifyJoinKeys(JoinedSource src, BinExpr e) throws VisitException {
    if (!e.getOp().equals(BinOp.Eq)) {
      // Don't currently know how to handle non-equijoins.
      throw new VisitException("Join should be performed with the '=' operator.");
    }

    Expr e1 = e.getLeftExpr();
    Expr e2 = e.getRightExpr();

    assert e1 != null;
    assert e2 != null;

    if (!(e1 instanceof IdentifierExpr)) {
      throw new VisitException("Join can only be performed on identifier comparisons.");
    }

    if (!(e2 instanceof IdentifierExpr)) {
      throw new VisitException("Join can only be performed on identifier comparisons.");
    }

    String e1Ident = ((IdentifierExpr) e1).getIdentifier();
    String e2Ident = ((IdentifierExpr) e2).getIdentifier();

    assert e1Ident != null;
    assert e2Ident != null;

    SymbolTable symTab = src.getFieldSymbols();

    Symbol e1Sym = symTab.resolve(e1Ident);
    Symbol e2Sym = symTab.resolve(e2Ident);

    assert e1Sym != null;
    assert e2Sym != null;

    e1Sym = e1Sym.resolveAliases();
    e2Sym = e2Sym.resolveAliases();

    // We now have the symbols for the e1 and e2 sides of the BinExpr.
    // Determine which of these is from the left source and the right source.
    // Verify that both sources are represented here.

    // The typechecker should have already assigned labels to these.
    assert e1Sym instanceof AssignedSymbol;
    assert e2Sym instanceof AssignedSymbol;

    // Get the names of the input streams for each symbol, verify they're
    // nonnull.
    String e1Parent = ((AssignedSymbol) e1Sym).getParentName();
    String e2Parent = ((AssignedSymbol) e2Sym).getParentName();

    if (null == e1Parent) {
      throw new VisitException("Identifier " + e1Ident + " is not from a known stream.");
    } else if (null == e2Parent) {
      throw new VisitException("Identifier " + e2Ident + " is not from a known stream.");
    }

    List<String> leftSrcNames = src.getLeft().getSourceNames();
    List<String> rightSrcNames = src.getRight().getSourceNames();

    LOG.debug("left sources: " + StringUtils.listToStr(leftSrcNames));
    LOG.debug("right sources: " + StringUtils.listToStr(rightSrcNames));
    LOG.debug("e1sym: " + e1Sym);
    LOG.debug("e2sym: " + e2Sym);

    if (leftSrcNames.contains(e1Parent)) {
      src.setLeftKey(e1Sym);
    } else if (rightSrcNames.contains(e1Parent)) {
      src.setRightKey(e1Sym);
    } else {
      throw new VisitException("Identifier " + e1Ident + " is not a valid join key");
    }

    if (leftSrcNames.contains(e2Parent)) {
      src.setLeftKey(e2Sym);
    } else if (rightSrcNames.contains(e2Parent)) {
      src.setRightKey(e2Sym);
    } else {
      throw new VisitException("Identifier " + e2Ident + " is not a valid join key");
    }

    if (src.getLeftKey() == null || src.getRightKey() == null) {
      throw new VisitException("Join clause does not contain keys from both input streams");
    }
  }

  @Override
  protected void visit(JoinedSource src) throws VisitException {
    Expr joinExpr = src.getJoinExpr();
    if (!(joinExpr instanceof BinExpr)) {
      // Need a BinExpr here.. don't know how to handle other top-level
      // expressions.
      throw new VisitException("Join should be performed with binary comparison operation");
    }
    identifyJoinKeys(src, (BinExpr) joinExpr);

    // Handle nested joins.
    src.getLeft().accept(this);
    src.getRight().accept(this);
  }
}
TOP

Related Classes of com.odiago.flumebase.lang.JoinKeyVisitor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.