Package cascading.lingual.flow

Source Code of cascading.lingual.flow.SQLPlanner

/*
* Copyright (c) 2007-2014 Concurrent, Inc. All Rights Reserved.
*
* Project and contact information: http://www.cascading.org/
*
* This file is part of the Cascading project.
*
* Licensed 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 cascading.lingual.flow;

import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import cascading.flow.AssemblyPlanner;
import cascading.flow.Flow;
import cascading.flow.FlowDef;
import cascading.flow.FlowDescriptors;
import cascading.lingual.platform.PlannerPlatformBroker;
import cascading.pipe.Pipe;
import net.hydromatic.optiq.prepare.OptiqPrepareImpl;

/**
* Class SQLPlanner is an implementation of an {@link AssemblyPlanner} that supports parsing ANSI SQL statements
* against {@link cascading.tap.Tap} meta-data into a pipe assembly, which in turn is used by a
* {@link cascading.flow.FlowConnector} to create a new {@link Flow} instance.
* <p/>
* SQLPlanner uses available meta-data from a partially initialized Flow instance created by the current
* {@link cascading.flow.planner.FlowPlanner} for the given platform. Specifically, internal "table" meta-data
* is created from source and sink Tap instances provided by the current {@link cascading.flow.FlowDef}.
* <p/>
* Currently table names as expected in the given SQL statement are expected to match the source and sink names, if
* the SQL names have a schema, {@link #setDefaultSchema(String)} must be called, or it must be prepended to the
* names as provided to the FlowDef instance.
* <p/>
* For example with this from clause {@code "select * from employees.salaries"}, either the source Tap should be
* named {@code "employees.salaries"} or {@code sqlPlanner.setDefaultSchema( "employees" );} must be called if the source
* Tap is named {@code "salaries"}. Both approaches result in an internal "table" being named
* {@code "employees.salaries"}.
*
* @see FlowDef
*/
public class SQLPlanner implements AssemblyPlanner
  {
  protected String sql;
  protected String defaultSchema;
  protected String tailName;

  public SQLPlanner()
    {
    }

  public String getSql()
    {
    return sql;
    }

  public SQLPlanner setSql( String sql )
    {
    this.sql = sql;

    return this;
    }

  public String getTailName()
    {
    return tailName;
    }

  public SQLPlanner setTailName( String tailName )
    {
    this.tailName = tailName;

    return this;
    }

  public String getDefaultSchema()
    {
    return defaultSchema;
    }

  public SQLPlanner setDefaultSchema( String defaultSchema )
    {
    this.defaultSchema = defaultSchema;

    return this;
    }

  @Override
  public List<Pipe> resolveTails( Context context )
    {
    if( getSql() == null )
      throw new IllegalStateException( "a sql statement must be provided" );

    Flow flow = context.getFlow();

    flow.getSink().getSinkFields();

    PlannerPlatformBroker platformBroker = new PlannerPlatformBroker();

    LingualContext lingualContext = new LingualContext( this, flow, platformBroker );

    OptiqPrepareImpl prepare = new OptiqPrepareImpl();

    prepare.prepareSql( lingualContext, getSql(), null, Object[].class, -1 );

    Pipe current = platformBroker.getTail();

    String name;

    if( getTailName() != null )
      name = getTailName();
    else if( flow.getSinks().size() == 1 )
      name = (String) flow.getSinkNames().get( 0 );
    else
      throw new IllegalStateException( "too many sinks to choose from, found: " + flow.getSinks().size() + ", use setTailName to match tail pipe with sink Tap" );

    current = new Pipe( name, current ); // bind the tail to the sink name

    return Arrays.asList( current );
    }

  @Override
  public Map<String, String> getFlowDescriptor()
    {
    Map<String, String> flowDescriptor = new LinkedHashMap<String, String>();
    flowDescriptor.put( FlowDescriptors.STATEMENTS, getSql() );
    return flowDescriptor;
    }
  }
TOP

Related Classes of cascading.lingual.flow.SQLPlanner

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.