blob: 95aa41a5bb914ffffa9344a6ea18f35be42c8a08 [file] [log] [blame]
/*
// Licensed to Julian Hyde under one or more contributor license
// agreements. See the NOTICE file distributed with this work for
// additional information regarding copyright ownership.
//
// Julian Hyde 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.eigenbase.sql;
import org.eigenbase.sql.util.SqlString;
/**
* A <code>SqlWriter</code> is the target to construct a SQL statement from a
* parse tree. It deals with dialect differences; for example, Oracle quotes
* identifiers as <code>"scott"</code>, while SQL Server quotes them as <code>
* [scott]</code>.
*
* @author Julian Hyde
* @version $Id$
* @since 2002/8/8
*/
public interface SqlWriter
{
//~ Enums ------------------------------------------------------------------
/**
* Style of formatting subqueries.
*/
enum SubqueryStyle
{
/**
* Julian's style of subquery nesting. Like this:
*
* <pre>SELECT *
* FROM (
* SELECT *
* FROM t
* )
* WHERE condition</pre>
*/
Hyde,
/**
* Damian's style of subquery nesting. Like this:
*
* <pre>SELECT *
* FROM
* ( SELECT *
* FROM t
* )
* WHERE condition</pre>
*/
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.
*/
SelectList,
/**
* The WINDOW clause of a SELECT statement.
*/
WindowDeclList,
/**
* The SET clause of an UPDATE statement.
*/
UpdateSetList,
/**
* Function declaration.
*/
FunDecl,
/**
* Function call or datatype declaration.
*
* <p>Examples:
* <li>SUBSTRING('foobar' FROM 1 + 2 TO 4)</li>
* <li>DECIMAL(10, 5)</li>
*/
FunCall,
/**
* Window specification.
*
* <p>Examples:
* <li>SUM(x) OVER (ORDER BY hireDate ROWS 3 PRECEDING)</li>
* <li>WINDOW w1 AS (ORDER BY hireDate), w2 AS (w1 PARTITION BY gender
* RANGE BETWEEN INTERVAL '1' YEAR PRECEDING AND '2' MONTH
* PRECEDING)</li>
*/
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.
*/
OrderBy,
/**
* ORDER BY list.
*
* <p>Example:
* <li>ORDER BY x, y DESC, z
*/
OrderByList,
/**
* GROUP BY list.
*
* <p>Example:
* <li>GROUP BY x, FLOOR(y)
*/
GroupByList,
/**
* Sub-query list. Encloses a SELECT, UNION, EXCEPT, INTERSECT query
* with optional ORDER BY.
*
* <p>Example:
* <li>GROUP BY x, FLOOR(y)
*/
Subquery,
/**
* Set operation.
*
* <p>Example:
* <li>SELECT * FROM a UNION SELECT * FROM b
*/
Setop,
/**
* FROM clause (containing various kinds of JOIN).
*/
FromList,
/**
* WHERE clause.
*/
WhereList,
/**
* Compound identifier.
*
* <p>Example:
* <li>"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, <code>keyword("SELECT")</code>, <code>
* keyword("CHARACTER SET")</code>.
*/
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 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.
*
* <p>For example, the parentheses are required in the expression <code>(a +
* b) * c</code> because the '*' operator has higher precedence than the '+'
* operator, and so without the parentheses, the expression would be
* equivalent to <code>a + (b * c)</code>. The fully-parenthesized
* expression, <code>((a + b) * c)</code> 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.
*
* <p>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 ")".
*
* <p>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.
*
* <p>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.
*/
public interface Frame
{
}
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