org.apache.calcite.sql.SqlWriter Maven / Gradle / Ivy
Show all versions of calcite-core Show documentation
/*
* 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.sql;
import org.apache.calcite.sql.util.SqlString;
/**
* A SqlWriter
is the target to construct a SQL statement from a
* parse tree. It deals with dialect differences; for example, Oracle quotes
* identifiers as "scott"
, while SQL Server quotes them as
* [scott]
.
*/
public interface SqlWriter {
//~ Enums ------------------------------------------------------------------
/**
* Style of formatting sub-queries.
*/
enum SubQueryStyle {
/**
* Julian's style of sub-query nesting. Like this:
*
* SELECT *
* FROM (
* SELECT *
* FROM t
* )
* WHERE condition
*/
HYDE,
/**
* Damian's style of sub-query nesting. Like this:
*
* SELECT *
* FROM
* ( SELECT *
* FROM t
* )
* WHERE condition
*/
BLACK
}
/**
* Enumerates the types of frame.
*/
enum FrameTypeEnum implements FrameType {
/**
* SELECT query (or UPDATE or DELETE). The items in the list are the
* clauses: FROM, WHERE, etc.
*/
SELECT,
/**
* Simple list.
*/
SIMPLE,
/**
* The SELECT clause of a SELECT statement.
*/
SELECT_LIST,
/**
* The WINDOW clause of a SELECT statement.
*/
WINDOW_DECL_LIST,
/**
* The SET clause of an UPDATE statement.
*/
UPDATE_SET_LIST,
/**
* Function declaration.
*/
FUN_DECL,
/**
* Function call or datatype declaration.
*
* Examples:
*
* SUBSTRING('foobar' FROM 1 + 2 TO 4)
* DECIMAL(10, 5)
*
*/
FUN_CALL,
/**
* Window specification.
*
* Examples:
*
* SUM(x) OVER (ORDER BY hireDate ROWS 3 PRECEDING)
* WINDOW w1 AS (ORDER BY hireDate), w2 AS (w1 PARTITION BY gender
* RANGE BETWEEN INTERVAL '1' YEAR PRECEDING AND '2' MONTH
* PRECEDING)
*
*/
WINDOW,
/**
* ORDER BY clause of a SELECT statement. The "list" has only two items:
* the query and the order by clause, with ORDER BY as the separator.
*/
ORDER_BY,
/**
* ORDER BY list.
*
* Example:
*
* ORDER BY x, y DESC, z
*
*/
ORDER_BY_LIST,
/**
* WITH clause of a SELECT statement. The "list" has only two items:
* the WITH clause and the query, with AS as the separator.
*/
WITH,
/**
* OFFSET clause.
*
* Example:
*
* OFFSET 10 ROWS
*
*/
OFFSET,
/**
* FETCH clause.
*
* Example:
*
* FETCH FIRST 3 ROWS ONLY
*
*/
FETCH,
/**
* GROUP BY list.
*
* Example:
*
* GROUP BY x, FLOOR(y)
*
*/
GROUP_BY_LIST,
/**
* Sub-query list. Encloses a SELECT, UNION, EXCEPT, INTERSECT query
* with optional ORDER BY.
*
* Example:
*
* GROUP BY x, FLOOR(y)
*
*/
SUB_QUERY,
/**
* Set operation.
*
* Example:
*
* SELECT * FROM a UNION SELECT * FROM b
*
*/
SETOP,
/**
* VALUES clause.
*
* Example:
*
*
VALUES (1, 'a'),
* (2, 'b')
*/
VALUES,
/**
* FROM clause (containing various kinds of JOIN).
*/
FROM_LIST,
/**
* Pair-wise join.
*/
JOIN(false),
/**
* WHERE clause.
*/
WHERE_LIST,
/**
* Compound identifier.
*
* Example:
*
* "A"."B"."C"
*
*/
IDENTIFIER(false);
private final boolean needsIndent;
/**
* Creates a list type.
*/
FrameTypeEnum() {
this(true);
}
/**
* Creates a list type.
*/
FrameTypeEnum(boolean needsIndent) {
this.needsIndent = needsIndent;
}
public boolean needsIndent() {
return needsIndent;
}
/**
* Creates a frame type.
*
* @param name Name
* @return frame type
*/
public static FrameType create(final String name) {
return new FrameType() {
public String getName() {
return name;
}
public boolean needsIndent() {
return true;
}
};
}
public String getName() {
return name();
}
}
//~ Methods ----------------------------------------------------------------
/**
* Resets this writer so that it can format another expression. Does not
* affect formatting preferences (see {@link #resetSettings()}
*/
void reset();
/**
* Resets all properties to their default values.
*/
void resetSettings();
/**
* Returns the dialect of SQL.
*
* @return SQL dialect
*/
SqlDialect getDialect();
/**
* Returns the contents of this writer as a 'certified kocher' SQL string.
*
* @return SQL string
*/
SqlString toSqlString();
/**
* Prints a literal, exactly as provided. Does not attempt to indent or
* convert to upper or lower case. Does not add quotation marks. Adds
* preceding whitespace if necessary.
*/
void literal(String s);
/**
* Prints a sequence of keywords. Must not start or end with space, but may
* contain a space. For example, keyword("SELECT")
,
* keyword("CHARACTER SET")
.
*/
void keyword(String s);
/**
* Prints a string, preceded by whitespace if necessary.
*/
void print(String s);
/**
* Prints an integer.
*
* @param x Integer
*/
void print(int x);
/**
* Prints an identifier, quoting as necessary.
*/
void identifier(String name);
/**
* Prints the OFFSET/FETCH clause.
*/
void fetchOffset(SqlNode fetch, SqlNode offset);
/**
* Prints a new line, and indents.
*/
void newlineAndIndent();
/**
* Returns whether this writer should quote all identifiers, even those
* that do not contain mixed-case identifiers or punctuation.
*
* @return whether to quote all identifiers
*/
boolean isQuoteAllIdentifiers();
/**
* Returns whether this writer should start each clause (e.g. GROUP BY) on
* a new line.
*
* @return whether to start each clause on a new line
*/
boolean isClauseStartsLine();
/**
* Returns whether the items in the SELECT clause should each be on a
* separate line.
*
* @return whether to put each SELECT clause item on a new line
*/
boolean isSelectListItemsOnSeparateLines();
/**
* Returns whether to output all keywords (e.g. SELECT, GROUP BY) in lower
* case.
*
* @return whether to output SQL keywords in lower case
*/
boolean isKeywordsLowerCase();
/**
* Starts a list which is a call to a function.
*
* @see #endFunCall(Frame)
*/
Frame startFunCall(String funName);
/**
* Ends a list which is a call to a function.
*
* @param frame Frame
* @see #startFunCall(String)
*/
void endFunCall(Frame frame);
/**
* Starts a list.
*/
Frame startList(String open, String close);
/**
* Starts a list with no opening string.
*
* @param frameType Type of list. For example, a SELECT list will be
*/
Frame startList(FrameTypeEnum frameType);
/**
* Starts a list.
*
* @param frameType Type of list. For example, a SELECT list will be
* governed according to SELECT-list formatting preferences.
* @param open String to start the list; typically "(" or the empty
* string.
* @param close String to close the list
*/
Frame startList(FrameType frameType, String open, String close);
/**
* Ends a list.
*
* @param frame The frame which was created by {@link #startList}.
*/
void endList(Frame frame);
/**
* Writes a list separator, unless the separator is "," and this is the
* first occurrence in the list.
*
* @param sep List separator, typically ",".
*/
void sep(String sep);
/**
* Writes a list separator.
*
* @param sep List separator, typically ","
* @param printFirst Whether to print the first occurrence of the separator
*/
void sep(String sep, boolean printFirst);
/**
* Sets whether whitespace is needed before the next token.
*/
void setNeedWhitespace(boolean needWhitespace);
/**
* Returns the offset for each level of indentation. Default 4.
*/
int getIndentation();
/**
* Returns whether to enclose all expressions in parentheses, even if the
* operator has high enough precedence that the parentheses are not
* required.
*
* For example, the parentheses are required in the expression (a +
* b) * c
because the '*' operator has higher precedence than the '+'
* operator, and so without the parentheses, the expression would be
* equivalent to a + (b * c)
. The fully-parenthesized
* expression, ((a + b) * c)
is unambiguous even if you don't
* know the precedence of every operator.
*/
boolean isAlwaysUseParentheses();
/**
* Returns whether we are currently in a query context (SELECT, INSERT,
* UNION, INTERSECT, EXCEPT, and the ORDER BY operator).
*/
boolean inQuery();
//~ Inner Interfaces -------------------------------------------------------
/**
* A Frame is a piece of generated text which shares a common indentation
* level.
*
*
Every frame has a beginning, a series of clauses and separators, and
* an end. A typical frame is a comma-separated list. It begins with a "(",
* consists of expressions separated by ",", and ends with a ")".
*
*
A select statement is also a kind of frame. The beginning and end are
* are empty strings, but it consists of a sequence of clauses. "SELECT",
* "FROM", "WHERE" are separators.
*
*
A frame is current between a call to one of the
* {@link SqlWriter#startList} methods and the call to
* {@link SqlWriter#endList(Frame)}. If other code starts a frame in the mean
* time, the sub-frame is put onto a stack.
*/
interface Frame {
}
/** Frame type. */
interface FrameType {
/**
* Returns the name of this frame type.
*
* @return name
*/
String getName();
/**
* Returns whether this frame type should cause the code be further
* indented.
*
* @return whether to further indent code within a frame of this type
*/
boolean needsIndent();
}
}
// End SqlWriter.java