All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.calcite.piglet.Ast Maven / Gradle / Ivy

The newest version!
/*
 * 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.calcite.piglet;

import org.apache.calcite.avatica.util.Spacer;
import org.apache.calcite.linq4j.Ord;
import org.apache.calcite.sql.parser.SqlParserPos;
import org.apache.calcite.sql.parser.SqlParserUtil;
import org.apache.calcite.util.Pair;
import org.apache.calcite.util.Util;

import com.google.common.collect.ImmutableList;

import java.math.BigDecimal;
import java.util.List;

import static java.util.Objects.requireNonNull;

/** Abstract syntax tree.
 *
 * 

Contains inner classes for various kinds of parse tree node. */ public class Ast { private Ast() {} public static String toString(Node x) { return new UnParser().append(x).buf.toString(); } /** Formats a node and its children as a string. */ public static UnParser unParse(UnParser u, Node n) { switch (n.op) { case PROGRAM: final Program program = (Program) n; return u.append("{op: PROGRAM, stmts: ").appendList(program.stmtList) .append("}"); case LOAD: final LoadStmt load = (LoadStmt) n; return u.append("{op: LOAD, target: " + load.target.value + ", name: " + load.name.value + "}"); case DUMP: final DumpStmt dump = (DumpStmt) n; return u.append("{op: DUMP, relation: " + dump.relation.value + "}"); case DESCRIBE: final DescribeStmt describe = (DescribeStmt) n; return u.append("{op: DESCRIBE, relation: " + describe.relation.value + "}"); case FOREACH: final ForeachStmt foreach = (ForeachStmt) n; return u.append("{op: FOREACH, target: " + foreach.target.value + ", source: " + foreach.source.value + ", expList: ") .appendList(foreach.expList) .append("}"); case FOREACH_NESTED: final ForeachNestedStmt foreachNested = (ForeachNestedStmt) n; return u.append("{op: FOREACH, target: " + foreachNested.target.value + ", source: " + foreachNested.source.value + ", nestedOps: ") .appendList(foreachNested.nestedStmtList) .append(", expList: ") .appendList(foreachNested.expList) .append("}"); case FILTER: final FilterStmt filter = (FilterStmt) n; u.append("{op: FILTER, target: " + filter.target.value + ", source: " + filter.source.value + ", condition: "); u.in().append(filter.condition).out(); return u.append("}"); case DISTINCT: final DistinctStmt distinct = (DistinctStmt) n; return u.append("{op: DISTINCT, target: " + distinct.target.value + ", source: " + distinct.source.value + "}"); case LIMIT: final LimitStmt limit = (LimitStmt) n; return u.append("{op: LIMIT, target: ").append(limit.target.value) .append(", source: ").append(limit.source.value) .append(", count: ").append(limit.count.value.toString()) .append("}"); case ORDER: final OrderStmt order = (OrderStmt) n; return u.append("{op: ORDER, target: " + order.target.value + ", source: " + order.source.value + "}"); case GROUP: final GroupStmt group = (GroupStmt) n; u.append("{op: GROUP, target: " + group.target.value + ", source: " + group.source.value); if (group.keys != null) { u.append(", keys: ").appendList(group.keys); } return u.append("}"); case LITERAL: final Literal literal = (Literal) n; return u.append(String.valueOf(literal.value)); case IDENTIFIER: final Identifier id = (Identifier) n; return u.append(id.value); default: throw new AssertionError("unknown op " + n.op); } } /** Parse tree node type. */ public enum Op { PROGRAM, // atoms LITERAL, IDENTIFIER, BAG, TUPLE, // statements DESCRIBE, DISTINCT, DUMP, LOAD, FOREACH, FILTER, FOREACH_NESTED, LIMIT, ORDER, GROUP, VALUES, // types SCHEMA, SCALAR_TYPE, BAG_TYPE, TUPLE_TYPE, MAP_TYPE, FIELD_SCHEMA, // operators DOT, EQ, NE, GT, LT, GTE, LTE, PLUS, MINUS, AND, OR, NOT } /** Abstract base class for parse tree node. */ public abstract static class Node { public final Op op; public final SqlParserPos pos; protected Node(SqlParserPos pos, Op op) { this.op = requireNonNull(op, "op"); this.pos = requireNonNull(pos, "pos"); } } /** Abstract base class for parse tree node representing a statement. */ public abstract static class Stmt extends Node { protected Stmt(SqlParserPos pos, Op op) { super(pos, op); } } /** Abstract base class for statements that assign to a named relation. */ public abstract static class Assignment extends Stmt { final Identifier target; protected Assignment(SqlParserPos pos, Op op, Identifier target) { super(pos, op); this.target = requireNonNull(target, "target"); } } /** Parse tree node for LOAD statement. */ public static class LoadStmt extends Assignment { final Literal name; public LoadStmt(SqlParserPos pos, Identifier target, Literal name) { super(pos, Op.LOAD, target); this.name = requireNonNull(name, "name"); } } /** Parse tree node for VALUES statement. * *

VALUES is an extension to Pig, inspired by SQL's VALUES clause. */ public static class ValuesStmt extends Assignment { final List> tupleList; final Schema schema; public ValuesStmt(SqlParserPos pos, Identifier target, Schema schema, List> tupleList) { super(pos, Op.VALUES, target); this.schema = schema; this.tupleList = ImmutableList.copyOf(tupleList); } } /** Abstract base class for an assignment with one source relation. */ public static class Assignment1 extends Assignment { final Identifier source; protected Assignment1(SqlParserPos pos, Op op, Identifier target, Identifier source) { super(pos, op, target); this.source = source; } } /** Parse tree node for FOREACH statement (non-nested). * *

Syntax: *

* alias = FOREACH alias GENERATE expression [, expression]... * [ AS schema ]; *
* * @see org.apache.calcite.piglet.Ast.ForeachNestedStmt */ public static class ForeachStmt extends Assignment1 { final List expList; public ForeachStmt(SqlParserPos pos, Identifier target, Identifier source, List expList, Schema schema) { super(pos, Op.FOREACH, target, source); this.expList = expList; assert schema == null; // not supported yet } } /** Parse tree node for FOREACH statement (nested). * *

Syntax: * *

* alias = FOREACH nested_alias { * alias = nested_op; [alias = nested_op; ]... * GENERATE expression [, expression]... * };
*   * nested_op ::= DISTINCT, FILTER, LIMIT, ORDER, SAMPLE *
*
* * @see org.apache.calcite.piglet.Ast.ForeachStmt */ public static class ForeachNestedStmt extends Assignment1 { final List nestedStmtList; final List expList; public ForeachNestedStmt(SqlParserPos pos, Identifier target, Identifier source, List nestedStmtList, List expList, Schema schema) { super(pos, Op.FOREACH_NESTED, target, source); this.nestedStmtList = nestedStmtList; this.expList = expList; assert schema == null; // not supported yet } } /** Parse tree node for FILTER statement. * *

Syntax: *

alias = FILTER alias BY expression;
*/ public static class FilterStmt extends Assignment1 { final Node condition; public FilterStmt(SqlParserPos pos, Identifier target, Identifier source, Node condition) { super(pos, Op.FILTER, target, source); this.condition = condition; } } /** Parse tree node for DISTINCT statement. * *

Syntax: *

alias = DISTINCT alias;
*/ public static class DistinctStmt extends Assignment1 { public DistinctStmt(SqlParserPos pos, Identifier target, Identifier source) { super(pos, Op.DISTINCT, target, source); } } /** Parse tree node for LIMIT statement. * *

Syntax: *

alias = LIMIT alias n;
*/ public static class LimitStmt extends Assignment1 { final Literal count; public LimitStmt(SqlParserPos pos, Identifier target, Identifier source, Literal count) { super(pos, Op.LIMIT, target, source); this.count = count; } } /** Parse tree node for ORDER statement. * *

Syntax: *

* alias = ORDER alias BY (* | field) [ASC | DESC] * [, field [ASC | DESC] ]...; *
*/ public static class OrderStmt extends Assignment1 { final List> fields; public OrderStmt(SqlParserPos pos, Identifier target, Identifier source, List> fields) { super(pos, Op.ORDER, target, source); this.fields = fields; } } /** Parse tree node for GROUP statement. * *

Syntax: *

* alias = GROUP alias * ( ALL | BY ( exp | '(' exp [, exp]... ')' ) ) *
*/ public static class GroupStmt extends Assignment1 { /** Grouping keys. May be null (for ALL), or a list of one or more * expressions. */ final List keys; public GroupStmt(SqlParserPos pos, Identifier target, Identifier source, List keys) { super(pos, Op.GROUP, target, source); this.keys = keys; assert keys == null || keys.size() >= 1; } } /** Parse tree node for DUMP statement. */ public static class DumpStmt extends Stmt { final Identifier relation; public DumpStmt(SqlParserPos pos, Identifier relation) { super(pos, Op.DUMP); this.relation = requireNonNull(relation, "relation"); } } /** Parse tree node for DESCRIBE statement. */ public static class DescribeStmt extends Stmt { final Identifier relation; public DescribeStmt(SqlParserPos pos, Identifier relation) { super(pos, Op.DESCRIBE); this.relation = requireNonNull(relation, "relation"); } } /** Parse tree node for Literal. */ public static class Literal extends Node { final Object value; public Literal(SqlParserPos pos, Object value) { super(pos, Op.LITERAL); this.value = requireNonNull(value, "value"); } public static NumericLiteral createExactNumeric(String s, SqlParserPos pos) { BigDecimal value; int prec; int scale; int i = s.indexOf('.'); if ((i >= 0) && ((s.length() - 1) != i)) { value = SqlParserUtil.parseDecimal(s); scale = s.length() - i - 1; assert scale == value.scale() : s; prec = s.length() - 1; } else if ((i >= 0) && ((s.length() - 1) == i)) { value = SqlParserUtil.parseInteger(s.substring(0, i)); scale = 0; prec = s.length() - 1; } else { value = SqlParserUtil.parseInteger(s); scale = 0; prec = s.length(); } return new NumericLiteral(pos, value, prec, scale, true); } } /** Parse tree node for NumericLiteral. */ public static class NumericLiteral extends Literal { final int prec; final int scale; final boolean exact; NumericLiteral(SqlParserPos pos, BigDecimal value, int prec, int scale, boolean exact) { super(pos, value); this.prec = prec; this.scale = scale; this.exact = exact; } public NumericLiteral negate(SqlParserPos pos) { BigDecimal value = (BigDecimal) this.value; return new NumericLiteral(pos, value.negate(), prec, scale, exact); } } /** Parse tree node for Identifier. */ public static class Identifier extends Node { final String value; public Identifier(SqlParserPos pos, String value) { super(pos, Op.IDENTIFIER); this.value = requireNonNull(value, "value"); } public boolean isStar() { return false; } } /** Parse tree node for "*", a special kind of identifier. */ public static class SpecialIdentifier extends Identifier { public SpecialIdentifier(SqlParserPos pos) { super(pos, "*"); } @Override public boolean isStar() { return true; } } /** Parse tree node for a call to a function or operator. */ public static class Call extends Node { final ImmutableList operands; private Call(SqlParserPos pos, Op op, ImmutableList operands) { super(pos, op); this.operands = ImmutableList.copyOf(operands); } public Call(SqlParserPos pos, Op op, Iterable operands) { this(pos, op, ImmutableList.copyOf(operands)); } public Call(SqlParserPos pos, Op op, Node... operands) { this(pos, op, ImmutableList.copyOf(operands)); } } /** Parse tree node for a program. */ public static class Program extends Node { public final List stmtList; public Program(SqlParserPos pos, List stmtList) { super(pos, Op.PROGRAM); this.stmtList = stmtList; } } /** Parse tree for field schema. * *

Syntax: *

identifier:type
*/ public static class FieldSchema extends Node { final Identifier id; final Type type; public FieldSchema(SqlParserPos pos, Identifier id, Type type) { super(pos, Op.FIELD_SCHEMA); this.id = requireNonNull(id, "id"); this.type = requireNonNull(type, "type"); } } /** Parse tree for schema. * *

Syntax: *

*
AS ( identifier:type [, identifier:type]... )
*
*/ public static class Schema extends Node { final List fieldSchemaList; public Schema(SqlParserPos pos, List fieldSchemaList) { super(pos, Op.SCHEMA); this.fieldSchemaList = ImmutableList.copyOf(fieldSchemaList); } } /** Parse tree for type. */ public abstract static class Type extends Node { protected Type(SqlParserPos pos, Op op) { super(pos, op); } } /** Parse tree for scalar type such as {@code int}. */ public static class ScalarType extends Type { final String name; public ScalarType(SqlParserPos pos, String name) { super(pos, Op.SCALAR_TYPE); this.name = name; } } /** Parse tree for a bag type. */ public static class BagType extends Type { final Type componentType; public BagType(SqlParserPos pos, Type componentType) { super(pos, Op.BAG_TYPE); this.componentType = componentType; } } /** Parse tree for a tuple type. */ public static class TupleType extends Type { final List fieldSchemaList; public TupleType(SqlParserPos pos, List fieldSchemaList) { super(pos, Op.TUPLE_TYPE); this.fieldSchemaList = ImmutableList.copyOf(fieldSchemaList); } } /** Parse tree for a map type. */ public static class MapType extends Type { final Type keyType; final Type valueType; public MapType(SqlParserPos pos) { super(pos, Op.MAP_TYPE); // REVIEW: Why does Pig's "map" type not have key and value types? this.keyType = new ScalarType(pos, "int"); this.valueType = new ScalarType(pos, "int"); } } /** Contains output and indentation level while a tree of nodes is * being converted to text. */ static class UnParser { final StringBuilder buf = new StringBuilder(); final Spacer spacer = new Spacer(0); public UnParser in() { spacer.add(2); return this; } public UnParser out() { spacer.subtract(2); return this; } public UnParser newline() { buf.append(Util.LINE_SEPARATOR); spacer.spaces(buf); return this; } public UnParser append(String s) { buf.append(s); return this; } public UnParser append(Node n) { return unParse(this, n); } public UnParser appendList(List list) { append("[").in(); for (Ord n : Ord.zip(list)) { newline().append(n.e); if (n.i < list.size() - 1) { append(","); } } return out().append("]"); } } /** Sort direction. */ public enum Direction { ASC, DESC, NOT_SPECIFIED } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy